diff options
author | Norbert Preining <norbert@preining.info> | 2021-03-30 03:00:56 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2021-03-30 03:00:56 +0000 |
commit | 93809c868bf15852ddc7b50542713131a5d8c05f (patch) | |
tree | 3c741be9d43fdee2f3ecdb17d463deb188d881a8 /macros/latex/contrib | |
parent | 3c5dd0d2f091e5e866af1de0327171b253ec9178 (diff) |
CTAN sync 202103300300
Diffstat (limited to 'macros/latex/contrib')
27 files changed, 436 insertions, 9095 deletions
diff --git a/macros/latex/contrib/pkuthss/doc/example.pdf b/macros/latex/contrib/pkuthss/doc/example.pdf Binary files differindex ea1a631bda..a548fbcc13 100644 --- a/macros/latex/contrib/pkuthss/doc/example.pdf +++ b/macros/latex/contrib/pkuthss/doc/example.pdf diff --git a/macros/latex/contrib/pkuthss/doc/example/chap/abs.tex b/macros/latex/contrib/pkuthss/doc/example/chap/abs.tex index 305792f836..ea215a83c1 100644 --- a/macros/latex/contrib/pkuthss/doc/example/chap/abs.tex +++ b/macros/latex/contrib/pkuthss/doc/example/chap/abs.tex @@ -1,12 +1,12 @@ -% Copyright (c) 2014,2016 Casper Ti. Vector +% Copyright (c) 2014,2016,2021 Casper Ti. Vector % Public domain. \begin{cabstract} \pkuthssffaq % 中文测试文字。 \end{cabstract} -\begin{eabstract} +\ifblind\begin{beabstract}\else\begin{eabstract}\fi Test of the English abstract. -\end{eabstract} +\ifblind\end{beabstract}\else\end{eabstract}\fi % vim:ts=4:sw=4 diff --git a/macros/latex/contrib/pkuthss/doc/example/chap/origin.tex b/macros/latex/contrib/pkuthss/doc/example/chap/origin.tex index 49d25b5425..b4103f1bf4 100644 --- a/macros/latex/contrib/pkuthss/doc/example/chap/origin.tex +++ b/macros/latex/contrib/pkuthss/doc/example/chap/origin.tex @@ -1,5 +1,6 @@ % Copyright (c) 2008-2009 solvethis -% Copyright (c) 2010-2017 Casper Ti. Vector +% Copyright (c) 2010-2017,2021 Casper Ti. Vector +% Copyright (c) 2021 Kurapica % All rights reserved. % % Redistribution and use in source and binary forms, with or without @@ -31,10 +32,11 @@ \ctexset{section = { format+ = {\centering}, beforeskip = {40bp}, afterskip = {15bp} }} - - % 学校书面要求本页面不要页码,但在给出的 Word 模版中又有页码且编入了目录。 - % 此处以 Word 模版为实际标准进行设定。 \specialchap{北京大学学位论文原创性声明和使用授权说明} + + % 学校书面要求本页面不要页码,但在给出的 Word 模版中又有页码。 + % 此处以学校书面要求为准。 + \thispagestyle{empty} \mbox{}\vspace*{-3em} \section*{原创性声明} diff --git a/macros/latex/contrib/pkuthss/doc/example/thesis.tex b/macros/latex/contrib/pkuthss/doc/example/thesis.tex index 9c5f042cb4..30bc89d1aa 100644 --- a/macros/latex/contrib/pkuthss/doc/example/thesis.tex +++ b/macros/latex/contrib/pkuthss/doc/example/thesis.tex @@ -1,5 +1,6 @@ % Copyright (c) 2008-2009 solvethis -% Copyright (c) 2010-2016,2018-2019 Casper Ti. Vector +% Copyright (c) 2010-2016,2018-2019,2021 Casper Ti. Vector +% Copyright (c) 2021 Kurapica % Public domain. % % 使用前请先仔细阅读 pkuthss 和 biblatex-caspervector 的文档, @@ -9,6 +10,7 @@ % texdoc biblatex-caspervector % 调出。 +% 如果格式审查提示字号不严格符合标准,可以在 [] 中加入“ugly”选项。 \documentclass[UTF8]{pkuthss} % 如果的确须要使脚注按页编号的话,可以去掉后面 footmisc 包的注释。 %\usepackage[perpage]{footmisc} @@ -18,6 +20,8 @@ % 若须按照中文文献在前,西文文献在后排序,请设置“sorting = cenyt”; % 若须按照引用顺序排序,请设置“sorting = none”。 % 若须在排序中实现更复杂的需求,请参考 biblatex-caspervector 的文档。 +% biblatex-caspervector 也有一个“ugly”选项,使其更像国标格式;此外也可考虑 +% 改用 style = gb7714-2015 并去掉之后两选项,详见 biblatex-gb7714-2015 的文档。 \usepackage[backend = biber, style = caspervector, utf8, sorting = ecnyt]{biblatex} % 对于 linespread 值的计算过程有兴趣的同学可以参考 pkuthss.cls。 @@ -25,19 +29,26 @@ % 按学校要求设定参考文献列表的段间距。 \setlength{\bibitemsep}{3bp} +% 如是双盲版论文,将 \blindfalse 改为 \blindtrue。后面可用 +% \ifblind 根据是否双盲来条件地启用代码(参见本文件后面部分)。 +\newif\ifblind\blindfalse % 设定文档的基本信息。 \pkuthssinfo{ - cthesisname = {博士研究生学位论文}, ethesisname = {Doctor Thesis}, - ctitle = {测试文档}, etitle = {Test Document}, - cauthor = {某某}, - eauthor = {Test}, - studentid = {0123456789}, - date = {某年某月}, - school = {某某学院}, + cthesisname = {博士学位论文}, ethesisname = {Doctor Thesis}, + thesiscover = {博士研究生学位论文}, + % 长标题可用 \thssnl 强制换行,不能用“\\”(双盲版会出错)。 + ctitle = {测试文档}, + etitle = {Test Document}, + cauthor = {某某}, eauthor = {Test}, date = {某年某月}, + studentid = {0123456789}, school = {某某学院}, cmajor = {某某专业}, emajor = {Some Major}, direction = {某某方向}, cmentor = {某某教授}, ementor = {Prof.\ Somebody}, - ckeywords = {其一,其二}, ekeywords = {First, Second} + ckeywords = {其一,其二}, + ekeywords = {First, Second}, + % 以下两项无双盲评审需求的用户可保持原状。 + % 注意 discipline/major 分别指一/二级学科。 + blindid = {9876543210}, discipline = {某某学科} } % 载入参考文献数据库(注意不要省略“.bib”)。 \addbibresource{thesis.bib} @@ -57,7 +68,9 @@ 如果编译时不出参考文献, 请参考 \texttt{texdoc pkuthss}“问题及其解决”一章 - “上游宏包可能引起的问题”一节中关于 biber 的说明。% + “上游宏包可能引起的问题”一节中关于 biber 的说明。 + + 因无法假定用户使用哪种方式排版表格,用户须自行保证表格字号符合学校规定。% } \begin{document} @@ -66,7 +79,7 @@ % 此后到下一 \pagestyle 命令之前不排版页眉或页脚。 \pagestyle{empty} % 自动生成封面。 - \maketitle + \ifblind\makeblind\else\maketitle\fi % 版权声明。封面要求单面打印,故须新开右页。 \cleardoublepage \include{chap/copy} @@ -100,7 +113,7 @@ % 以下为正文之后的部分,默认不进行章节编号。 \backmatter % 致谢。 - \include{chap/ack} + \ifblind\else\include{chap/ack}\fi % 原创性声明和使用授权说明。 \include{chap/origin} \end{document} diff --git a/macros/latex/contrib/pkuthss/doc/pkuthss.pdf b/macros/latex/contrib/pkuthss/doc/pkuthss.pdf Binary files differindex 837e526455..9d172c6554 100644 --- a/macros/latex/contrib/pkuthss/doc/pkuthss.pdf +++ b/macros/latex/contrib/pkuthss/doc/pkuthss.pdf diff --git a/macros/latex/contrib/pkuthss/doc/readme/ChangeLog.txt b/macros/latex/contrib/pkuthss/doc/readme/ChangeLog.txt index aaf026bf9f..1d7835cf92 100644 --- a/macros/latex/contrib/pkuthss/doc/readme/ChangeLog.txt +++ b/macros/latex/contrib/pkuthss/doc/readme/ChangeLog.txt @@ -1,3 +1,19 @@ +2010-03-29, v1.9.0 + + * API changes: + - Add support for double-blind review (thank @Kurapikov). + - Add `\thesiscover' for possibly different thesis name on the cover. + + * Changes to package code: + - Greatly improve format compliance (thank @Kurapikov). + + * Changes to documentation: + - More notes about table font and GB/T 7714. + - Avoid undefined `\textepsilon'. + + * Misc: + - Minor fixes and cosmetics. + 2020-11-02, v1.8.3 * Changes to example template: diff --git a/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-abs.tex b/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-abs.tex index 453d56bb69..06d2032350 100644 --- a/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-abs.tex +++ b/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-abs.tex @@ -1,7 +1,7 @@ % Documentation for pkuthss. % % Copyright (c) 2008-2009 solvethis -% Copyright (c) 2010-2014 Casper Ti. Vector +% Copyright (c) 2010-2014,2021 Casper Ti. Vector % % This work may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3 of this license or (at @@ -31,9 +31,9 @@ 本文介绍了 pkuthss 文档模版所提供的功能。 \end{cabstract} -\begin{eabstract} +\ifblind\begin{beabstract}\else\begin{eabstract}\fi This document describes the the functions provided by the pkuthss document template. -\end{eabstract} +\ifblind\end{beabstract}\else\end{eabstract}\fi % vim:ts=4:sw=4 diff --git a/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-ack.tex b/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-ack.tex index 2859463747..cd2deb28e9 100644 --- a/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-ack.tex +++ b/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-ack.tex @@ -1,7 +1,7 @@ % Documentation for pkuthss. % % Copyright (c) 2008-2009 solvethis -% Copyright (c) 2010-2012,2015 Casper Ti. Vector +% Copyright (c) 2010-2012,2015,2021 Casper Ti. Vector % % This work may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3 of this license or (at @@ -31,7 +31,8 @@ 感谢北大未名 BBS 上 MathTools 版和 Thesis 版诸位同学的支持。 特别感谢 pkuthss 模版的最初创作者 solvethis 网友, -以及不断地对 Casper 提出的诸多问题予以解答的 cauchy 网友 :) +不断地对 Casper 提出的诸多问题予以解答的 cauchy 网友, +以及在论文格式合规性和双盲版论文格式上有主要贡献的 Kurapica 网友~:) 此外还要感谢 \parencite{pku-thesisstyle} 的作者, 让我校在学位论文格式要求的繁复程度上离隔壁更近了一步, diff --git a/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-chap2.tex b/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-chap2.tex index c7c1c75c18..5d2f91185b 100644 --- a/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-chap2.tex +++ b/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-chap2.tex @@ -1,7 +1,7 @@ % Documentation for pkuthss. % % Copyright (c) 2008-2009 solvethis -% Copyright (c) 2010-2019 Casper Ti. Vector +% Copyright (c) 2010-2019,2021 Casper Ti. Vector % % This work may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3 of this license or (at @@ -150,7 +150,7 @@ \end{Verbatim} \section{pkuthss 文档类提供的命令和环境} -\subsection{设定文档信息的命令} +\subsection{设定文档信息的命令}\label{ssec:set-cmd} 这一类命令的语法为 \begin{Verbatim} @@ -159,21 +159,29 @@ 这些命令总结如下: \begin{itemize} - \item \texttt{\bfseries\string\ctitle}:设定论文中文标题; + \item \texttt{\bfseries\string\ctitle}:设定论文中文标题\footnote{% + 因为 pkuthss 内部实现机制的缘故,\myemph{双盲版论文的(中文和西文) + 标题如须强制换行,必须使用 pkuthss 提供的 \texttt{\string\thssnl} + 命令而非 \texttt{\string\\}},否则会出错。% + }; \item \texttt{\bfseries\string\etitle}:设定论文西文标题; \item \texttt{\bfseries\string\cauthor}:设定作者的中文名; \item \texttt{\bfseries\string\eauthor}:设定作者的西文名; - \item \texttt{\bfseries\string\studentid}:设定作者的学号; \item \texttt{\bfseries\string\date}:设定日期; + \item \texttt{\bfseries\string\studentid}:设定作者的学号; \item \texttt{\bfseries\string\school}:设定作者的学院名; - \item \texttt{\bfseries\string\cmajor}:设定作者专业的中文名; - \item \texttt{\bfseries\string\emajor}:设定作者专业的西文名; + \item \texttt{\bfseries\string\cmajor}:设定作者专业(二级学科)的中文名; + \item \texttt{\bfseries\string\emajor}:设定作者专业(二级学科)的西文名; \item \texttt{\bfseries\string\direction}:设定作者的研究方向; \item \texttt{\bfseries\string\cmentor}:设定导师的中文名; \item \texttt{\bfseries\string\ementor}:设定导师的西文名; \item \texttt{\bfseries\string\ckeywords}:设定中文关键词; - \item \texttt{\bfseries\string\ekeywords}:设定西文关键词。 + \item \texttt{\bfseries\string\ekeywords}:设定西文关键词; + \item \texttt{\bfseries\string\blindid}:设定论文编号(双盲评审用); + \item \texttt{\bfseries\string\discipline}:设定一级学科(双盲评审用)。 \end{itemize} +排版双盲版论文时除了要去掉致谢等章节、隐去论文中其它可能泄露个人信息的部分外, +还应注意在排版封面时须使用 \verb|\makeblind| 而非 \verb|\maketitle| 命令。 例如,如果要设定专业为“化学”(“Chemistry”),则可以使用以下命令: \begin{Verbatim} @@ -195,16 +203,20 @@ \item \texttt{\bfseries\string\euniversity}:大学的西文名。 \item \texttt{\bfseries\string\cthesisname}:论文类别的中文名。 \item \texttt{\bfseries\string\ethesisname}:论文类别的西文名。 + \item \texttt{\bfseries\string\thesiscover}:封面显示的论文类别\footnote{% + 出于兼容性的考虑,如果 \texttt{\string\thesiscover} 为空, + 那么封面将显示 \texttt{\string\cthesisname}。% + }。 \item \texttt{\bfseries\string\cabstractname}:摘要的中文标题。 \item \texttt{\bfseries\string\eabstractname}:摘要的西文标题。 \end{itemize} -例如, -如果要设定论文的类别为“本科生毕业论文”(“Undergraduate Thesis”), -则可以使用以下命令: +例如,如果要设定论文的类别为“博士学位论文”(“Doctor Thesis”), +但封面要显示“博士研究生学位论文”,则可以使用以下命令: \begin{Verbatim} -\renewcommand{\cthesisname}{本科生毕业论文} -\renewcommand{\ethesisname}{Undergraduate Thesis} +\renewcommand{\cthesisname}{博士学位论文} +\renewcommand{\ethesisname}{Doctor Thesis} +\renewcommand{\thesiscover}{博士研究生学位论文} \end{Verbatim} \subsection{以“key = value”格式设置文档信息} @@ -235,8 +247,8 @@ \subsection{其它命令和环境}\label{ssec:misc} -\texttt{\bfseries cabstract} 和 \texttt{\bfseries eabstract} -环境用于编写中西文摘要。 +\texttt{\bfseries cabstract} 和 \texttt{\bfseries eabstract} 环境用于编写 +中西文摘要;\texttt{\bfseries beabstract} 环境用于编写双盲评审版的西文摘要。 用户只须要写摘要的正文;标题、作者、导师、专业等部分会自动生成。 \texttt{\bfseries\string\specialchap} 命令 @@ -258,6 +270,9 @@ 此时就须要在设定完文档信息之后调用 \verb|\setpdfproperties|。% \myemph{注意:须要启用 \texttt{pdfprop} 选项才能使用此命令。} +\texttt{\bfseries\string\thssnl} 命令用于在双盲版论文的(中文和西文)标题中 +强制换行,见第 \ref{ssec:set-cmd} 小节中关于 \verb|\ctitle| 说明的脚注。 + \section{从其它文档类和宏包继承的功能}\label{sec:thirdparty} pkuthss 文档类建立在 ctexbook\cupercite{ctex} 文档类之上, diff --git a/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-chap3.tex b/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-chap3.tex index 0fbd72bd47..b5482a08eb 100644 --- a/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-chap3.tex +++ b/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-chap3.tex @@ -1,7 +1,7 @@ % Documentation for pkuthss. % % Copyright (c) 2008-2009 solvethis -% Copyright (c) 2010-2019 Casper Ti. Vector +% Copyright (c) 2010-2019,2021 Casper Ti. Vector % % This work may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3 of this license or (at @@ -33,6 +33,9 @@ 文档默认情况下是双面模式,章末可能产生空白页, 解决方式见第 \ref{sec:options} 节。 +双盲版论文的(中文和西文)标题只能使用 pkuthss 提供的 +\verb|\thssnl| 命令而非 \verb|\\| 换行,见第 \ref{sec:options} 节。 + 通过一些设置,还可以满足例如被引用的文献按照引用顺序排序, 而未引用的文献按照西文文献在前、中文文献在后排序这样的需求, 见第 \ref{sec:thirdparty} 节。 @@ -97,14 +100,20 @@ data source .../par-xxxxxxxx/cache-xxxxxxxx/ \section{文档格式可能存在的问题} -学校对学位论文格式的规定\cupercite{pku-thesisstyle}% -显然没有考虑到非 MS Word 类排版工具的工作方式, +目前在 \hologo{LaTeX} 中似乎没有一个可以很好地替代其它各类似宏包的 +用于排版表格的宏包,而 pkuthss 文档模版的作者也无意假定用户使用 +某一个宏包,因此模版并未尝试设定表格的默认字号,\myemph{用户 +须自行按学校规定\cupercite{pku-thesisstyle}进行设置}。 + +学校对学位论文格式的规定显然没有考虑到非 MS Word 类排版工具的工作方式, 因此 pkuthss 文档模版只是对其要求的格式进行模仿, 而在一些小的细节上可能有所出入。 -biblatex-caspervector\cupercite{biblatex-caspervector} 所实现的格式和 -\parencite{pku-thesisstyle} 的规定并不一致, -但其作者暂时没有精力也不愿意去实现后者所规定的比原格式更丑陋得多的格式。 +biblatex-caspervector\cupercite{biblatex-caspervector} +所实现的格式和 \parencite{pku-thesisstyle} 的规定并不一致, +但其作者没有精力也不愿意去实现后者所规定的比原格式更丑陋得多的格式。 +国标 GB/T 7714-2015 现在已经有了 biblatex-gb7714-2015% +\cupercite{biblatex-gb7714-2015} 这一 biblatex 实现,用户也可以考虑使用。 \section{反馈意见和建议} diff --git a/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-copy.tex b/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-copy.tex index 68d86f34de..e9cecd08d3 100644 --- a/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-copy.tex +++ b/macros/latex/contrib/pkuthss/doc/readme/chap/pkuthss-copy.tex @@ -32,7 +32,9 @@ 版权所有 \copyright\ 2008--2009 solvethis \par -版权所有 \copyright\ 2010--2019 Casper Ti. Vector +版权所有 \copyright\ 2010--2021 Casper Ti. Vector +\par +版权所有 \copyright\ 2021 Kurapica \vskip 1em pkuthss 文档类及其说明文档均以 \hologo{LaTeX} Project Public License 发布。 diff --git a/macros/latex/contrib/pkuthss/doc/readme/pkuthss-english.patch b/macros/latex/contrib/pkuthss/doc/readme/pkuthss-english.patch index ee9cadcad2..40b508c77c 100644 --- a/macros/latex/contrib/pkuthss/doc/readme/pkuthss-english.patch +++ b/macros/latex/contrib/pkuthss/doc/readme/pkuthss-english.patch @@ -1,5 +1,5 @@ diff --git a/doc/example/chap/abs.tex b/doc/example/chap/abs.tex -index 305792f..cfa6cd3 100644 +index dcffe0e..8fd046f 100644 --- a/doc/example/chap/abs.tex +++ b/doc/example/chap/abs.tex @@ -2,7 +2,7 @@ @@ -10,7 +10,7 @@ index 305792f..cfa6cd3 100644 + 中文摘要。 \end{cabstract} - \begin{eabstract} + \ifblind\begin{beabstract}\else\begin{eabstract}\fi diff --git a/doc/example/chap/ack.tex b/doc/example/chap/ack.tex index 4af4d39..09de33d 100644 --- a/doc/example/chap/ack.tex @@ -100,10 +100,10 @@ index ac5b0c9..9d2ad60 100644 - % vim:ts=4:sw=4 diff --git a/doc/example/thesis.tex b/doc/example/thesis.tex -index 9c5f042..a54d01f 100644 +index 0009fe6..3f2d945 100644 --- a/doc/example/thesis.tex +++ b/doc/example/thesis.tex -@@ -12,54 +12,44 @@ +@@ -14,36 +14,42 @@ \documentclass[UTF8]{pkuthss} % 如果的确须要使脚注按页编号的话,可以去掉后面 footmisc 包的注释。 %\usepackage[perpage]{footmisc} @@ -113,6 +113,8 @@ index 9c5f042..a54d01f 100644 -% 若须按照中文文献在前,西文文献在后排序,请设置“sorting = cenyt”; -% 若须按照引用顺序排序,请设置“sorting = none”。 -% 若须在排序中实现更复杂的需求,请参考 biblatex-caspervector 的文档。 +-% biblatex-caspervector 也有一个“ugly”选项,使其更像国标格式;此外也可考虑 +-% 改用 style = gb7714-2015 并去掉之后两选项,详见 biblatex-gb7714-2015 的文档。 -\usepackage[backend = biber, style = caspervector, utf8, sorting = ecnyt]{biblatex} +% 使用 biblatex 排版参考文献,并规定其格式(详见 biblatex 的文档)。 +\usepackage[backend = biber]{biblatex} @@ -136,27 +138,32 @@ index 9c5f042..a54d01f 100644 + chapter/number = {\thechapter}, +} + + % 如是双盲版论文,将 \blindfalse 改为 \blindtrue。后面可用 + % \ifblind 根据是否双盲来条件地启用代码(参见本文件后面部分)。 + \newif\ifblind\blindfalse % 设定文档的基本信息。 \pkuthssinfo{ -- cthesisname = {博士研究生学位论文}, ethesisname = {Doctor Thesis}, -- ctitle = {测试文档}, etitle = {Test Document}, -- cauthor = {某某}, +- cthesisname = {博士学位论文}, ethesisname = {Doctor Thesis}, +- thesiscover = {博士研究生学位论文}, + ethesisname = {Doctor Thesis}, -+ etitle = {Test Document}, - eauthor = {Test}, - studentid = {0123456789}, -- date = {某年某月}, -- school = {某某学院}, + % 长标题可用 \thssnl 强制换行,不能用“\\”(双盲版会出错)。 +- ctitle = {测试文档}, + etitle = {Test Document}, +- cauthor = {某某}, eauthor = {Test}, date = {某年某月}, +- studentid = {0123456789}, school = {某某学院}, - cmajor = {某某专业}, emajor = {Some Major}, - direction = {某某方向}, - cmentor = {某某教授}, ementor = {Prof.\ Somebody}, -+ date = {Some Date}, ++ eauthor = {Test}, ++ date = {Month Year}, studentid = {0123456789}, + school = {Some School}, + emajor = {Some Major}, + direction = {Some Direction}, + ementor = {Prof.\ Somebody}, - ckeywords = {其一,其二}, ekeywords = {First, Second} - } + ckeywords = {其一,其二}, + ekeywords = {First, Second}, + % 以下两项无双盲评审需求的用户可保持原状。 +@@ -53,26 +59,6 @@ % 载入参考文献数据库(注意不要省略“.bib”)。 \addbibresource{thesis.bib} @@ -175,18 +182,20 @@ index 9c5f042..a54d01f 100644 - - 如果编译时不出参考文献, - 请参考 \texttt{texdoc pkuthss}“问题及其解决”一章 -- “上游宏包可能引起的问题”一节中关于 biber 的说明。% +- “上游宏包可能引起的问题”一节中关于 biber 的说明。 +- +- 因无法假定用户使用哪种方式排版表格,用户须自行保证表格字号符合学校规定。% -} - \begin{document} % 以下为正文之前的部分,默认不进行章节编号。 \frontmatter diff --git a/tex/pkuthss-utf8.def b/tex/pkuthss-utf8.def -index 9bc6000..7650e53 100644 +index d968f90..f99a891 100644 --- a/tex/pkuthss-utf8.def +++ b/tex/pkuthss-utf8.def -@@ -25,13 +25,13 @@ - [2019/11/17 v1.8.2 Labels and captions in UTF-8 encoding +@@ -26,13 +26,13 @@ + [2020/11/02 v1.8.3 Labels and captions in UTF-8 encoding for the pkuthss document class] -\def\label@ctitle{题目:} @@ -207,10 +216,10 @@ index 9bc6000..7650e53 100644 \def\label@ckeywords{关键词:} \def\label@ekeywords{KEYWORDS:\ } diff --git a/tex/pkuthss.cls b/tex/pkuthss.cls -index e34fe2d..477b3f4 100644 +index 4499528..e6311cb 100644 --- a/tex/pkuthss.cls +++ b/tex/pkuthss.cls -@@ -304,7 +304,7 @@ +@@ -317,7 +317,7 @@ \fancyhf{}\renewcommand*{\headrulewidth}{0.75bp} \fancyfoot[C]{\zihao{5}\normalfont{\thepage}} \if@twoside @@ -219,23 +228,24 @@ index e34fe2d..477b3f4 100644 \fancyhead[CO]{\zihao{5}\normalfont\thss@int@setcase{\leftmark}} \else \fancyhead[C]{\zihao{5}\normalfont\thss@int@setcase{\leftmark}} -@@ -350,13 +350,13 @@ - \zihao{1}% - \includegraphics[height = 2.4em]{pkulogo}\hspace{0.4em}% - \raisebox{0.4em}{\includegraphics[height = 1.6em]{pkuword}}\\[0.8em] -- {\bfseries{\cthesisname}}% -+ {\bfseries{\ethesisname}}% +@@ -367,14 +367,14 @@ + \zihao{1}\includegraphics[height = 2.4em]{pkulogo}\hspace{0.4em}% + \raisebox{0.4em}{\includegraphics[height = 1.6em]{pkuword}}\\[0.8em] + \fi% +- {\bfseries\ifx\thesiscover\empty{\cthesisname}\else{\thesiscover}\fi}% ++ {\bfseries\ethesisname}% } \vfill % Title of the thesis. {% - \zihao{2}{\label@ctitle}\linespread{1.6}\selectfont% + \ifthss@opt@ugly\zihao{-1}\else\zihao{2}\fi% + \linespread{1.6}\selectfont{\label@ctitle}% - \thss@int@fillinblank{2}{0.64\textwidth}{\textbf{\@ctitle}}% + \thss@int@fillinblank{2}{0.64\textwidth}{\textbf{\@etitle}}% } \vfill % Information about the author. -@@ -364,19 +364,19 @@ +@@ -382,19 +382,19 @@ % Slightly adjust the line skip when using new font size. \zihao{3}\linespread{1.75}\selectfont \def\thss@tmp@len{0.56\textwidth} diff --git a/macros/latex/contrib/pkuthss/doc/readme/pkuthss.bib b/macros/latex/contrib/pkuthss/doc/readme/pkuthss.bib index 3404e2a59a..3f4adbe05f 100644 --- a/macros/latex/contrib/pkuthss/doc/readme/pkuthss.bib +++ b/macros/latex/contrib/pkuthss/doc/readme/pkuthss.bib @@ -1,7 +1,7 @@ % Documentation for pkuthss. % % Copyright (c) 2008-2009 solvethis -% Copyright (c) 2010-2019 Casper Ti. Vector +% Copyright (c) 2010-2021 Casper Ti. Vector % % This work may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3 of this license or (at @@ -30,7 +30,7 @@ @online{amsthm, author = {{Publications Technical Group, American Mathematical Society}}, title = {Using the amsthm Package}, - edition = {Ver.\ 2.20.3}, + edition = {Ver.~2.20.3}, type = {M/OL}, date = {2017-09}, url = {https://ctan.org/pkg/amsthm}, @@ -41,7 +41,7 @@ @online{biber, author = {Kime, Philip and Charette, Fran\c{c}ois}, title = {Biber: A backend bibliography processor for biblatex}, - edition = {Ver.\ 2.7}, + edition = {Ver.~2.7}, type = {M/OL}, date = {2016-12-05}, url = {https://ctan.org/pkg/biber}, @@ -52,7 +52,7 @@ @online{biblatex, author = {Lehman, Philipp}, title = {The biblatex Package: Programmable Bibliographies and Citations}, - edition = {Ver.\ 3.7}, + edition = {Ver.~3.7}, type = {M/OL}, date = {2016-11-16}, url = {https://ctan.org/pkg/biblatex}, @@ -63,7 +63,7 @@ @online{biblatex-caspervector, author = {Vector, Casper Ti.}, title = {biblatex 参考文献和引用样式:caspervector}, - edition = {Ver.\ 0.3.3}, + edition = {Ver.~0.3.3}, type = {M/OL}, date = {2018-06-29}, url = {https://ctan.org/pkg/biblatex-caspervector}, @@ -71,6 +71,17 @@ language = {chinese}, } +@online{biblatex-gb7714-2015, + author = {胡振震}, + title = {符合 GB/T 7714-2015 标准的 biblatex 参考文献样式}, + edition = {Ver.~0.1w}, + type = {M/OL}, + date = {2021-01-19}, + url = {https://ctan.org/pkg/biblatex-gb7714-2015}, + urldate = {2021-03-04}, + language = {chinese}, +} + @online{caption, author = {Sommerfeldt, Alex}, title = {Customizing captions of floating environments}, @@ -84,7 +95,7 @@ @online{ctex, author = {{ctex.org}}, title = {\CTeX 宏集手册}, - edition = {Ver.\ 2.4.8}, + edition = {Ver.~2.4.8}, type = {M/OL}, date = {2017-02-23}, url = {https://ctan.org/pkg/ctex}, @@ -105,7 +116,7 @@ @online{fancyhdr, author = {van Oostrum, Piet}, title = {Page layout in \hologo{LaTeX}}, - edition = {Ver.\ 3.8}, + edition = {Ver.~3.8}, type = {M/OL}, date = {2016-09-06}, url = {https://ctan.org/pkg/fancyhdr}, @@ -116,7 +127,7 @@ @online{geometry, author = {Umeki, Hideo}, title = {The geometry package}, - edition = {Ver.\ 5.6}, + edition = {Ver.~5.6}, type = {M/OL}, date = {2010-09-12}, url = {https://ctan.org/pkg/geometry}, @@ -137,7 +148,7 @@ @online{hyperref, author = {Rahtz, Sebastian and Oberdiek, Heiko}, title = {Hypertext marks in \hologo{LaTeX}: a manual for hyperref}, - edition = {Ver.\ 6.82q}, + edition = {Ver.~6.82q}, type = {M/OL}, date = {2012-11}, url = {https://ctan.org/pkg/hyperref}, @@ -148,7 +159,7 @@ @online{latexsym, author = {Mittelbach, Frank}, title = {The \hologo{LaTeX} symbol fonts for use with \hologo{LaTeX2e}}, - edition = {Ver.\ 2.2e}, + edition = {Ver.~2.2e}, type = {M/OL}, date = {1998-08-17}, url = {https://ctan.org/tex-archive/macros/latex/base}, @@ -179,7 +190,7 @@ @online{subcaption, author = {Sommerfeldt, Alex}, title = {The subcaption package}, - edition = {Ver.\ 1.1-75}, + edition = {Ver.~1.1-75}, type = {M/OL}, date = {2013-04-16}, url = {https://ctan.org/pkg/subcaption}, @@ -200,7 +211,7 @@ @online{tocloft, author = {Robertson, Will}, title = {The tocloft package}, - edition = {Ver.\ 2.3f}, + edition = {Ver.~2.3f}, type = {M/OL}, date = {2013-05-02}, url = {https://ctan.org/pkg/tocloft}, @@ -281,7 +292,7 @@ @online{pku-thesisstyle, author = {北京大学学位办公室}, title = {北京大学研究生学位论文写作指南}, - edition = {Ver.\ 2.0}, + edition = {Ver.~2.0}, type = {M/OL}, date = {2015-06-11}, url = {http://grs.pku.edu.cn/document/20150611115317661150.pdf}, diff --git a/macros/latex/contrib/pkuthss/doc/readme/pkuthss.tex b/macros/latex/contrib/pkuthss/doc/readme/pkuthss.tex index 522ebd9d54..8305720841 100644 --- a/macros/latex/contrib/pkuthss/doc/readme/pkuthss.tex +++ b/macros/latex/contrib/pkuthss/doc/readme/pkuthss.tex @@ -1,7 +1,7 @@ % Documentation for pkuthss. % % Copyright (c) 2008-2009 solvethis -% Copyright (c) 2010-2016,2018-2019 Casper Ti. Vector +% Copyright (c) 2010-2016,2018-2019,2021 Casper Ti. Vector % % This work may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3 of this license or (at @@ -50,31 +50,31 @@ tabsize = 4, formatcom = {\ifXeTeX\xeCJKVerbAddon\fi} } -\newcommand*{\docversion}{v1.8.3} +\newif\ifblind\blindfalse +\newcommand*{\docversion}{v1.9.0} \pkuthssinfo{ cthesisname = {本科生毕业论文}, ethesisname = {Undergraduate Thesis}, - ctitle = {北京大学学位论文模版\\pkuthss \docversion}, + ctitle = {北京大学学位论文模版{\thssnl}pkuthss \docversion}, etitle = {% - PKU dissertation document class\texorpdfstring{\\}{: }% - pkuthss \docversion% + PKU dissertation document class% + \texorpdfstring{\thssnl}{: }pkuthss \docversion% }, - cauthor = {盖茨波·钛·维克托}, - eauthor = {Casper Ti.\ Vector}, - studentid = {00910???}, - date = {\zhdigits{2020}年\zhnumber{11}月}, - school = {化学与分子工程学院}, - cmajor = {化学(?)}, emajor = {Chemistry ... ?}, + cauthor = {盖茨波·钛·维克托}, eauthor = {Casper Ti.\ Vector}, + date = {\zhdigits{2021}年\zhnumber{3}月}, + studentid = {00910???}, school = {化学与分子工程学院}, + cmajor = {应用化学}, emajor = {Applied Chemistry}, direction = {据说 Casper 自己也不知道}, cmentor = {XX 教授}, ementor = {Prof.\ XX}, - ckeywords = {\hologo{LaTeX2e},排版,文档类,\CTeX{}}, - ekeywords = {\hologo{LaTeX2e}, Typesetting, Document class, \CTeX{}} + ckeywords = {\hologo{LaTeX},排版,文档类,\CTeX{}}, + ekeywords = {\hologo{LaTeX}, Typesetting, Document class, \CTeX{}}, + blindid = {???01900}, discipline = {化学} } \addbibresource{pkuthss.bib} \begin{document} \frontmatter \pagestyle{empty} - \maketitle + \ifblind\makeblind\else\maketitle\fi \cleardoublepage \include{chap/pkuthss-copy} @@ -97,7 +97,7 @@ \include{chap/pkuthss-encl1} \backmatter - \include{chap/pkuthss-ack} + \ifblind\else\include{chap/pkuthss-ack}\fi \include{chap/origin} \end{document} diff --git a/macros/latex/contrib/pkuthss/tex/pkulogo.pdf b/macros/latex/contrib/pkuthss/tex/pkulogo.pdf Binary files differindex 03850ac253..bf9659a692 100644 --- a/macros/latex/contrib/pkuthss/tex/pkulogo.pdf +++ b/macros/latex/contrib/pkuthss/tex/pkulogo.pdf diff --git a/macros/latex/contrib/pkuthss/tex/pkuthss-gbk.def b/macros/latex/contrib/pkuthss/tex/pkuthss-gbk.def index caf9986940..28eb1ade7e 100644 --- a/macros/latex/contrib/pkuthss/tex/pkuthss-gbk.def +++ b/macros/latex/contrib/pkuthss/tex/pkuthss-gbk.def @@ -1,7 +1,8 @@ % Peking University dissertation document class % % Copyright (c) 2008-2009 solvethis -% Copyright (c) 2010-2013,2015 Casper Ti. Vector +% Copyright (c) 2010-2013,2015,2021 Casper Ti. Vector +% Copyright (c) 2021 Kurapica % % This work may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3 of this license or (at @@ -22,7 +23,7 @@ % pkuword.eps \ProvidesFile{pkuthss-gbk.def} - [2020/11/02 v1.8.3 Labels and captions in GBK encoding + [2021/03/29 v1.9.0 Labels and captions in GBK encoding for the pkuthss document class] \def\label@ctitle{Ŀ} @@ -35,12 +36,19 @@ \def\label@ementor{Directed by\ } \def\label@ckeywords{ؼʣ} \def\label@ekeywords{KEYWORDS:\ } +\def\label@blindcover{ķ棩} +\def\label@blindctitle{Ŀ} +\def\label@blindetitle{ӢĿ} +\def\label@blinddiscipline{һѧƣ} +\def\label@blindmajor{ѧƣ} +\def\label@blindid{ıţ} \def\titlepagename{} \def\cuniversity{ѧ} \def\euniversity{Peking University} -\def\cthesisname{ʿоѧλ} +\def\cthesisname{ʿѧλ} \def\ethesisname{Doctor Thesis} +\def\thesiscover{} \def\cabstractname{ժҪ} \def\eabstractname{ABSTRACT} diff --git a/macros/latex/contrib/pkuthss/tex/pkuthss-utf8.def b/macros/latex/contrib/pkuthss/tex/pkuthss-utf8.def index a5f2722160..6ab9dc0ec8 100644 --- a/macros/latex/contrib/pkuthss/tex/pkuthss-utf8.def +++ b/macros/latex/contrib/pkuthss/tex/pkuthss-utf8.def @@ -1,7 +1,8 @@ % Peking University dissertation document class % % Copyright (c) 2008-2009 solvethis -% Copyright (c) 2010-2013,2015 Casper Ti. Vector +% Copyright (c) 2010-2013,2015,2021 Casper Ti. Vector +% Copyright (c) 2021 Kurapica % % This work may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3 of this license or (at @@ -22,7 +23,7 @@ % pkuword.eps \ProvidesFile{pkuthss-utf8.def} - [2020/11/02 v1.8.3 Labels and captions in UTF-8 encoding + [2021/03/29 v1.9.0 Labels and captions in UTF-8 encoding for the pkuthss document class] \def\label@ctitle{题目:} @@ -35,12 +36,19 @@ \def\label@ementor{Directed by\ } \def\label@ckeywords{关键词:} \def\label@ekeywords{KEYWORDS:\ } +\def\label@blindcover{(匿名评阅论文封面)} +\def\label@blindctitle{中文题目:} +\def\label@blindetitle{英文题目:} +\def\label@blinddiscipline{一级学科:} +\def\label@blindmajor{二级学科:} +\def\label@blindid{论文编号:} \def\titlepagename{封面} \def\cuniversity{北京大学} \def\euniversity{Peking University} -\def\cthesisname{博士研究生学位论文} +\def\cthesisname{博士学位论文} \def\ethesisname{Doctor Thesis} +\def\thesiscover{} \def\cabstractname{摘要} \def\eabstractname{ABSTRACT} diff --git a/macros/latex/contrib/pkuthss/tex/pkuthss.cls b/macros/latex/contrib/pkuthss/tex/pkuthss.cls index 0a021b8bd7..2abf2d72fb 100644 --- a/macros/latex/contrib/pkuthss/tex/pkuthss.cls +++ b/macros/latex/contrib/pkuthss/tex/pkuthss.cls @@ -1,7 +1,8 @@ % Peking University dissertation document class % % Copyright (c) 2008-2009 solvethis -% Copyright (c) 2010-2019 Casper Ti. Vector +% Copyright (c) 2010-2021 Casper Ti. Vector +% Copyright (c) 2021 Kurapica % % This work may be distributed and/or modified under the conditions of the % LaTeX Project Public License, either version 1.3 of this license or (at @@ -23,7 +24,7 @@ \NeedsTeXFormat{LaTeX2e}[1995/12/01] \ProvidesClass{pkuthss} - [2020/11/02 v1.8.3 Peking University dissertation document class] + [2021/03/29 v1.9.0 Peking University dissertation document class] % eg. `\thss@int@boolopt{spacing}{true}' will expand to: % \newif\ifthss@opt@spacing \thss@opt@spacingtrue @@ -113,11 +114,11 @@ \ifthss@opt@pkufoot % Handle the `Unparsed material' issue with latex/dvipdfmx compilation. \unless\ifxetex\unless\ifpdf - \newcommand*\pgfsysdriver{pgfsys-dvipdfm.def} + \newcommand*{\pgfsysdriver}{pgfsys-dvipdfm.def} \fi\fi % Circled text, cf. <https://tex.stackexchange.com/questions/7032/>. \RequirePackage{tikz} - \newcommand*\thss@int@circled[1]{% + \newcommand*{\thss@int@circled}[1]{% \scalebox{0.8}{\tikz[baseline = (char.base)]{ \node[ shape = circle, draw = black, minimum size = 1.25em, inner sep = 0pt @@ -150,9 +151,14 @@ % `tocloft'; it clashes with `subfigure'/`subfig', but the error message will % say they cannot be used simultaneously. \RequirePackage{caption, subcaption} - \DeclareCaptionFont{cfive}{\zihao{5}} + \ifthss@opt@ugly + \DeclareCaptionFont{capfsize}{\fontsize{11bp}{13.2bp}} + \else + \DeclareCaptionFont{capfsize}{\zihao{5}} + \fi \DeclareCaptionLabelSeparator{quad}{\quad} - \captionsetup{font = cfive, labelsep = quad} + \captionsetup{font = capfsize, labelsep = quad} + \captionsetup[sub]{font = capfsize} \fi \ifthss@opt@spacing @@ -235,20 +241,27 @@ \thss@int@infoitema{ementor} \thss@int@infoitema{ckeywords} \thss@int@infoitema{ekeywords} +\thss@int@infoitema{blindid} +\thss@int@infoitema{discipline} \thss@int@infoitemb{cuniversity} \thss@int@infoitemb{euniversity} \thss@int@infoitemb{cthesisname} \thss@int@infoitemb{ethesisname} +\thss@int@infoitemb{thesiscover} \thss@int@infoitemb{cabstractname} \thss@int@infoitemb{eabstractname} % Set up document information using the `key = value' grammar. \newcommand*{\pkuthssinfo}[1]{\setkeys{thss@info}{#1}} +% Becomes \newline in the \makeblind scope. +\newcommand{\thssnl}{\\} % Set up page layout. -\geometry{ - a4paper, hmargin = 2.6cm, top = 2.92cm, bottom = 3.03cm, - headheight = 0.45cm, headsep = 0.59cm, footskip = 1.05cm -} +\geometry{a4paper, hmargin = 2.6cm, headheight = 0.5cm, headsep = 0.6cm} +\ifthss@opt@ugly + \geometry{top = 3.1cm, bottom = 3.0cm, footskip = 0.8cm} +\else + \geometry{top = 3.0cm, bottom = 3.1cm, footskip = 1.1cm} +\fi % Set up chapter/section/... captions. % The `*skip' values are not supposed to be modified by the `ugly' option: @@ -258,29 +271,29 @@ \setcounter{secnumdepth}{3} \setcounter{tocdepth}{2} \ctexset{ - chapter = { - beforeskip = {0bp}, afterskip = {18bp plus 0.2ex}, - nameformat = {}, titleformat = {} - }, section = + chapter = {beforeskip = {0bp}, afterskip = {18bp plus 0.2ex}}, + section = {beforeskip = {20bp plus 1ex minus 0.2ex}, afterskip = {5bp plus 0.2ex}}, subsection = {beforeskip = {12bp plus 1ex minus 0.2ex}, afterskip = {5bp plus 0.2ex}}, subsubsection = {beforeskip = {12bp plus 1ex minus 0.2ex}, afterskip = {5bp plus 0.2ex}} } +\ctexset{ + chapter = {nameformat = {}, titleformat = {}}, + subsubsection = {format = {\zihao{-4}\bfseries}} +} \ifthss@opt@ugly \ctexset{ chapter = {format = {\zihao{3}\bfseries\centering}}, section = {format = {\zihao{4}\bfseries}}, - subsection = {format = {\fontsize{13bp}{15.6bp}\selectfont\bfseries}}, - subsubsection = {format = {\zihao{-4}\bfseries}} + subsection = {format = {\fontsize{13bp}{15.6bp}\selectfont\bfseries}} } \else \ctexset{ chapter = {format = {\zihao{-2}\bfseries\centering}}, section = {format = {\zihao{-3}\bfseries}}, - subsection = {format = {\zihao{4}\bfseries}}, - subsubsection = {format = {\bfseries}} + subsection = {format = {\zihao{4}\bfseries}} } \fi @@ -344,18 +357,23 @@ \renewcommand{\maketitle}{% \thss@int@pdfmark{\titlepagename}{titlepage} % Make the title page centered. - \begin{titlepage}\begingroup\centering + \begin{titlepage}\centering % Emblem and inscription of the university, and type of thesis. {% - \zihao{1}% - \includegraphics[height = 2.4em]{pkulogo}\hspace{0.4em}% - \raisebox{0.4em}{\includegraphics[height = 1.6em]{pkuword}}\\[0.8em] - {\bfseries{\cthesisname}}% + \ifthss@opt@ugly% + \zihao{-0}\includegraphics[height = 1.9em]{pkulogo}\hspace{0.3em}% + \raisebox{0.32em}{\includegraphics[height = 1.3em]{pkuword}}\\[0.5em] + \else% + \zihao{1}\includegraphics[height = 2.4em]{pkulogo}\hspace{0.4em}% + \raisebox{0.4em}{\includegraphics[height = 1.6em]{pkuword}}\\[0.8em] + \fi% + {\bfseries\ifx\thesiscover\empty{\cthesisname}\else{\thesiscover}\fi}% } \vfill % Title of the thesis. {% - \zihao{2}{\label@ctitle}\linespread{1.6}\selectfont% + \ifthss@opt@ugly\zihao{-1}\else\zihao{2}\fi% + \linespread{1.6}\selectfont{\label@ctitle}% \thss@int@fillinblank{2}{0.64\textwidth}{\textbf{\@ctitle}}% } \vfill @@ -382,7 +400,27 @@ \vfill % Date. {\ifthss@opt@ugly\zihao{3}\else\zihao{-2}\fi\@date} - \par\endgroup\end{titlepage}% + \par\end{titlepage}% +} + +% Typeset the title page for double-blind review. +\newcommand{\makeblind}{% + \thss@int@pdfmark{\titlepagename}{titlepage} + \begin{titlepage}\renewcommand{\thssnl}{\newline} + \centering\zihao{3}\selectfont\fangsong\vspace*{0.5cm} + {\zihao{-0}\heiti\cuniversity\cthesisname}\\[0.36\baselineskip] + {\zihao{-2}\fangsong\label@blindcover}% + \par\vspace{4\baselineskip} + \renewcommand{\arraystretch}{1.25} + \begin{tabular}{lp{0.75\textwidth}} + \label@blindctitle & {\@ctitle} \\ + \label@blindetitle & {\@etitle} \\\\ + \label@blinddiscipline & {\@discipline} \\ + \label@blindmajor & {\@cmajor} \\ + \label@blindid & {\@blindid} \\ + \end{tabular}\par\vfill + {\@date}\par\vspace*{0.5cm} + \end{titlepage}% } % Typeset the Chinese abstract. @@ -406,5 +444,14 @@ \vfill\noindent\textbf{\label@ekeywords}{\@ekeywords}% } +% Typeset the English abstract for double-blind review. +\newenvironment{beabstract}{% + \thss@int@pdfmark{\eabstractname}{eabstract} + \chapter*{\sffamily\@etitle}\markboth{\eabstractname}{} + \begin{center}\textbf{\sffamily\eabstractname}\end{center}\par% +}{% Keywords at the bottom of the page. + \vfill\noindent\textbf{\label@ekeywords}{\@ekeywords}% +} + \endinput % vim:ft=tex:ts=2:sw=2 diff --git a/macros/latex/contrib/pkuthss/tex/pkuword.pdf b/macros/latex/contrib/pkuthss/tex/pkuword.pdf Binary files differindex 5884b8efd3..58b5193f46 100644 --- a/macros/latex/contrib/pkuthss/tex/pkuword.pdf +++ b/macros/latex/contrib/pkuthss/tex/pkuword.pdf diff --git a/macros/latex/contrib/polexpr/README.md b/macros/latex/contrib/polexpr/README.md deleted file mode 100644 index a901b56adc..0000000000 --- a/macros/latex/contrib/polexpr/README.md +++ /dev/null @@ -1,102 +0,0 @@ -Package polexpr README -====================== - -License -------- - -Copyright (C) 2018-2020 Jean-François Burnol - -See documentation of package [xint](http://www.ctan.org/pkg/xint) for -contact information. - -This Work may be distributed and/or modified under the conditions of the -LaTeX Project Public License version 1.3c. This version of this license -is in - -> <http://www.latex-project.org/lppl/lppl-1-3c.txt> - -and version 1.3 or later is part of all distributions of LaTeX version -2005/12/01 or later. - -This Work has the LPPL maintenance status author-maintained. - -The Author of this Work is Jean-François Burnol. - -This Work consists of the package file polexpr.sty, this README.md and -the documentation file polexpr.txt. - -Abstract --------- - -The package provides `\poldef`. This a parser of polynomial expressions -based upon the `\xintdeffunc` mechanism of xintexpr. - -The parsed expressions use the operations of algebra (inclusive of -composition of functions) with standard operators, fractional numbers -(possibly in scientific notation) and previously defined polynomial -functions or other constructs as recognized by the `\xintexpr` numerical -parser. - -The polynomials are then not only genuine `\xintexpr` (and -`\xintfloatexpr`) numerical functions but additionally are known to the -package via their coefficients. This allows dedicated macros to -implement polynomial algorithmics. - -Releases --------- - -- 0.1 (2018/01/11) - Initial release (files README, polexpr.sty). -- 0.2 (2018/01/14) - Documentation moved to polexpr.{txt,html}. -- 0.3 (2018/01/17) - Make polynomials known to `\xintfloatexpr` and improve - documentation. -- 0.3.1 (2018/01/18) - Fix two typos in documentation. -- 0.4 (2018/02/16) - - Revert 0.3 automatic generation of floating point variants. - - Move CHANGE LOG from README.md to HTML documentation. - - A few bug fixes and breaking changes. Please refer to - `polexpr.html`. - - Main new feature: root localization via [Sturm - Theorem](https://en.wikipedia.org/wiki/Sturm%27s_theorem). -- 0.4.1 (2018/03/01) - Synced with xint 1.3. -- 0.4.2 (2018/03/03) - Documentation fix. -- 0.5 (2018/04/08) - - new macros `\PolMakePrimitive` and `\PolIContent`. - - main (breaking) change: `\PolToSturm` creates a chain of primitive - integer coefficients polynomials. -- 0.5.1 (2018/04/22) - The `'` character can be used in polynomial names. -- 0.6 (2018/11/20) - New feature: multiplicity of roots. -- 0.7 (2018/12/08), 0.7.1 (bugfix), 0.7.2 (bugfix) (2018/12/09) - New feature: finding all rational roots. -- 0.7.3 (2019/02/04) - Bugfix: polynomial names ending in digits caused errors. Thanks to - Thomas Söll for report. -- 0.7.4 (2019/02/12) - Bugfix: 20000000000 is too big for \numexpr, shouldn't I know that? - Thanks to Jürgen Gilg for report. -- 0.7.5 (2020/01/31) - Synced with xint 1.4. Requires it. - -Files of 0.7.5 release: - -- README.md, -- polexpr.sty (package file), -- polexpr.txt (documentation), -- polexpr.html (conversion via - [DocUtils](http://docutils.sourceforge.net/docs/index.html) - rst2html.py) - -Acknowledgments ---------------- - -Thanks to Jürgen Gilg whose question about -[xint](http://www.ctan.org/pkg/xint) usage for differentiating -polynomials was the initial trigger leading to this package, and to -Jürgen Gilg and Thomas Söll for testing it on some concrete problems. diff --git a/macros/latex/contrib/polexpr/polexpr.html b/macros/latex/contrib/polexpr/polexpr.html deleted file mode 100644 index 7496332976..0000000000 --- a/macros/latex/contrib/polexpr/polexpr.html +++ /dev/null @@ -1,2911 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> -<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="generator" content="Docutils 0.14: http://docutils.sourceforge.net/" /> -<title>Package polexpr documentation</title> -<style type="text/css"> - -/* -:Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $ -:Copyright: This stylesheet has been placed in the public domain. - -Default cascading style sheet for the HTML output of Docutils. - -See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to -customize this style sheet. -*/ - -/* used to remove borders from tables and images */ -.borderless, table.borderless td, table.borderless th { - border: 0 } - -table.borderless td, table.borderless th { - /* Override padding for "table.docutils td" with "! important". - The right padding separates the table cells. */ - padding: 0 0.5em 0 0 ! important } - -.first { - /* Override more specific margin styles with "! important". */ - margin-top: 0 ! important } - -.last, .with-subtitle { - margin-bottom: 0 ! important } - -.hidden { - display: none } - -.subscript { - vertical-align: sub; - font-size: smaller } - -.superscript { - vertical-align: super; - font-size: smaller } - -a.toc-backref { - text-decoration: none ; - color: black } - -blockquote.epigraph { - margin: 2em 5em ; } - -dl.docutils dd { - margin-bottom: 0.5em } - -object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] { - overflow: hidden; -} - -/* Uncomment (and remove this text!) to get bold-faced definition list terms -dl.docutils dt { - font-weight: bold } -*/ - -div.abstract { - margin: 2em 5em } - -div.abstract p.topic-title { - font-weight: bold ; - text-align: center } - -div.admonition, div.attention, div.caution, div.danger, div.error, -div.hint, div.important, div.note, div.tip, div.warning { - margin: 2em ; - border: medium outset ; - padding: 1em } - -div.admonition p.admonition-title, div.hint p.admonition-title, -div.important p.admonition-title, div.note p.admonition-title, -div.tip p.admonition-title { - font-weight: bold ; - font-family: sans-serif } - -div.attention p.admonition-title, div.caution p.admonition-title, -div.danger p.admonition-title, div.error p.admonition-title, -div.warning p.admonition-title, .code .error { - color: red ; - font-weight: bold ; - font-family: sans-serif } - -/* Uncomment (and remove this text!) to get reduced vertical space in - compound paragraphs. -div.compound .compound-first, div.compound .compound-middle { - margin-bottom: 0.5em } - -div.compound .compound-last, div.compound .compound-middle { - margin-top: 0.5em } -*/ - -div.dedication { - margin: 2em 5em ; - text-align: center ; - font-style: italic } - -div.dedication p.topic-title { - font-weight: bold ; - font-style: normal } - -div.figure { - margin-left: 2em ; - margin-right: 2em } - -div.footer, div.header { - clear: both; - font-size: smaller } - -div.line-block { - display: block ; - margin-top: 1em ; - margin-bottom: 1em } - -div.line-block div.line-block { - margin-top: 0 ; - margin-bottom: 0 ; - margin-left: 1.5em } - -div.sidebar { - margin: 0 0 0.5em 1em ; - border: medium outset ; - padding: 1em ; - background-color: #ffffee ; - width: 40% ; - float: right ; - clear: right } - -div.sidebar p.rubric { - font-family: sans-serif ; - font-size: medium } - -div.system-messages { - margin: 5em } - -div.system-messages h1 { - color: red } - -div.system-message { - border: medium outset ; - padding: 1em } - -div.system-message p.system-message-title { - color: red ; - font-weight: bold } - -div.topic { - margin: 2em } - -h1.section-subtitle, h2.section-subtitle, h3.section-subtitle, -h4.section-subtitle, h5.section-subtitle, h6.section-subtitle { - margin-top: 0.4em } - -h1.title { - text-align: center } - -h2.subtitle { - text-align: center } - -hr.docutils { - width: 75% } - -img.align-left, .figure.align-left, object.align-left, table.align-left { - clear: left ; - float: left ; - margin-right: 1em } - -img.align-right, .figure.align-right, object.align-right, table.align-right { - clear: right ; - float: right ; - margin-left: 1em } - -img.align-center, .figure.align-center, object.align-center { - display: block; - margin-left: auto; - margin-right: auto; -} - -table.align-center { - margin-left: auto; - margin-right: auto; -} - -.align-left { - text-align: left } - -.align-center { - clear: both ; - text-align: center } - -.align-right { - text-align: right } - -/* reset inner alignment in figures */ -div.align-right { - text-align: inherit } - -/* div.align-center * { */ -/* text-align: left } */ - -.align-top { - vertical-align: top } - -.align-middle { - vertical-align: middle } - -.align-bottom { - vertical-align: bottom } - -ol.simple, ul.simple { - margin-bottom: 1em } - -ol.arabic { - list-style: decimal } - -ol.loweralpha { - list-style: lower-alpha } - -ol.upperalpha { - list-style: upper-alpha } - -ol.lowerroman { - list-style: lower-roman } - -ol.upperroman { - list-style: upper-roman } - -p.attribution { - text-align: right ; - margin-left: 50% } - -p.caption { - font-style: italic } - -p.credits { - font-style: italic ; - font-size: smaller } - -p.label { - white-space: nowrap } - -p.rubric { - font-weight: bold ; - font-size: larger ; - color: maroon ; - text-align: center } - -p.sidebar-title { - font-family: sans-serif ; - font-weight: bold ; - font-size: larger } - -p.sidebar-subtitle { - font-family: sans-serif ; - font-weight: bold } - -p.topic-title { - font-weight: bold } - -pre.address { - margin-bottom: 0 ; - margin-top: 0 ; - font: inherit } - -pre.literal-block, pre.doctest-block, pre.math, pre.code { - margin-left: 2em ; - margin-right: 2em } - -pre.code .ln { color: grey; } /* line numbers */ -pre.code, code { background-color: #eeeeee } -pre.code .comment, code .comment { color: #5C6576 } -pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } -pre.code .literal.string, code .literal.string { color: #0C5404 } -pre.code .name.builtin, code .name.builtin { color: #352B84 } -pre.code .deleted, code .deleted { background-color: #DEB0A1} -pre.code .inserted, code .inserted { background-color: #A3D289} - -span.classifier { - font-family: sans-serif ; - font-style: oblique } - -span.classifier-delimiter { - font-family: sans-serif ; - font-weight: bold } - -span.interpreted { - font-family: sans-serif } - -span.option { - white-space: nowrap } - -span.pre { - white-space: pre } - -span.problematic { - color: red } - -span.section-subtitle { - /* font-size relative to parent (h1..h6 element) */ - font-size: 80% } - -table.citation { - border-left: solid 1px gray; - margin-left: 1px } - -table.docinfo { - margin: 2em 4em } - -table.docutils { - margin-top: 0.5em ; - margin-bottom: 0.5em } - -table.footnote { - border-left: solid 1px black; - margin-left: 1px } - -table.docutils td, table.docutils th, -table.docinfo td, table.docinfo th { - padding-left: 0.5em ; - padding-right: 0.5em ; - vertical-align: top } - -table.docutils th.field-name, table.docinfo th.docinfo-name { - font-weight: bold ; - text-align: left ; - white-space: nowrap ; - padding-left: 0 } - -/* "booktabs" style (no vertical lines) */ -table.docutils.booktabs { - border: 0px; - border-top: 2px solid; - border-bottom: 2px solid; - border-collapse: collapse; -} -table.docutils.booktabs * { - border: 0px; -} -table.docutils.booktabs th { - border-bottom: thin solid; - text-align: left; -} - -h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, -h4 tt.docutils, h5 tt.docutils, h6 tt.docutils { - font-size: 100% } - -ul.auto-toc { - list-style-type: none } - -</style> -</head> -<body> -<div class="document" id="package-polexpr-documentation"> -<h1 class="title">Package polexpr documentation</h1> -<h2 class="subtitle" id="id1">0.7.5 (2020/01/31)</h2> - -<!-- comment: -*- fill-column: 72; mode: rst; -*- --> -<div class="contents topic" id="contents"> -<p class="topic-title first">Contents</p> -<ul class="simple"> -<li><a class="reference internal" href="#basic-syntax" id="id38">Basic syntax</a></li> -<li><a class="reference internal" href="#examples-of-localization-of-roots" id="id39">Examples of localization of roots</a><ul> -<li><a class="reference internal" href="#a-typical-example" id="id40">A typical example</a></li> -<li><a class="reference internal" href="#a-degree-four-polynomial-with-nearby-roots" id="id41">A degree four polynomial with nearby roots</a></li> -<li><a class="reference internal" href="#the-degree-nine-polynomial-with-0-99-0-999-0-9999-as-triple-roots" id="id42">The degree nine polynomial with 0.99, 0.999, 0.9999 as triple roots</a></li> -<li><a class="reference internal" href="#a-degree-five-polynomial-with-three-rational-roots" id="id43">A degree five polynomial with three rational roots</a></li> -<li><a class="reference internal" href="#a-mignotte-type-polynomial" id="id44">A Mignotte type polynomial</a></li> -<li><a class="reference internal" href="#the-wilkinson-polynomial" id="id45">The Wilkinson polynomial</a></li> -<li><a class="reference internal" href="#the-second-wilkinson-polynomial" id="id46">The second Wilkinson polynomial</a></li> -<li><a class="reference internal" href="#the-degree-41-polynomial-with-2-1-9-1-8-0-0-1-1-9-2-as-roots" id="id47">The degree 41 polynomial with -2, -1.9, -1.8, ..., 0, 0.1, ..., 1.9, 2 as roots</a></li> -<li><a class="reference internal" href="#roots-of-chebyshev-polynomials" id="id48">Roots of Chebyshev polynomials</a></li> -</ul> -</li> -<li><a class="reference internal" href="#non-expandable-macros" id="id49">Non-expandable macros</a><ul> -<li><a class="reference internal" href="#poldef-polname-letter-expression-in-letter" id="id50"><tt class="docutils literal">\poldef <span class="pre">polname(letter):=</span> expression in letter;</tt></a></li> -<li><a class="reference internal" href="#poldef-letter-polname-expression-in-letter" id="id51"><tt class="docutils literal"><span class="pre">\PolDef[letter]{polname}{expression</span> in letter}</tt></a></li> -<li><a class="reference internal" href="#polgenfloatvariant-polname" id="id52"><tt class="docutils literal">\PolGenFloatVariant{polname}</tt></a></li> -<li><a class="reference internal" href="#pollet-polname-2-polname-1" id="id53"><tt class="docutils literal"><span class="pre">\PolLet{polname_2}={polname_1}</span></tt></a></li> -<li><a class="reference internal" href="#polgloballet-polname-2-polname-1" id="id54"><tt class="docutils literal"><span class="pre">\PolGlobalLet{polname_2}={polname_1}</span></tt></a></li> -<li><a class="reference internal" href="#polassign-polname-toarray-macro" id="id55"><tt class="docutils literal"><span class="pre">\PolAssign{polname}\toarray\macro</span></tt></a></li> -<li><a class="reference internal" href="#polget-polname-fromarray-macro" id="id56"><tt class="docutils literal"><span class="pre">\PolGet{polname}\fromarray\macro</span></tt></a></li> -<li><a class="reference internal" href="#polfromcsv-polname-csv" id="id57"><tt class="docutils literal"><span class="pre">\PolFromCSV{polname}{<csv>}</span></tt></a></li> -<li><a class="reference internal" href="#poltypeset-polname" id="id58"><tt class="docutils literal">\PolTypeset{polname}</tt></a><ul> -<li><a class="reference internal" href="#poltypesetcmd-raw-coeff" id="id59"><tt class="docutils literal">\PolTypesetCmd{raw_coeff}</tt></a></li> -<li><a class="reference internal" href="#poltypesetone-raw-coeff" id="id60"><tt class="docutils literal">\PolTypesetOne{raw_coeff}</tt></a></li> -<li><a class="reference internal" href="#id6" id="id61"><tt class="docutils literal">\PolTypesetMonomialCmd</tt></a></li> -<li><a class="reference internal" href="#poltypesetcmdprefix-raw-coeff" id="id62"><tt class="docutils literal">\PolTypesetCmdPrefix{raw_coeff}</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#id8" id="id63"><tt class="docutils literal"><span class="pre">\PolTypeset*{polname}</span></tt></a></li> -<li><a class="reference internal" href="#poldiff-polname-1-polname-2" id="id64"><tt class="docutils literal"><span class="pre">\PolDiff{polname_1}{polname_2}</span></tt></a></li> -<li><a class="reference internal" href="#poldiff-n-polname-1-polname-2" id="id65"><tt class="docutils literal"><span class="pre">\PolDiff[N]{polname_1}{polname_2}</span></tt></a></li> -<li><a class="reference internal" href="#polantidiff-polname-1-polname-2" id="id66"><tt class="docutils literal"><span class="pre">\PolAntiDiff{polname_1}{polname_2}</span></tt></a></li> -<li><a class="reference internal" href="#polantidiff-n-polname-1-polname-2" id="id67"><tt class="docutils literal"><span class="pre">\PolAntiDiff[N]{polname_1}{polname_2}</span></tt></a></li> -<li><a class="reference internal" href="#poldivide-polname-1-polname-2-polname-q-polname-r" id="id68"><tt class="docutils literal"><span class="pre">\PolDivide{polname_1}{polname_2}{polname_Q}{polname_R}</span></tt></a></li> -<li><a class="reference internal" href="#polquo-polname-1-polname-2-polname-q" id="id69"><tt class="docutils literal"><span class="pre">\PolQuo{polname_1}{polname_2}{polname_Q}</span></tt></a></li> -<li><a class="reference internal" href="#polrem-polname-1-polname-2-polname-r" id="id70"><tt class="docutils literal"><span class="pre">\PolRem{polname_1}{polname_2}{polname_R}</span></tt></a></li> -<li><a class="reference internal" href="#polgcd-polname-1-polname-2-polname-gcd" id="id71"><tt class="docutils literal"><span class="pre">\PolGCD{polname_1}{polname_2}{polname_GCD}</span></tt></a></li> -<li><a class="reference internal" href="#poltosturm-polname-sturmname" id="id72"><tt class="docutils literal"><span class="pre">\PolToSturm{polname}{sturmname}</span></tt></a></li> -<li><a class="reference internal" href="#id10" id="id73"><tt class="docutils literal"><span class="pre">\PolToSturm*{polname}{sturmname}</span></tt></a></li> -<li><a class="reference internal" href="#polsettosturmchainsignchangesat-macro-sturmname-fraction" id="id74"><tt class="docutils literal"><span class="pre">\PolSetToSturmChainSignChangesAt{\macro}{sturmname}{fraction}</span></tt></a></li> -<li><a class="reference internal" href="#polsettonbofzeroswithin-macro-sturmname-value-a-value-b" id="id75"><tt class="docutils literal"><span class="pre">\PolSetToNbOfZerosWithin{\macro}{sturmname}{value_a}{value_b}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmisolatezeros-sturmname" id="id76"><tt class="docutils literal">\PolSturmIsolateZeros{sturmname}</tt></a></li> -<li><a class="reference internal" href="#id12" id="id77"><tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros*{sturmname}</span></tt></a></li> -<li><a class="reference internal" href="#id14" id="id78"><tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros**{sturmname}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmisolatezerosandgetmultiplicities-sturmname" id="id79"><tt class="docutils literal">\PolSturmIsolateZerosAndGetMultiplicities{sturmname}</tt></a></li> -<li><a class="reference internal" href="#polsturmisolatezerosgetmultiplicitiesandrationalroots-sturmname" id="id80"><tt class="docutils literal">\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{sturmname}</tt></a></li> -<li><a class="reference internal" href="#polsturmisolatezerosandfindrationalroots-sturmname" id="id81"><tt class="docutils literal">\PolSturmIsolateZerosAndFindRationalRoots{sturmname}</tt></a></li> -<li><a class="reference internal" href="#polrefineinterval-sturmname-index" id="id82"><tt class="docutils literal"><span class="pre">\PolRefineInterval*{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#polrefineinterval-n-sturmname-index" id="id83"><tt class="docutils literal"><span class="pre">\PolRefineInterval[N]{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#polensureintervallength-sturmname-index-e" id="id84"><tt class="docutils literal"><span class="pre">\PolEnsureIntervalLength{sturmname}{index}{E}</span></tt></a></li> -<li><a class="reference internal" href="#polensureintervallengths-sturmname-e" id="id85"><tt class="docutils literal"><span class="pre">\PolEnsureIntervalLengths{sturmname}{E}</span></tt></a></li> -<li><a class="reference internal" href="#polprintintervals-varname-sturmname" id="id86"><tt class="docutils literal"><span class="pre">\PolPrintIntervals[varname]{sturmname}</span></tt></a><ul> -<li><a class="reference internal" href="#polprintintervalsnorealroots" id="id87"><tt class="docutils literal">\PolPrintIntervalsNoRealRoots</tt></a></li> -<li><a class="reference internal" href="#polprintintervalsbeginenv" id="id88"><tt class="docutils literal">\PolPrintIntervalsBeginEnv</tt></a></li> -<li><a class="reference internal" href="#polprintintervalsendenv" id="id89"><tt class="docutils literal">\PolPrintIntervalsEndEnv</tt></a></li> -<li><a class="reference internal" href="#polprintintervalsknownroot" id="id90"><tt class="docutils literal">\PolPrintIntervalsKnownRoot</tt></a></li> -<li><a class="reference internal" href="#polprintintervalsunknownroot" id="id91"><tt class="docutils literal">\PolPrintIntervalsUnknownRoot</tt></a></li> -<li><a class="reference internal" href="#id15" id="id92"><tt class="docutils literal">\PolPrintIntervalsPrintExactZero</tt></a></li> -<li><a class="reference internal" href="#id16" id="id93"><tt class="docutils literal">\PolPrintIntervalsPrintLeftEndPoint</tt></a></li> -<li><a class="reference internal" href="#id17" id="id94"><tt class="docutils literal">\PolPrintIntervalsPrintRightEndPoint</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#id19" id="id95"><tt class="docutils literal"><span class="pre">\PolPrintIntervals*[varname]{sturmname}</span></tt></a><ul> -<li><a class="reference internal" href="#polprintintervalsprintmultiplicity" id="id96"><tt class="docutils literal">\PolPrintIntervalsPrintMultiplicity</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#polmapcoeffs-macro-polname" id="id97"><tt class="docutils literal"><span class="pre">\PolMapCoeffs{\macro}{polname}</span></tt></a></li> -<li><a class="reference internal" href="#polreducecoeffs-polname" id="id98"><tt class="docutils literal">\PolReduceCoeffs{polname}</tt></a></li> -<li><a class="reference internal" href="#id21" id="id99"><tt class="docutils literal"><span class="pre">\PolReduceCoeffs*{polname}</span></tt></a></li> -<li><a class="reference internal" href="#polmakemonic-polname" id="id100"><tt class="docutils literal">\PolMakeMonic{polname}</tt></a></li> -<li><a class="reference internal" href="#polmakeprimitive-polname" id="id101"><tt class="docutils literal">\PolMakePrimitive{polname}</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#expandable-macros" id="id102">Expandable macros</a><ul> -<li><a class="reference internal" href="#poleval-polname-atexpr-numerical-expression" id="id103"><tt class="docutils literal"><span class="pre">\PolEval{polname}\AtExpr{numerical</span> expression}</tt></a></li> -<li><a class="reference internal" href="#poleval-polname-at-fraction" id="id104"><tt class="docutils literal"><span class="pre">\PolEval{polname}\At{fraction}</span></tt></a></li> -<li><a class="reference internal" href="#polevalreduced-polname-atexpr-numerical-expression" id="id105"><tt class="docutils literal"><span class="pre">\PolEvalReduced{polname}\AtExpr{numerical</span> expression}</tt></a></li> -<li><a class="reference internal" href="#polevalreduced-polname-at-fraction" id="id106"><tt class="docutils literal"><span class="pre">\PolEvalReduced{polname}\At{fraction}</span></tt></a></li> -<li><a class="reference internal" href="#polfloateval-polname-atexpr-numerical-expression" id="id107"><tt class="docutils literal"><span class="pre">\PolFloatEval{polname}\AtExpr{numerical</span> expression}</tt></a></li> -<li><a class="reference internal" href="#polfloateval-polname-at-fraction" id="id108"><tt class="docutils literal"><span class="pre">\PolFloatEval{polname}\At{fraction}</span></tt></a></li> -<li><a class="reference internal" href="#polifcoeffisplusorminusone-a-b" id="id109"><tt class="docutils literal"><span class="pre">\PolIfCoeffIsPlusOrMinusOne{A}{B}</span></tt></a></li> -<li><a class="reference internal" href="#polleadingcoeff-polname" id="id110"><tt class="docutils literal">\PolLeadingCoeff{polname}</tt></a></li> -<li><a class="reference internal" href="#polnthcoeff-polname-number" id="id111"><tt class="docutils literal"><span class="pre">\PolNthCoeff{polname}{number}</span></tt></a></li> -<li><a class="reference internal" href="#poldegree-polname" id="id112"><tt class="docutils literal">\PolDegree{polname}</tt></a></li> -<li><a class="reference internal" href="#policontent-polname" id="id113"><tt class="docutils literal">\PolIContent{polname}</tt></a></li> -<li><a class="reference internal" href="#poltoexpr-polname" id="id114"><tt class="docutils literal">\PolToExpr{polname}</tt></a><ul> -<li><a class="reference internal" href="#poltoexproneterm-raw-coeff-number" id="id115"><tt class="docutils literal"><span class="pre">\PolToExprOneTerm{raw_coeff}{number}</span></tt></a></li> -<li><a class="reference internal" href="#poltoexpronetermstylea-raw-coeff-number" id="id116"><tt class="docutils literal"><span class="pre">\PolToExprOneTermStyleA{raw_coeff}{number}</span></tt></a></li> -<li><a class="reference internal" href="#poltoexpronetermstyleb-raw-coeff-number" id="id117"><tt class="docutils literal"><span class="pre">\PolToExprOneTermStyleB{raw_coeff}{number}</span></tt></a></li> -<li><a class="reference internal" href="#poltoexprcmd-raw-coeff" id="id118"><tt class="docutils literal">\PolToExprCmd{raw_coeff}</tt></a></li> -<li><a class="reference internal" href="#poltoexprtermprefix-raw-coeff" id="id119"><tt class="docutils literal">\PolToExprTermPrefix{raw_coeff}</tt></a></li> -<li><a class="reference internal" href="#id28" id="id120"><tt class="docutils literal">\PolToExprVar</tt></a></li> -<li><a class="reference internal" href="#id29" id="id121"><tt class="docutils literal">\PolToExprTimes</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#id31" id="id122"><tt class="docutils literal"><span class="pre">\PolToExpr*{polname}</span></tt></a></li> -<li><a class="reference internal" href="#poltofloatexpr-polname" id="id123"><tt class="docutils literal">\PolToFloatExpr{polname}</tt></a><ul> -<li><a class="reference internal" href="#poltofloatexproneterm-raw-coeff-number" id="id124"><tt class="docutils literal"><span class="pre">\PolToFloatExprOneTerm{raw_coeff}{number}</span></tt></a></li> -<li><a class="reference internal" href="#poltofloatexprcmd-raw-coeff" id="id125"><tt class="docutils literal">\PolToFloatExprCmd{raw_coeff}</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#id35" id="id126"><tt class="docutils literal"><span class="pre">\PolToFloatExpr*{polname}</span></tt></a></li> -<li><a class="reference internal" href="#poltolist-polname" id="id127"><tt class="docutils literal">\PolToList{polname}</tt></a></li> -<li><a class="reference internal" href="#poltocsv-polname" id="id128"><tt class="docutils literal">\PolToCSV{polname}</tt></a></li> -<li><a class="reference internal" href="#polsturmchainlength-sturmname" id="id129"><tt class="docutils literal">\PolSturmChainLength{sturmname}</tt></a></li> -<li><a class="reference internal" href="#polsturmifzeroexactlyknown-sturmname-index-a-b" id="id130"><tt class="docutils literal"><span class="pre">\PolSturmIfZeroExactlyKnown{sturmname}{index}{A}{B}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmisolatedzeroleft-sturmname-index" id="id131"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroLeft{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmisolatedzeroright-sturmname-index" id="id132"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroRight{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmisolatedzeromultiplicity-sturmname-index" id="id133"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmnbofisolatedzeros-sturmname" id="id134"><tt class="docutils literal">\PolSturmNbOfIsolatedZeros{sturmname}</tt></a><ul> -<li><a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequalto-value" id="id135"><tt class="docutils literal"><span class="pre">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequaltoexpr-expression" id="id136"><tt class="docutils literal"><span class="pre">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmnbwithmultofrootsof-sturmname-lessthanorequalto-value" id="id137"><tt class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualTo{value}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmnbwithmultofrootsof-sturmname-lessthanorequaltoexpr-expression" id="id138"><tt class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#polsturmnbofrationalroots-sturmname" id="id139"><tt class="docutils literal">\PolSturmNbOfRationalRoots{sturmname}</tt></a></li> -<li><a class="reference internal" href="#polsturmnbofrationalrootswithmultiplicities-sturmname" id="id140"><tt class="docutils literal">\PolSturmNbOfRationalRootsWithMultiplicities{sturmname}</tt></a></li> -<li><a class="reference internal" href="#polsturmrationalroot-sturmname-k" id="id141"><tt class="docutils literal"><span class="pre">\PolSturmRationalRoot{sturmname}{k}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmrationalrootindex-sturmname-k" id="id142"><tt class="docutils literal"><span class="pre">\PolSturmRationalRootIndex{sturmname}{k}</span></tt></a></li> -<li><a class="reference internal" href="#polsturmrationalrootmultiplicity-sturmname-k" id="id143"><tt class="docutils literal"><span class="pre">\PolSturmRationalRootMultiplicity{sturmname}{k}</span></tt></a></li> -<li><a class="reference internal" href="#polintervalwidth-sturmname-index" id="id144"><tt class="docutils literal"><span class="pre">\PolIntervalWidth{sturmname}{index}</span></tt></a></li> -<li><a class="reference internal" href="#expandable-macros-for-use-within-execution-of-polprintintervals" id="id145">Expandable macros for use within execution of <tt class="docutils literal">\PolPrintIntervals</tt></a><ul> -<li><a class="reference internal" href="#polprintintervalsthevar" id="id146"><tt class="docutils literal">\PolPrintIntervalsTheVar</tt></a></li> -<li><a class="reference internal" href="#polprintintervalstheindex" id="id147"><tt class="docutils literal">\PolPrintIntervalsTheIndex</tt></a></li> -<li><a class="reference internal" href="#polprintintervalsthesturmname" id="id148"><tt class="docutils literal">\PolPrintIntervalsTheSturmName</tt></a></li> -<li><a class="reference internal" href="#polprintintervalstheleftendpoint" id="id149"><tt class="docutils literal">\PolPrintIntervalsTheLeftEndPoint</tt></a></li> -<li><a class="reference internal" href="#polprintintervalstherightendpoint" id="id150"><tt class="docutils literal">\PolPrintIntervalsTheRightEndPoint</tt></a></li> -<li><a class="reference internal" href="#polprintintervalsthemultiplicity" id="id151"><tt class="docutils literal">\PolPrintIntervalsTheMultiplicity</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#poldectostring-decimal-number" id="id152"><tt class="docutils literal">\PolDecToString{decimal number}</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#booleans-with-default-setting-as-indicated" id="id153">Booleans (with default setting as indicated)</a><ul> -<li><a class="reference internal" href="#xintverbosefalse" id="id154"><tt class="docutils literal">\xintverbosefalse</tt></a></li> -<li><a class="reference internal" href="#poltypesetallfalse" id="id155"><tt class="docutils literal">\poltypesetallfalse</tt></a></li> -<li><a class="reference internal" href="#poltoexprallfalse" id="id156"><tt class="docutils literal">\poltoexprallfalse</tt></a></li> -</ul> -</li> -<li><a class="reference internal" href="#polexprsetup" id="id157"><tt class="docutils literal">\polexprsetup</tt></a></li> -<li><a class="reference internal" href="#technicalities" id="id158">Technicalities</a></li> -<li><a class="reference internal" href="#change-log" id="id159">CHANGE LOG</a></li> -<li><a class="reference internal" href="#acknowledgments" id="id160">Acknowledgments</a></li> -</ul> -</div> -<div class="section" id="basic-syntax"> -<h1><a class="toc-backref" href="#id38">Basic syntax</a></h1> -<p>The syntax is:</p> -<pre class="literal-block"> -\poldef polname(x):= expression in variable x; -</pre> -<p>where:</p> -<ul class="simple"> -<li>in place of <tt class="docutils literal">x</tt> an arbitrary <em>dummy variable</em> is authorized, -i.e. per default any of <tt class="docutils literal"><span class="pre">[a-z|A-Z]</span></tt> (more letters can be declared -under Unicode engines.)</li> -<li><tt class="docutils literal">polname</tt> consists of letters, digits, and the <tt class="docutils literal">_</tt> and -<tt class="docutils literal">'</tt> characters. It must start with a letter.</li> -</ul> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last">The <tt class="docutils literal">'</tt> is authorized since <tt class="docutils literal">0.5.1</tt>. As a result some constructs -recognized by the <tt class="docutils literal">\xintexpr</tt> parser, such as <tt class="docutils literal">var1 'and' var2</tt> -will get misinterpreted and cause errors. However these constructs -are unlikely to be frequently needed in polynomial expressions, and -the <tt class="docutils literal">\xintexpr</tt> syntax offers alternatives, so it was deemed a -small evil. Of course the <tt class="docutils literal">\xintexpr</tt> parser is modified only -temporarily during execution of <tt class="docutils literal">\poldef</tt>.</p> -</div> -<p>One can also issue:</p> -<pre class="literal-block"> -\PolDef{polname}{expression in variable x} -</pre> -<p>which admits an optional first argument to modify the variable letter -from its default <tt class="docutils literal">x</tt>.</p> -<dl class="docutils"> -<dt><tt class="docutils literal">\poldef <span class="pre">f(x):=</span> <span class="pre">1-x+x^2;</span></tt></dt> -<dd>defines polynomial <tt class="docutils literal">f</tt>. Polynomial names must start with a -letter and may contain letters, digits, underscores and the right -tick character. The -variable must be a single letter. The colon character is optional. -The semi-colon at end of expression is mandatory.</dd> -<dt><tt class="docutils literal"><span class="pre">\PolDef{f}{1-x+x^2}</span></tt></dt> -<dd>does the same as <tt class="docutils literal">\poldef <span class="pre">f(x):=</span> <span class="pre">1-x+x^2;</span></tt> To use another letter -than <tt class="docutils literal">x</tt> in the expression, one must pass it as an extra optional -argument to <tt class="docutils literal">\PolDef</tt>. Useful if the semi-colon has been assigned -some non-standard catcode by some package.</dd> -<dt><tt class="docutils literal"><span class="pre">\PolLet{g}={f}</span></tt></dt> -<dd>saves a copy of <tt class="docutils literal">f</tt> under name <tt class="docutils literal">g</tt>. Also usable without <tt class="docutils literal">=</tt>.</dd> -<dt><tt class="docutils literal">\poldef <span class="pre">f(z):=</span> <span class="pre">f(z)^2;</span></tt></dt> -<dd>redefines <tt class="docutils literal">f</tt> in terms of itself.</dd> -<dt><tt class="docutils literal">\poldef <span class="pre">f(T):=</span> <span class="pre">f(f(T));</span></tt></dt> -<dd>again redefines <tt class="docutils literal">f</tt> in terms of its (new) self.</dd> -<dt><tt class="docutils literal">\poldef <span class="pre">k(z):=</span> <span class="pre">f(z)-g(g(z)^2)^2;</span></tt></dt> -<dd>should now define the zero polynomial... Let's check: -<tt class="docutils literal">\[ k(z) = <span class="pre">\PolTypeset[z]{k}</span> \]</tt></dd> -<dt><tt class="docutils literal"><span class="pre">\PolDiff{f}{f'}</span></tt></dt> -<dd>sets <tt class="docutils literal">f'</tt> to the derivative of <tt class="docutils literal">f</tt>. The name doesn't have to be -<tt class="docutils literal">f'</tt> (in fact the <tt class="docutils literal">'</tt> is licit only since <tt class="docutils literal">0.5.1</tt>).</dd> -</dl> -<div class="admonition important"> -<p class="first admonition-title">Important</p> -<p class="last">This is not done automatically. If some new definition needs to use -the derivative of some available polynomial, that derivative -polynomial must have been defined via <tt class="docutils literal">\PolDiff</tt>: something like -<tt class="docutils literal"><span class="pre">T'(x)^2</span></tt> will not work without a prior <tt class="docutils literal"><span class="pre">\PolDiff{T}{T'}</span></tt>.</p> -</div> -<dl class="docutils"> -<dt><tt class="docutils literal"><span class="pre">\PolDiff{f'}{f''}</span></tt></dt> -<dd>obtains second derivative.</dd> -<dt><tt class="docutils literal"><span class="pre">\PolDiff[3]{f}{f'''}</span></tt></dt> -<dd>computes the third derivative.</dd> -</dl> -<pre class="literal-block"> -$f(z) = \PolTypeset[z]{f} $\newline -$f'(z) = \PolTypeset[z]{f'} $\newline -$f''(z) = \PolTypeset[z]{f''} $\newline -$f'''(z)= \PolTypeset[z]{f'''} $\par -</pre> -<div class="admonition important"> -<p class="first admonition-title">Important</p> -<p>The package does not currently know rational functions: <tt class="docutils literal">/</tt> in -a parsed polynomial expression does the Euclidean quotient:</p> -<pre class="literal-block"> -(1-x^2)/(1-x) -</pre> -<p>does give <tt class="docutils literal">1+x</tt> but</p> -<pre class="literal-block"> -(1/(1-x))*(1-x^2) -</pre> -<p>evaluates to zero. This will work as expected:</p> -<pre class="last literal-block"> -\poldef k(x):= (x-1)(x-2)(x-3)(x-4)/(x^2-5x+4); -</pre> -</div> -<div class="admonition attention" id="warningtacit"> -<p class="first admonition-title">Attention!</p> -<p><tt class="docutils literal">1/2 x^2</tt> skips the space and is treated like <tt class="docutils literal"><span class="pre">1/(2*x^2)</span></tt> because -of the tacit multiplication rules of xintexpr. But this means it -gives zero! Thus one must use <tt class="docutils literal">(1/2)x^2</tt> or <tt class="docutils literal">1/2*x^2</tt> or -<tt class="docutils literal"><span class="pre">(1/2)*x^2</span></tt> for disambiguation: <tt class="docutils literal">x - 1/2*x^2 + <span class="pre">1/3*x^3...</span></tt>. It is -even simpler to move the denominator to the right: <tt class="docutils literal">x - x^2/2 + -x^3/3 - ...</tt>.</p> -<p class="last">It is worth noting that <tt class="docutils literal"><span class="pre">1/2(x-1)(x-2)</span></tt> suffers the same issue: -<a class="reference external" href="http://www.ctan.org/pkg/xint">xint</a> tacit multiplication always "ties more", hence this gets -interpreted as <tt class="docutils literal"><span class="pre">1/(2*(x-1)*(x-2))</span></tt> which gives zero by polynomial -division. Thus, use one of <tt class="docutils literal"><span class="pre">(1/2)(x-1)(x-2)</span></tt>, <tt class="docutils literal"><span class="pre">1/2*(x-1)(x-2)</span></tt> or -<tt class="docutils literal"><span class="pre">(x-1)(x-2)/2</span></tt>.</p> -</div> -<p>After:</p> -<pre class="literal-block"> -\poldef f_1(x):= 25(x-1)(x^2-2)(x-3)(x-4)(x-5);% -\poldef f_2(x):= 37(x-1)(x^2-2)(x-6)(x-7)(x-8);% -</pre> -<p>the macro call <tt class="docutils literal"><span class="pre">\PolGCD{f_1}{f_2}{k}</span></tt> sets <tt class="docutils literal">k</tt> to the (unitary) GCD of -<tt class="docutils literal">f_1</tt> and <tt class="docutils literal">f_2</tt> (hence to the expansion of <tt class="docutils literal"><span class="pre">(x-1)(x^2-2)</span></tt>.)</p> -<dl class="docutils"> -<dt><tt class="docutils literal">\PolToExpr{k}</tt></dt> -<dd>will (expandably) give in this case <tt class="docutils literal"><span class="pre">x^3-x^2-2*x+2</span></tt>. This is -useful for console or file output (the syntax is Maple- and -PSTricks-compatible; the letter used in output can be -(non-expandably) changed via a redefinition of <a class="reference internal" href="#poltoexprvar">\PolToExprVar</a>.)</dd> -<dt><tt class="docutils literal"><span class="pre">\PolToExpr*{k}</span></tt></dt> -<dd>gives ascending powers: <tt class="docutils literal"><span class="pre">2-2*x-x^2+x^3</span></tt>.</dd> -</dl> -</div> -<div class="section" id="examples-of-localization-of-roots"> -<h1><a class="toc-backref" href="#id39">Examples of localization of roots</a></h1> -<ul> -<li><p class="first">To make printed decimal numbers more enjoyable than via -<tt class="docutils literal">\xintSignedFrac</tt>:</p> -<pre class="literal-block"> -\renewcommand\PolTypesetOne[1]{\PolDecToString{\xintREZ{#1}}}% -</pre> -<p><tt class="docutils literal">\PolDecToString</tt> will use decimal notation to incorporate the power -of ten part; and the <tt class="docutils literal">\xintREZ</tt> will have the effect to suppress -trailing zeros if present in raw numerator (if those digits end up -after decimal mark.) Notice that the above are expandable macros and -that one can also do:</p> -<pre class="literal-block"> -\renewcommand\PolToExprCmd[1]{\PolDecToString{\xintREZ{#1}}}% -</pre> -<p>to modify output of <a class="reference internal" href="#poltoexpr-polname">\PolToExpr{polname}</a>.</p> -</li> -<li><p class="first">For extra info in log file use <tt class="docutils literal">\xintverbosetrue</tt>.</p> -</li> -<li><p class="first">Only for some of these examples is the output included here.</p> -</li> -</ul> -<div class="section" id="a-typical-example"> -<h2><a class="toc-backref" href="#id40">A typical example</a></h2> -<p>In this example the polynomial is square-free.</p> -<pre class="literal-block"> -\poldef f(x) := x^7 - x^6 - 2x + 1; - -\PolToSturm{f}{f} -\PolSturmIsolateZeros{f} -The \PolTypeset{f} polynomial has \PolSturmNbOfIsolatedZeros{f} distinct real -roots which are located in the following intervals: -\PolPrintIntervals{f} -Here is the second root with ten more decimal digits: -\PolRefineInterval[10]{f}{2} -\[\PolSturmIsolatedZeroLeft{f}{2}<Z_2<\PolSturmIsolatedZeroRight{f}{2}\] -And here is the first root with twenty digits after decimal mark: -\PolEnsureIntervalLength{f}{1}{-20} -\[\PolSturmIsolatedZeroLeft{f}{1}<Z_1<\PolSturmIsolatedZeroRight{f}{1}\] -The first element of the Sturm chain has degree $\PolDegree{f_0}$. As -this is the original degreee $\PolDegree{f}$ we know that $f$ is square free. -Its derivative is up to a constant \PolTypeset{f_1} (in this example -it is identical with it). -\PolToSturm{f_1}{f_1}\PolSturmIsolateZeros{f_1}% -The derivative has \PolSturmNbOfIsolatedZeros{f_1} distinct real -roots: -\PolPrintIntervals[W]{f_1} -\PolEnsureIntervalLengths{f_1}{-10}% -Here they are with ten digits after decimal mark: -\PolPrintIntervals[W]{f_1} -\PolDiff{f_1}{f''} -\PolToSturm{f''}{f''} -\PolSturmIsolateZeros{f''} -The second derivative is \PolTypeset{f''}. -It has \PolSturmNbOfIsolatedZeros{f''} distinct real -roots: -\PolPrintIntervals[X]{f''} -Here is the positive one with 20 digits after decimal mark: -\PolEnsureIntervalLength{f''}{2}{-20}% -\[X_2 = \PolSturmIsolatedZeroLeft{f''}{2}\dots\] -The more mathematically advanced among our dear readers will be able -to give the exact value for $X_2$! -</pre> -</div> -<div class="section" id="a-degree-four-polynomial-with-nearby-roots"> -<h2><a class="toc-backref" href="#id41">A degree four polynomial with nearby roots</a></h2> -<p>Notice that this example is a bit outdated as <tt class="docutils literal">0.7</tt> release has -added <tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros**{sturmname}</span></tt> which would find exactly -the roots. The steps here retain their interest when one is interested -in finding isolating intervals for example to prepare some demonstration -of dichotomy method.</p> -<pre class="literal-block"> -\PolDef{Q}{(x-1.050001)(x-1.105001)(x-1.110501)(x-1.111051)} -\PolTypeset{Q} -\PolToSturm{Q}{Q} % it is allowed to use same prefix for Sturm chain -\PolSturmIsolateZeros{Q} -\PolPrintIntervals{Q} -% reports 1.0 < Z_1 < 1.1, 1.10 < Z_2 < 1.11, 1.110 < Z_3 < 1.111, and 1.111 < Z_4 < 1.112 -% but the above bounds do not allow minimizing separation between roots -% so we refine: -\PolRefineInterval*{Q}{1} -\PolRefineInterval*{Q}{2} -\PolRefineInterval*{Q}{3} -\PolRefineInterval*{Q}{4} -\PolPrintIntervals{Q} -% reports 1.05 < Z_1 < 1.06, 1.105 < Z_2 < 1.106, 1.1105 < Z_3 < 1.1106, -% and 1.11105 < Z_4 < 1.11106. -\PolEnsureIntervalLengths{Q}{-6} -\PolPrintIntervals{Q} -% of course finds here all roots exactly -</pre> -</div> -<div class="section" id="the-degree-nine-polynomial-with-0-99-0-999-0-9999-as-triple-roots"> -<h2><a class="toc-backref" href="#id42">The degree nine polynomial with 0.99, 0.999, 0.9999 as triple roots</a></h2> -<pre class="literal-block"> -% define a user command (xinttools is loaded automatically by polexpr) -\newcommand\showmultiplicities[1]{% #1 = "sturmname" -\xintFor* ##1 in {\xintSeq{1}{\PolSturmNbOfIsolatedZeros{#1}}}\do{% - The multiplicity is \PolSturmIsolatedZeroMultiplicity{#1}{##1} - \PolSturmIfZeroExactlyKnown{#1}{##1}% - {at the root $x=\PolSturmIsolatedZeroLeft{#1}{##1}$} - {for the root such that - $\PolSturmIsolatedZeroLeft{#1}{##1}<x<\PolSturmIsolatedZeroRight{#1}{##1}$} - \par -}}% -\PolDef{f}{(x-0.99)^3(x-0.999)^3(x-0.9999)^3} -\renewcommand\PolTypesetOne[1]{\PolDecToString{\xintREZ{#1}}} -\PolTypeset{f}\par -\PolToSturm{f}{f}% it is allowed to use "polname" as "sturmname" too -\PolSturmIsolateZerosAndGetMultiplicities{f}% use the "sturmname" here -% or \PolSturmIsolateZeros*{f} which is exactly the same, but shorter.. - -\showmultiplicities{f} -</pre> -<p>In this example, the output will look like this (but using math mode):</p> -<pre class="literal-block"> -x^9 - 8.9667x^8 + 35.73400293x^7 - 83.070418400109x^6 + 124.143648875193123x^5 -- 123.683070924326075877x^4 + 82.149260397553075617891x^3 -- 35.07602992699900159127007x^2 + 8.7364078733314648368671733x -- 0.967100824643585986488103299 - -The multiplicity is 3 at the root x = 0.99 -The multiplicity is 3 at the root x = 0.999 -The multiplicity is 3 at the root x = 0.9999 -</pre> -<p>On first pass, these rational roots were found (due to their relative -magnitudes, using <tt class="docutils literal">\PolSturmIsolateZeros**</tt> was not needed here). But -multiplicity computation works also with (decimal) roots not yet -identified or with non-decimal or irrational roots.</p> -<p>It is fun to modify only a tiny bit the polynomial and see if polexpr -survives:</p> -<pre class="literal-block"> -\PolDef{g}{f(x)+1e-27} -\PolTypeset{g}\par -\PolToSturm{g}{g} -\PolSturmIsolateZeros*{g} - -\showmultiplicities{g} -</pre> -<p>This produces:</p> -<pre class="literal-block"> -x^9 - 8.9667x^8 + 35.73400293x^7 - 83.070418400109x^6 + 124.143648875193123x^5 -- 123.683070924326075877x^4 + 82.149260397553075617891x^3 -- 35.07602992699900159127007x^2 + 8.7364078733314648368671733x -- 0.967100824643585986488103298 - -The multiplicity is 1 for the root such that 0.98 < x < 0.99 -The multiplicity is 1 for the root such that 0.9991 < x < 0.9992 -The multiplicity is 1 for the root such that 0.9997 < x < 0.9998 -</pre> -<p>Which means that the multiplicity-3 roots each became a real and a pair of -complex ones. Let's see them better:</p> -<pre class="literal-block"> -\PolEnsureIntervalLengths{g}{-10} - -\showmultiplicities{g} -</pre> -<p>which produces:</p> -<pre class="literal-block"> -The multiplicity is 1 for the root such that 0.9899888032 < x < 0.9899888033 -The multiplicity is 1 for the root such that 0.9991447980 < x < 0.9991447981 -The multiplicity is 1 for the root such that 0.9997663986 < x < 0.9997663987 -</pre> -</div> -<div class="section" id="a-degree-five-polynomial-with-three-rational-roots"> -<h2><a class="toc-backref" href="#id43">A degree five polynomial with three rational roots</a></h2> -<pre class="literal-block"> -\poldef Q(x) := 1581755751184441 x^5 - -14907697165025339 x^4 - +48415668972339336 x^3 - -63952057791306264 x^2 - +46833913221154895 x - -49044360626280925; - -\PolToSturm{Q}{Q} -%\begin{flushleft} - \renewcommand\PolTypesetCmdPrefix[1]{\allowbreak\xintiiifSgn{#1}{}{+}{+}}% - $Q_0(x) = \PolTypeset{Q_0}$ -%\end{flushleft} -\PolSturmIsolateZeros**{Q} -\PolPrintIntervals{Q} - -$Q_{norr}(x) = \PolTypeset{Q_norr}$ -</pre> -<p>Here, all real roots are rational:</p> -<pre class="literal-block"> -Z_1 = 833719/265381 -Z_2 = 165707065/52746197 -Z_3 = 355/113 - -Q_norr(x) = x^2 + 1 -</pre> -<p>And let's get their decimal expansion too:</p> -<pre class="literal-block"> -% print decimal expansion of the found roots -\renewcommand\PolPrintIntervalsPrintExactZero - {\xintTrunc{20}{\PolPrintIntervalsTheLeftEndPoint}\dots} -\PolPrintIntervals{Q} - -Z_1 = 3.14159265358107777120... -Z_2 = 3.14159265358979340254... -Z_3 = 3.14159292035398230088... -</pre> -</div> -<div class="section" id="a-mignotte-type-polynomial"> -<h2><a class="toc-backref" href="#id44">A Mignotte type polynomial</a></h2> -<pre class="literal-block"> -\PolDef{P}{x^10 - (10x-1)^2}% -\PolTypeset{P} % prints it in expanded form -\PolToSturm{P}{P} % we can use same prefix for Sturm chain -\PolSturmIsolateZeros{P} % finds 4 real roots -This polynomial has \PolSturmNbOfIsolatedZeros{P} distinct real roots: -\PolPrintIntervals{P}% -% reports -2 < Z_1 < -1, 0.09 < Z_2 < 0.10, 0.1 < Z_3 < 0.2, 1 < Z_4 < 2 -Let us refine the second and third intervals to separate the corresponding -roots: -\PolRefineInterval*{P}{2}% will refine to 0.0999990 < Z_2 < 0.0999991 -\PolRefineInterval*{P}{3}% will refine to 0.100001 < Z_3 < 0.100002 -\PolPrintIntervals{P}% -Let us now get to know all roots with 10 digits after decimal mark: -\PolEnsureIntervalLengths{P}{-10}% -\PolPrintIntervals{P}% now all roots are known 10 decimal digits after mark -Finally, we display 20 digits of the second root: -\PolEnsureIntervalLength{P}{2}{-20}% makes Z_2 known with 20 digits after mark -\[\PolSturmIsolatedZeroLeft{P}{2}<Z_2<\PolSturmIsolatedZeroRight{P}{2}\] -</pre> -<p>The last line produces:</p> -<pre class="literal-block"> -0.09999900004999650028 < Z_2 < 0.09999900004999650029 -</pre> -</div> -<div class="section" id="the-wilkinson-polynomial"> -<h2><a class="toc-backref" href="#id45">The Wilkinson polynomial</a></h2> -<p>See <a class="reference external" href="https://en.wikipedia.org/wiki/Wilkinson%27s_polynomial">Wilkinson polynomial</a>.</p> -<pre class="literal-block"> -\documentclass{article} -\usepackage{polexpr} -\begin{document} -%\xintverbosetrue % for the curious... - -\poldef f(x) := mul((x - i), i = 1..20); - -\renewcommand\PolTypesetCmdPrefix[1]{\allowbreak\xintiiifSgn{#1}{}{+}{+}}% -\renewcommand\PolTypesetOne[1]{\xintDecToString{#1}}% - -\noindent\PolTypeset{f} - -\PolToSturm{f}{f} -\PolSturmIsolateZeros{f} -\PolPrintIntervals{f} - -\clearpage - -\poldef g(x) := f(x) - 2**{-23} x**19; - -% be patient! -\PolToSturm{g}{g} -\noindent\PolTypeset{g_0}% integer coefficient primitive polynomial - -\PolSturmIsolateZeros{g} -\PolEnsureIntervalLengths{g}{-10} - -\renewcommand\PolPrintIntervalsPrintMultiplicity{} -\PolPrintIntervals*{g} - -\end{document} -</pre> -<p>The first polynomial:</p> -<pre class="literal-block"> -f(x) = x**20 -- 210 x**19 -+ 20615 x**18 -- 1256850 x**17 -+ 53327946 x**16 -- 1672280820 x**15 -+ 40171771630 x**14 -- 756111184500 x**13 -+ 11310276995381 x**12 -- 135585182899530 x**11 -+ 1307535010540395 x**10 -- 10142299865511450 x**9 -+ 63030812099294896 x**8 -- 311333643161390640 x**7 -+ 1206647803780373360 x**6 -- 3599979517947607200 x**5 -+ 8037811822645051776 x**4 -- 12870931245150988800 x**3 -+ 13803759753640704000 x**2 -- 8752948036761600000 x -+ 2432902008176640000 -</pre> -<p>is handled fast enough (a few seconds), but the modified one <tt class="docutils literal">f(x) - -<span class="pre">2**-23</span> <span class="pre">x**19</span></tt> takes about 20x longer (the Sturm chain polynomials -have integer coefficients with up to 321 digits, whereas (surprisingly -perhaps) those of the Sturm chain polynomials derived from <tt class="docutils literal">f</tt> never -have more than 21 digits ...).</p> -<p>Once the Sturm chain is computed and the zeros isolated, obtaining their -decimal digits is relatively faster. Here is for the ten real roots of -<tt class="docutils literal">f(x) - <span class="pre">2**-23</span> <span class="pre">x**19</span></tt> as computed by the code above:</p> -<pre class="literal-block"> -Z_1 = 0.9999999999... -Z_2 = 2.0000000000... -Z_3 = 2.9999999999... -Z_4 = 4.0000000002... -Z_5 = 4.9999999275... -Z_6 = 6.0000069439... -Z_7 = 6.9996972339... -Z_8 = 8.0072676034... -Z_9 = 8.9172502485... -Z_10 = 20.8469081014... -</pre> -</div> -<div class="section" id="the-second-wilkinson-polynomial"> -<h2><a class="toc-backref" href="#id46">The second Wilkinson polynomial</a></h2> -<pre class="literal-block"> -\documentclass{article} -\usepackage{polexpr} -\begin{document} -\poldef f(x) := mul(x - 2^-i, i = 1..20); - -%\PolTypeset{f} - -\PolToSturm{f}{f} -\PolSturmIsolateZeros**{f} -\PolPrintIntervals{f} -\end{document} -</pre> -<p>This takes more time than the polynomial with 1, 2, .., 20 as roots but -less than the latter modified by the <tt class="docutils literal"><span class="pre">2**-23</span></tt> change in one -coefficient.</p> -<p>Here is the output (with release 0.7.2):</p> -<pre class="literal-block"> -Z_1 = 0.00000095367431640625 -Z_2 = 0.0000019073486328125 -Z_3 = 0.000003814697265625 -Z_4 = 0.00000762939453125 -Z_5 = 0.0000152587890625 -Z_6 = 0.000030517578125 -Z_7 = 0.00006103515625 -Z_8 = 0.0001220703125 -Z_9 = 1/4096 -Z_10 = 1/2048 -Z_11 = 1/1024 -Z_12 = 1/512 -Z_13 = 1/256 -Z_14 = 1/128 -Z_15 = 0.015625 -Z_16 = 0.03125 -Z_17 = 0.0625 -Z_18 = 0.125 -Z_19 = 0.25 -Z_20 = 0.5 -</pre> -<p>There is some incoherence in output format which has its source in the -fact that some roots are found in branches which can only find decimal -roots, whereas some are found in branches which could find general -fractions and they use <tt class="docutils literal">\xintIrr</tt> before storage of the found root. -This may evolve in future.</p> -</div> -<div class="section" id="the-degree-41-polynomial-with-2-1-9-1-8-0-0-1-1-9-2-as-roots"> -<h2><a class="toc-backref" href="#id47">The degree 41 polynomial with -2, -1.9, -1.8, ..., 0, 0.1, ..., 1.9, 2 as roots</a></h2> -<pre class="literal-block"> -\PolDef{P}{mul((x-i*1e-1), i=-20..20)}% i/10 is same but less efficient -</pre> -<p>In the defining expression we could have used <tt class="docutils literal">i/10</tt> but this gives -less efficient internal form for the coefficients (the <tt class="docutils literal">10</tt>'s end up -in denominators). Using <tt class="docutils literal">\PolToExpr{P}</tt> after having done</p> -<pre class="literal-block"> -\renewcommand\PolToExprCmd[1]{\PolDecToString{\xintREZ{#1}}} -</pre> -<p>we get this expanded form:</p> -<pre class="literal-block"> -x^41 --28.7*x^39 -+375.7117*x^37 --2975.11006*x^35 -+15935.28150578*x^33 --61167.527674162*x^31 -+173944.259366417394*x^29 --373686.963560544648*x^27 -+613012.0665016658846445*x^25 --771182.31133138163125495*x^23 -+743263.86672885754888959569*x^21 --545609.076599482896371978698*x^19 -+301748.325708943677229642930528*x^17 --123655.8987669450434698869844544*x^15 -+36666.1782054884005855608205864192*x^13 --7607.85821367459445649518380016128*x^11 -+1053.15135918687298508885950223794176*x^9 --90.6380005918141132650786081964032*x^7 -+4.33701563847327366842552218288128*x^5 --0.0944770968420804735498178265088*x^3 -+0.00059190121813899276854174416896*x -</pre> -<p>which shows coefficients with up to 36 significant digits...</p> -<p>Stress test: not a hard challenge to <tt class="docutils literal">xint + polexpr</tt>, but be a bit patient!</p> -<pre class="literal-block"> -\PolDef{P}{mul((x-i*1e-1), i=-20..20)}% -\PolToSturm{P}{S} % dutifully computes S_0, ..., S_{41} -% the [1] optional argument limits the search to interval (-10,10) -\PolSturmIsolateZeros[1]{S} % finds *exactly* (but a bit slowly) all 41 roots! -\PolPrintIntervals{S} % nice, isn't it? -</pre> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p>Release <tt class="docutils literal">0.5</tt> has <em>experimental</em> addition of optional argument -<tt class="docutils literal">E</tt> to <tt class="docutils literal">\PolSturmIsolateZeros</tt>. It instructs to search roots only -in interval <tt class="docutils literal"><span class="pre">(-10^E,</span> 10^E)</tt>. Important: the extremities are -<em>assumed to not be roots</em>. In this example, the <tt class="docutils literal">[1]</tt> in -<tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros[1]{S}</span></tt> gives some speed gain; without it, it -turns out in this case that <tt class="docutils literal">polexpr</tt> would have started with -<tt class="docutils literal"><span class="pre">(-10^6,</span> 10^6)</tt> interval.</p> -<p class="last">Please note that this will probably get replaced in future by the -specification of a general interval. Do not rely on meaning of this -optional argument keeping the same.</p> -</div> -</div> -<div class="section" id="roots-of-chebyshev-polynomials"> -<h2><a class="toc-backref" href="#id48">Roots of Chebyshev polynomials</a></h2> -<pre class="literal-block"> -\newcount\mycount -\poldef T_0(x) := 1; -\poldef T_1(x) := x; -\mycount 2 -\xintloop - \poldef T_\the\mycount(x) := - 2x*T_\the\numexpr\mycount-1(x) - - T_\the\numexpr\mycount-2(x); -\ifnum\mycount<15 -\advance\mycount 1 -\repeat - -\[T_{15} = \PolTypeset[X]{T_15}\] -\PolToSturm{T_15}{T_15} -\PolSturmIsolateZeros{T_15} -\PolEnsureIntervalLengths{T_15}{-10} -\PolPrintIntervals{T_15} -</pre> -</div> -</div> -<div class="section" id="non-expandable-macros"> -<h1><a class="toc-backref" href="#id49">Non-expandable macros</a></h1> -<div class="section" id="poldef-polname-letter-expression-in-letter"> -<span id="poldef"></span><h2><a class="toc-backref" href="#id50"><tt class="docutils literal">\poldef <span class="pre">polname(letter):=</span> expression in letter;</tt></a></h2> -<blockquote> -<p>This evaluates the <em>polynomial expression</em> and stores the coefficients -in a private structure accessible later via other package macros, -under the user-chosen <tt class="docutils literal">polname</tt>. Of course the <em>expression</em> can -use other previously defined polynomials. Names must start with a -letter and are constituted of letters, digits, underscores and -(since <tt class="docutils literal">0.5.1</tt>) the right tick <tt class="docutils literal">'</tt>. -The whole <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> syntax is authorized:</p> -<pre class="literal-block"> -\poldef sin(z) := add((-1)^i z^(2i+1)/(2i+1)!, i = 0..10); -</pre> -<p>With fractional coefficients, beware the <a class="reference internal" href="#warningtacit">tacit multiplication issue</a>.</p> -<p>As a side effect the function <tt class="docutils literal">polname()</tt> is recognized as a -genuine <tt class="docutils literal"><span class="pre">\xintexpr...\relax</span></tt> function for (exact) numerical -evaluation (or within an <tt class="docutils literal">\xintdefvar</tt> assignment.) It computes -values not according to the original expression but via the Horner -scheme corresponding to the polynomial coefficients.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p>Release <tt class="docutils literal">0.3</tt> also did the necessary set-up to let the -polynomial be known to the <tt class="docutils literal">\xintfloatexpr</tt> (or -<tt class="docutils literal">\xintdeffloatvar</tt>) parser.</p> -<p>Since <tt class="docutils literal">0.4</tt> this isn't done automatically. Even more, a -previously existing floating point variant of the same name will -be let undefined again, to avoid hard to debug mismatches between -exact and floating point polynomials. This also applies when the -polynomial is produced not via <tt class="docutils literal">\poldef</tt> or <tt class="docutils literal">\PolDef</tt> but as -a product of the other package macros.</p> -<p class="last">See <a class="reference internal" href="#polgenfloatvariant-polname">\PolGenFloatVariant{polname}</a>.</p> -</div> -<p>The original expression is lost after parsing, and in particular -the package provides no way to typeset it. This has to be done -manually, if needed.</p> -</blockquote> -</div> -<div class="section" id="poldef-letter-polname-expression-in-letter"> -<span id="id2"></span><h2><a class="toc-backref" href="#id51"><tt class="docutils literal"><span class="pre">\PolDef[letter]{polname}{expression</span> in letter}</tt></a></h2> -<blockquote> -Does the same as <a class="reference external" href="poldef;">\poldef</a> in an undelimited macro -format (thus avoiding potential problems with the catcode of the -semi-colon in presence of some packages.) In absence of the -<tt class="docutils literal">[letter]</tt> optional argument, the variable is assumed to be <tt class="docutils literal">x</tt>.</blockquote> -</div> -<div class="section" id="polgenfloatvariant-polname"> -<span id="polgenfloatvariant"></span><h2><a class="toc-backref" href="#id52"><tt class="docutils literal">\PolGenFloatVariant{polname}</tt></a></h2> -<blockquote> -<p>Makes the polynomial also usable in the <tt class="docutils literal">\xintfloatexpr</tt> parser. -It will therein evaluates via an Horner scheme with coefficients -already pre-rounded to the float precision.</p> -<p>See also <a class="reference internal" href="#poltofloatexpr-polname">\PolToFloatExpr{polname}</a>.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p>Release <tt class="docutils literal">0.3</tt> did this automatically on <tt class="docutils literal">\PolDef</tt> and -<tt class="docutils literal">\poldef</tt> but this was removed at <tt class="docutils literal">0.4</tt> for optimization.</p> -<p class="last">Any operation, for example generating the derivative polynomial, -or dividing two polynomials or using the <tt class="docutils literal">\PolLet</tt>, <strong>must</strong> be -followed by explicit usage of <tt class="docutils literal">\PolGenFloatVariant{polname}</tt> if -the new polynomial is to be used in <tt class="docutils literal">\xintfloatexpr</tt> or alike -context.</p> -</div> -</blockquote> -</div> -<div class="section" id="pollet-polname-2-polname-1"> -<span id="pollet"></span><h2><a class="toc-backref" href="#id53"><tt class="docutils literal"><span class="pre">\PolLet{polname_2}={polname_1}</span></tt></a></h2> -<blockquote> -Makes a copy of the already defined polynomial <tt class="docutils literal">polname_1</tt> to a -new one <tt class="docutils literal">polname_2</tt>. Same effect as -<tt class="docutils literal"><span class="pre">\PolDef{polname_2}{polname_1(x)}</span></tt> but with less overhead. The -<tt class="docutils literal">=</tt> is optional.</blockquote> -</div> -<div class="section" id="polgloballet-polname-2-polname-1"> -<span id="polgloballet"></span><h2><a class="toc-backref" href="#id54"><tt class="docutils literal"><span class="pre">\PolGlobalLet{polname_2}={polname_1}</span></tt></a></h2> -<blockquote> -Acts globally.</blockquote> -</div> -<div class="section" id="polassign-polname-toarray-macro"> -<span id="polassign"></span><h2><a class="toc-backref" href="#id55"><tt class="docutils literal"><span class="pre">\PolAssign{polname}\toarray\macro</span></tt></a></h2> -<blockquote> -<p>Defines a one-argument expandable macro <tt class="docutils literal"><span class="pre">\macro{#1}</span></tt> which expands -to the (raw) #1th polynomial coefficient.</p> -<ul class="simple"> -<li>Attention, coefficients here are indexed starting at 1.</li> -<li>With #1=-1, -2, ..., <tt class="docutils literal"><span class="pre">\macro{#1}</span></tt> returns leading coefficients.</li> -<li>With #1=0, returns the number of coefficients, i.e. <tt class="docutils literal">1 + deg f</tt> -for non-zero polynomials.</li> -<li>Out-of-range #1's return <tt class="docutils literal">0/1[0]</tt>.</li> -</ul> -<p>See also <a class="reference internal" href="#polnthcoeff-polname-number">\PolNthCoeff{polname}{number}</a>. The main difference is that -with <tt class="docutils literal">\PolAssign</tt>, <tt class="docutils literal">\macro</tt> is made a prefix to <tt class="docutils literal">1 + deg f</tt> -already defined (hidden to user) macros holding individually the -coefficients but <a class="reference internal" href="#polnthcoeff-polname-number">\PolNthCoeff{polname}{number}</a> does each time the job -to expandably recover the <tt class="docutils literal">Nth</tt> coefficient, and due to -expandability can not store it in a macro for future usage (of course, -it can be an argument in an <tt class="docutils literal">\edef</tt>.) The other difference -is the shift by one in indexing, mentioned above (negative -indices act the same in both.)</p> -</blockquote> -</div> -<div class="section" id="polget-polname-fromarray-macro"> -<span id="polget"></span><h2><a class="toc-backref" href="#id56"><tt class="docutils literal"><span class="pre">\PolGet{polname}\fromarray\macro</span></tt></a></h2> -<blockquote> -<p>Does the converse operation to -<tt class="docutils literal"><span class="pre">\PolAssign{polname}\toarray\macro</span></tt>. Each individual -<tt class="docutils literal">\macro{number}</tt> gets expanded in an <tt class="docutils literal">\edef</tt> and then normalized -via <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a>'s macro <tt class="docutils literal">\xintRaw</tt>.</p> -<p>The leading zeros are removed from the polynomial.</p> -<p>(contrived) Example:</p> -<pre class="literal-block"> -\xintAssignArray{1}{-2}{5}{-3}\to\foo -\PolGet{f}\fromarray\foo -</pre> -<p>This will define <tt class="docutils literal">f</tt> as would have <tt class="docutils literal">\poldef <span class="pre">f(x):=1-2x+5x^2-3x^3;</span></tt>.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">Prior to <tt class="docutils literal">0.5</tt>, coefficients were not normalized via -<tt class="docutils literal">\xintRaw</tt> for internal storage.</p> -</div> -</blockquote> -</div> -<div class="section" id="polfromcsv-polname-csv"> -<span id="polfromcsv"></span><h2><a class="toc-backref" href="#id57"><tt class="docutils literal"><span class="pre">\PolFromCSV{polname}{<csv>}</span></tt></a></h2> -<blockquote> -<p>Defines a polynomial directly from the comma separated list of values -(or a macro expanding to such a list) of its coefficients, the <em>first -item</em> gives the constant term, the <em>last item</em> gives the leading -coefficient, except if zero, then it is dropped (iteratively). List -items are each expanded in an <tt class="docutils literal">\edef</tt> and then put into normalized -form via <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a>'s macro <tt class="docutils literal">\xintRaw</tt>.</p> -<p>As leading zero coefficients are removed:</p> -<pre class="literal-block"> -\PolFromCSV{f}{0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -</pre> -<p>defines the zero polynomial, which holds only one coefficient.</p> -<p>See also expandable macro <a class="reference internal" href="#poltocsv-polname">\PolToCSV</a>.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">Prior to <tt class="docutils literal">0.5</tt>, coefficients were not normalized via -<tt class="docutils literal">\xintRaw</tt> for internal storage.</p> -</div> -</blockquote> -</div> -<div class="section" id="poltypeset-polname"> -<span id="poltypeset"></span><h2><a class="toc-backref" href="#id58"><tt class="docutils literal">\PolTypeset{polname}</tt></a></h2> -<blockquote> -<p>Typesets in descending powers in math mode. It uses letter <tt class="docutils literal">x</tt> but -this can be changed via an optional argument:</p> -<pre class="literal-block"> -\PolTypeset[z]{polname} -</pre> -<p>By default zero coefficients are skipped (issue <tt class="docutils literal">\poltypesetalltrue</tt> -to get all of them in output).</p> -<p>These commands (whose meanings will be found in the package code) -can be re-defined for customization. Their default definitions are -expandable, but this is not a requirement.</p> -</blockquote> -<div class="section" id="poltypesetcmd-raw-coeff"> -<span id="poltypesetcmd"></span><h3><a class="toc-backref" href="#id59"><tt class="docutils literal">\PolTypesetCmd{raw_coeff}</tt></a></h3> -<blockquote> -<p>Checks if the coefficient is <tt class="docutils literal">1</tt> or <tt class="docutils literal"><span class="pre">-1</span></tt> and then skips printing -the <tt class="docutils literal">1</tt>, except for the constant term. Also it sets conditional -<a class="reference internal" href="#polifcoeffisplusorminusone-a-b">\PolIfCoeffIsPlusOrMinusOne{A}{B}</a>.</p> -<p>The actual printing of the coefficients, when not equal to plus or -minus one is handled by <a class="reference internal" href="#poltypesetone-raw-coeff">\PolTypesetOne{raw_coeff}</a>.</p> -</blockquote> -</div> -<div class="section" id="poltypesetone-raw-coeff"> -<span id="poltypesetone"></span><h3><a class="toc-backref" href="#id60"><tt class="docutils literal">\PolTypesetOne{raw_coeff}</tt></a></h3> -<blockquote> -<p>The default is <tt class="docutils literal">\xintSignedFrac</tt> but this macro is annoying as it -insists to use a power of ten, and not decimal notation.</p> -<p>One can do things such as for example: <a class="footnote-reference" href="#id5" id="id4">[1]</a></p> -<pre class="literal-block"> -\renewcommand\PolTypesetOne[1]{\num{\xintPFloat[5]{#1}}} -\renewcommand\PolTypesetOne[1]{\num{\xintRound{4}{#1}}} -</pre> -<p>where e.g. we used the <tt class="docutils literal">\num</tt> macro of <tt class="docutils literal">siunitx</tt> as it -understands floating point notation.</p> -<table class="docutils footnote" frame="void" id="id5" rules="none"> -<colgroup><col class="label" /><col /></colgroup> -<tbody valign="top"> -<tr><td class="label"><a class="fn-backref" href="#id4">[1]</a></td><td>the difference in the syntaxes of <tt class="docutils literal">\xintPFloat</tt> and -<tt class="docutils literal">\xintRound</tt> is explained from the fact that -<tt class="docutils literal">\xintPFloat</tt> by default uses the prevailing precision -hence the extra argument like here <tt class="docutils literal">5</tt> is an optional one.</td></tr> -</tbody> -</table> -<p>One can also give a try to using <a class="reference internal" href="#poldectostring-decimal-number">\PolDecToString{decimal number}</a> -which uses decimal notation (at least for the numerator part).</p> -</blockquote> -</div> -<div class="section" id="id6"> -<span id="poltypesetmonomialcmd"></span><h3><a class="toc-backref" href="#id61"><tt class="docutils literal">\PolTypesetMonomialCmd</tt></a></h3> -<blockquote> -This decides how a monomial (in variable <tt class="docutils literal">\PolVar</tt> and with -exponent <tt class="docutils literal">\PolIndex</tt>) is to be printed. The default does nothing -for the constant term, <tt class="docutils literal">\PolVar</tt> for the first degree and -<tt class="docutils literal"><span class="pre">\PolVar^{\PolIndex}</span></tt> for higher degrees monomials. Beware that -<tt class="docutils literal">\PolIndex</tt> expands to digit tokens and needs termination in -<tt class="docutils literal">\ifnum</tt> tests.</blockquote> -</div> -<div class="section" id="poltypesetcmdprefix-raw-coeff"> -<span id="poltypesetcmdprefix"></span><h3><a class="toc-backref" href="#id62"><tt class="docutils literal">\PolTypesetCmdPrefix{raw_coeff}</tt></a></h3> -<blockquote> -Expands to a <tt class="docutils literal">+</tt> if the <tt class="docutils literal">raw_coeff</tt> is zero or positive, and to -nothing if <tt class="docutils literal">raw_coeff</tt> is negative, as in latter case the -<tt class="docutils literal">\xintSignedFrac</tt> used by <a class="reference internal" href="#poltypesetcmd-raw-coeff">\PolTypesetCmd{raw_coeff}</a> will put -the <tt class="docutils literal">-</tt> sign in front of the fraction (if it is a fraction) and -this will thus serve as separator in the typeset formula. Not used -for the first term.</blockquote> -</div> -</div> -<div class="section" id="id8"> -<span id="id7"></span><h2><a class="toc-backref" href="#id63"><tt class="docutils literal"><span class="pre">\PolTypeset*{polname}</span></tt></a></h2> -<blockquote> -Typesets in ascending powers. Use e.g. <tt class="docutils literal">[h]</tt> optional argument -(after the <tt class="docutils literal">*</tt>) to use letter <tt class="docutils literal">h</tt> rather than <tt class="docutils literal">x</tt>.</blockquote> -</div> -<div class="section" id="poldiff-polname-1-polname-2"> -<span id="poldiff"></span><h2><a class="toc-backref" href="#id64"><tt class="docutils literal"><span class="pre">\PolDiff{polname_1}{polname_2}</span></tt></a></h2> -<blockquote> -<p>This sets <tt class="docutils literal">polname_2</tt> to the first derivative of <tt class="docutils literal">polname_1</tt>. It -is allowed to issue <tt class="docutils literal"><span class="pre">\PolDiff{f}{f}</span></tt>, effectively replacing <tt class="docutils literal">f</tt> -by <tt class="docutils literal">f'</tt>.</p> -<p>Coefficients of the result <tt class="docutils literal">polname_2</tt> are irreducible fractions -(see <a class="reference internal" href="#technicalities">Technicalities</a> for the whole story.)</p> -</blockquote> -</div> -<div class="section" id="poldiff-n-polname-1-polname-2"> -<span id="poldiff-n"></span><h2><a class="toc-backref" href="#id65"><tt class="docutils literal"><span class="pre">\PolDiff[N]{polname_1}{polname_2}</span></tt></a></h2> -<blockquote> -This sets <tt class="docutils literal">polname_2</tt> to the <tt class="docutils literal">N</tt>-th derivative of <tt class="docutils literal">polname_1</tt>. -Identical arguments is allowed. With <tt class="docutils literal">N=0</tt>, same effect as -<tt class="docutils literal"><span class="pre">\PolLet{polname_2}={polname_1}</span></tt>. With negative <tt class="docutils literal">N</tt>, switches to -using <tt class="docutils literal">\PolAntiDiff</tt>.</blockquote> -</div> -<div class="section" id="polantidiff-polname-1-polname-2"> -<span id="polantidiff"></span><h2><a class="toc-backref" href="#id66"><tt class="docutils literal"><span class="pre">\PolAntiDiff{polname_1}{polname_2}</span></tt></a></h2> -<blockquote> -<p>This sets <tt class="docutils literal">polname_2</tt> to the primitive of <tt class="docutils literal">polname_1</tt> vanishing -at zero.</p> -<p>Coefficients of the result <tt class="docutils literal">polname_2</tt> are irreducible fractions -(see <a class="reference internal" href="#technicalities">Technicalities</a> for the whole story.)</p> -</blockquote> -</div> -<div class="section" id="polantidiff-n-polname-1-polname-2"> -<span id="polantidiff-n"></span><h2><a class="toc-backref" href="#id67"><tt class="docutils literal"><span class="pre">\PolAntiDiff[N]{polname_1}{polname_2}</span></tt></a></h2> -<blockquote> -This sets <tt class="docutils literal">polname_2</tt> to the result of <tt class="docutils literal">N</tt> successive integrations on -<tt class="docutils literal">polname_1</tt>. With negative <tt class="docutils literal">N</tt>, it switches to using <tt class="docutils literal">\PolDiff</tt>.</blockquote> -</div> -<div class="section" id="poldivide-polname-1-polname-2-polname-q-polname-r"> -<span id="poldivide"></span><h2><a class="toc-backref" href="#id68"><tt class="docutils literal"><span class="pre">\PolDivide{polname_1}{polname_2}{polname_Q}{polname_R}</span></tt></a></h2> -<blockquote> -This sets <tt class="docutils literal">polname_Q</tt> and <tt class="docutils literal">polname_R</tt> to be the quotient and -remainder in the Euclidean division of <tt class="docutils literal">polname_1</tt> by -<tt class="docutils literal">polname_2</tt>.</blockquote> -</div> -<div class="section" id="polquo-polname-1-polname-2-polname-q"> -<span id="polquo"></span><h2><a class="toc-backref" href="#id69"><tt class="docutils literal"><span class="pre">\PolQuo{polname_1}{polname_2}{polname_Q}</span></tt></a></h2> -<blockquote> -This sets <tt class="docutils literal">polname_Q</tt> to be the quotient in the Euclidean division -of <tt class="docutils literal">polname_1</tt> by <tt class="docutils literal">polname_2</tt>.</blockquote> -</div> -<div class="section" id="polrem-polname-1-polname-2-polname-r"> -<span id="polrem"></span><h2><a class="toc-backref" href="#id70"><tt class="docutils literal"><span class="pre">\PolRem{polname_1}{polname_2}{polname_R}</span></tt></a></h2> -<blockquote> -This sets <tt class="docutils literal">polname_R</tt> to be the remainder in the Euclidean division -of <tt class="docutils literal">polname_1</tt> by <tt class="docutils literal">polname_2</tt>.</blockquote> -</div> -<div class="section" id="polgcd-polname-1-polname-2-polname-gcd"> -<span id="polgcd"></span><h2><a class="toc-backref" href="#id71"><tt class="docutils literal"><span class="pre">\PolGCD{polname_1}{polname_2}{polname_GCD}</span></tt></a></h2> -<blockquote> -This sets <tt class="docutils literal">polname_GCD</tt> to be the (monic) GCD of the two first -polynomials. It is a unitary polynomial except if both <tt class="docutils literal">polname_1</tt> -and <tt class="docutils literal">polname_2</tt> vanish, then <tt class="docutils literal">polname_GCD</tt> is the zero -polynomial.</blockquote> -<!-- ``\PolIGCD{polname_1}{polname_2}{polname_iGCD}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - **NOT YET** - - This **assumes** that the two polynomials have integer coefficients. - It then computes the greatest common divisor in the integer - polynomial ring, normalized to have a positive leading coefficient - (if the inputs are not both zero). - -``\PolIContent{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~ - - **NOT YET** - - This computes a positive rational number such that dividing the - polynomial with it returns an integer coefficients polynomial with - no common factor among the coefficients. --> -</div> -<div class="section" id="poltosturm-polname-sturmname"> -<span id="poltosturm"></span><h2><a class="toc-backref" href="#id72"><tt class="docutils literal"><span class="pre">\PolToSturm{polname}{sturmname}</span></tt></a></h2> -<blockquote> -<p>With <tt class="docutils literal">polname</tt> being for example <tt class="docutils literal">P</tt>, the macro starts by -computing polynomials <tt class="docutils literal">P</tt> and <tt class="docutils literal">P'</tt>, then computes the (opposite -of the) remainder in euclidean division, iteratively.</p> -<p>The last non-zero remainder <tt class="docutils literal">P_N_</tt> (where <tt class="docutils literal">N</tt> is obtainable as -<a class="reference internal" href="#polsturmchainlength-sturmname">\PolSturmChainLength{sturmname}</a>) is up to a factor -the GCD of <tt class="docutils literal">P</tt> and <tt class="docutils literal">P'</tt> hence it is a constant if and only if -<tt class="docutils literal">P</tt> is square-free.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<ul class="last simple"> -<li>Since <tt class="docutils literal">0.5</tt> all these polynomials are divided by their rational -content, so they have integer coefficients with no common factor, -and the last one if a constant is either <tt class="docutils literal">1</tt> or <tt class="docutils literal"><span class="pre">-1</span></tt>.</li> -<li>After this normalization to primitive polynomials, they are -stored internally as <tt class="docutils literal">sturmname_k_</tt>, <tt class="docutils literal">k=0,1, ...</tt>.</li> -<li>These polynomials are used internally only. To keep them as -genuine declared polynomials also after the macro call, use the -starred variant <a class="reference internal" href="#id9">PolToSturm*</a>.</li> -</ul> -</div> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">It is perfectly allowed to use the polynomial name as Sturm chain name: -<tt class="docutils literal"><span class="pre">\PolToSturm{f}(f}</span></tt>.</p> -</div> -<p>The macro then declares <tt class="docutils literal">sturmname_0</tt>, <tt class="docutils literal">sturmname_1</tt>, ..., which are -the (non-declared) <tt class="docutils literal">sturmname_k_</tt> divided by the last one. Division is -not done if this last one is the constant <tt class="docutils literal">1</tt> or <tt class="docutils literal"><span class="pre">-1</span></tt>, i.e. if the -original polynomial was square-free. These polynomials are primitive -polynomials too, i.e. with integer coefficients having no common factor.</p> -<p>Thus <tt class="docutils literal">sturmname_0</tt> has exactly the same real and complex roots as -polynomial <tt class="docutils literal">polname</tt>, but with each root now of multiplicity one: -i.e. it is the "square-free part" of original polynomial <tt class="docutils literal">polname</tt>.</p> -<p>Notice that <tt class="docutils literal">sturmname_1</tt> isn't necessarily the derivative of -<tt class="docutils literal">sturmname_0</tt> due to the various normalizations.</p> -<p>The polynomials <tt class="docutils literal">sturmname_k</tt> main utility is for the execution of -<a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a>. Be careful not to use these -names <tt class="docutils literal">sturmname_0</tt>, <tt class="docutils literal">sturmname_1</tt>, etc... for defining other -polynomials after having done <tt class="docutils literal"><span class="pre">\PolToSturm{polname}{sturmname}</span></tt> and -before executing <tt class="docutils literal">\PolSturmIsolateZeros{sturmname}</tt> else the -latter will behave erroneously.</p> -<p><a class="reference internal" href="#polsturmchainlength-sturmname">\PolSturmChainLength{sturmname}</a> gives the index of the last -element of the Sturm chain.</p> -</blockquote> -</div> -<div class="section" id="id10"> -<span id="id9"></span><h2><a class="toc-backref" href="#id73"><tt class="docutils literal"><span class="pre">\PolToSturm*{polname}{sturmname}</span></tt></a></h2> -<blockquote> -<p>Does the same as <a class="reference internal" href="#poltosturm">un-starred version</a> and additionally it -keeps for user usage the memory of the <em>un-normalized</em> Sturm chain -polynomials <tt class="docutils literal">sturmname_k_</tt>, <tt class="docutils literal">k=0,1, <span class="pre">...,</span> N</tt>, with -<tt class="docutils literal">N</tt> being <a class="reference internal" href="#polsturmchainlength-sturmname">\PolSturmChainLength{sturmname}</a>.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">This behaviour was modified at <tt class="docutils literal">0.6</tt>, anyhow the macro was -broken at <tt class="docutils literal">0.5</tt>.</p> -</div> -<div class="admonition hint"> -<p class="first admonition-title">Hint</p> -<p class="last">The square-free part of <tt class="docutils literal">polname</tt> is <tt class="docutils literal">sturmname_0</tt>, and their -quotient is the polynomial with name -<tt class="docutils literal">sturname_\PolSturmChainLength{sturmname}_</tt>. It thus easy to -set-up a loop iteratively computing the latter until the last one -is a constant, thus obtaining the decomposition of an <tt class="docutils literal">f</tt> as -a product <tt class="docutils literal">c f_1 f_2 f_3 ...</tt> of a constant and square-free (primitive) -polynomials, where each <tt class="docutils literal">f_i</tt> divides its predecessor.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsettosturmchainsignchangesat-macro-sturmname-fraction"> -<span id="polsettosturmchainsignchangesat"></span><h2><a class="toc-backref" href="#id74"><tt class="docutils literal"><span class="pre">\PolSetToSturmChainSignChangesAt{\macro}{sturmname}{fraction}</span></tt></a></h2> -<blockquote> -<p>Sets macro <tt class="docutils literal">\macro</tt> to the number of sign changes in the Sturm -chain with name prefix <tt class="docutils literal">sturmname</tt>, at location <tt class="docutils literal">fraction</tt> -(which must be in format as acceptable by the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> macros.)</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p>The author was lazy and did not provide rather an expandable -variant, where one would do <tt class="docutils literal"><span class="pre">\edef\macro{\PolNbOf...}</span></tt>.</p> -<p>This will presumably get added in a future release.</p> -<p class="last">After some hesitation it was decided the macro would by default -act globally. To make the scope of its macro definition local, -use <tt class="docutils literal">[\empty]</tt> as extra optional argument.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsettonbofzeroswithin-macro-sturmname-value-a-value-b"> -<span id="polsettonbofzeroswithin"></span><h2><a class="toc-backref" href="#id75"><tt class="docutils literal"><span class="pre">\PolSetToNbOfZerosWithin{\macro}{sturmname}{value_a}{value_b}</span></tt></a></h2> -<blockquote> -<p>Applies the <a class="reference external" href="https://en.wikipedia.org/wiki/Sturm%27s_theorem">Sturm Theorem</a> to set <tt class="docutils literal">\macro</tt> to the exact number -of <strong>distinct</strong> roots of <tt class="docutils literal">sturmname_0</tt> in the interval <tt class="docutils literal">(value_a, -value_b]</tt> (the macro first re-orders the value for <tt class="docutils literal">value_a <= -value_b</tt> to hold).</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p>The author was lazy and did not provide rather an expandable -variant, where one would do <tt class="docutils literal"><span class="pre">\edef\macro{\PolNbOf...}</span></tt>.</p> -<p>This will presumably get added in future.</p> -<p class="last">After some hesitation it was decided the macro would by default -act globally. To make the scope of its macro definition local, -use <tt class="docutils literal">[\empty]</tt> as extra optional argument.</p> -</div> -<p>See also the expandable -<a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequalto-value">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}</a>, from -which it is immediate (with <tt class="docutils literal">\numexpr</tt>) to create an expandable -variant of this macro. However the difference is that this macro -requires only <a class="reference internal" href="#poltosturm">\PolToSturm</a> to have been executed, -whereas the expandable variant requires prior execution of -<a class="reference internal" href="#polsturmisolatezeros">\PolSturmIsolateZeros</a>.</p> -<p>See also the expandable -<a class="reference internal" href="#polsturmnbwithmultofrootsof-sturmname-lessthanorequalto-value">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualTo{value}</a> -which requires prior execution of -<a class="reference internal" href="#id11">\PolSturmIsolateZeros*</a>.</p> -</blockquote> -</div> -<div class="section" id="polsturmisolatezeros-sturmname"> -<span id="polsturmisolatezeros"></span><h2><a class="toc-backref" href="#id76"><tt class="docutils literal">\PolSturmIsolateZeros{sturmname}</tt></a></h2> -<blockquote> -<p>The macros locates, using <a class="reference external" href="https://en.wikipedia.org/wiki/Sturm%27s_theorem">Sturm theorem</a>, as many disjoint -intervals as there are (real) roots.</p> -<div class="admonition important"> -<p class="first admonition-title">Important</p> -<p>The Sturm chain must have been produced by an earlier -<a class="reference internal" href="#poltosturm-polname-sturmname">\PolToSturm{polname}{sturmname}</a>.</p> -<p>Why does this macro ask for argument the name of Sturm chain, -rather than the name of a polynomial? well this is mainly for -legacy reason, and because it is accompanied by other macros for -which it is simpler to assume the argument will be the name of an -already computed Sturm chain.</p> -<p>Notice that <tt class="docutils literal"><span class="pre">\PolToSturm{f}{f}</span></tt> is perfectly legal (the -<tt class="docutils literal">sturmname</tt> can be same as the <tt class="docutils literal">polname</tt>): it defines -polynomials <tt class="docutils literal">f_0</tt>, <tt class="docutils literal">f_1</tt>, ... having <tt class="docutils literal">f</tt> has name prefix.</p> -<p class="last">Such a prior call -to <tt class="docutils literal">\PolToSturm</tt> must have been made at any rate for -<tt class="docutils literal">\PolSturmIsolateZeros</tt> to be usable.</p> -</div> -<p>After its execution they are two types of such intervals (stored in -memory and accessible via macros or <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> variables, see below):</p> -<ul class="simple"> -<li>singleton <tt class="docutils literal">{a}</tt>: then <tt class="docutils literal">a</tt> is a root, (necessarily a decimal -number, but not all such decimal numbers are exactly identified yet).</li> -<li>open intervals <tt class="docutils literal">(a,b)</tt>: then there is exactly one root <tt class="docutils literal">z</tt> -such that <tt class="docutils literal">a < z < b</tt>, and the end points are guaranteed to not -be roots.</li> -</ul> -<p>The interval boundaries are decimal numbers, originating -in iterated decimal subdivision from initial intervals -<tt class="docutils literal"><span class="pre">(-10^E,</span> 0)</tt> and <tt class="docutils literal">(0, 10^E)</tt> with <tt class="docutils literal">E</tt> chosen initially large -enough so that all roots are enclosed; if zero is a root it is always -identified as such. The non-singleton intervals are of the -type <tt class="docutils literal">(a/10^f, <span class="pre">(a+1)/10^f)</span></tt> with <tt class="docutils literal">a</tt> an integer, which is -neither <tt class="docutils literal">0</tt> nor <tt class="docutils literal"><span class="pre">-1</span></tt>. Hence either <tt class="docutils literal">a</tt> and <tt class="docutils literal">a+1</tt> are both positive -or they are both negative.</p> -<p>One does not <em>a priori</em> know what will be the lengths of these -intervals (except that they are always powers of ten), they -vary depending on how many digits two successive roots have in -common in their respective decimal expansions.</p> -<div class="admonition important"> -<p class="first admonition-title">Important</p> -<p>If some two consecutive intervals share an end-point, no -information is yet gained about the separation between the two -roots which could at this stage be arbitrarily small.</p> -<p class="last">See <a class="reference internal" href="#polrefineinterval-sturmname-index">\PolRefineInterval*{sturmname}{index}</a> which addresses -this issue.</p> -</div> -<!-- This procedure is covariant -with the independent variable ``x`` becoming ``-x``. -Hmm, pas sûr et trop fatigué --> -<p>The interval boundaries (and exactly found roots) are made available -for future computations in <tt class="docutils literal">\xintexpr</tt>-essions or polynomial -definitions as variables <tt class="docutils literal"><sturmname>L_1</tt>, -<tt class="docutils literal"><sturmname>L_2</tt>, etc..., for the left end-points and -<tt class="docutils literal"><sturmname>R_1</tt>, <tt class="docutils literal"><sturmname>R_2</tt>, ..., for the right -end-points.</p> -<p>Thus for example, if <tt class="docutils literal">sturmname</tt> is <tt class="docutils literal">f</tt>, one can use the -<a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> variables <tt class="docutils literal">fL_1</tt>, <tt class="docutils literal">fL_2</tt>, ... to refer in expressions -to the left end-points (or to the exact root, if left and right end -points coincide). Additionally, <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> variable <tt class="docutils literal">fZ_1_isknown</tt> -will have value <tt class="docutils literal">1</tt> if the root in the first interval is known, -and <tt class="docutils literal">0</tt> otherwise. And similarly for the other intervals.</p> -<p>Also, macros <a class="reference internal" href="#polsturmisolatedzeroleft-sturmname-index">\PolSturmIsolatedZeroLeft{sturmname}{index}</a> and -<a class="reference internal" href="#polsturmisolatedzeroright-sturmname-index">\PolSturmIsolatedZeroRight{sturmname}{index}</a> are provided which -expand to these same values, written in decimal notation (i.e. -pre-processed by <a class="reference internal" href="#poldectostring">\PolDecToString</a>.) And there -is also <a class="reference internal" href="#polsturmifzeroexactlyknown-sturmname-index-a-b">\PolSturmIfZeroExactlyKnown{sturmname}{index}{A}{B}</a>.</p> -<div class="admonition important"> -<p class="first admonition-title">Important</p> -<p class="last">Trailing zeroes in the stored decimal numbers accessible via the -macros are significant: they are also present in the decimal -expansion of the exact root.</p> -</div> -<p>These variables and macros are automatically updated when one next -uses macros such as <a class="reference internal" href="#polrefineinterval-sturmname-index">\PolRefineInterval*{sturmname}{index}</a>.</p> -<p>The start of decimal expansion of a positive <tt class="docutils literal">k</tt>-th root is given -by <a class="reference internal" href="#polsturmisolatedzeroleft">\PolSturmIsolatedZeroLeft{sturmname}{k}</a>, and for a negative root it is given -by <a class="reference internal" href="#polsturmisolatedzeroright">PolSturmIsolatedZeroRight{sturmname}{k}</a>. These two decimal -numbers are either both zero or both of the same sign.</p> -<p>The number of distinct roots is obtainable expandably as -<a class="reference internal" href="#polsturmnbofisolatedzeros-sturmname">\PolSturmNbOfIsolatedZeros{sturmname}</a>.</p> -<p>Furthermore -<a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequalto-value">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}</a> and -<a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequaltoexpr-expression">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</a>. -will expandably compute respectively the number of real roots at -most equal to <tt class="docutils literal">value</tt> or <tt class="docutils literal">expression</tt>, and the same but with -multiplicities.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">In the current implementation the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> variables -and <a class="reference external" href="http://www.ctan.org/pkg/xint">xinttools</a> arrays are globally defined. On the -other hand the Sturm sequence polynomials obey the current scope.</p> -</div> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p>As all computations are done <em>exactly</em> there can be no errors... -apart those due to bad coding by author. The results are exact -bounds for the mathematically exact real roots.</p> -<p class="last">Future releases will perhaps also provide macros based on Newton -or Regula Falsi methods. Exact computations with such methods -lead however quickly to very big fractions, and this forces usage -of some rounding scheme for the abscissas if computation times -are to remain reasonable. This raises issues of its own, which -are studied in numerical mathematics.</p> -</div> -</blockquote> -</div> -<div class="section" id="id12"> -<span id="id11"></span><h2><a class="toc-backref" href="#id77"><tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros*{sturmname}</span></tt></a></h2> -<blockquote> -<p>The macro does the same as <a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a> and -then in addition it does the extra work to determine all -multiplicities (of the real roots): -after executing this macro, -<a class="reference internal" href="#polsturmisolatedzeromultiplicity-sturmname-index">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</a> will expand -to the multiplicity of the root located in the <tt class="docutils literal">index</tt>-th -interval (intervals are enumerated from left to right, with index -starting at <tt class="docutils literal">1</tt>).</p> -<p>Furthermore, if for example the <tt class="docutils literal">sturmname</tt> is <tt class="docutils literal">f</tt>, <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> -variables <tt class="docutils literal">fM_1</tt>, <tt class="docutils literal">fM_2</tt>... hold the multiplicities thus -computed.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">It is <strong>not</strong> necessary to have executed the <a class="reference internal" href="#id9">PolToSturm*</a> starred -variant, as the non-starred variant keeps internally the memory of the -original GCD (and even of the full non-normalized original Sturm -chain), even though it does not make the declarations as <em>user-level</em> -genuine polynomials.</p> -</div> -<p>See <a class="reference internal" href="#the-degree-nine-polynomial-with-0-99-0-999-0-9999-as-triple-roots">The degree nine polynomial with 0.99, 0.999, 0.9999 as triple -roots</a> for an example.</p> -</blockquote> -</div> -<div class="section" id="id14"> -<span id="id13"></span><h2><a class="toc-backref" href="#id78"><tt class="docutils literal"><span class="pre">\PolSturmIsolateZeros**{sturmname}</span></tt></a></h2> -<blockquote> -<p>The macro does the same as <a class="reference internal" href="#id12">\PolSturmIsolateZeros*{sturmname}</a> and -in addition it does the extra work to determine all the <em>rational</em> -roots.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">After execution of this macro, a root is "known" if and only if -it is rational.</p> -</div> -<p>Furthermore, primitive polynomial <tt class="docutils literal">sturmname_sqf_norr</tt> is created -to match the (square-free) <tt class="docutils literal">sturmname_0</tt> from which all rational -roots have been removed (see <a class="reference internal" href="#polexprsetup">\polexprsetup</a> for customizing this -name). The number of distinct rational roots is thus the difference -between the degrees of these two polynomials (see also -<a class="reference internal" href="#polsturmnbofrationalroots-sturmname">\PolSturmNbOfRationalRoots{sturmname}</a>).</p> -<p>And <tt class="docutils literal">sturmname_norr</tt> is <tt class="docutils literal">sturmname_0_</tt> from which all rational -roots have been removed (see <a class="reference internal" href="#polexprsetup">\polexprsetup</a>), i.e. it contains -the irrational roots of the original polynomial, with the same -multiplicities.</p> -<p>See <a class="reference internal" href="#a-degree-five-polynomial-with-three-rational-roots">A degree five polynomial with three rational -roots</a> for an example.</p> -</blockquote> -</div> -<div class="section" id="polsturmisolatezerosandgetmultiplicities-sturmname"> -<span id="polsturmisolatezerosandgetmultiplicities"></span><h2><a class="toc-backref" href="#id79"><tt class="docutils literal">\PolSturmIsolateZerosAndGetMultiplicities{sturmname}</tt></a></h2> -<blockquote> -This is another name for <a class="reference internal" href="#id12">\PolSturmIsolateZeros*{sturmname}</a>.</blockquote> -</div> -<div class="section" id="polsturmisolatezerosgetmultiplicitiesandrationalroots-sturmname"> -<span id="polsturmisolatezerosgetmultiplicitiesandrationalroots"></span><h2><a class="toc-backref" href="#id80"><tt class="docutils literal">\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{sturmname}</tt></a></h2> -<blockquote> -This is another name for <a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a>.</blockquote> -</div> -<div class="section" id="polsturmisolatezerosandfindrationalroots-sturmname"> -<h2><a class="toc-backref" href="#id81"><tt class="docutils literal">\PolSturmIsolateZerosAndFindRationalRoots{sturmname}</tt></a></h2> -<blockquote> -<p>This works exactly like <a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> -(inclusive of declaring the polynomials <tt class="docutils literal">sturmname_sqf_norr</tt> and -<tt class="docutils literal">sturmname_norr</tt> with no rational roots) except that it does <em>not</em> -compute the multiplicities of the <em>non-rational</em> roots.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">There is no macro to find the rational roots but not compute -their multiplicities at the same time.</p> -</div> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p>This macro does <em>not</em> define <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> variables -<tt class="docutils literal">sturmnameM_1</tt>, <tt class="docutils literal">sturmnameM_2</tt>, ... holding the -multiplicities and it leaves the multiplicity array (whose accessor -is <a class="reference internal" href="#polsturmisolatedzeromultiplicity-sturmname-index">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</a>) into -a broken state, as all non-rational roots will supposedly have -multiplicity one. This means that the output of -<a class="reference internal" href="#id18">\PolPrintIntervals*</a> for example will be -erroneous for the intervals with irrational roots.</p> -<p class="last">I decided to document it because finding multiplicities of the -non rational roots is somewhat costly, and one may be interested -only into finding the rational roots (of course random -polynomials with integer coefficients will not have <em>any</em> -rational root anyhow).</p> -</div> -</blockquote> -</div> -<div class="section" id="polrefineinterval-sturmname-index"> -<span id="polrefineinterval"></span><h2><a class="toc-backref" href="#id82"><tt class="docutils literal"><span class="pre">\PolRefineInterval*{sturmname}{index}</span></tt></a></h2> -<blockquote> -The <tt class="docutils literal">index</tt>-th interval (starting indexing at one) is further -subdivided as many times as is necessary in order for the newer -interval to have both its end-points distinct from the end-points of -the original interval. This means that the <tt class="docutils literal">k</tt>th root is then -strictly separated from the other roots.</blockquote> -</div> -<div class="section" id="polrefineinterval-n-sturmname-index"> -<span id="polrefineinterval-n"></span><h2><a class="toc-backref" href="#id83"><tt class="docutils literal"><span class="pre">\PolRefineInterval[N]{sturmname}{index}</span></tt></a></h2> -<blockquote> -The <tt class="docutils literal">index</tt>-th interval (starting count at one) is further -subdivided once, reducing its length by a factor of 10. This is done -<tt class="docutils literal">N</tt> times if the optional argument <tt class="docutils literal">[N]</tt> is present.</blockquote> -</div> -<div class="section" id="polensureintervallength-sturmname-index-e"> -<span id="polensureintervallength"></span><h2><a class="toc-backref" href="#id84"><tt class="docutils literal"><span class="pre">\PolEnsureIntervalLength{sturmname}{index}{E}</span></tt></a></h2> -<blockquote> -The <tt class="docutils literal">index</tt>-th interval is subdivided until its length becomes at -most <tt class="docutils literal">10^E</tt>. This means (for <tt class="docutils literal">E<0</tt>) that the first <tt class="docutils literal"><span class="pre">-E</span></tt> digits -after decimal mark of the <tt class="docutils literal">k</tt>th root will then be known exactly.</blockquote> -</div> -<div class="section" id="polensureintervallengths-sturmname-e"> -<span id="polensureintervallengths"></span><h2><a class="toc-backref" href="#id85"><tt class="docutils literal"><span class="pre">\PolEnsureIntervalLengths{sturmname}{E}</span></tt></a></h2> -<blockquote> -<p>The intervals as obtained from <tt class="docutils literal">\PolSturmIsolateZeros</tt> are (if -necessary) subdivided further by (base 10) dichotomy in order for -each of them to have length at most <tt class="docutils literal">10^E</tt> (length will be shorter -than <tt class="docutils literal">10^E</tt> in output only if it did not change or became zero.)</p> -<p>This means that decimal expansions of all roots will be known with -<tt class="docutils literal"><span class="pre">-E</span></tt> digits (for <tt class="docutils literal">E<0</tt>) after decimal mark.</p> -</blockquote> -</div> -<div class="section" id="polprintintervals-varname-sturmname"> -<span id="polprintintervals"></span><h2><a class="toc-backref" href="#id86"><tt class="docutils literal"><span class="pre">\PolPrintIntervals[varname]{sturmname}</span></tt></a></h2> -<blockquote> -<p>This is a convenience macro which prints the bounds for the roots -<tt class="docutils literal">Z_1</tt>, <tt class="docutils literal">Z_2</tt>, ... (the optional argument <tt class="docutils literal">varname</tt> allows to -specify a replacement for the default <tt class="docutils literal">Z</tt>). This will be done (by -default) in a -math mode <tt class="docutils literal">array</tt>, one interval per row, and pattern <tt class="docutils literal">rcccl</tt>, -where the second and fourth column hold the <tt class="docutils literal"><</tt> sign, except when -the interval reduces to a singleton, which means the root is known -exactly.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last">This macro was refactored at 0.7, its default output remained -identical but the ways to customize it got completely -modified.</p> -</div> -<p>See next macros which govern its output.</p> -</blockquote> -<div class="section" id="polprintintervalsnorealroots"> -<h3><a class="toc-backref" href="#id87"><tt class="docutils literal">\PolPrintIntervalsNoRealRoots</tt></a></h3> -<blockquote> -<p>Executed in place of an <tt class="docutils literal">array</tt> environment, when there are no -real roots. Default definition:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsNoRealRoots{} -</pre> -</blockquote> -</div> -<div class="section" id="polprintintervalsbeginenv"> -<h3><a class="toc-backref" href="#id88"><tt class="docutils literal">\PolPrintIntervalsBeginEnv</tt></a></h3> -<blockquote> -<p>Default definition:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsBeginEnv{\[\begin{array}{rcccl}} -</pre> -</blockquote> -</div> -<div class="section" id="polprintintervalsendenv"> -<h3><a class="toc-backref" href="#id89"><tt class="docutils literal">\PolPrintIntervalsEndEnv</tt></a></h3> -<blockquote> -<p>Default definition:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsEndEnv{\end{array}\]} -</pre> -</blockquote> -</div> -<div class="section" id="polprintintervalsknownroot"> -<h3><a class="toc-backref" href="#id90"><tt class="docutils literal">\PolPrintIntervalsKnownRoot</tt></a></h3> -<blockquote> -<p>Default definition:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsKnownRoot{% - &&\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}% - &=&\PolPrintIntervalsPrintExactZero -} -</pre> -</blockquote> -</div> -<div class="section" id="polprintintervalsunknownroot"> -<h3><a class="toc-backref" href="#id91"><tt class="docutils literal">\PolPrintIntervalsUnknownRoot</tt></a></h3> -<blockquote> -<p>Default definition:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsUnknownRoot{% - \PolPrintIntervalsPrintLeftEndPoint&<&% - \PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}&<&% - \PolPrintIntervalsPrintRightEndPoint -} -</pre> -</blockquote> -</div> -<div class="section" id="id15"> -<span id="polprintintervalsprintexactzero"></span><h3><a class="toc-backref" href="#id92"><tt class="docutils literal">\PolPrintIntervalsPrintExactZero</tt></a></h3> -<blockquote> -<p>Default definition:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsPrintExactZero{\PolPrintIntervalsTheLeftEndPoint} -</pre> -</blockquote> -</div> -<div class="section" id="id16"> -<span id="polprintintervalsprintleftendpoint"></span><h3><a class="toc-backref" href="#id93"><tt class="docutils literal">\PolPrintIntervalsPrintLeftEndPoint</tt></a></h3> -<blockquote> -<p>Default definition:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsPrintLeftEndPoint{\PolPrintIntervalsTheLeftEndPoint} -</pre> -</blockquote> -</div> -<div class="section" id="id17"> -<span id="polprintintervalsprintrightendpoint"></span><h3><a class="toc-backref" href="#id94"><tt class="docutils literal">\PolPrintIntervalsPrintRightEndPoint</tt></a></h3> -<blockquote> -<p>Default definition is:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheRightEndPoint} -</pre> -</blockquote> -</div> -</div> -<div class="section" id="id19"> -<span id="id18"></span><h2><a class="toc-backref" href="#id95"><tt class="docutils literal"><span class="pre">\PolPrintIntervals*[varname]{sturmname}</span></tt></a></h2> -<blockquote> -<p>This starred variant produces an alternative output (which -displays the root multiplicity), and is provided as an -example of customization.</p> -<p>As replacement for <a class="reference internal" href="#polprintintervalsknownroot">\PolPrintIntervalsKnownRoot</a>, -<a class="reference internal" href="#polprintintervalsprintexactzero">\PolPrintIntervalsPrintExactZero</a>, -<a class="reference internal" href="#polprintintervalsunknownroot">\PolPrintIntervalsUnknownRoot</a> it uses its own -<tt class="docutils literal"><span class="pre">\POL@@PrintIntervals...</span></tt> macros. We only reproduce here one -definition:</p> -<pre class="literal-block"> -\newcommand\POL@@PrintIntervalsPrintExactZero{% - \displaystyle - \xintSignedFrac{\PolPrintIntervalsTheLeftEndPoint}% -}% -</pre> -<p>Multiplicities are printed using this auxiliary macro:</p> -</blockquote> -<div class="section" id="polprintintervalsprintmultiplicity"> -<h3><a class="toc-backref" href="#id96"><tt class="docutils literal">\PolPrintIntervalsPrintMultiplicity</tt></a></h3> -<blockquote> -<p>whose default definition is:</p> -<pre class="literal-block"> -\newcommand\PolPrintIntervalsPrintMultiplicity{(\mbox{mult. }\PolPrintIntervalsTheMultiplicity)} -</pre> -</blockquote> -</div> -</div> -<div class="section" id="polmapcoeffs-macro-polname"> -<span id="polmapcoeffs"></span><h2><a class="toc-backref" href="#id97"><tt class="docutils literal"><span class="pre">\PolMapCoeffs{\macro}{polname}</span></tt></a></h2> -<blockquote> -<p>It modifies ('in-place': original coefficients get lost) each -coefficient of the defined polynomial via the <em>expandable</em> macro -<tt class="docutils literal">\macro</tt>. The degree is adjusted as necessary if some leading -coefficients vanish after the operation. In replacement text of -<tt class="docutils literal">\macro</tt>, <tt class="docutils literal">\index</tt> expands to the coefficient index (which is -defined to be zero for the constant term).</p> -<p>Notice that <tt class="docutils literal">\macro</tt> will have to handle inputs of the shape -<tt class="docutils literal">A/B[N]</tt> (<a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> internal notation). This means that it probably -will have to be expressed in terms of macros from <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> package.</p> -<p>Example:</p> -<pre class="literal-block"> -\def\foo#1{\xintMul{#1}{\the\numexpr\index*\index\relax}} -</pre> -<p>(or with <tt class="docutils literal"><span class="pre">\xintSqr{\index}</span></tt>) to replace <tt class="docutils literal">n</tt>-th coefficient -<tt class="docutils literal">f_n</tt> by <tt class="docutils literal">f_n*n^2</tt>.</p> -</blockquote> -</div> -<div class="section" id="polreducecoeffs-polname"> -<span id="polreducecoeffs"></span><h2><a class="toc-backref" href="#id98"><tt class="docutils literal">\PolReduceCoeffs{polname}</tt></a></h2> -<blockquote> -About the same as <tt class="docutils literal"><span class="pre">\PolMapCoeffs{\xintIrr}{polname}</span></tt> (but -maintaining a <tt class="docutils literal">[0]</tt> postfix for speedier <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> parsing when -polynomial function is used for computations.) This is a -one-argument macro, working 'in-place'.</blockquote> -</div> -<div class="section" id="id21"> -<span id="id20"></span><h2><a class="toc-backref" href="#id99"><tt class="docutils literal"><span class="pre">\PolReduceCoeffs*{polname}</span></tt></a></h2> -<blockquote> -<p>This starred variant leaves un-touched the decimal exponent in the -internal representation of the fractional coefficients, i.e. if a -coefficient is internally <tt class="docutils literal">A/B[N]</tt>, then <tt class="docutils literal">A/B</tt> is reduced to -smallest terms, but the <tt class="docutils literal">10^N</tt> part is kept as is. Note: if the -polynomial is freshly defined directly via <a class="reference internal" href="#polfromcsv">\PolFromCSV</a> its coefficients might still be internally in some -format like <tt class="docutils literal">1.5e7</tt>; the macro will anyhow always first do the -needed conversion to strict format <tt class="docutils literal">A/B[N]</tt>.</p> -<p>Evaluations with polynomials treated by this can be much faster than -with those handled by the non-starred variant -<a class="reference internal" href="#polreducecoeffs-polname">\PolReduceCoeffs{polname}</a>: as the numerators and denominators -remain smaller, this proves very beneficial in favorable cases -(especially when the coefficients are decimal numbers) to the -expansion speed of the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> macros used internally by -<a class="reference internal" href="#polevalat">\PolEval</a>.</p> -</blockquote> -</div> -<div class="section" id="polmakemonic-polname"> -<span id="polmakemonic"></span><h2><a class="toc-backref" href="#id100"><tt class="docutils literal">\PolMakeMonic{polname}</tt></a></h2> -<blockquote> -Divides by the leading coefficient. It is recommended to execute -<a class="reference internal" href="#id21">\PolReduceCoeffs*{polname}</a> immediately afterwards. This is not -done automatically, due to the case the original polynomial had integer -coefficients and we want to keep the leading one as common -denominator.</blockquote> -</div> -<div class="section" id="polmakeprimitive-polname"> -<span id="polmakeprimitive"></span><h2><a class="toc-backref" href="#id101"><tt class="docutils literal">\PolMakePrimitive{polname}</tt></a></h2> -<blockquote> -Divides by the integer content see (<a class="reference internal" href="#policontent">\PolIContent</a>). This thus produces a polynomial with integer -coefficients having no common factor. The sign of the leading -coefficient is not modified.</blockquote> -</div> -</div> -<div class="section" id="expandable-macros"> -<h1><a class="toc-backref" href="#id102">Expandable macros</a></h1> -<p>All these macros expand completely in two steps except <tt class="docutils literal">\PolToExpr</tt> -and <tt class="docutils literal">\PolToFloatExpr</tt> (and their auxiliaries) which need a -<tt class="docutils literal">\write</tt>, <tt class="docutils literal">\edef</tt> or a <tt class="docutils literal"><span class="pre">\csname...\endcsname</span></tt> context.</p> -<div class="section" id="poleval-polname-atexpr-numerical-expression"> -<span id="polevalatexpr"></span><h2><a class="toc-backref" href="#id103"><tt class="docutils literal"><span class="pre">\PolEval{polname}\AtExpr{numerical</span> expression}</tt></a></h2> -<blockquote> -It boils down to -<tt class="docutils literal">\xinttheexpr polname(numerical <span class="pre">expression)\relax</span></tt>.</blockquote> -</div> -<div class="section" id="poleval-polname-at-fraction"> -<span id="polevalat"></span><h2><a class="toc-backref" href="#id104"><tt class="docutils literal"><span class="pre">\PolEval{polname}\At{fraction}</span></tt></a></h2> -<blockquote> -Evaluates the polynomial at value <tt class="docutils literal">fraction</tt> which must be in (or -expand to) a format acceptable to the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> macros.</blockquote> -</div> -<div class="section" id="polevalreduced-polname-atexpr-numerical-expression"> -<span id="polevalreducedatexpr"></span><h2><a class="toc-backref" href="#id105"><tt class="docutils literal"><span class="pre">\PolEvalReduced{polname}\AtExpr{numerical</span> expression}</tt></a></h2> -<blockquote> -Boils down to <tt class="docutils literal">\xinttheexpr reduce(polname(numerical <span class="pre">expression))\relax</span></tt>.</blockquote> -</div> -<div class="section" id="polevalreduced-polname-at-fraction"> -<span id="polevalreducedat"></span><h2><a class="toc-backref" href="#id106"><tt class="docutils literal"><span class="pre">\PolEvalReduced{polname}\At{fraction}</span></tt></a></h2> -<blockquote> -Evaluates the polynomial at value <tt class="docutils literal">fraction</tt> which must be in (or -expand to) a format acceptable to the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> macros, and produce -an irreducible fraction.</blockquote> -</div> -<div class="section" id="polfloateval-polname-atexpr-numerical-expression"> -<span id="polfloatevalatexpr"></span><h2><a class="toc-backref" href="#id107"><tt class="docutils literal"><span class="pre">\PolFloatEval{polname}\AtExpr{numerical</span> expression}</tt></a></h2> -<blockquote> -<p>Boils down to <tt class="docutils literal">\xintthefloatexpr polname(numerical <span class="pre">expression)\relax</span></tt>.</p> -<p>This is done via a Horner Scheme (see <a class="reference internal" href="#poldef">\poldef</a> and -<a class="reference internal" href="#polgenfloatvariant-polname">\PolGenFloatVariant{polname}</a>), with already rounded -coefficients. <a class="footnote-reference" href="#id24" id="id22">[2]</a> To use the <em>exact coefficients</em> with <em>exactly -executed</em> additions and multiplications, just insert it in the float -expression as in this example: <a class="footnote-reference" href="#id25" id="id23">[3]</a></p> -<pre class="literal-block"> -\xintthefloatexpr 3.27*\xintexpr f(2.53)\relax^2\relax -</pre> -<p>The <tt class="docutils literal">f(2.53)</tt> is exactly computed then rounded at the time of -getting raised to the power <tt class="docutils literal">2</tt>. Moving the <tt class="docutils literal">^2</tt> inside, that -operation would also be treated exactly.</p> -<table class="docutils footnote" frame="void" id="id24" rules="none"> -<colgroup><col class="label" /><col /></colgroup> -<tbody valign="top"> -<tr><td class="label"><a class="fn-backref" href="#id22">[2]</a></td><td>Anyway each floating point operation starts by rounding its -operands to the floating point precision.</td></tr> -</tbody> -</table> -<table class="docutils footnote" frame="void" id="id25" rules="none"> -<colgroup><col class="label" /><col /></colgroup> -<tbody valign="top"> -<tr><td class="label"><a class="fn-backref" href="#id23">[3]</a></td><td>The <tt class="docutils literal">\xintexpr</tt> here could be <tt class="docutils literal">\xinttheexpr</tt> but that -would be less efficient. Cf. <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> documentation about -nested expressions.</td></tr> -</tbody> -</table> -</blockquote> -</div> -<div class="section" id="polfloateval-polname-at-fraction"> -<span id="polfloatevalat"></span><h2><a class="toc-backref" href="#id108"><tt class="docutils literal"><span class="pre">\PolFloatEval{polname}\At{fraction}</span></tt></a></h2> -<blockquote> -Evaluates the polynomial at value <tt class="docutils literal">fraction</tt> which must be in (or -expand to) a format acceptable to the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> macros, and produces -a floating point number.</blockquote> -</div> -<div class="section" id="polifcoeffisplusorminusone-a-b"> -<span id="polifcoeffisplusorminusone"></span><h2><a class="toc-backref" href="#id109"><tt class="docutils literal"><span class="pre">\PolIfCoeffIsPlusOrMinusOne{A}{B}</span></tt></a></h2> -<blockquote> -<p>This macro is a priori undefined.</p> -<p>It is defined via the default <a class="reference internal" href="#poltypesetcmd-raw-coeff">\PolTypesetCmd{raw_coeff}</a> to be -used if needed in the execution of <a class="reference internal" href="#poltypesetmonomialcmd">\PolTypesetMonomialCmd</a>, -e.g. to insert a <tt class="docutils literal">\cdot</tt> in front of <tt class="docutils literal"><span class="pre">\PolVar^{\PolIndex}</span></tt> if -the coefficient is not plus or minus one.</p> -<p>The macro will execute <tt class="docutils literal">A</tt> if the coefficient has been found to be -plus or minus one, and <tt class="docutils literal">B</tt> if not.</p> -</blockquote> -</div> -<div class="section" id="polleadingcoeff-polname"> -<span id="polleadingcoeff"></span><h2><a class="toc-backref" href="#id110"><tt class="docutils literal">\PolLeadingCoeff{polname}</tt></a></h2> -<blockquote> -Expands to the leading coefficient.</blockquote> -</div> -<div class="section" id="polnthcoeff-polname-number"> -<span id="polnthcoeff"></span><h2><a class="toc-backref" href="#id111"><tt class="docutils literal"><span class="pre">\PolNthCoeff{polname}{number}</span></tt></a></h2> -<blockquote> -It expands to the raw <tt class="docutils literal">N</tt>-th coefficient (<tt class="docutils literal">0/1[0]</tt> if the index -number is out of range). With <tt class="docutils literal"><span class="pre">N=-1</span></tt>, <tt class="docutils literal"><span class="pre">-2</span></tt>, ... expands to the -leading coefficients.</blockquote> -</div> -<div class="section" id="poldegree-polname"> -<span id="poldegree"></span><h2><a class="toc-backref" href="#id112"><tt class="docutils literal">\PolDegree{polname}</tt></a></h2> -<blockquote> -It expands to the degree. This is <tt class="docutils literal"><span class="pre">-1</span></tt> if zero polynomial but this -may change in future. Should it then expand to <tt class="docutils literal"><span class="pre">-\infty</span></tt> ?</blockquote> -</div> -<div class="section" id="policontent-polname"> -<span id="policontent"></span><h2><a class="toc-backref" href="#id113"><tt class="docutils literal">\PolIContent{polname}</tt></a></h2> -<blockquote> -<p>It expands to the contents of the polynomial, i.e. to the positive -fraction such that dividing by this fraction produces a polynomial -with integer coefficients having no common prime divisor.</p> -<p>See <a class="reference internal" href="#polmakeprimitive">\PolMakePrimitive</a>.</p> -</blockquote> -</div> -<div class="section" id="poltoexpr-polname"> -<span id="poltoexpr"></span><h2><a class="toc-backref" href="#id114"><tt class="docutils literal">\PolToExpr{polname}</tt></a></h2> -<blockquote> -<p>Expands <a class="footnote-reference" href="#id27" id="id26">[4]</a> to <tt class="docutils literal"><span class="pre">coeff_N*x^N+...</span></tt> (descending powers.)</p> -<table class="docutils footnote" frame="void" id="id27" rules="none"> -<colgroup><col class="label" /><col /></colgroup> -<tbody valign="top"> -<tr><td class="label"><a class="fn-backref" href="#id26">[4]</a></td><td>in a <tt class="docutils literal">\write</tt>, <tt class="docutils literal">\edef</tt>, or <tt class="docutils literal"><span class="pre">\csname...\endcsname</span></tt>, but -not under <tt class="docutils literal"><span class="pre">\romannumeral-`0</span></tt>.</td></tr> -</tbody> -</table> -<p>By default zero coefficients are skipped (issue <tt class="docutils literal">\poltoexpralltrue</tt> to -get all of them in output).</p> -<p>By default, no <tt class="docutils literal">+</tt> sign before negative coefficients, for -compliance with Maple input format (but see -<a class="reference internal" href="#poltoexprtermprefix-raw-coeff">\PolToExprTermPrefix{raw_coeff}</a>.) Also, like the default -behaviour of <a class="reference internal" href="#poltypeset-polname">\PolTypeset{polname}</a>, does not print (for the non -constant terms) coefficients equal to plus or minus one. The degree -one monomial is output as <tt class="docutils literal">x</tt>, not <tt class="docutils literal">x^1</tt>. Complete customization is -possible, see next macros.</p> -<p>Of course <tt class="docutils literal">\PolToExpr{f}</tt> can be inserted in a <tt class="docutils literal">\poldef</tt>, as the -latter expands token by token, hence will force complete expansion -of <tt class="docutils literal">\PolToExpr{f}</tt>, but a simple <tt class="docutils literal">f(x)</tt> is more efficient for -the identical result.</p> -</blockquote> -<div class="section" id="poltoexproneterm-raw-coeff-number"> -<span id="poltoexproneterm"></span><h3><a class="toc-backref" href="#id115"><tt class="docutils literal"><span class="pre">\PolToExprOneTerm{raw_coeff}{number}</span></tt></a></h3> -<blockquote> -<p>This two argument expandable command takes care of the monomial and -its coefficient. The default definition is done in order for -coefficients of absolute value <tt class="docutils literal">1</tt> not be printed explicitely -(except of course for the constant term). Also by default, the -monomial of degree one is <tt class="docutils literal">x</tt> not <tt class="docutils literal">x^1</tt>, and <tt class="docutils literal">x^0</tt> is skipped.</p> -<p>For compatibility with Maple input requirements, by default a <tt class="docutils literal">*</tt> -always precedes the <tt class="docutils literal">x^number</tt>, except if the coefficient is a one -or a minus one. See <a class="reference internal" href="#poltoexprtimes">\PolToExprTimes</a>.</p> -</blockquote> -</div> -<div class="section" id="poltoexpronetermstylea-raw-coeff-number"> -<span id="poltoexpronetermstylea"></span><h3><a class="toc-backref" href="#id116"><tt class="docutils literal"><span class="pre">\PolToExprOneTermStyleA{raw_coeff}{number}</span></tt></a></h3> -<blockquote> -Holds the default package meaning of -<a class="reference internal" href="#poltoexproneterm-raw-coeff-number">\PolToExprOneTerm{raw_coeff}{number}</a>.</blockquote> -</div> -<div class="section" id="poltoexpronetermstyleb-raw-coeff-number"> -<span id="poltoexpronetermstyleb"></span><h3><a class="toc-backref" href="#id117"><tt class="docutils literal"><span class="pre">\PolToExprOneTermStyleB{raw_coeff}{number}</span></tt></a></h3> -<blockquote> -<p>For output in this style:</p> -<pre class="literal-block"> -2*x^11/3+3*x^8/7-x^5-x^4/4-x^3-x^2/2-2*x+1 -</pre> -<p>issue <tt class="docutils literal">\let\PolToExprOneTerm\PolToExprOneTermStyleB</tt> before usage of -<tt class="docutils literal">\PolToExpr</tt>. Note that then <tt class="docutils literal">\PolToExprCmd</tt> isn't used at all. -To revert to package default, issue -<tt class="docutils literal">\let\PolToExprOneTerm\PolToExprOneTermStyleA</tt>.</p> -<p>To suppress the <tt class="docutils literal">*</tt>'s, cf. <a class="reference internal" href="#poltoexprtimes">\PolToExprTimes</a>.</p> -</blockquote> -</div> -<div class="section" id="poltoexprcmd-raw-coeff"> -<span id="poltoexprcmd"></span><h3><a class="toc-backref" href="#id118"><tt class="docutils literal">\PolToExprCmd{raw_coeff}</tt></a></h3> -<blockquote> -It is the one-argument macro used by the package definition of -<tt class="docutils literal">\PolToExprOneTerm</tt> for the coefficients themselves (when not -equal to plus or minus one), and it defaults to -<tt class="docutils literal"><span class="pre">\xintPRaw{\xintRawWithZeros{#1}}</span></tt>. One will have to redefine it -to <tt class="docutils literal"><span class="pre">\xintIrr{#1}</span></tt> or to <tt class="docutils literal"><span class="pre">\xintPRaw{\xintIrr{#1}}</span></tt> to obtain in the -output forcefully reduced coefficients.</blockquote> -</div> -<div class="section" id="poltoexprtermprefix-raw-coeff"> -<span id="poltoexprtermprefix"></span><h3><a class="toc-backref" href="#id119"><tt class="docutils literal">\PolToExprTermPrefix{raw_coeff}</tt></a></h3> -<blockquote> -Defined identically as <a class="reference internal" href="#poltypesetcmdprefix-raw-coeff">\PolTypesetCmdPrefix{raw_coeff}</a>. It -prefixes with a plus sign for non-negative coefficients, because -they don't carry one by themselves.</blockquote> -</div> -<div class="section" id="id28"> -<span id="poltoexprvar"></span><h3><a class="toc-backref" href="#id120"><tt class="docutils literal">\PolToExprVar</tt></a></h3> -<blockquote> -This expands to the variable to use in output (it does not have to -be a single letter, may be an expandable macro.) Initial definition -is <tt class="docutils literal">x</tt>.</blockquote> -</div> -<div class="section" id="id29"> -<span id="poltoexprtimes"></span><h3><a class="toc-backref" href="#id121"><tt class="docutils literal">\PolToExprTimes</tt></a></h3> -<blockquote> -This expands to the symbol used for multiplication of an -<tt class="docutils literal"><span class="pre">x^{number}</span></tt> by the corresponding coefficient. The default is -<tt class="docutils literal">*</tt>. Redefine the macro to expand to nothing to get rid of it (but -this will give output incompatible with some professional computer -algebra software).</blockquote> -</div> -</div> -<div class="section" id="id31"> -<span id="id30"></span><h2><a class="toc-backref" href="#id122"><tt class="docutils literal"><span class="pre">\PolToExpr*{polname}</span></tt></a></h2> -<blockquote> -Expands to <tt class="docutils literal"><span class="pre">coeff_0+coeff_1*x+coeff_2*x^2+...</span></tt> (ascending powers). -Customizable like <a class="reference internal" href="#poltoexpr-polname">\PolToExpr{polname}</a> via the same macros.</blockquote> -</div> -<div class="section" id="poltofloatexpr-polname"> -<span id="poltofloatexpr"></span><h2><a class="toc-backref" href="#id123"><tt class="docutils literal">\PolToFloatExpr{polname}</tt></a></h2> -<blockquote> -<p>Similar to <a class="reference internal" href="#poltoexpr-polname">\PolToExpr{polname}</a> but uses <a class="reference external" href="\PolToFloatExprCmd{raw_coeff}">\PolToFloatExprCmd</a> -which by default rounds and converts the coefficients to floating -point format.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p>It is not necessary to have issued -<a class="reference internal" href="#polgenfloatvariant-polname">\PolGenFloatVariant{polname}</a>. The rounded coefficients are -not easily recoverable from the <tt class="docutils literal">\xintfloatexpr</tt> polynomial -function hence <tt class="docutils literal">\PolToFloatExprCmd</tt> operates from the <em>exact</em> -coefficients anew.</p> -<p class="last">Attention that both macros obey the prevailing float precision. -If it is changed between those macro calls, then a mismatch -exists between the coefficients as used in <tt class="docutils literal">\xintfloatexpr</tt> and -those output by <tt class="docutils literal">\PolToFloatExpr{polname}</tt>.</p> -</div> -</blockquote> -<div class="section" id="poltofloatexproneterm-raw-coeff-number"> -<span id="poltofloatexproneterm"></span><h3><a class="toc-backref" href="#id124"><tt class="docutils literal"><span class="pre">\PolToFloatExprOneTerm{raw_coeff}{number}</span></tt></a></h3> -<blockquote> -Similar to <a class="reference external" href="\PolToExprOneTerm{raw_coeff}{number}">\PolToExprOneTerm</a>. But does not treat -especially coefficients equal to plus or minus one.</blockquote> -</div> -<div class="section" id="poltofloatexprcmd-raw-coeff"> -<span id="id33"></span><h3><a class="toc-backref" href="#id125"><tt class="docutils literal">\PolToFloatExprCmd{raw_coeff}</tt></a></h3> -<blockquote> -<p>It is the one-argument macro used by <tt class="docutils literal">\PolToFloatExprOneTerm</tt>. -Its package definition is <tt class="docutils literal"><span class="pre">\xintFloat{#1}</span></tt>.</p> -<div class="admonition caution"> -<p class="first admonition-title">Caution!</p> -<p>Currently (<a class="reference external" href="http://www.ctan.org/pkg/xint">xint</a> <tt class="docutils literal">1.3c</tt>) <tt class="docutils literal">\xintFloat{0}</tt> outputs <tt class="docutils literal">0.e0</tt> -which is perfectly acceptable input for Python, but not for -Maple. Thus, one should better leave the <a class="reference internal" href="#poltoexprallfalse">\poltoexprallfalse</a> -toggle to its default <tt class="docutils literal">\iffalse</tt> state, if one intends to use -the output in a Maple worksheet.</p> -<p>But even then the zero polynomial will cause a problem. Workaround:</p> -<pre class="literal-block"> -\renewcommand\PolToFloatExprCmd[1]{\xintiiifZero{#1}{0.0}{\xintFloat{#1}}} -</pre> -<p class="last">Usage of <tt class="docutils literal">\xintiiifZero</tt> and not <tt class="docutils literal">\xintifZero</tt> is only for -optimization (I can't help it) because <tt class="docutils literal">#1</tt> is known to be -in <tt class="docutils literal">xintfrac</tt> raw format.</p> -</div> -</blockquote> -</div> -</div> -<div class="section" id="id35"> -<span id="id34"></span><h2><a class="toc-backref" href="#id126"><tt class="docutils literal"><span class="pre">\PolToFloatExpr*{polname}</span></tt></a></h2> -<blockquote> -Typesets in ascending powers.</blockquote> -</div> -<div class="section" id="poltolist-polname"> -<span id="poltolist"></span><h2><a class="toc-backref" href="#id127"><tt class="docutils literal">\PolToList{polname}</tt></a></h2> -<blockquote> -Expands to <tt class="docutils literal"><span class="pre">{coeff_0}{coeff_1}...{coeff_N}</span></tt> with <tt class="docutils literal">N</tt> = degree, and -<tt class="docutils literal">coeff_N</tt> the leading coefficient -(the zero polynomial does give <tt class="docutils literal">{0/1[0]}</tt> and not an -empty output.)</blockquote> -</div> -<div class="section" id="poltocsv-polname"> -<span id="poltocsv"></span><h2><a class="toc-backref" href="#id128"><tt class="docutils literal">\PolToCSV{polname}</tt></a></h2> -<blockquote> -Expands to <tt class="docutils literal">coeff_0, coeff_1, coeff_2, <span class="pre">.....,</span> coeff_N</tt>, starting -with constant term and ending with leading coefficient. Converse -to <a class="reference internal" href="#polfromcsv-polname-csv">\PolFromCSV</a>.</blockquote> -</div> -<div class="section" id="polsturmchainlength-sturmname"> -<span id="polsturmchainlength"></span><h2><a class="toc-backref" href="#id129"><tt class="docutils literal">\PolSturmChainLength{sturmname}</tt></a></h2> -<blockquote> -<p>Returns the integer <tt class="docutils literal">N</tt> such that <tt class="docutils literal">sturmname_N</tt> is the last one -in the Sturm chain <tt class="docutils literal">sturmname_0</tt>, <tt class="docutils literal">sturmname_1</tt>, ...</p> -<p>See <a class="reference internal" href="#poltosturm-polname-sturmname">\PolToSturm{polname}{sturmname}</a>.</p> -</blockquote> -</div> -<div class="section" id="polsturmifzeroexactlyknown-sturmname-index-a-b"> -<span id="polsturmifzeroexactlyknown"></span><h2><a class="toc-backref" href="#id130"><tt class="docutils literal"><span class="pre">\PolSturmIfZeroExactlyKnown{sturmname}{index}{A}{B}</span></tt></a></h2> -<blockquote> -<p>Executes <tt class="docutils literal">A</tt> if the <tt class="docutils literal">index</tt>-th interval reduces to a singleton, -i.e. the root is known exactly, else <tt class="docutils literal">B</tt>.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last"><tt class="docutils literal">index</tt> is allowed to be something like <tt class="docutils literal">1+2*3</tt> as it is fed -to <tt class="docutils literal"><span class="pre">\the\numexpr...\relax</span></tt>.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsturmisolatedzeroleft-sturmname-index"> -<span id="polsturmisolatedzeroleft"></span><h2><a class="toc-backref" href="#id131"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroLeft{sturmname}{index}</span></tt></a></h2> -<blockquote> -<p>Expands to the left end-point for the <tt class="docutils literal">index</tt>-th interval, as -computed by some earlier <a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a>.</p> -<div class="admonition note"> -<p class="first admonition-title">Note</p> -<p class="last">Of course, this is kept updated by macros such as -<a class="reference internal" href="#polrefineinterval-n">\PolRefineInterval{sturmname}{index}</a>.</p> -</div> -<p>The value is pre-formatted using <a class="reference internal" href="#poldectostring">\PolDecTostring</a>.</p> -</blockquote> -</div> -<div class="section" id="polsturmisolatedzeroright-sturmname-index"> -<span id="polsturmisolatedzeroright"></span><h2><a class="toc-backref" href="#id132"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroRight{sturmname}{index}</span></tt></a></h2> -<blockquote> -<p>Expands to the right end-point for the <tt class="docutils literal">index</tt>-th interval as -computed by some earlier <a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a> and -possibly refined afterwards.</p> -<p>The value is pre-formatted using <a class="reference internal" href="#poldectostring">\PolDecTostring</a>.</p> -</blockquote> -</div> -<div class="section" id="polsturmisolatedzeromultiplicity-sturmname-index"> -<span id="polsturmisolatedzeromultiplicity"></span><h2><a class="toc-backref" href="#id133"><tt class="docutils literal"><span class="pre">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</span></tt></a></h2> -<blockquote> -<p>Expands to the multiplicity of the unique root contained in the -<tt class="docutils literal">index</tt>-th interval.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last">A prior execution of <a class="reference internal" href="#id12">\PolSturmIsolateZeros*{sturmname}</a> is mandatory.</p> -</div> -<p>See <a class="reference internal" href="#the-degree-nine-polynomial-with-0-99-0-999-0-9999-as-triple-roots">The degree nine polynomial with 0.99, 0.999, 0.9999 as triple -roots</a> for an example of use.</p> -</blockquote> -</div> -<div class="section" id="polsturmnbofisolatedzeros-sturmname"> -<span id="polsturmnbofisolatedzeros"></span><h2><a class="toc-backref" href="#id134"><tt class="docutils literal">\PolSturmNbOfIsolatedZeros{sturmname}</tt></a></h2> -<blockquote> -Expands to the number of real roots of the polynomial -<tt class="docutils literal"><sturmname>_0</tt>, i.e. the number of distinct real roots of the -polynomial originally used to create the Sturm chain via -<a class="reference internal" href="#poltosturm-polname-sturmname">\PolToSturm{polname}{sturmname}</a>.</blockquote> -<div class="admonition warning"> -<p class="first admonition-title">Warning</p> -<p class="last">The next few macros counting roots, with or without multiplicities, -less than or equal to some value, are under evaluation and may be -removed from the package if their utility is judged to be not high -enough. They can be re-coded at user level on the basis of the other -documented package macros anyway.</p> -</div> -<div class="section" id="polsturmnbofrootsof-sturmname-lessthanorequalto-value"> -<h3><a class="toc-backref" href="#id135"><tt class="docutils literal"><span class="pre">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}</span></tt></a></h3> -<blockquote> -<p>Expands to the number of distinct roots (of the polynomial used to -create the Sturm chain) less than or equal to the <tt class="docutils literal">value</tt> (i.e. a -number of fraction recognizable by the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> macros).</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p><a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a> must have been executed -beforehand.</p> -<p class="last">And the argument is a <tt class="docutils literal">sturmname</tt>, not a <tt class="docutils literal">polname</tt> (this is -why the macro contains Sturm in its name), simply to be reminded -of the above constraint.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsturmnbofrootsof-sturmname-lessthanorequaltoexpr-expression"> -<h3><a class="toc-backref" href="#id136"><tt class="docutils literal"><span class="pre">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></tt></a></h3> -<blockquote> -<p>Expands to the number of distinct roots (of the polynomial -used to create the Sturm chain) which are less than or equal to the -given <tt class="docutils literal">expression</tt>.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last"><a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a> must have been executed -beforehand.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsturmnbwithmultofrootsof-sturmname-lessthanorequalto-value"> -<h3><a class="toc-backref" href="#id137"><tt class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualTo{value}</span></tt></a></h3> -<blockquote> -<p>Expands to the number counted with multiplicities of the roots (of -the polynomial used to create the Sturm chain) which are less than -or equal to the given <tt class="docutils literal">value</tt>.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last"><a class="reference internal" href="#id12">\PolSturmIsolateZeros*{sturmname}</a> (or the double starred -variant) must have been executed beforehand.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsturmnbwithmultofrootsof-sturmname-lessthanorequaltoexpr-expression"> -<h3><a class="toc-backref" href="#id138"><tt class="docutils literal"><span class="pre">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</span></tt></a></h3> -<blockquote> -<p>Expands to the total number of roots (counted with multiplicities) -which are less than or equal to the given <tt class="docutils literal">expression</tt>.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last"><a class="reference internal" href="#id12">\PolSturmIsolateZeros*{sturmname}</a> (or the double starred -variant) must have been executed beforehand.</p> -</div> -</blockquote> -</div> -</div> -<div class="section" id="polsturmnbofrationalroots-sturmname"> -<h2><a class="toc-backref" href="#id139"><tt class="docutils literal">\PolSturmNbOfRationalRoots{sturmname}</tt></a></h2> -<blockquote> -<p>Expands to the number of rational roots (without multiplicities).</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last"><a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> must have been executed -beforehand.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsturmnbofrationalrootswithmultiplicities-sturmname"> -<h2><a class="toc-backref" href="#id140"><tt class="docutils literal">\PolSturmNbOfRationalRootsWithMultiplicities{sturmname}</tt></a></h2> -<blockquote> -<p>Expands to the number of rational roots (counted with multiplicities).</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last"><a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> must have been executed -beforehand.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsturmrationalroot-sturmname-k"> -<h2><a class="toc-backref" href="#id141"><tt class="docutils literal"><span class="pre">\PolSturmRationalRoot{sturmname}{k}</span></tt></a></h2> -<blockquote> -<p>Expands to the <tt class="docutils literal">k</tt>th rational root (they are ordered and indexed -starting at 1 for the most negative).</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last"><a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> must have been executed -beforehand.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsturmrationalrootindex-sturmname-k"> -<h2><a class="toc-backref" href="#id142"><tt class="docutils literal"><span class="pre">\PolSturmRationalRootIndex{sturmname}{k}</span></tt></a></h2> -<blockquote> -<p>Expands to <tt class="docutils literal">index</tt> of the <tt class="docutils literal">k</tt>th rational root as part of the -ordered real roots (without multiplicities). I.e., above macro -<a class="reference internal" href="#polsturmrationalroot-sturmname-k">\PolSturmRationalRoot{sturmname}{k}</a> is equivalent to this -nested call:</p> -<pre class="literal-block"> -\PolSturmIsolatedZeroLeft{sturmname}{\PolSturmRationalRootIndex{sturmname}{k}} -</pre> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last"><a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> must have been executed -beforehand.</p> -</div> -</blockquote> -</div> -<div class="section" id="polsturmrationalrootmultiplicity-sturmname-k"> -<h2><a class="toc-backref" href="#id143"><tt class="docutils literal"><span class="pre">\PolSturmRationalRootMultiplicity{sturmname}{k}</span></tt></a></h2> -<blockquote> -<p>Expands to the multiplicity of the <tt class="docutils literal">k</tt>th rational root.</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last"><a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> must have been executed -beforehand.</p> -</div> -</blockquote> -</div> -<div class="section" id="polintervalwidth-sturmname-index"> -<span id="polintervalwidth"></span><h2><a class="toc-backref" href="#id144"><tt class="docutils literal"><span class="pre">\PolIntervalWidth{sturmname}{index}</span></tt></a></h2> -<blockquote> -The <tt class="docutils literal">10^E</tt> width of the current <tt class="docutils literal">index</tt>-th root localization -interval. Output is in <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> raw <tt class="docutils literal">1/1[E]</tt> format (if not zero).</blockquote> -</div> -<div class="section" id="expandable-macros-for-use-within-execution-of-polprintintervals"> -<h2><a class="toc-backref" href="#id145">Expandable macros for use within execution of <tt class="docutils literal">\PolPrintIntervals</tt></a></h2> -<p>These macros are for usage within custom user redefinitions of -<a class="reference internal" href="#polprintintervalsknownroot">\PolPrintIntervalsKnownRoot</a>, <a class="reference internal" href="#polprintintervalsunknownroot">\PolPrintIntervalsUnknownRoot</a>, or -in redefinitions of <a class="reference internal" href="#polprintintervalsprintexactzero">PolPrintIntervalsPrintExactZero</a> (used in the -default for the former) and of <a class="reference internal" href="#polprintintervalsprintleftendpoint">\PolPrintIntervalsPrintLeftEndPoint</a>, -<a class="reference internal" href="#polprintintervalsprintrightendpoint">\PolPrintIntervalsPrintRightEndPoint</a> (used in the default for the -latter).</p> -<div class="admonition attention"> -<p class="first admonition-title">Attention!</p> -<p class="last">Some macros formerly mentioned here got removed at 0.7: -<tt class="docutils literal">\PolPrintIntervalsTheEndPoint</tt>, -<tt class="docutils literal"><span class="pre">\PolIfEndPointIsPositive{A}{B}</span></tt>, -<tt class="docutils literal"><span class="pre">\PolIfEndPointIsNegative{A}{B}</span></tt>, -<tt class="docutils literal"><span class="pre">\PolIfEndPointIsZero{A}{B}</span></tt>.</p> -</div> -<div class="section" id="polprintintervalsthevar"> -<h3><a class="toc-backref" href="#id146"><tt class="docutils literal">\PolPrintIntervalsTheVar</tt></a></h3> -<blockquote> -Expands to the name (default <tt class="docutils literal">Z</tt>) used for representing the roots, -which was passed as optional argument <tt class="docutils literal">varname</tt> to -<a class="reference internal" href="#polprintintervals-varname-sturmname">\PolPrintIntervals[varname]{sturmname}</a>.</blockquote> -</div> -<div class="section" id="polprintintervalstheindex"> -<h3><a class="toc-backref" href="#id147"><tt class="docutils literal">\PolPrintIntervalsTheIndex</tt></a></h3> -<blockquote> -Expands to the index of the considered interval (indexing starting -at 1 for the leftmost interval).</blockquote> -</div> -<div class="section" id="polprintintervalsthesturmname"> -<h3><a class="toc-backref" href="#id148"><tt class="docutils literal">\PolPrintIntervalsTheSturmName</tt></a></h3> -<blockquote> -Expands to the argument which was passed as <tt class="docutils literal">sturmname</tt> to -<a class="reference internal" href="#polprintintervals-varname-sturmname">\PolPrintIntervals[varname]{sturmname}</a>.</blockquote> -</div> -<div class="section" id="polprintintervalstheleftendpoint"> -<h3><a class="toc-backref" href="#id149"><tt class="docutils literal">\PolPrintIntervalsTheLeftEndPoint</tt></a></h3> -<blockquote> -The left end point of the interval, as would be produced by -<a class="reference internal" href="#polsturmisolatedzeroleft">\PolSturmIsolatedZeroLeft</a> if it was -used with arguments the Sturm chain name and interval index returned -by <a class="reference internal" href="#polprintintervalsthesturmname">\PolPrintIntervalsTheSturmName</a> and -<a class="reference internal" href="#polprintintervalstheindex">\PolPrintIntervalsTheIndex</a>.</blockquote> -</div> -<div class="section" id="polprintintervalstherightendpoint"> -<h3><a class="toc-backref" href="#id150"><tt class="docutils literal">\PolPrintIntervalsTheRightEndPoint</tt></a></h3> -<blockquote> -The right end point of the interval, as would be produced by -<a class="reference internal" href="#polsturmisolatedzeroright">\PolSturmIsolatedZeroRight</a> for -this Sturm chain name and index.</blockquote> -</div> -<div class="section" id="polprintintervalsthemultiplicity"> -<h3><a class="toc-backref" href="#id151"><tt class="docutils literal">\PolPrintIntervalsTheMultiplicity</tt></a></h3> -<blockquote> -The multiplicity of the unique root within the interval of index -<a class="reference internal" href="#polprintintervalstheindex">\PolPrintIntervalsTheIndex</a>. Makes sense only if the starred (or -double-starred) variant of <a class="reference internal" href="#polsturmisolatezeros">\PolSturmIsolateZeros</a> was used earlier.</blockquote> -</div> -</div> -<div class="section" id="poldectostring-decimal-number"> -<span id="poldectostring"></span><h2><a class="toc-backref" href="#id152"><tt class="docutils literal">\PolDecToString{decimal number}</tt></a></h2> -<blockquote> -<p>This is a utility macro to print decimal numbers. It has been -backported to <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> (release <tt class="docutils literal">1.3</tt> of <tt class="docutils literal">2018/03/01</tt>) under -the name <tt class="docutils literal">\xintDecToString</tt>, and the <tt class="docutils literal">polexpr</tt> macro is simply -now an alias to it.</p> -<p>For example -<tt class="docutils literal"><span class="pre">\PolDecToString{123.456e-8}</span></tt> will expand to <tt class="docutils literal">0.00000123456</tt> -and <tt class="docutils literal"><span class="pre">\PolDecToString{123.450e-8}</span></tt> to <tt class="docutils literal">0.00000123450</tt> which -illustrates that trailing zeros are not trimmed. To trim trailing -zeroes, one can use <tt class="docutils literal"><span class="pre">\PolDecToString{\xintREZ{#1}}</span></tt>.</p> -<p>The precise behaviour of this macro may evolve in future releases of -<a class="reference external" href="http://www.ctan.org/pkg/xint">xint</a>.</p> -</blockquote> -</div> -</div> -<div class="section" id="booleans-with-default-setting-as-indicated"> -<h1><a class="toc-backref" href="#id153">Booleans (with default setting as indicated)</a></h1> -<div class="section" id="xintverbosefalse"> -<h2><a class="toc-backref" href="#id154"><tt class="docutils literal">\xintverbosefalse</tt></a></h2> -<blockquote> -<p>This is actually an <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> configuration. Setting it to -<tt class="docutils literal">true</tt> triggers the writing of information to the log when new -polynomials are defined.</p> -<div class="admonition caution"> -<p class="first admonition-title">Caution!</p> -<p class="last">The macro meanings as written to the log are to be considered -unstable and undocumented internal structures.</p> -</div> -</blockquote> -</div> -<div class="section" id="poltypesetallfalse"> -<h2><a class="toc-backref" href="#id155"><tt class="docutils literal">\poltypesetallfalse</tt></a></h2> -<blockquote> -If <tt class="docutils literal">true</tt>, <a class="reference internal" href="#poltypeset-polname">\PolTypeset{polname}</a> will also typeset the vanishing -coefficients.</blockquote> -</div> -<div class="section" id="poltoexprallfalse"> -<h2><a class="toc-backref" href="#id156"><tt class="docutils literal">\poltoexprallfalse</tt></a></h2> -<blockquote> -If <tt class="docutils literal">true</tt>, <a class="reference internal" href="#poltoexpr-polname">\PolToExpr{polname}</a> and <a class="reference internal" href="#poltofloatexpr-polname">\PolToFloatExpr{polname}</a> will -also include the vanishing coefficients in their outputs.</blockquote> -</div> -</div> -<div class="section" id="polexprsetup"> -<h1><a class="toc-backref" href="#id157"><tt class="docutils literal">\polexprsetup</tt></a></h1> -<blockquote> -<p>Serves to customize the package. Currently only two keys are -recognized:</p> -<ul class="simple"> -<li><tt class="docutils literal">norr</tt>: the postfix that <a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> -should append to <tt class="docutils literal">sturmname</tt> to declare the primitive polynomial -obtained from original one after removal of all rational roots. -The default value is <tt class="docutils literal">_norr</tt> (standing for “no rational roots”).</li> -<li><tt class="docutils literal">sqfnorr</tt>: the postfix that <a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a> -should append to <tt class="docutils literal">sturmname</tt> to declare the primitive polynomial -obtained from original one after removal of all rational roots and -suppression of all multiplicities. -The default value is <tt class="docutils literal">_sqf_norr</tt> (standing for “square-free with -no rational roots”).</li> -</ul> -<p>The package executes <tt class="docutils literal">\polexprsetup{norr=_norr, -sqfnorr=_sqf_norr}</tt> as default.</p> -</blockquote> -</div> -<div class="section" id="technicalities"> -<h1><a class="toc-backref" href="#id158">Technicalities</a></h1> -<ul> -<li><p class="first">The catcode of the semi-colon is reset temporarily by <a class="reference internal" href="#poldef">\poldef</a> macro in case some other package (for example the French -babel module) may have made it active. This will fail though if the -whole thing was already part of a macro argument, in such cases one -can use <a class="reference internal" href="#id2">\PolDef{f}{P(x)}</a> -rather. The colon in <tt class="docutils literal">:=</tt> may be active with no consequences.</p> -</li> -<li><p class="first">As a consequence of <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> addition and subtraction always using -least common multiples for the denominators <a class="footnote-reference" href="#id37" id="id36">[5]</a>, user-chosen common -denominators survive additions and multiplications. For example, this:</p> -<pre class="literal-block"> -\poldef P(x):= 1/2 + 2/2*x + 3/2*x^3 + 4/2*x^4; -\poldef Q(x):= 1/3 + (2/3)x + (3/3)x^3 + (4/3)x^4; -\poldef PQ(x):= P(x)Q(x); -</pre> -<p>gives internally the polynomial:</p> -<pre class="literal-block"> -1/6+4/6*x^1+4/6*x^2+6/6*x^3+20/6*x^4+16/6*x^5+9/6*x^6+24/6*x^7+16/6*x^8 -</pre> -<p>where all coefficients have the same denominator 6. Notice though that -<tt class="docutils literal">\PolToExpr{PQ}</tt> outputs the <tt class="docutils literal">6/6*x^3</tt> as <tt class="docutils literal">x^3</tt> because (by -default) it recognizes and filters out coefficients equal to one or -minus one (since release <tt class="docutils literal">0.3</tt>). One can use for example -<tt class="docutils literal">\PolToCSV{PQ}</tt> to see the internally stored coefficients.</p> -<table class="docutils footnote" frame="void" id="id37" rules="none"> -<colgroup><col class="label" /><col /></colgroup> -<tbody valign="top"> -<tr><td class="label"><a class="fn-backref" href="#id36">[5]</a></td><td><p class="first last">prior to <tt class="docutils literal">0.4.1</tt>, <tt class="docutils literal">polexpr</tt> used to temporarily patch -during the parsing of polynomials the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a> macros. This -patch was backported to <a class="reference external" href="http://www.ctan.org/pkg/xint">xint</a> at release <tt class="docutils literal">1.3</tt>.</p> -</td></tr> -</tbody> -</table> -</li> -<li><p class="first"><a class="reference internal" href="#poldiff-polname-1-polname-2">\PolDiff{polname_1}{polname_2}</a> always applies <tt class="docutils literal">\xintIrr</tt> to the -resulting coefficients, except that the <em>power of ten</em> part <tt class="docutils literal">[N]</tt> -(for example an input in scientific notation such as <tt class="docutils literal">1.23e5</tt> gives -<tt class="docutils literal">123/1[3]</tt> internally in xintfrac) is not taken into account in the -reduction of the fraction. This is tentative and may change.</p> -<p>Same remark for <a class="reference internal" href="#polantidiff-polname-1-polname-2">\PolAntiDiff{polname_1}{polname_2}</a>.</p> -</li> -<li><p class="first">Currently, the package stores all coefficients from index <tt class="docutils literal">0</tt> to -index equal to the polynomial degree inside a single macro, as a list. -This data structure is obviously very inefficient for polynomials of -high degree and few coefficients (as an example with <tt class="docutils literal">\poldef -<span class="pre">f(x):=x^1000</span> + x^500;</tt> the subsequent definition <tt class="docutils literal">\poldef <span class="pre">g(x):=</span> -<span class="pre">f(x)^2;</span></tt> will do of the order of 1,000,000 multiplications and -additions involvings only zeroes... which does take time). This -may change in the future.</p> -</li> -<li><p class="first">As is to be expected internal structures of the package are barely -documented and unstable. Don't use them.</p> -</li> -</ul> -</div> -<div class="section" id="change-log"> -<h1><a class="toc-backref" href="#id159">CHANGE LOG</a></h1> -<ul> -<li><p class="first">v0.1 (2018/01/11): initial release. Features:</p> -<ul class="simple"> -<li>The <a class="reference internal" href="#poldef">\poldef</a> parser itself,</li> -<li>Differentiation and anti-differentiation,</li> -<li>Euclidean division and GCDs,</li> -<li>Various utilities such as <a class="reference internal" href="#polfromcsv">\PolFromCSV</a>, -<a class="reference internal" href="#polmapcoeffs">\PolMapCoeffs</a>, -<a class="reference internal" href="#poltocsv">\PolToCSV</a>, <a class="reference internal" href="#poltoexpr">\PolToExpr</a>, ...</li> -</ul> -<p>Only one-variable polynomials so far.</p> -</li> -<li><p class="first">v0.2 (2018/01/14)</p> -<ul class="simple"> -<li>Fix: <tt class="docutils literal">"README thinks \numexpr recognizes ^ operator"</tt>.</li> -<li>Convert README to reStructuredText markup.</li> -<li>Move main documentation from README to separate <tt class="docutils literal">polexpr.txt</tt> file.</li> -<li>Provide <tt class="docutils literal">polexpr.html</tt> as obtained via <a class="reference external" href="http://docutils.sourceforge.net/docs/index.html">DocUtils</a> <tt class="docutils literal">rst2html.py</tt>.</li> -<li>Convert README to (CTAN compatible) Markdown markup.</li> -</ul> -<p>Due to lack of available time the test suite might not be extensive -enough. Bug reports are very welcome!</p> -</li> -<li><p class="first">v0.3 (2018/01/17)</p> -<ul> -<li><p class="first">bug fixes:</p> -<ul> -<li><p class="first">the <tt class="docutils literal">0.1</tt> <a class="reference internal" href="#polevalat">\PolEval</a> accepted expressions for its second -argument, but this was removed by mistake at <tt class="docutils literal">0.2</tt>. Restored.</p> -<p><strong>Attention</strong>: at <tt class="docutils literal">0.4</tt> this has been reverted again, and -<a class="reference internal" href="#polevalatexpr">\PolEval{P}\AtExpr{foo}</a> syntax is needed for -using expressions in the second argument.</p> -</li> -</ul> -</li> -<li><p class="first">incompatible or breaking changes:</p> -<ul class="simple"> -<li><a class="reference internal" href="#poltoexpr">\PolToExpr</a> now by default uses <em>descending</em> -powers (it also treats differently coefficients equal to 1 or -1.) -Use <a class="reference internal" href="#id30">\PolToExpr*</a> for <em>ascending</em> powers.</li> -<li><a class="reference internal" href="#polevalat">\PolEval</a> reduced the output to smallest terms, -but as this is costly with big fractions and not needed if e.g. -wrapped in an <tt class="docutils literal">\xintRound</tt> or <tt class="docutils literal">\xintFloat</tt>, this step has been -removed; the former meaning is available as <a class="reference internal" href="#polevalreducedat">\PolEvalReduced</a>.</li> -</ul> -</li> -<li><p class="first">new (or newly documented) macros:</p> -<ul class="simple"> -<li><a class="reference internal" href="#poltypesetcmd">\PolTypesetCmd</a></li> -<li><a class="reference internal" href="#poltypesetcmdprefix">\PolTypesetCmdPrefix</a></li> -<li><a class="reference internal" href="#poltypesetmonomialcmd">\PolTypesetMonomialCmd</a></li> -<li><a class="reference internal" href="#polevalreducedat">\PolEvalReducedAt</a></li> -<li><a class="reference internal" href="#poltofloatexpr">\PolToFloatExpr</a></li> -<li><a class="reference internal" href="#poltoexproneterm">\PolToExprOneTerm</a></li> -<li><a class="reference internal" href="#poltofloatexproneterm">\PolToFloatExprOneTerm</a></li> -<li><a class="reference internal" href="#poltoexprcmd">\PolToExprCmd</a></li> -<li><a class="reference internal" href="#id33">\PolToFloatExprCmd</a></li> -<li><a class="reference internal" href="#poltoexprtermprefix">\PolToExprTermPrefix</a></li> -<li><a class="reference internal" href="#poltoexprvar">\PolToExprVar</a></li> -<li><a class="reference internal" href="#poltoexprtimes">\PolToExprTimes</a></li> -</ul> -</li> -<li><p class="first">improvements:</p> -<ul> -<li><p class="first">documentation has a table of contents, internal hyperlinks, -standardized signature notations and added explanations.</p> -</li> -<li><p class="first">one can do <tt class="docutils literal"><span class="pre">\PolLet{g}={f}</span></tt> or <tt class="docutils literal"><span class="pre">\PolLet{g}{f}</span></tt>.</p> -</li> -<li><p class="first"><tt class="docutils literal">\PolToExpr{f}</tt> is highly customizable.</p> -</li> -<li><p class="first"><a class="reference internal" href="#poldef">\poldef</a> and other defining macros prepare the polynomial -functions for usage within <tt class="docutils literal">\xintthefloatexpr</tt> (or -<tt class="docutils literal">\xintdeffloatvar</tt>). Coefficients are pre-rounded to the -floating point precision. Indispensible for numerical algorithms, -as exact fractions, even reduced, quickly become very big. See the -documentation about how to use the exact polynomials also in -floating point context.</p> -<p><strong>Attention</strong>: this has been reverted at <tt class="docutils literal">0.4</tt>. The macro -<a class="reference internal" href="#polgenfloatvariant">\PolGenFloatVariant</a> must be used for -generation floating point polynomial functions.</p> -</li> -</ul> -</li> -</ul> -</li> -<li><p class="first">v0.3.1 (2018/01/18)</p> -<p>Fixes two typos in example code included in the documentation.</p> -</li> -<li><p class="first">v0.4 (2018/02/16)</p> -<ul> -<li><p class="first">bug fixes:</p> -<ul class="simple"> -<li>when Euclidean division gave a zero remainder, the internal -representation of this zero polynomial could be faulty; this -could cause mysterious bugs in conjunction with other package -macros such as <a class="reference internal" href="#polmapcoeffs">\PolMapCoeffs</a>.</li> -<li><a class="reference internal" href="#polgcd">\PolGCD</a> was buggy in case of first polynomial being -of lesser degree than the second one.</li> -</ul> -</li> -<li><p class="first">breaking changes:</p> -<ul> -<li><p class="first">formerly <a class="reference internal" href="#polevalat">\PolEval{P}\At{foo}</a> allowed <tt class="docutils literal">foo</tt> to -be an expression, which was transparently handled via -<tt class="docutils literal">\xinttheexpr</tt>. Now, <tt class="docutils literal">foo</tt> must be a fraction (or a macro -expanding to such) in the format acceptable by <tt class="docutils literal">xintfrac.sty</tt> -macros. Use <a class="reference internal" href="#polevalatexpr">\PolEval{P}\AtExpr{foo}</a> for more -general arguments using expression syntax. E.g., if <tt class="docutils literal">foo</tt> is the -name of a variable known to <tt class="docutils literal">\xintexpr</tt>.</p> -<p>The same holds for <a class="reference internal" href="#polevalreducedat">\PolEvalReduced</a> -and <a class="reference internal" href="#polfloatevalat">\PolFloatEval</a>.</p> -</li> -<li><p class="first">the <tt class="docutils literal">3.0</tt> automatic generation of floating point variants has -been reverted. Not only do <em>not</em> the package macros automatically -generate floating point variants of newly created polynomials, -they actually make pre-existing such variant undefined.</p> -<p>See <a class="reference internal" href="#polgenfloatvariant">\PolGenFloatVariant</a>.</p> -</li> -</ul> -</li> -<li><p class="first">new non-expandable macros:</p> -<ul class="simple"> -<li><a class="reference internal" href="#polgenfloatvariant">\PolGenFloatVariant</a></li> -<li><a class="reference internal" href="#polgloballet">\PolGlobalLet</a></li> -<li><a class="reference internal" href="#poltypesetone">\PolTypesetOne</a></li> -<li><a class="reference internal" href="#polquo">\PolQuo</a></li> -<li><a class="reference internal" href="#polrem">\PolRem</a></li> -<li><a class="reference internal" href="#poltosturm">\PolToSturm</a></li> -<li><a class="reference internal" href="#id9">\PolToSturm*</a></li> -<li><a class="reference internal" href="#polsettosturmchainsignchangesat">\PolSetToSturmChainSignChangesAt</a></li> -<li><a class="reference internal" href="#polsettonbofzeroswithin">\PolSetToNbOfZerosWithin</a></li> -<li><a class="reference internal" href="#polsturmisolatezeros">\PolSturmIsolateZeros</a></li> -<li><a class="reference internal" href="#polrefineinterval">\PolRefineInterval*</a></li> -<li><a class="reference internal" href="#polrefineinterval-n">\PolRefineInterval[N]</a></li> -<li><a class="reference internal" href="#polensureintervallength">\PolEnsureIntervalLength</a></li> -<li><a class="reference internal" href="#polensureintervallengths">\PolEnsureIntervalLengths</a></li> -<li><a class="reference internal" href="#polprintintervals">\PolPrintIntervals</a></li> -<li><a class="reference internal" href="#polprintintervalsprintexactzero">\PolPrintIntervalsPrintExactZero</a></li> -<li><a class="reference internal" href="#polprintintervalsprintleftendpoint">\PolPrintIntervalsPrintLeftEndPoint</a></li> -<li><a class="reference internal" href="#polprintintervalsprintrightendpoint">\PolPrintIntervalsPrintRightEndPoint</a></li> -<li><a class="reference internal" href="#id20">\PolReduceCoeffs*</a></li> -<li><a class="reference internal" href="#polmakemonic">\PolMakeMonic</a></li> -</ul> -</li> -<li><p class="first">new expandable macros:</p> -<ul class="simple"> -<li><a class="reference internal" href="#poltoexpronetermstylea">\PolToExprOneTermStyleA</a></li> -<li><a class="reference internal" href="#polifcoeffisplusorminusone">\PolIfCoeffIsPlusOrMinusOne</a></li> -<li><a class="reference internal" href="#polleadingcoeff">\PolLeadingCoeff</a></li> -<li><a class="reference internal" href="#polsturmchainlength">\PolSturmChainLength</a></li> -<li><a class="reference internal" href="#polsturmnbofisolatedzeros">\PolSturmNbOfIsolatedZeros</a></li> -<li><a class="reference internal" href="#polsturmifzeroexactlyknown">\PolSturmIfZeroExactlyKnown</a></li> -<li><a class="reference internal" href="#polsturmisolatedzeroleft">\PolSturmIsolatedZeroLeft</a></li> -<li><a class="reference internal" href="#polsturmisolatedzeroright">\PolSturmIsolatedZeroRight</a></li> -<li><tt class="docutils literal">\PolPrintIntervalsTheEndPoint</tt> (removed at 0.7)</li> -<li><a class="reference internal" href="#polprintintervalstheindex">\PolPrintIntervalsTheIndex</a></li> -<li><tt class="docutils literal">\PolIfEndPointIsPositive</tt> (removed at 0.7)</li> -<li><tt class="docutils literal">\PolIfEndPointIsNegative</tt> (removed at 0.7)</li> -<li><tt class="docutils literal">\PolIfEndPointIsZero</tt> (removed at 0.7)</li> -<li><a class="reference internal" href="#polintervalwidth">\PolIntervalWidth</a></li> -<li><a class="reference internal" href="#poldectostring">\PolDecToString</a></li> -</ul> -</li> -<li><p class="first">improvements:</p> -<p>The main new feature is implementation of the <a class="reference external" href="https://en.wikipedia.org/wiki/Sturm%27s_theorem">Sturm algorithm</a> -for localization of the real roots of polynomials.</p> -</li> -</ul> -</li> -<li><p class="first">v0.4.1 (2018/03/01)</p> -<p>Synced with xint 1.3.</p> -</li> -<li><p class="first">v0.4.2 (2018/03/03)</p> -<p>Documentation fix.</p> -</li> -<li><p class="first">v0.5 (2018/04/08)</p> -<ul class="simple"> -<li>bug fixes:<ul> -<li><a class="reference internal" href="#polget-polname-fromarray-macro">\PolGet{polname}\fromarray\macro</a> crashed when <tt class="docutils literal">\macro</tt> was -an <a class="reference external" href="http://www.ctan.org/pkg/xint">xinttools</a> array macro with no items. It now produces the zero -polynomial.</li> -</ul> -</li> -<li>breaking changes:<ul> -<li><a class="reference internal" href="#poltosturm">\PolToSturm</a> creates primitive integer coefficients polynomials. -This speeds up localization of roots via -<a class="reference internal" href="#polsturmisolatezeros">\PolSturmIsolateZeros</a>. In case of user protests the author -will make available again the code producing the bona fide Sturm -polynomials as used formerly.</li> -<li>polynomials created from <a class="reference internal" href="#polfromcsv">\PolFromCSV</a> or <a class="reference internal" href="#polget">\PolGet</a> -get their coefficients normalized via <a class="reference external" href="http://www.ctan.org/pkg/xint">xintfrac</a>'s <tt class="docutils literal">\xintRaw</tt>.</li> -</ul> -</li> -<li>experimental change:<ul> -<li>optional argument to <a class="reference internal" href="#polsturmisolatezeros">\PolSturmIsolateZeros</a> (see <a class="reference internal" href="#the-degree-41-polynomial-with-2-1-9-1-8-0-0-1-1-9-2-as-roots">The -degree 41 polynomial with -2, -1.9, -1.8, ..., 0, 0.1, ..., 1.9, 2 -as roots</a> for usage). It will presumably be replaced in future by -an interval specification.</li> -</ul> -</li> -<li>new non-expandable macro:<ul> -<li><a class="reference internal" href="#polmakeprimitive">\PolMakePrimitive</a></li> -</ul> -</li> -<li>new expandable macro:<ul> -<li><a class="reference internal" href="#policontent">\PolIContent</a></li> -</ul> -</li> -</ul> -</li> -<li><p class="first">v0.5.1 (2018/04/22)</p> -<ul class="simple"> -<li>new feature:<ul> -<li>the character <tt class="docutils literal">'</tt> can be used in polynomial names.</li> -</ul> -</li> -</ul> -</li> -<li><p class="first">v0.6 (2018/11/20)</p> -<ul class="simple"> -<li>bugfix:<ul> -<li>the starred variant <a class="reference internal" href="#id10">\PolToSturm*{polname}{sturmname}</a> was -broken. On the occasion of the fix, its meaning has been modified, -see its documentation.</li> -<li>using <a class="reference internal" href="#poltosturm">\PolToSturm</a> with a constant polynomial -caused a division by zero error.</li> -</ul> -</li> -<li>new macro:<ul> -<li><a class="reference internal" href="#id11">\PolSturmIsolateZeros*</a> -acts like the <a class="reference internal" href="#polsturmisolatezeros">non-starred variant</a> then computes all the multiplicities.</li> -</ul> -</li> -<li>new expandable macros:<ul> -<li><a class="reference internal" href="#polsturmisolatedzeromultiplicity-sturmname-index">\PolSturmIsolatedZeroMultiplicity{sturmname}{index}</a></li> -<li><a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequalto-value">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}</a></li> -<li><a class="reference internal" href="#polsturmnbofrootsof-sturmname-lessthanorequaltoexpr-expression">\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</a></li> -<li><a class="reference internal" href="#polsturmnbwithmultofrootsof-sturmname-lessthanorequalto-value">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualTo{value}</a></li> -<li><a class="reference internal" href="#polsturmnbwithmultofrootsof-sturmname-lessthanorequaltoexpr-expression">\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}</a></li> -</ul> -</li> -</ul> -</li> -<li><p class="first">v0.7 (2018/12/08), v0.7.1 (bugfix), v0.7.2 (2nd bugfix) (2018/12/09)</p> -<ul class="simple"> -<li>breaking changes:<ul> -<li>although <a class="reference internal" href="#polprintintervals-varname-sturmname">\PolPrintIntervals[varname]{sturmname}</a> default output -remains the same, some auxiliary macros for user-customization -have been removed: <tt class="docutils literal">\PolPrintIntervalsTheEndPoint</tt>, -<tt class="docutils literal"><span class="pre">\PolIfEndPointIsPositive{A}{B}</span></tt>, -<tt class="docutils literal"><span class="pre">\PolIfEndPointIsNegative{A}{B}</span></tt>, and -<tt class="docutils literal"><span class="pre">\PolIfEndPointIsZero{A}{B}</span></tt>.</li> -</ul> -</li> -<li>bugfix:<ul> -<li>it could happen that, contrarily to documentation, an interval -computed by <a class="reference internal" href="#polsturmisolatezeros-sturmname">\PolSturmIsolateZeros{sturmname}</a> had zero as an -endpoint,</li> -<li><a class="reference internal" href="#polensureintervallength-sturmname-index-e">\PolEnsureIntervalLength{sturmname}{index}{E}</a> could under -certain circumstances erroneously replace a non-zero root by -zero,</li> -<li><a class="reference internal" href="#polensureintervallengths-sturmname-e">\PolEnsureIntervalLengths{sturmname}{E}</a> crashed when used with -a polynomial with no real roots, hence for which no isolation intervals -existed (thanks to Thomas Söll for report).</li> -</ul> -</li> -<li>new macros:<ul> -<li><a class="reference internal" href="#id14">\PolSturmIsolateZeros**{sturmname}</a></li> -<li><a class="reference internal" href="#polsturmisolatezerosgetmultiplicitiesandrationalroots-sturmname">\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{sturmname}</a></li> -<li><a class="reference internal" href="#polsturmisolatezerosandfindrationalroots-sturmname">\PolSturmIsolateZerosAndFindRationalRoots{sturmname}</a></li> -<li><a class="reference internal" href="#polexprsetup">\polexprsetup</a></li> -<li><a class="reference internal" href="#id18">\PolPrintIntervals*</a></li> -<li><a class="reference internal" href="#polprintintervalsnorealroots">\PolPrintIntervalsNoRealRoots</a></li> -<li><a class="reference internal" href="#polprintintervalsbeginenv">\PolPrintIntervalsBeginEnv</a></li> -<li><a class="reference internal" href="#polprintintervalsendenv">\PolPrintIntervalsEndEnv</a></li> -<li><a class="reference internal" href="#polprintintervalsknownroot">\PolPrintIntervalsKnownRoot</a></li> -<li><a class="reference internal" href="#polprintintervalsunknownroot">\PolPrintIntervalsUnknownRoot</a></li> -<li><a class="reference internal" href="#polprintintervalsprintmultiplicity">\PolPrintIntervalsPrintMultiplicity</a></li> -</ul> -</li> -<li>new expandable macros:<ul> -<li><a class="reference internal" href="#polsturmnbofrationalroots-sturmname">\PolSturmNbOfRationalRoots{sturmname}</a></li> -<li><a class="reference internal" href="#polsturmnbofrationalrootswithmultiplicities-sturmname">\PolSturmNbOfRationalRootsWithMultiplicities{sturmname}</a></li> -<li><a class="reference internal" href="#polsturmrationalroot-sturmname-k">\PolSturmRationalRoot{sturmname}{k}</a></li> -<li><a class="reference internal" href="#polsturmrationalrootindex-sturmname-k">\PolSturmRationalRootIndex{sturmname}{k}</a></li> -<li><a class="reference internal" href="#polsturmrationalrootmultiplicity-sturmname-k">\PolSturmRationalRootMultiplicity{sturmname}{k}</a></li> -<li><a class="reference internal" href="#polprintintervalsthevar">\PolPrintIntervalsTheVar</a></li> -<li><a class="reference internal" href="#polprintintervalsthesturmname">\PolPrintIntervalsTheSturmName</a></li> -<li><a class="reference internal" href="#polprintintervalsthemultiplicity">\PolPrintIntervalsTheMultiplicity</a></li> -</ul> -</li> -</ul> -</li> -<li><p class="first">v0.7.3 (2019/02/04)</p> -<ul class="simple"> -<li>bugfix:<ul> -<li>Debugging information not destined to user showed in log if root -finding was done under <tt class="docutils literal">\xintverbosetrue</tt> regime.</li> -<li><a class="reference internal" href="#polprintintervalsthevar">\PolPrintIntervalsTheVar</a> remained defined after -<a class="reference internal" href="#polprintintervals">\PolPrintIntervals</a> but was left undefined after -<a class="reference internal" href="#id18">\PolPrintIntervals*</a> (reported by Jürgen Gilg). Now remains -defined in both cases, and <a class="reference internal" href="#polprintintervalsthesturmname">\PolPrintIntervalsTheSturmName</a> -also.</li> -<li>Polynomial names ending in digits caused errors (reported by Thomas -Söll).</li> -</ul> -</li> -</ul> -</li> -<li><p class="first">v0.7.4 (2019/02/12)</p> -<ul class="simple"> -<li>bugfix:<ul> -<li>20000000000 is too big for <tt class="docutils literal">\numexpr</tt>, shouldn't I know that? -Thanks to Jürgen Gilg for report.</li> -</ul> -</li> -</ul> -</li> -<li><p class="first">v0.7.5 (2020/01/31)</p> -<p>Synced with xint 1.4. Requires it.</p> -</li> -</ul> -</div> -<div class="section" id="acknowledgments"> -<h1><a class="toc-backref" href="#id160">Acknowledgments</a></h1> -<p>Thanks to Jürgen Gilg whose question about <a class="reference external" href="http://www.ctan.org/pkg/xint">xint</a> usage for -differentiating polynomials was the initial trigger leading to this -package, and to Jürgen Gilg and Thomas Söll for testing it on some -concrete problems.</p> -<p>Renewed thanks to them on occasion of the <tt class="docutils literal">0.6</tt> and <tt class="docutils literal">0.7</tt> releases for their -continued interest.</p> -<p>See README.md for the License.</p> -</div> -</div> -</body> -</html> diff --git a/macros/latex/contrib/polexpr/polexpr.sty b/macros/latex/contrib/polexpr/polexpr.sty deleted file mode 100644 index 30fef28914..0000000000 --- a/macros/latex/contrib/polexpr/polexpr.sty +++ /dev/null @@ -1,3164 +0,0 @@ -% author: Jean-François Burnol -% License: LPPL 1.3c (author-maintained) -\ProvidesPackage{polexpr}% - [2020/01/31 v0.7.5 Polynomial expressions with rational coefficients (JFB)]% -\RequirePackage{xintexpr}[2020/01/31]% xint 1.4 -\edef\POL@restorecatcodes % TODO: think better about what is reasonable here - {\catcode`\noexpand\_ \the\catcode`\_ % - \catcode`\noexpand\! \the\catcode`\! % - \catcode`\noexpand\* \the\catcode`\* % - \catcode`\noexpand\~ \the\catcode`\~ % - \catcode`\noexpand\: \the\catcode`\: % - \catcode0 \the\catcode0\relax}% -\catcode`\_ 11 \catcode0 12 \catcode`\* 12 -\long\def\xint_stop_atfirstoftwo #1#2{ #1}% not yet in xint 1.3c -\long\def\xint_stop_atsecondoftwo #1#2{ #2}% - -%% 0.7.5 VERY SERIOUS TROUBLES TO GET polexpr TO WORK WITH xintexpr 1.4 - -%% I hesitated about incorporating it directly into xint 1.4 -%% Don't do this at home, only xint gurus are allowed. -\let\POL@originalXINT_expr_redefinemacros\XINT_expr_redefinemacros -\def\XINT_expr_redefinemacros -{% - \POL@originalXINT_expr_redefinemacros - \POL@activateNEhook -}% -%% Using \def's and not \let's to get better readable trace -%% in case I need to debug but this never happens -\def\POL@activateNEhook@xint % done in a group -{% - \def\POL@NEhook@polfunc{\POL@NE@polfunc}% -}% -\def\POL@activateNEhook@pol -{% - \def\POL@NEhook@polfunc{\POL@NP@polfunc}% -}% -\def\POL@activateNEhook{\POL@activateNEhook@xint}% -% -% -\catcode`~ 12 -\catcode`! 11 -\catcode`: 11 -% We drop consideration of \XINT_global matters -% because we have other more urgent and arduous problems -\def\POL@defpolfunc #1#2% -{% - \expandafter\POL@defpolfunc_a - \csname XINT_#2_func_#1\expandafter\endcsname - \csname XINT_#2_polfunc_#1\endcsname {#1}{#2}% -}% -\def\POL@defpolfunc_a #1#2#3#4% -{% - \protected % xintexpr 1.4 does things such as \expandafter\xintAdd\expanded - \expandafter\def\expandafter#2\expandafter##\expandafter1\expandafter - {% - #2{##1}% - }% - \def#1##1##2##3% - {% - % put it directly at the correct level of bracing - % don't worry for now about minimizing how many times ##3 is grabbed - \expandafter##1\expandafter##2\expandafter{\expandafter - {\romannumeral`^^@\POL@NEhook@polfunc{XINT_#4_polfunc_#3}#2{##3}}}% - }% -}% -% -\def\POL@polfunc@go #1#2#3{#2#3}% brace stripping intentional -\def\POL@NEhook@polfunc{\POL@polfunc@go}% default for pure numerics -% -% Hook for expansion in \poldef -\def\POL@NP@polfunc #1{% -\def\POL@NP@polfunc ##1##2##3% -{% - \if0\expandafter\XINT:NE:hastilde\detokenize{##3}~!\relax - \expandafter\XINT:NE:hashash\detokenize{##3}#1!\relax 0% - \expandafter\POL@polfunc@go - \else - \expandafter\POL:NP:polfunc:p - \fi {##1}{##2}{##3}% -}}\expandafter\POL@NP@polfunc\string#% -\def\POL:NP:polfunc:p #1#2#3% -{% - ~romannumeral~POL:usepolfunc:pol{#1}{#3}% -}% -\def\POL:usepolfunc:pol #1%#2% -{% -% Here we are in the core of \poldef and we really -% need to get rid of some \expanded tokens so -% we accept being exposed to \expanded but arrange to -% remain invariant. Then we will try to speed up -% polynomial composition (at this time the \#1 -% is a nested Horner type macro) by «pre-expanding» -% the argument, but this means using the \POL@get -% methods inside an \hbox -% -% \POL@applypolfunc will be defined \protected -% - \expandafter\xint_c_\expandafter\POL@applypolfunc -% This will be \protected - \csname#1\endcsname -% #2% brace stripping is deliberate -}% -% -% Hook for expansion in \xintexpr -\def\POL@NE@polfunc #1{% -\def\POL@NE@polfunc ##1##2##3% -{% - \if0\expandafter\XINT:NE:hastilde\detokenize{##3}~!\relax - \expandafter\XINT:NE:hashash\detokenize{##3}#1!\relax 0% - \expandafter\POL@polfunc@go - \else - \expandafter\POL:NE:polfunc:p - \fi {##1}{##2}{##3}% -}}\expandafter\POL@NE@polfunc\string#% -\def\POL:NE:polfunc:p #1#2#3% -{% - ~romannumeral~POL:usepolfunc:xint{#1}{#3}% -}% -\def\POL:usepolfunc:xint #1% -{% -% This is done to overcome \protected and is useful -% in case the polynomial function ends up nested -% in some non-polynomial user declared function -% as the latter (and other things) tries to pre-expand -% its arguments (as they may be used multiple time) -% using \expanded, but \#1 is protected. -% And this works recursively. We are inside braces. -% However we have a very big problem with constant -% polynomial functions. We have to handle them -% in a special way. - -`0\csname#1\expandafter\endcsname\expanded -}% -\catcode`~ 13 -\catcode`: 12 - - -%% Start defining some \protected ones here -\protected\def\POL@empty{}% -\newif\ifPOL@pol -\protected\def\POL@polglobaltrue {\global\let\ifPOL@pol\iftrue}% -\protected\def\POL@polglobalfalse{\global\let\ifPOL@pol\iffalse}% - - -%% Patch xintexpr to authorize ' in names (0.5.1) -%% Adapted 0.7.5 to follow-up on xintexpr 1.4 internal changes -%% (much simpler than previous stuff...) -%% This allows ' as a character in a polynomial name (not initial one) -\def\POL@XINT_expr_scanfunc_b #1% -{% - \ifcat \relax#1\xint_dothis{\iffalse{\fi}(_#1}\fi - \if (#1\xint_dothis{\iffalse{\fi}(`}\fi - \if 1\ifcat a#10\fi - \ifnum\xint_c_ix<1\string#1 0\fi - \if @#10\fi - \if _#10\fi - \if '#10\fi - 1% - \xint_dothis{\iffalse{\fi}(_#1}\fi - \xint_orthat {#1\XINT_expr_scanfunc_a}% -}% - - -%% Activate polexp's modified xintexpr (only during definitions -%% of polynomials) -\def\POL@hackxintexpr {% - \let\POL@originalXINT_expr_scanfunc_b\XINT_expr_scanfunc_b - \let\XINT_expr_scanfunc_b\POL@XINT_expr_scanfunc_b - \def\POL@activateNEhook{\POL@activateNEhook@pol}% -}% -\def\POL@restorexintexpr {% - \let\XINT_expr_scanfunc_b\POL@originalXINT_expr_scanfunc_b - \def\POL@activateNEhook{\POL@activateNEhook@xint}% -}% - - -%% AUXILIARIES -\catcode`! 3 -%% added at 0.7 -\newcommand\polexprsetup[1]{\POL@setup_parsekeys #1,=!,\xint_bye}% -\def\POL@setup_parsekeys #1=#2#3,{% - \ifx!#2\expandafter\xint_bye\fi - \csname POL@setup_setkey_\xint_zapspaces #1 \xint_gobble_i\endcsname - \xint_firstoftwo - {\PackageWarning{polexpr}{The \detokenize{#1} key is unknown! ignoring}}% - {\xintZapLastSpaces{#2#3}}% - \POL@setup_parsekeys -}% -\catcode`! 11 -\def\POL@setup_setkey_norr #1#2{\edef\POL@norr}% -\def\POL@setup_setkey_sqfnorr #1#2{\edef\POL@sqfnorr}% -\polexprsetup{norr=_norr, sqfnorr=_sqf_norr} - -\newcount\POL@count -\newif\ifxintveryverbose -\newif\ifpoltypesetall -\newif\ifPOL@tosturm@makefirstprimitive -\POL@tosturm@makefirstprimitivetrue -\newif\ifPOL@isolz@nextwillneedrefine -\newif\ifpoltoexprall -%% the main exchange structure (stored in macros \POLuserpol@<name>) -%% is: degree.\POL@empty{coeff0}{coeff1}....{coeffN} -%% (degree=N except zero polynomial recognized from degree set to -1 -%% but it has always the {0/1[0]} coeff0.) -\def\POL@ifZero#1{\expandafter\POL@ifZero@aux#1;}% -\def\POL@ifZero@aux #1#2;{\if-#1\expandafter\xint_firstoftwo - \else\expandafter\xint_secondoftwo - \fi}% -\def\POL@split#1.#2;#3#4% separates degree and list of coefficients -% The \expandafter chain removes the \empty token - {\def#3{#1}\expandafter\def\expandafter#4\expandafter{#2}}% -% -\def\POL@resultfromarray #1{% ATTENTION, **MUST** be executed with -% \count@ set to 1 + degree (\count@ = 0 for zero polynomial) -% Attention to the \protected here at 0.7.5 -% They are many all over the place - \protected\edef\POL@result{\ifnum\count@>\z@ - \the\numexpr\count@-\@ne.\POL@empty - \xintiloop [1+1]% - \expandafter\POL@braceit\csname POL@array#1\xintiloopindex\endcsname - \ifnum\xintiloopindex<\count@ - \repeat -% Attention to this \protected\POL@empty -% They are many all over the place - \else-1.\POL@empty{0/1[0]}\fi}% -}% -\def\POL@braceit#1{{#1}}% needed as \xintiloopindex can not "see" through braces - - -\newcommand\PolDef[3][x]{\poldef #2(#1):=#3;}% -\def\poldef{\edef\POL@restoresemicolon{\catcode59=\the\catcode59\relax}% - \catcode59 12 \POL@defpol}% -\def\POL@defpol #1(#2)#3=#4;{% - \POL@restoresemicolon - \edef\POL@tmp{\ifxintverbose1\else0\fi}% - \unless\ifxintveryverbose\xintverbosefalse\fi - \POL@hackxintexpr - \xintdeffunc __pol(#2):=0+(#4);% force conversion to raw if a constant - \POL@restorexintexpr - \if1\POL@tmp\xintverbosetrue\fi - \edef\POL@polname{\xint_zapspaces #1 \xint_gobble_i}% - \begingroup - \setbox0\hbox{% - \let\xintScalarAdd\xintAdd - \let\xintScalarSub\xintSub - \let\xintScalarMul\xintMul - \let\xintScalarDiv\xintDiv - \let\xintScalarPow\xintPow - \let\xintScalarOpp\xintOpp - \let\xintAdd\POL@add - \let\xintMul\POL@mul - \let\xintDiv\POL@div - \let\xintPow\POL@pow - \let\xintOpp\POL@opp - \def\xintSub ##1##2{\xintAdd{##1}{\xintOpp{##2}}}% - % \xintAdd{0} to get \POL@result defined even if numerical only expression - % I could also test \ifPOL@pol, but this is anyhow small overhead -% Attention that xintexpr 1.4 has braces all over the place - \expandafter\xintAdd\expandafter{\expandafter0\expandafter}% - \romannumeral0\csname XINT_expr_userfunc___pol\endcsname - {\POL@polglobaltrue\protected\def\POL@result{1.\POL@empty{0/1[0]}{1/1[0]}}}% - \expandafter}\expandafter - \endgroup\expandafter - \def\csname POLuserpol@\POL@polname\expandafter\endcsname - \expandafter{\POL@result}% - \expandafter\POL@newpol\expandafter{\POL@polname}% -}% -% - - -\def\POL@newpol#1{% -%% We must handle specially constant polynomials because they must -%% be made to work expandably in \poldef of other polynomials due -%% to complicated matters having to do with the \POL@ifpol conditional - \ifnum\PolDegree{#1}<\@ne - % non-zero constant - % I am defining this one only for the Info message, no time now - \expandafter\edef\csname XINT_expr_polfunc_#1\endcsname - ##1{\PolNthCoeff{#1}{0}}% - % No hooks here! - \expandafter\edef\csname XINT_expr_func_#1\endcsname ##1##2##3% - {##1##2{{\PolNthCoeff{#1}{0}}}}% - \else - % polynomial of degree at least 1. This means that mechanism - % to get \POL@result will get activated and we must be very careful - % to never \edef when the Horner macro will be converted to - % a polynomial - \POL@newpolhorner{#1}% - \POL@defpolfunc{#1}{expr}% - \fi - \expandafter\let\csname XINT_flexpr_func_#1\endcsname\@undefined - \ifxintverbose\POL@info{#1}\fi -}% -\def\POL@newfloatpol#1{% -%% We must handle specially constant polynomials because they must -%% be made to work expandably in \poldef of other polynomials due -%% to complicated matters having to do with the \POL@ifpol conditional - \ifnum\PolDegree{#1}<\@ne - % non-zero constant - % I am defining this one only for the Info message, no time now - \expandafter\edef\csname XINT_flexpr_polfunc_#1\endcsname - ##1{\PolNthCoeff{#1}{0}}% - % No hooks here! - \expandafter\edef\csname XINT_flexpr_func_#1\endcsname ##1##2##3% - {##1##2{{\PolNthCoeff{#1}{0}}}}% - \else - % polynomial of degree at least 1. This means that mechanism - % to get \POL@result will get activated and we must be very careful - % to never \edef when the Horner macro will be converted to - % a polynomial - \POL@newfloatpolhorner{#1}% - \POL@defpolfunc{#1}{flexpr}% - \fi - \ifxintverbose\POL@floatinfo{#1}\fi -}% -\def\POL@info #1{% - \xintMessage {polexpr}{Info}% - {Function #1 for the \string\xintexpr\space parser is - associated to \string\XINT_expr_polfunc_#1\space - whose meaning uses Horner scheme: - \expandafter\meaning - \csname XINT_expr_polfunc_#1\endcsname}% -}% -\def\POL@floatinfo #1{% - \xintMessage {polexpr}{Info}% - {Function #1 for the \string\xintfloatexpr\space parser is - associated to \string\XINT_flexpr_polfunc_#1\space - whose meaning uses Horner scheme: - \expandafter\meaning - \csname XINT_flexpr_polfunc_#1\endcsname}% -}% -% -\def\POL@newpolhorner#1{% - %% redefine function to expand by Horner scheme. Is this useful? - %% perhaps bad idea for numerical evaluation of thing such as (1+x)^10? -% note: I added {0/1[0]} item to zero polynomial also to facilitate this - \expandafter\expandafter\expandafter\POL@split - \csname POLuserpol@#1\endcsname;\POL@var@deg\POL@var@coeffs - \edef\POL@var@coeffs{\xintRevWithBraces{\POL@var@coeffs}}% - \begingroup - \expandafter\POL@newpol@horner\POL@var@coeffs\relax - \expandafter - \endgroup - \expandafter\def\csname XINT_expr_polfunc_#1\expandafter\endcsname - \expandafter##\expandafter1\expandafter{\POL@tmp{##1}}% -}% -\def\POL@newfloatpolhorner#1{% - %% redefine function to expand by Horner scheme. Is this useful? - %% perhaps bad idea for numerical evaluation of thing such as (1+x)^10? -% note: I added {0/1[0]} item to zero polynomial also to facilitate this - \expandafter\expandafter\expandafter\POL@split - \csname POLuserpol@#1\endcsname;\POL@var@deg\POL@var@coeffs - \edef\POL@var@coeffs{\xintRevWithBraces{\POL@var@coeffs}}% - \begingroup - \expandafter\POL@newpol@floathorner\POL@var@coeffs\relax - \expandafter - \endgroup - \expandafter\def\csname XINT_flexpr_polfunc_#1\expandafter\endcsname - \expandafter##\expandafter1\expandafter{\POL@tmp{##1}}% -}% -\def\POL@newpol@horner#1{\let\xintAdd\relax\let\xintMul\relax - \def\POL@tmp##1{#1}\POL@newpol@horner@loop.}% -\def\POL@newpol@horner@loop.#1{% - \if\relax#1\expandafter\xint_gob_til_dot\fi - \edef\POL@tmp##1{\xintiiifZero{#1} - {\@firstofone}{\xintAdd{#1}}% - {\xintMul{##1}{\POL@tmp{##1}}}}% - \POL@newpol@horner@loop.% -}% -\def\POL@newpol@floathorner#1{\let\XINTinFloatAdd\relax\let\XINTinFloatMul\relax - \def\xintAdd{\XINTinFloatAdd}\def\xintMul{\XINTinFloatMul}% - \edef\POL@tmp##1{\XINTinFloatdigits{#1}}% - \POL@newpol@floathorner@loop.}% -\def\POL@newpol@floathorner@loop.#1{% - \if\relax#1\expandafter\xint_gob_til_dot\fi - \edef\POL@tmp##1{\xintiiifZero{#1} - {\@firstofone}{\xintAdd{\XINTinFloatdigits{#1}}}% - {\xintMul{##1}{\POL@tmp{##1}}}}% - \POL@newpol@floathorner@loop.% -}% - - -\newcommand\PolGenFloatVariant[1]{\POL@newfloatpol{#1}}% - - -\newcommand\PolLet[2]{\if=\noexpand#2\expandafter\xint_firstoftwo - \else\expandafter\xint_secondoftwo\fi - \POL@@let\POL@let{#1}{#2}}% -\def\POL@@let#1#2#3{\POL@let{#1}{#3}}% -\def\POL@let#1#2{% - \expandafter\let\csname POLuserpol@#1\expandafter\endcsname - \csname POLuserpol@#2\endcsname - \expandafter\let\csname XINT_expr_polfunc_#1\expandafter\endcsname - \csname XINT_expr_polfunc_#2\endcsname - \POL@defpolfunc{#1}{expr}% - \ifxintverbose\POL@info{#1}\fi -}% -\newcommand\PolGlobalLet[2]{\begingroup - \globaldefs\@ne - \if=\noexpand#2\expandafter\xint_firstoftwo - \else\expandafter\xint_secondoftwo\fi -% do I need to check something here relative to \xintNewExpr? - \POL@@globallet\POL@globallet {#1}{#2}}% -\def\POL@@globallet#1#2#3{\POL@globallet{#1}{#3}}% -\def\POL@globallet#1#2{\POL@let{#1}{#2}\endgroup}% - -\newcommand\PolAssign[1]{\def\POL@polname{#1}\POL@assign}% zap spaces in #1? -\def\POL@assign#1\toarray#2{% - \expandafter\expandafter\expandafter\POL@split - \csname POLuserpol@\POL@polname\endcsname;\POL@var@deg\POL@var@coeffs - \xintAssignArray\POL@var@coeffs\to#2% - % modify \#200 macro to return 0/1[0] for out of range indices - \@namedef{\xint_arrayname00}##1##2##3{% - \@namedef{\xint_arrayname00}####1{% - \ifnum####1>##1 \xint_dothis{ 0/1[0]}\fi - \ifnum####1>\m@ne \xint_dothis - {\expandafter\expandafter\expandafter##3% - \csname##2####1\endcsname}\fi - \unless\ifnum-####1>##1 \xint_dothis - {\expandafter\expandafter\expandafter##3% - \csname##2\the\numexpr##1+####1+\@ne\endcsname}\fi - \xint_orthat{ 0/1[0]}}% space stops a \romannumeral0 - }% - \csname\xint_arrayname00\expandafter\expandafter\expandafter\endcsname - \expandafter\expandafter\expandafter - {\csname\xint_arrayname0\expandafter\endcsname\expandafter}\expandafter - {\xint_arrayname}{ }% -}% - - -\newcommand\PolGet{}% -\def\PolGet#1#2\fromarray#3{% - \begingroup % closed in \POL@getfromarray - \POL@getfromarray{#1}{#3}% - \POL@newpol{#1}% -}% -\def\POL@getfromarray#1#2{% - \count@=#2{0} %<- intentional space - \ifnum\count@=\z@ - \protected\def\POL@result{-1.\POL@empty{0/1[0]}}% 0.5 fix for empty array - \else - \xintloop - \edef\POL@tmp{#2{\count@}}% - \edef\POL@tmp{\xintRaw{\POL@tmp}}% -% sadly xinttools (current 1.3a) arrays have no setters for individual items... - \expandafter\let\csname POL@tmparray\the\count@\endcsname\POL@tmp - \if0\xintiiSgn{\POL@tmp}% - \advance\count@\m@ne - \repeat -% dans le cas particulier d'un array avec que des éléments nuls, \count@ est -% ici devenu 0 et la boucle s'est arrêtée car #2{0} était au moins 1. De plus -% \POL@tmparray1 est bien 0/1[0] donc ok pour polynôme nul dans \POL@result - \count\tw@\count@ - \xintloop -% on mouline tous les coeffs via \xintRaw - \ifnum\count@>\@ne - \advance\count@\m@ne - \edef\POL@tmp{#2{\count@}}% - \edef\POL@tmp{\xintRaw{\POL@tmp}}% - \expandafter\let\csname POL@tmparray\the\count@\endcsname\POL@tmp - \repeat - \count@\count\tw@ - \def\POL@tmp##1.{{\csname POL@tmparray##1\endcsname}}% - \protected\edef\POL@result{\the\numexpr\count@-\@ne.\POL@empty - \xintiloop[1+1]% - \expandafter\POL@tmp\xintiloopindex.% - \ifnum\xintiloopindex<\count@ - \repeat}% - \fi - \expandafter - \endgroup - \expandafter - \def\csname POLuserpol@#1\expandafter\endcsname - \expandafter{\POL@result}% -}% - - -\newcommand\PolFromCSV[2]{% - \begingroup % closed in \POL@getfromarray - \xintAssignArray\xintCSVtoList{#2}\to\POL@arrayA - \POL@getfromarray{#1}\POL@arrayA - \POL@newpol{#1}% -% semble un peu indirect et sous-optimal -% mais je veux élaguer les coefficients nuls. Peut-être à revoir. -}% - - -\newcommand\PolTypesetCmdPrefix[1]{\xintiiifSgn{#1}{}{+}{+}}% -\newcommand\PolTypesetCmd[1]{\xintifOne{\xintiiAbs{#1}}% - {\ifnum\PolIndex=\z@\xintiiSgn{#1}\else - \xintiiifSgn{#1}{-}{}{}\fi - \let\PolIfCoeffIsPlusOrMinusOne\@firstoftwo}% - {\PolTypesetOne{#1}% - \let\PolIfCoeffIsPlusOrMinusOne\@secondoftwo}% - }% -\newcommand\PolTypesetOne{\xintSignedFrac}% -\newcommand\PolTypesetMonomialCmd{% - \ifcase\PolIndex\space - % - \or\PolVar - \else\PolVar^{\PolIndex}% - \fi -}% -\newcommand\PolTypeset{\@ifstar - {\def\POL@ts@ascending{1}\POL@Typeset}% - {\def\POL@ts@ascending{0}\POL@Typeset}% -}% -\newcommand\POL@Typeset[2][x]{% LaTeX \newcommand forces optional argument first - \ensuremath{% - \expandafter\expandafter\expandafter\POL@split - \csname POLuserpol@#2\endcsname;\POL@var@deg\POL@var@coeffs - \if\POL@ts@ascending1% - \def\PolIndex{0}% - \let\POL@ts@reverse\@firstofone - \let\POL@@ne@or@m@ne\@ne - \else - \let\PolIndex\POL@var@deg - \ifnum\PolIndex<\z@\def\PolIndex{0}\fi - \let\POL@ts@reverse\xintRevWithBraces - \let\POL@@ne@or@m@ne\m@ne - \fi - \def\PolVar{#1}% - \ifnum\POL@var@deg<\z@ - \PolTypesetCmd{0/1[0]}\PolTypesetMonomialCmd - \else - \ifnum\POL@var@deg=\z@ - \expandafter\PolTypesetCmd\POL@var@coeffs\PolTypesetMonomialCmd - \else - \def\POL@ts@prefix##1{\let\POL@ts@prefix\PolTypesetCmdPrefix}% - \expandafter\POL@ts@loop - \romannumeral-`0\POL@ts@reverse{\POL@var@coeffs}\relax - \fi - \fi - }% -}% -\def\POL@ts@loop{\ifpoltypesetall\expandafter\xint_firstoftwo - \else\expandafter\xint_secondoftwo\fi - {\POL@ts@nocheck}{\POL@ts@check}.% -}% -\def\POL@ts@check.#1{% - \if\relax#1\expandafter\xint_gob_til_dot\fi - \xintiiifZero{#1}% - {}% - {\POL@ts@prefix{#1}\PolTypesetCmd{#1}\PolTypesetMonomialCmd}% - \edef\PolIndex{\the\numexpr\PolIndex+\POL@@ne@or@m@ne}\POL@ts@check.% -}% -\def\POL@ts@nocheck.#1{% - \if\relax#1\expandafter\xint_gob_til_dot\fi - \POL@ts@prefix{#1}\PolTypesetCmd{#1}\PolTypesetMonomialCmd - \edef\PolIndex{\the\numexpr\PolIndex+\POL@@ne@or@m@ne}\POL@ts@nocheck.% -}% - - -\newcommand\PolMapCoeffs[2]{% #1 = macro, #2 = name - \POL@mapcoeffs{#1}{#2}% - \POL@newpol{#2}% -}% -\def\POL@mapcoeffs#1#2{% - \begingroup - \def\POL@mapcoeffs@macro{#1}% - \expandafter\expandafter\expandafter\POL@split - \csname POLuserpol@#2\endcsname;\POL@mapcoeffs@deg\POL@mapcoeffs@coeffs -% ATTENTION à ne pas faire un \expandafter ici, car brace removal si 1 item - \xintAssignArray\POL@mapcoeffs@coeffs\to\POL@arrayA - \def\index{0}% - \count@\z@ - \expandafter\POL@map@loop\expandafter.\POL@mapcoeffs@coeffs\relax - \xintloop -% this abuses that \POL@arrayA0 is never 0. - \xintiiifZero{\csname POL@arrayA\the\count@\endcsname}% - {\iftrue}% - {\iffalse}% - \advance\count@\m@ne - \repeat -% donc en sortie \count@ est 0 ssi pol nul. - \POL@resultfromarray A% - \expandafter - \endgroup - \expandafter - \def\csname POLuserpol@#2\expandafter\endcsname\expandafter{\POL@result}% -}% -\def\POL@map@loop.#1{\if\relax#1\expandafter\xint_gob_til_dot\fi - \advance\count@\@ne - \edef\POL@map@coeff{\POL@mapcoeffs@macro{#1}}% - \expandafter - \let\csname POL@arrayA\the\count@\endcsname\POL@map@coeff - \edef\index{\the\numexpr\index+\@ne}% - \POL@map@loop.}% -\def\POL@xintIrr#1{\xintIrr{#1}[0]}% -\newcommand\PolReduceCoeffs{\@ifstar\POL@sreducecoeffs\POL@reducecoeffs}% -\def\POL@reducecoeffs#1{\PolMapCoeffs{\POL@xintIrr}{#1}}% -\def\POL@sreducecoeffs#1{\PolMapCoeffs{\xintPIrr}{#1}}% - - -%% EUCLIDEAN DIVISION -\newcommand\PolDivide[4]{% #3=quotient, #4=remainder of #1 by #2 - \POL@divide{#1}{#2}% - \expandafter\let\csname POLuserpol@#3\endcsname\POL@Q - \POL@newpol{#3}% - \expandafter\let\csname POLuserpol@#4\endcsname\POL@R - \POL@newpol{#4}% -}% -\newcommand\PolQuo[3]{% #3=quotient of #1 by #2 - \POL@divide{#1}{#2}% - \expandafter\let\csname POLuserpol@#3\endcsname\POL@Q - \POL@newpol{#3}% -}% -\newcommand\PolRem[3]{% #3=remainder of #1 by #2 - \POL@divide{#1}{#2}% - \expandafter\let\csname POLuserpol@#3\endcsname\POL@R - \POL@newpol{#3}% -}% -\newcommand\POL@divide[2]{% - \begingroup - \let\xintScalarSub\xintSub - \let\xintScalarAdd\xintAdd - \let\xintScalarMul\xintMul - \let\xintScalarDiv\xintDiv - \expandafter\let\expandafter\POL@A\csname POLuserpol@#1\endcsname - \expandafter\let\expandafter\POL@B\csname POLuserpol@#2\endcsname - \POL@div@c - \let\POL@Q\POL@result - \ifnum\POL@degQ<\z@ - \let\POL@R\POL@A - \else - \count@\numexpr\POL@degR+\@ne\relax - \POL@resultfromarray R% - \let\POL@R\POL@result - \fi - \expandafter - \endgroup - \expandafter - \def\csname POL@Q\expandafter\expandafter\expandafter\endcsname - \expandafter\expandafter\expandafter{\expandafter\POL@Q\expandafter}% - \expandafter - \def\csname POL@R\expandafter\endcsname\expandafter{\POL@R}% -}% - - -%% GCD -\newcommand\PolGCD[3]{% sets #3 to the (unitary) G.C.D. of #1 and #2 - \POL@GCD{#1}{#2}{#3}% - \POL@newpol{#3}% -}% -\def\POL@GCD #1#2#3{% - \begingroup - \let\xintScalarSub\xintSub - \let\xintScalarAdd\xintAdd - \let\xintScalarMul\xintMul - \let\xintScalarDiv\xintDiv - \expandafter\let\expandafter\POL@A\csname POLuserpol@#1\endcsname - \expandafter\let\expandafter\POL@B\csname POLuserpol@#2\endcsname - \expandafter\POL@split\POL@A;\POL@degA\POL@polA - \expandafter\POL@split\POL@B;\POL@degB\POL@polB - \ifnum\POL@degA<\z@ - \expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo - \fi - {\ifnum\POL@degB<\z@ - \expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo - \fi - {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}% - {\xintAssignArray\POL@polB\to\POL@arrayB - \POL@normalize{B}% - \POL@gcd@exit BA}}% - {\ifnum\POL@degB<\z@ - \expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo - \fi - {\xintAssignArray\POL@polA\to\POL@arrayA - \POL@normalize{A}% - \POL@gcd@exit AB}% - {\ifnum\POL@degA<\POL@degB\space - \let\POL@tmp\POL@B\let\POL@B\POL@A\let\POL@A\POL@tmp - \let\POL@tmp\POL@degB\let\POL@degB\POL@degA\let\POL@degA\POL@tmp - \let\POL@tmp\POL@polB\let\POL@polB\POL@polA\let\POL@polA\POL@tmp - \fi - \xintAssignArray\POL@polA\to\POL@arrayA - \xintAssignArray\POL@polB\to\POL@arrayB - \POL@gcd AB% - }}% - \expandafter - \endgroup - \expandafter\def\csname POLuserpol@#3\expandafter\endcsname - \expandafter{\POL@result}% -}% -\def\POL@normalize#1{% - \expandafter\def\expandafter\POL@tmp\expandafter - {\csname POL@array#1\csname POL@array#10\endcsname\endcsname}% - \edef\POL@normalize@leading{\POL@tmp}% - \expandafter\def\POL@tmp{1/1[0]}% - \count@\csname POL@deg#1\endcsname\space - \xintloop - \ifnum\count@>\z@ - \expandafter\edef\csname POL@array#1\the\count@\endcsname - {\xintIrr{\xintScalarDiv - {\csname POL@array#1\the\count@\endcsname}% - {\POL@normalize@leading}}[0]}% - \advance\count@\m@ne - \repeat -}% -\def\POL@gcd#1#2{% - \POL@normalize{#2}% - \edef\POL@degQ{\the\numexpr\csname POL@deg#1\endcsname - -\csname POL@deg#2\endcsname}% - \count@\numexpr\csname POL@deg#1\endcsname+\@ne\relax - \count\tw@\numexpr\POL@degQ+\@ne\relax - \xintloop - \POL@gcd@getremainder@loopbody#1#2% - \ifnum\count\tw@>\z@ - \repeat - \expandafter\def\csname POL@array#10\endcsname{1}% - \xintloop - \xintiiifZero{\csname POL@array#1\the\count@\endcsname}% - {\iftrue}% - {\iffalse}% - \advance\count@\m@ne - \repeat - \expandafter\edef\csname POL@deg#1\endcsname{\the\numexpr\count@-\@ne}% - \ifnum\count@<\@ne - \expandafter\POL@gcd@exit - \else - \expandafter\edef\csname POL@array#10\endcsname{\the\count@}% - \expandafter\POL@gcd - \fi{#2}{#1}% -}% -\def\POL@gcd@getremainder@loopbody#1#2{% - \edef\POL@gcd@ratio{\csname POL@array#1\the\count@\endcsname}% - \advance\count@\m@ne - \advance\count\tw@\m@ne - \count4 \count@ - \count6 \csname POL@deg#2\endcsname\space - \xintloop - \ifnum\count6>\z@ - \expandafter\edef\csname POL@array#1\the\count4\endcsname - {\xintScalarSub - {\csname POL@array#1\the\count4\endcsname}% - {\xintScalarMul - {\POL@gcd@ratio}% - {\csname POL@array#2\the\count6\endcsname}}}% - \advance\count4 \m@ne - \advance\count6 \m@ne - \repeat -}% -\def\POL@gcd@exit#1#2{% - \count@\numexpr\csname POL@deg#1\endcsname+\@ne\relax - \POL@resultfromarray #1% -}% - - -%% TODO: BEZOUT - - -%% DIFFERENTIATION -\def\POL@diff@loop@one #1/#2[#3]#4% - {\xintIrr{\xintiiMul{#4}{#1}/#2[0]}[#3]}% -\def\POL@diff#1{\POL@diff@loop1.}% -\def\POL@diff@loop#1.#2{% - \if\relax#2\expandafter\xint_gob_til_dot\fi - {\expandafter\POL@diff@loop@one\romannumeral0\xintraw{#2}{#1}}% - \expandafter\POL@diff@loop\the\numexpr#1+\@ne.% -}% -\newcommand\PolDiff[1][1]{% - % optional parameter is how many times to derivate - % first mandatory arg is name of polynomial function to derivate, - % same name as in \NewPolExpr - % second mandatory arg name of derivative - \edef\POL@iterindex{\the\numexpr#1\relax}% - \ifnum\POL@iterindex<\z@ - \expandafter\@firstoftwo - \else - \expandafter\@secondoftwo - \fi - {\PolAntiDiff[-\POL@iterindex]}{\POL@Diff}% -}% -\def\POL@Diff{% - \ifcase\POL@iterindex\space - \expandafter\POL@Diff@no - \or\expandafter\POL@Diff@one - \else\xint_afterfi{\POL@Iterate\POL@Diff@one}% - \fi -}% -\def\POL@Diff@no #1#2{\POL@let{#2}{#1}}% -\def\POL@Diff@one #1#2{\POL@Diff@@one {#1}{#2}\POL@newpol{#2}}% -\def\POL@Diff@@one#1#2{% - \expandafter\expandafter\expandafter\POL@split - \csname POLuserpol@#1\endcsname;\POL@var@deg\POL@var@coeffs - \ifnum\POL@var@deg<\@ne - \@namedef{POLuserpol@#2}{-1.\POL@empty{0/1[0]}}% - \else - \edef\POL@var@coeffs{\expandafter\POL@diff\POL@var@coeffs\relax}% - \expandafter\edef\csname POLuserpol@#2\endcsname - {\the\numexpr\POL@var@deg-\@ne.\POL@empty\POL@var@coeffs}% - \fi -}% -% lazy way but allows to share with AntiDiff -\def\POL@Iterate#1#2#3{% - \begingroup - \xintverbosefalse - #1{#2}{#3}% - \xintloop - \ifnum\POL@iterindex>\tw@ - #1{#3}{#3}% - \edef\POL@iterindex{\the\numexpr\POL@iterindex-\@ne}% - \repeat - \expandafter - \endgroup\expandafter - \def\csname POLuserpol@#3\expandafter\endcsname - \expandafter{\romannumeral`^^@\csname POLuserpol@#3\endcsname}% - #1{#3}{#3}% -}% - - -%% ANTI-DIFFERENTIATION -\def\POL@antidiff@loop@one #1/#2[#3]#4% - {\xintIrr{#1/\xintiiMul{#4}{#2}[0]}[#3]}% -\def\POL@antidiff{\POL@antidiff@loop1.}% -\def\POL@antidiff@loop#1.#2{% - \if\relax#2\expandafter\xint_gob_til_dot\fi - {\expandafter\POL@antidiff@loop@one\romannumeral0\xintraw{#2}{#1}}% - \expandafter\POL@antidiff@loop\the\numexpr#1+\@ne.% -}% -\newcommand\PolAntiDiff[1][1]{% - % optional parameter is how many times to derivate - % first mandatory arg is name of polynomial function to derivate, - % same name as in \NewPolExpr - % second mandatory arg name of derivative - \edef\POL@iterindex{\the\numexpr#1\relax}% - \ifnum\POL@iterindex<\z@ - \expandafter\@firstoftwo - \else - \expandafter\@secondoftwo - \fi - {\PolDiff[-\POL@iterindex]}{\POL@AntiDiff}% -}% -\def\POL@AntiDiff{% - \ifcase\POL@iterindex\space - \expandafter\POL@AntiDiff@no - \or\expandafter\POL@AntiDiff@one - \else\xint_afterfi{\POL@Iterate\POL@AntiDiff@one}% - \fi -}% -\let\POL@AntiDiff@no\POL@Diff@no -\def\POL@AntiDiff@one #1#2{\POL@AntiDiff@@one{#1}{#2}\POL@newpol{#2}}% -\def\POL@AntiDiff@@one#1#2{% - \expandafter\expandafter\expandafter\POL@split - \csname POLuserpol@#1\endcsname;\POL@var@deg\POL@var@coeffs - \ifnum\POL@var@deg<\z@ - \@namedef{POLuserpol@#2}{-1.\POL@empty{0/1[0]}}% - \else - \edef\POL@var@coeffs{\expandafter\POL@antidiff\POL@var@coeffs\relax}% - \expandafter\edef\csname POLuserpol@#2\endcsname - {\the\numexpr\POL@var@deg+\@ne.\POL@empty{0/1[0]}\POL@var@coeffs}% - \fi -}% - -%% IContent and \PolMakePrimitive (0.5) -\def\POL@aux@mgcd@loop#1#2{% - \if\relax#2\expandafter\POL@aux@mgcd@exit\fi - \expandafter - \POL@aux@mgcd@loop\romannumeral0\POL@aux@gcd#1.#2.% -}% -\def\POL@aux@mgcd@exit - \expandafter - \POL@aux@mgcd@loop\romannumeral0\POL@aux@gcd#1.\relax.{\xintiiabs{#1}}% -\def\POL@aux@gcd#1.#2.{% - \if0\xintiiSgn{#1}\expandafter\POL@aux@gcd@exit\fi - \expandafter\POL@aux@gcd\romannumeral0\xintmod {#2}{#1}.#1.}% -\def\POL@aux@gcd@exit - \expandafter\POL@aux@gcd\romannumeral0\xintmod #1#2.#3.{{#1}}% - -\def\POL@icontent #1{\romannumeral0\expandafter - \POL@aux@mgcd@loop\romannumeral`^^@#1\relax}% - -\newcommand\PolIContent[1]{\romannumeral0\expandafter - \POL@aux@mgcd@loop\romannumeral`^^@\PolToList{#1}\relax}% - - -\def\POL@makeprim@macro#1% - {\xintREZ{\xintNum{\xintDiv{#1}{\POL@makeprim@icontent}}}}% -\newcommand\PolMakePrimitive[1]{% - % This does not need a full user declared polynomial on input, only - % a \POLuserpol@name macro, but on output it is fully declared - \edef\POL@makeprim@icontent{\PolIContent{#1}}% - \PolMapCoeffs\POL@makeprim@macro{#1}% -}% -\def\POL@makeprimitive#1{% - % Avoids declaring the polynomial, internal usage in \PolToSturm - \edef\POL@makeprim@icontent{\PolIContent{#1}}% - \POL@mapcoeffs\POL@makeprim@macro{#1}% -}% - - -%% Sturm Algorithm (polexpr 0.4) -%% 0.5 uses primitive polynomials for faster evaluations afterwards -%% 0.6 corrects misuse of \@ifstar! (mumble). \PolToSturm* was broken. -%% 0.6's \PolToSturm* defines both normalized and unnormalized, the -%% unnormalized using two underscores, so both are available -%% Sole difference is that \PolToSturm* also declares them as -%% user polynomials, whereas the non-starred only keeps the macros -%% holding the coefficients in memory -%% 0.6 fixes the case of a constant polynomial P which caused division -%% by zero error from P'. -\newcommand\PolToSturm{\@ifstar{\PolToSturm@@}{\PolToSturm@}}% -\def\POL@aux@toint#1{\xintREZ{\xintNum{#1}}}% for polynomials with int. coeffs! -%% Attention that some macros rely upon this one setting \POL@sturmname -%% and \POL@sturm@N as it does -\def\PolToSturm@#1#2{% - \edef\POL@sturmname{#2}% - % 0.6 uses 2 underscores (one before index, one after) to keep in memory - % the unnormalized chain - % This supposes #1 to be a genuine polynomial, not only a name with - % a \POLuserpol@#1 macro - \POL@let{\POL@sturmname _0_}{#1}% - \ifnum\PolDegree{#1}=\z@ - \def\POL@sturm@N{0}% - \POL@count\z@ - % if I applied the same as for positive degree, I should make it -1 - % if constant is negative. I also don't worry if polynomial is zero. - \@namedef{POLuserpol@\POL@sturmname _0}{0.\POL@empty{1/1[0]}}% - \else - \ifPOL@tosturm@makefirstprimitive\POL@makeprimitive{\POL@sturmname _0_}\fi - \POL@tosturm@dosturm - \fi - \expandafter - \let\csname PolSturmChainLength_\POL@sturmname\endcsname\POL@sturm@N - % declare the normalized ones as full-fledged polynomials - % \POL@count\z@ - \xintloop - \POL@newpol{\POL@sturmname _\the\POL@count}% - \unless\ifnum\POL@sturm@N=\POL@count - \advance\POL@count\@ne - \repeat -}% -\def\PolToSturm@@#1#2{\PolToSturm@{#1}{#2}\POL@tosturm@declareunnormalized}% -\def\POL@tosturm@declareunnormalized{% - % optionally declare also the unnormalized ones - \POL@count\z@ - \xintloop - \POL@newpol{\POL@sturmname _\the\POL@count _}% - \unless\ifnum\POL@sturm@N=\POL@count - \advance\POL@count\@ne - \repeat -}% -\def\POL@tosturm@dosturm{% - \POL@Diff@@one{\POL@sturmname _0_}{\POL@sturmname _1_}% - % re-utiliser \POL@varcoeffs directement? - \POL@makeprimitive{\POL@sturmname _1_}% does not do \POL@newpol - \POL@count\@ne - \xintloop - \POL@divide{\POL@sturmname _\the\numexpr\POL@count-\@ne\relax _}% - {\POL@sturmname _\the\POL@count _}% - \expandafter\POL@split\POL@R;\POL@degR\POL@polR - \unless\ifnum\POL@degR=\m@ne - \advance\POL@count\@ne - \expandafter\let - \csname POLuserpol@\POL@sturmname _\the\POL@count _\endcsname\POL@R - \edef\POL@makeprim@icontent{-\POL@icontent\POL@polR}% - % this avoids the \POL@newpol from \PolMapCoeffs - \POL@mapcoeffs\POL@makeprim@macro{\POL@sturmname _\the\POL@count _}% - \repeat - \edef\POL@sturm@N{\the\POL@count}% - % normalize (now always done even by starred variant) - \ifnum\PolDegree{\POL@sturmname _\POL@sturm@N _}>\z@ - % \POL@count\POL@sturm@N\relax - \xintloop - \advance\POL@count\m@ne - \POL@divide{\POL@sturmname _\the\POL@count _}% - {\POL@sturmname _\POL@sturm@N _}% - \expandafter - \let\csname POLuserpol@\POL@sturmname _\the\POL@count\endcsname\POL@Q - % quotient actually belongs to Z[X] and is primitive - \POL@mapcoeffs\POL@aux@toint{\POL@sturmname _\the\POL@count}% - \ifnum\POL@count>\z@ - \repeat - \@namedef{POLuserpol@\POL@sturmname _\POL@sturm@N}{0.\POL@empty{1/1[0]}}% - \else % they are already normalized - \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 - \csname POLuserpol@\POL@sturmname _\the\POL@count _\endcsname - \ifnum\POL@count>\z@ - \repeat - \fi - % Back to \PolToSturm@, \POL@count holds 0 -}% -\newcommand\PolSturmChainLength[1] - {\romannumeral`^^@\csname PolSturmChainLength_#1\endcsname}% - -\newcommand\PolSetToSturmChainSignChangesAt[4][\global]{% - \edef\POL@sturmchain@X{\xintREZ{#4}}% - \edef\POL@sturmname{#3}% - \edef\POL@sturmlength{\PolSturmChainLength{\POL@sturmname}}% - \POL@sturmchain@getSV@at\POL@sturmchain@X - #1\let#2\POL@sturmchain@SV -}% -\def\POL@sturmchain@getSV@at#1{% ATTENTION USES \POL@count - \def\POL@sturmchain@SV{0}% - \edef\POL@sturmchain@sign{\xintiiSgn{\POL@eval{\POL@sturmname _0}{#1}}}% - \let\POL@isolz@lastsign\POL@sturmchain@sign - \POL@count \z@ - \ifnum\POL@isolz@lastsign=\z@ - \edef\POL@isolz@lastsign - {\xintiiSgn{\POL@eval{\POL@sturmname _1}{#1}}}% - \POL@count \@ne - \fi - \xintloop - \unless\ifnum\POL@sturmlength=\POL@count - \advance\POL@count \@ne - \edef\POL@isolz@newsign - {\xintiiSgn{\POL@eval{\POL@sturmname _\the\POL@count}{#1}}}% - \ifnum\POL@isolz@newsign=\numexpr-\POL@isolz@lastsign\relax - \edef\POL@sturmchain@SV{\the\numexpr\POL@sturmchain@SV+\@ne}% - \let\POL@isolz@lastsign=\POL@isolz@newsign - \fi - \repeat -}% -\newcommand\PolSetToNbOfZerosWithin[5][\global]{% - \edef\POL@tmpA{\xintREZ{#4}}% - \edef\POL@tmpB{\xintREZ{#5}}% - \edef\POL@sturmname{#3}% - \edef\POL@sturmlength{\PolSturmChainLength{\POL@sturmname}}% - \POL@sturmchain@getSV@at\POL@tmpA - \let\POL@SVA\POL@sturmchain@SV - \POL@sturmchain@getSV@at\POL@tmpB - \let\POL@SVB\POL@sturmchain@SV - \ifnum\POL@SVA<\POL@SVB\space - #1\edef#2{\the\numexpr\POL@SVB-\POL@SVA}% - \else - #1\edef#2{\the\numexpr\POL@SVA-\POL@SVB}% - \fi -}% - - -% 0.6 added starred variant to count multiplicities -% 0.7 added double starred variant to locate all rational roots -\newcommand\PolSturmIsolateZeros{\@ifstar - {\PolSturmIsolateZerosAndGetMultiplicities}% - {\PolSturmIsolateZeros@}% -}% -\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_ZM\POL@sturmname*\endcsname - \expandafter\xintAssignArray\expandafter\to\csname POL_RI\POL@sturmname*\endcsname - \endgroup - \else - % all we currently know is that multiplicities are at least one - \begingroup\globaldefs\@ne - \expandafter\POL@initarray\csname POL_ZM\POL@sturmname*\endcsname{1}% - \endgroup - % on ne va pas utiliser de Horner, mais des divisions par X - x, et ces - % choses vont évoluer, ainsi que le coefficient dominant entier - % (pour \POL@divide entre autres if faut des noms de user pol) - \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}}% -% ATTENTION QUE LA CONVENTION DE SIGNE POUR \POL@findrat@E EST OPPOSÉE À CELLE -% POUR LE CODE PLUS ANCIEN FAISANT "REFINE" - \POL@initarray\POL@IfMultIsKnown\xint_secondoftwo - \let\POL@findrat@nbofirrroots\POL@isolz@NbOfRoots - % find all rational roots, and their multiplicities, - % factor them out in passing from original (Sturm root) polynomial - \ifnum\POL@findrat@E<7 - \def\POL@findrat@index{1}% - \POL@findrat@loop@secondpass@direct - \else - % we do a first pass scanning for "small" roots p/q (i.e. q < 1000) - \def\POL@findrat@index{1}% - \POL@findrat@loop@firstpass - % and now we do the final pass finding them all - \def\POL@findrat@index{1}% - \POL@findrat@loop@secondpass - \fi - % declare the new polynomials - \POL@newpol{\POL@sturmname\POL@sqfnorr}% without multiplicities - \POL@newpol{\POL@sturmname\POL@norr}% with multiplicities - % declare the array holding the interval indices for the rational roots - \expandafter\POL@findrat@doRRarray\csname POL_RI\POL@sturmname*\endcsname - \fi -}% -\def\POL@findrat@doRRarray#1{% - % il faudrait un \xintAssignArray* qui fasse même expansion que \xintFor* - \edef\POL@temp{% - \xintiloop[1+1] - \romannumeral0\csname POL_ZK\POL@sturmname*\xintiloopindex\endcsname - \xintbracediloopindex % I should have named it \xintiloopbracedindex... - {}% - \ifnum\xintiloopindex<\POL@isolz@NbOfRoots\space - \repeat }% - \begingroup\globaldefs\@ne - % attention de ne surtout pas faire un \expandafter ici, car en cas d'un - % seul item, \xintAssignArray l'unbraces... - \xintAssignArray\POL@temp\to#1% - \endgroup -}% -\def\POL@findrat@loop@firstpass{% - \PolSturmIfZeroExactlyKnown{\POL@sturmname}{\POL@findrat@index}% - \POL@findrat@loop@decimal% get its multiplicity - \POL@findrat@loop@aa % refine interval and check - \edef\POL@findrat@index{\the\numexpr\POL@findrat@index+\@ne}% - \ifnum\POL@findrat@index>\POL@isolz@NbOfRoots - \else - \expandafter\POL@findrat@loop@firstpass - \fi -}% -\def\POL@findrat@loop@aa{% - % we do a first pass to identify roots with denominators < 1000 - \PolEnsureIntervalLength{\POL@sturmname}{\POL@findrat@index}{-6}% - % attention that perhaps now the root is known! - \PolSturmIfZeroExactlyKnown{\POL@sturmname}{\POL@findrat@index}% - \POL@findrat@loop@decimal - \POL@findrat@loop@a -}% -\def\POL@findrat@loop@decimal{% we have an already found decimal root - % we do not go via @storeit, as it is already stored - % j'ai beaucoup hésité néanmoins, car je pourrais faire \xintIrr ici, - % mais attention aussi à l'interaction avec le \PolDecToString. Les racines - % trouvées directement (qui peuvent être des nombres décimaux) sont elles - % stockées comme fraction irréductibles (modulo action additionnelle de - % \PolDecToString). - \POL@xintfrac@getNDE - {\xintIrr{\POL@xintexprGetVar{\POL@sturmname L_\POL@findrat@index}}[0]}% - \POL@findrat@xN\POL@findrat@xD\POl@_ - % we can't move this to updatequotients because other branch will - % need to do the division first anyhow - \edef\POLuserpol@_findrat@oneterm{1.\POL@empty - {\xintiiOpp\POL@findrat@xN/1[0]}{\POL@findrat@xD/1[0]}}% - \POL@divide{\POL@sturmname\POL@sqfnorr}{_findrat@oneterm}% the one without mult. - %\expandafter\POL@split\POL@R;\POL@degR\POL@polR - \POL@findrat@loop@updatequotients - \POL@findrat@loop@getmultiplicity -}% -% lacking from xint 1.3c, but \xintSgn has overhead, so we define ii version -\def\xintiiifNeg{\romannumeral0\xintiiifneg }% -\def\xintiiifneg #1% -{% - \ifcase \xintiiSgn{#1} - \expandafter\xint_stop_atsecondoftwo - \or\expandafter\xint_stop_atsecondoftwo - \else\expandafter\xint_stop_atfirstoftwo - \fi -}% -\def\POL@findrat@getE #1/1[#2]{#2}% /1 as it should be there. -% so an error will arise if not but cf \POL@refine@getE where I did not put it -\def\POL@findrat@loop@a{% - % attention that the width may have been already smaller than 10^{-6} - \POL@get@IsoLeft@rawin - \POL@get@IsoRight@rawin - \edef\POL@findrat@localW - {\the\numexpr-\expandafter\POL@findrat@getE - % do I really need the \xintREZ? - \romannumeral0\xintrez - {\xintSub{\POL@IsoRight@rawin}{\POL@IsoLeft@rawin}}% - }% at least 6, maybe larger - \expandafter\POL@get@Int@aux - \POL@IsoLeft@rawin\POL@IsoLeft@Int{-\POL@findrat@localW}% - \expandafter\POL@get@Int@aux - \POL@IsoRight@rawin\POL@IsoRight@Int{-\POL@findrat@localW}% - % in case of odd, some waste here - \edef\POL@findrat@halflocalW{\the\numexpr(\POL@findrat@localW+1)/2-1}% - % Legendre Theorem will be used now but we separate a branch where - % everything can be done with \numexpr - \ifnum\POL@findrat@localW>9 - % not implemented yet by lazyness! - % this root will be handled in second pass only - \else - \POL@findrat@gcdloop - \fi -}% -\def\POL@findrat@gcdloop{% - % we must be careful with sign - % but we are certain no extremity is a root - \let\POL@findrat@ifnegative\xint_secondoftwo - \xintiiifSgn\POL@IsoLeft@Int - \POL@findrat@gcdloop@n - \POL@error@thisisimpossible - \POL@findrat@gcdloop@p -}% -\def\POL@findrat@gcdloop@n{% - \let\POL@findrat@ifnegative\xint_firstoftwo - \let\POL@temp\POL@IsoRight@Int - \edef\POL@IsoRight@Int{\xintiiOpp{\POL@IsoLeft@Int}}% - \edef\POL@IsoLeft@Int{\xintiiOpp{\POL@temp}}% - \POL@findrat@gcdloop@p -}% -\def\POL@findrat@gcdloop@p{% - \edef\POL@findrat@gcdloop@Ap{\xintDec{\xintDouble\POL@IsoRight@Int}}% - \edef\POL@findrat@gcdloop@A - % at most 2e9: this is acceptable to \numexpr - {2\romannumeral\xintreplicate\POL@findrat@localW{0}}% - \xintAssign - \xintiiDivision\POL@findrat@gcdloop@Ap\POL@findrat@gcdloop@A - \to\POL@findrat@gcdloop@B\POL@findrat@gcdloop@An - % on fait de la tambouille pour n'utiliser que \numexpr par la suite - % le reste @An est < 2.10^9 au pire donc ok pour \numexpr - % we will drop integral part in our updating P - \let\POL@findrat@gcdloop@Binitial\POL@findrat@gcdloop@B - \def\POL@findrat@gcdloop@B{0}% do as if B1 = 0 - \def\POL@findrat@gcdloop@Pp{1}% P0 - \def\POL@findrat@gcdloop@P{0}% P1 - \def\POL@findrat@gcdloop@Qp{0}% Q0 - \def\POL@findrat@gcdloop@Q{1}% Q1 - % A2=An can not be zero, as Ap (=A0) is odd and A (=A1=200...000) is even - % first Binitial + P1/Q1 ( = Binitial) can not be root - \let\POL@findrat@gcdloop@Ap\POL@findrat@gcdloop@A % A1 - \let\POL@findrat@gcdloop@A\POL@findrat@gcdloop@An % A2 - \def\next{\POL@findrat@gcdloop@update}% - \def\POL@findrat@gcdloop@done{0}% - \POL@findrat@gcdloop@body -}% -\def\POL@findrat@gcdloop@body{% - % annoying that \numexpr has no divmod... use counts? but groups annoying - \edef\POL@findrat@gcdloop@B - {\the\numexpr(\POL@findrat@gcdloop@Ap+\POL@findrat@gcdloop@A/2)/% - \POL@findrat@gcdloop@A - \@ne}% - \edef\POL@findrat@gcdloop@An - {\the\numexpr\POL@findrat@gcdloop@Ap-% - \POL@findrat@gcdloop@B*\POL@findrat@gcdloop@A}% - \edef\POL@findrat@gcdloop@Pn - {\the\numexpr\POL@findrat@gcdloop@Pp+% - \POL@findrat@gcdloop@B*\POL@findrat@gcdloop@P}% - \edef\POL@findrat@gcdloop@Qn - {\the\numexpr\POL@findrat@gcdloop@Qp+% - \POL@findrat@gcdloop@B*\POL@findrat@gcdloop@Q}% - \ifnum\expandafter\xintLength\expandafter{\POL@findrat@gcdloop@Qn}% - >\POL@findrat@halflocalW\space - \let\next\empty % no solution was found - \else - % with these conditions on denom, only candidates are by Legendre - % theorem among the convergents as computed here - \ifnum\POL@findrat@gcdloop@Qn>\POL@findrat@gcdloop@An\space - % means that P/Q is in interval and is thus a candidate - % it is automatically irreducible - \edef\POL@findrat@x{\xintiiAdd - {\xintiiMul{\POL@findrat@gcdloop@Qn}{\POL@findrat@gcdloop@Binitial}}% - {\POL@findrat@gcdloop@Pn}/\POL@findrat@gcdloop@Qn[0]}% - \POL@findrat@gcdloop@testit - \if1\POL@findrat@gcdloop@done - \let\next\empty % a solution was found - \fi - \fi - \fi - \next -}% -\def\POL@findrat@gcdloop@update{% - \ifnum\POL@findrat@gcdloop@An>\z@ - \let\POL@findrat@gcdloop@Ap\POL@findrat@gcdloop@A - \let\POL@findrat@gcdloop@A\POL@findrat@gcdloop@An - \let\POL@findrat@gcdloop@Pp\POL@findrat@gcdloop@P - \let\POL@findrat@gcdloop@P\POL@findrat@gcdloop@Pn - \let\POL@findrat@gcdloop@Qp\POL@findrat@gcdloop@Q - \let\POL@findrat@gcdloop@Q\POL@findrat@gcdloop@Qn - \expandafter\POL@findrat@gcdloop@body - \fi -}% -\def\POL@findrat@gcdloop@testit{% - % zero should never occur here - \POL@findrat@ifnegative{\edef\POL@findrat@x{-\POL@findrat@x}}{}% - \POL@xintfrac@getNDE\POL@findrat@x\POL@findrat@xN\POL@findrat@xD\POL@_ - \edef\POLuserpol@_findrat@oneterm{1.\POL@empty - {\xintiiOpp{\POL@findrat@xN}/1[0]}{\POL@findrat@xD/1[0]}}% - \POL@divide{\POL@sturmname\POL@sqfnorr}{_findrat@oneterm}% the one without mult. - \expandafter\POL@split\POL@R;\POL@degR\POL@polR - \ifnum\POL@degR=\m@ne % found a root - \POL@findrat@loop@storeit - \POL@findrat@loop@updatequotients - \POL@findrat@loop@getmultiplicity % will continue updating the mult. one - \def\POL@findrat@gcdloop@done{1}% - \fi -}% -% This is second phase -\def\POL@findrat@loop@secondpass{% - \PolSturmIfZeroExactlyKnown{\POL@sturmname}{\POL@findrat@index}% - {}% nothing more to be done, already stored - \POL@findrat@loop@bb % refine interval and check - \edef\POL@findrat@index{\the\numexpr\POL@findrat@index+\@ne}% - \ifnum\POL@findrat@index>\POL@isolz@NbOfRoots - \else - \expandafter\POL@findrat@loop@secondpass - \fi -}% -\def\POL@findrat@loop@secondpass@direct{% - \PolSturmIfZeroExactlyKnown{\POL@sturmname}{\POL@findrat@index}% - \POL@findrat@loop@decimal - \POL@findrat@loop@bb - \edef\POL@findrat@index{\the\numexpr\POL@findrat@index+\@ne}% - \ifnum\POL@findrat@index>\POL@isolz@NbOfRoots - \else - \expandafter\POL@findrat@loop@secondpass@direct - \fi -}% -\def\POL@findrat@loop@bb{% - \PolEnsureIntervalLength{\POL@sturmname}{\POL@findrat@index}{-\POL@findrat@E}% - % ATTENTION THAT PERHAPS NOW THE ROOT IS KNOWN! - \PolSturmIfZeroExactlyKnown{\POL@sturmname}{\POL@findrat@index}% - \POL@findrat@loop@decimal - \POL@findrat@loop@b -}% -\def\POL@findrat@loop@b{% - \edef\POL@findrat@Lscaled{\xintMul{\POL@findrat@D}% - {\POL@xintexprGetVar{\POL@sturmname L_\POL@findrat@index}}}% - \edef\POL@findrat@Rscaled{\xintMul{\POL@findrat@D}% - {\POL@xintexprGetVar{\POL@sturmname R_\POL@findrat@index}}}% - \xintiiifNeg{\POL@findrat@Lscaled}% using ii version is an abuse - {% negative interval (right bound possibly zero!) - % truncate towards zero (i.e. to the right) the left bound - \edef\POL@findrat@Num{\xintNum{\POL@findrat@Lscaled}/1[0]}% - % interval boundaries are not root hence in case that was exact - % this will not be found as a root; check if in interval - \xintifLt\POL@findrat@Num\POL@findrat@Rscaled - \POL@findrat@loop@c - {}% iterate - }% - {% positive interval (left bound possibly zero!) - % truncate towards zero (i.e. to the left) the right bound - \edef\POL@findrat@Num{\xintNum{\POL@findrat@Rscaled}/1[0]}% - % check if in interval - \xintifGt\POL@findrat@Num\POL@findrat@Lscaled - \POL@findrat@loop@c - {}% iterate - }% -}% -\def\POL@findrat@loop@c{% - % safer to do the edef as \POL@findrat@x used later in storeit - \edef\POL@findrat@x{\xintIrr{\xintDiv\POL@findrat@Num\POL@findrat@D}[0]}% - \POL@xintfrac@getNDE\POL@findrat@x\POL@findrat@xN\POL@findrat@xD\POL@_ - \edef\POLuserpol@_findrat@oneterm{1.\POL@empty - {\xintiiOpp{\POL@findrat@xN}/1[0]}{\POL@findrat@xD/1[0]}}% - \POL@divide{\POL@sturmname\POL@sqfnorr}{_findrat@oneterm}% the one without mult. - \expandafter\POL@split\POL@R;\POL@degR\POL@polR - \ifnum\POL@degR=\m@ne % found a root - \POL@findrat@loop@storeit - \POL@findrat@loop@updatequotients - \POL@findrat@loop@getmultiplicity % will continue updating the mult. one - \fi - % iterate -}% -\def\POL@findrat@loop@storeit{% - % update storage, I can not use storeleftandright here (due to rawout etc...) - \expandafter - \xdef\csname POL_ZL\POL@sturmname*\POL@findrat@index\endcsname - {\PolDecToString{\POL@findrat@x}}% - \global\expandafter - \let\csname POL_ZR\POL@sturmname*\POL@findrat@index\expandafter\endcsname - \csname POL_ZL\POL@sturmname*\POL@findrat@index\endcsname - \global\expandafter - \let\csname POL_ZK\POL@sturmname*\POL@findrat@index\endcsname - \xint_stop_atfirstoftwo - \begingroup\xintglobaldefstrue - % skip some overhead of \xintdefvar... - \XINT_expr_defvar_one{\POL@sturmname L_\POL@findrat@index}% - {\POL@findrat@x}% - \XINT_expr_defvar_one{\POL@sturmname R_\POL@findrat@index}% - {\POL@findrat@x}% - \XINT_expr_defvar_one{\POL@sturmname Z_\POL@findrat@index _isknown}% - {1}% - \endgroup -}% -\def\POL@findrat@loop@updatequotients{% - % attention last division must have been one testing vanishing of\POL@sqfnorr - \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_ZM\POL@sturmname*\POL@findrat@index\endcsname - {\the\numexpr - \csname POL_ZM\POL@sturmname*\POL@findrat@index\endcsname+\@ne}% - \expandafter\POL@findrat@loop@getmultiplicity - \else - % done with multiplicity for this rational root, update stuff - \edef\POL@findrat@nbofirrroots - {\the\numexpr\POL@findrat@nbofirrroots-\@ne}% - \@namedef{POL@IfMultIsKnown\POL@findrat@index}{\xint_firstoftwo}% - \edef\POL@findrat@D{\xintAbs{\PolLeadingCoeff{\POL@sturmname\POL@sqfnorr}}}% - \POL@xintfrac@getNDE\POL@findrat@D\POL@findrat@Dint\POL@_\POL@findrat@Dexp - \xintiiifOne{\POL@findrat@Dint} - {\let\POL@findrat@E\POL@findrat@Dexp} % aussi ok pour 1[0] - {\edef\POL@findrat@E{\the\numexpr\xintLen{\POL@findrat@Dint}% - +\POL@findrat@Dexp}}% - \fi -}% -\def\POL@findrat@getirrmult{% - % first get the GCD of remaining pol with its derivative - \POL@divide{\POL@sturmname\POL@norr}{\POL@sturmname\POL@sqfnorr}% - \expandafter\let - % attention au _ (cf. grosse astuce pour \POL@isolzmult@loop) - \csname POLuserpol@@_1\POL@sturmname _\endcsname\POL@Q - \ifnum\PolDegree{@_1\POL@sturmname _}>\z@ - % il reste des multiplicités (mais peut-être pour des racines complexes) - % (ou pour des racines en-dehors de l'intervalle optionnel) - % attention recyclage ici de \POL@isolzmult@loop qui dépend de - % la grosse astuce avec \@gobble - \POL@makeprimitive{@_1\POL@sturmname _}% - \let\POL@originalsturmname\POL@sturmname - % trick to get isolzmult@loop to define @@lastGCD to @_1sturmname_ - % because it will do \POL@sturmname _\POL@sturm@N _ - \edef\POL@sturmname{@_1\POL@sturmname}% - \let\POL@sturm@N\@gobble% ! - \let\POL@isolz@NbOfRoots@with_unknown_mult\POL@findrat@nbofirrroots - \POL@tosturm@makefirstprimitivefalse - \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) - \edef\POL@sturmname{#2}% - \edef\POL@sturm@N{\@nameuse{PolSturmChainLength_\POL@sturmname}}% - % isolate the roots (detects case of constant polynomial) - \PolSturmIsolateZeros@{\POL@sturmname}% - \ifnum\POL@isolz@NbOfRoots=\z@ - % no roots, define empty array nevertheless - \begingroup\globaldefs\@ne - \expandafter\xintAssignArray\expandafter\to\csname POL_ZM\POL@sturmname*\endcsname - \endgroup - \else - % all we currently know is that multiplicities are at least one - \begingroup\globaldefs\@ne - \expandafter\POL@initarray\csname POL_ZM\POL@sturmname*\endcsname{1}% - \endgroup - % check if GCD had positive degree (hence some roots, maybe complex, have - % multiplicity) - \ifnum\PolDegree{\POL@sturmname _\POL@sturm@N _}>\z@ - % scratch array of flags to signal known multiplicities - \POL@initarray\POL@IfMultIsKnown\xint_secondoftwo - % this count has utility for the case there are other roots - % either complex or outside interval (in case of optional argument) - \let\POL@isolz@NbOfRoots@with_unknown_mult\POL@isolz@NbOfRoots - % store Sturm chain name, it is needed and altered in isolzmult@loop - \let\POL@originalsturmname\POL@sturmname - \POL@tosturm@makefirstprimitivefalse - \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 - % skip some overhead of \xintdefvar... - \XINT_expr_defvar_one{\POL@sturmname M_\x}% - {\csname POL_ZM\POL@sturmname*\x\endcsname}% - \edef\x{\the\numexpr\x-\@ne}% - \ifnum\x>\z@ - \repeat - \endgroup -}% -\def\POL@isolzmult@loop{% - % we are here only if last iteration gave a new GCD still of degree > 0 - % \POL@sturm@N is the one from last iteration - % Attention to not use \POL@sturmname directly in first arg. of \PolToSturm - % Attention that we need for the case of known roots also to have the last - % GCD (with its multiplicities) known as a genuine polynomial - % - because of usage of \POL@eval in @isknown branch - % - because \PolToSturm@ does a \POL@let which would be anomalous - % if the extended structure is not existing - \edef\POL@isolzmult@lastGCD{\POL@sturmname _\POL@sturm@N _}% - \edef\POL@isolzmult@newsturmname{@_1\POL@sturmname}% - \POL@newpol{\POL@isolzmult@lastGCD}% - \PolToSturm@{\POL@isolzmult@lastGCD}{\POL@isolzmult@newsturmname}% - % now both \POL@sturmname and \POL@sturm@N have changed - \edef\POL@isolzmult@newGCDdegree{\PolDegree{\POL@sturmname _\POL@sturm@N _}}% - \let\POL@isolzmult@index\POL@isolz@NbOfRoots - \xintloop - % ATTENTION that this executes macros which also modifies \POL@sturmname! - % (but not \POL@sturm@N) - \POL@isolzmult@doone - \edef\POL@isolzmult@index{\the\numexpr\POL@isolzmult@index-\@ne}% - \if1\ifnum\POL@isolz@NbOfRoots@with_unknown_mult=\z@ 0\fi - \ifnum\POL@isolzmult@index=\z@ 0\fi 1% - \repeat - \let\POL@sturmname\POL@isolzmult@newsturmname - \if1\ifnum\POL@isolz@NbOfRoots@with_unknown_mult=\z@ 0\fi - % (if new GCD is constant, time to abort) - \ifnum\POL@isolzmult@newGCDdegree=\z@ 0\fi 1% - \expandafter\POL@isolzmult@loop - \fi -}% -\def\POL@isolzmult@doone{% - \csname POL@IfMultIsKnown\POL@isolzmult@index\endcsname - {}% nothing to do - {\POL@SturmIfZeroExactlyKnown{\POL@originalsturmname}% - {\POL@isolzmult@index}% - \POL@isolzmult@loop@isknown - \POL@isolzmult@loop@isnotknown - \POL@isolzmult@loop@sharedbody - }% -}% -\def\POL@isolzmult@loop@isknown{% - \xintifZero - % attention that \POL@eval requires a declared polynomial - {\POL@eval{\POL@isolzmult@lastGCD}% - {\POL@xintexprGetVar{\POL@originalsturmname L_\POL@isolzmult@index}}}% - {\let\POL@isolzmult@haszero\@ne}% - {\let\POL@isolzmult@haszero\z@}% -}% -\def\POL@isolzmult@loop@isnotknown{% - \edef\POL@isolzmult@loop@A - {\POL@xintexprGetVar{\POL@originalsturmname L_\POL@isolzmult@index}} - \edef\POL@isolzmult@loop@B - {\POL@xintexprGetVar{\POL@originalsturmname - R_\POL@isolzmult@index}} - % attention that \PolSetToNbOfZerosWithin sets \POL@sturmname to 2nd argument - \PolSetToNbOfZerosWithin - \POL@isolzmult@haszero % nb of zeros A < x <= B, here 0 or 1 - \POL@isolzmult@newsturmname - \POL@isolzmult@loop@A - \POL@isolzmult@loop@B -}% -\def\POL@isolzmult@loop@sharedbody{% - \ifnum\POL@isolzmult@haszero>\z@ - \expandafter - \xdef - \csname POL_ZM\POL@originalsturmname*\POL@isolzmult@index\endcsname - {\the\numexpr - \csname POL_ZM\POL@originalsturmname - *\POL@isolzmult@index\endcsname+\@ne}% - \else - % multiplicity now known, no need to check this index in future - \@namedef{POL@IfMultIsKnown\POL@isolzmult@index}{\xint_firstoftwo}% - \edef\POL@isolz@NbOfRoots@with_unknown_mult - {\the\numexpr\POL@isolz@NbOfRoots@with_unknown_mult-\@ne}% - \fi -}% - - -\newcommand\PolSturmIsolateZeros@[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 from a given polynomial) - % For reasons I have forgotten (no time now) this code **must** be used - % with a *normalized* Sturm chain. - \edef\POL@sturmname{#2}% - \edef\POL@sturmlength{\PolSturmChainLength{#2}}% - % attention to constant polynomial, we must redefine the arrays then - \ifnum\POL@sturmlength>\z@ - \ifx\empty#1\relax - \POL@isolz@getsignchanges@plusinf - \POL@isolz@getsignchanges@minusinf - \else - \edef\POL@isolz@E{\the\numexpr\xint_zapspaces #1 \xint_gobble_i\relax}% - \POL@sturmchain@getSV@at{1[\POL@isolz@E]}% - \let\POL@isolz@plusinf@SV \POL@sturmchain@SV - \let\POL@isolz@plusinf@sign\POL@sturmchain@sign - \POL@sturmchain@getSV@at{-1[\POL@isolz@E]}% - \let\POL@isolz@minusinf@SV \POL@sturmchain@SV - \let\POL@isolz@minusinf@sign\POL@sturmchain@sign - \ifnum\POL@isolz@plusinf@sign=\z@ - \PackageError{polexpr}% -{The polynomial #2 vanishes at set upper bound 10^\POL@isolz@E}% -{Compile again with a bigger exponent in source. (X to abort).}% - \fi - \ifnum\POL@isolz@minusinf@sign=\z@ - \PackageError{polexpr}% -{The polynomial #2 vanishes at set lower bound -10^\POL@isolz@E}% -{Compile again with a bigger exponent in source. (X to abort).}% - \fi - \fi - \edef\POL@isolz@NbOfRoots - {\the\numexpr\POL@isolz@minusinf@SV-\POL@isolz@plusinf@SV}% - \else - % constant polynomial - \def\POL@isolz@NbOfRoots{0}% - \fi - \ifnum\POL@isolz@NbOfRoots=\z@ - \begingroup\globaldefs\@ne - \expandafter\xintAssignArray\expandafter\to\csname POL_ZL#2*\endcsname - \expandafter\xintAssignArray\expandafter\to\csname POL_ZR#2*\endcsname - \expandafter\xintAssignArray\expandafter\to\csname POL_ZK#2*\endcsname - \endgroup - \else - \begingroup\globaldefs\@ne - \expandafter\POL@initarray\csname POL_ZL#2*\endcsname{0}% - \expandafter\POL@initarray\csname POL_ZR#2*\endcsname{0}% - \expandafter\POL@initarray\csname POL_ZK#2*\endcsname - \xint_stop_atsecondoftwo - \endgroup - \ifx\empty#1\relax\expandafter\POL@isolz@getaprioribound\fi - \expandafter\POL@isolz@main - \fi -}% -\def\POL@initarray#1#2{% -% ATTENTION, if only one item, \xintAssignArray UNBRACES IT -% so we use an \empty trick to avoid that. Maybe considered a bug of xinttools? - \expandafter\xintAssignArray\expandafter\empty - \romannumeral\xintreplicate{\POL@isolz@NbOfRoots}{{#2}}\to#1% -}% -\def\POL@isolz@getsignchanges@plusinf{% - % Count number of sign changes at plus infinity in Sturm sequence - \def\POL@isolz@plusinf@SV{0}% - \edef\POL@isolz@lastsign{\xintiiSgn{\PolLeadingCoeff{\POL@sturmname _0}}}% - \let\POL@isolz@plusinf@sign\POL@isolz@lastsign - \POL@count\@ne - \xintloop - \edef\POL@isolz@newsign - {\xintiiSgn{\PolLeadingCoeff{\POL@sturmname _\the\POL@count}}}% - \unless\ifnum\POL@isolz@newsign=\POL@isolz@lastsign - \edef\POL@isolz@plusinf@SV{\the\numexpr\POL@isolz@plusinf@SV+\@ne}% - \fi - \let\POL@isolz@lastsign=\POL@isolz@newsign - \ifnum\POL@sturmlength>\POL@count - \advance\POL@count\@ne - \repeat -}% -\def\POL@isolz@getsignchanges@minusinf{% - % Count number of sign changes at minus infinity in Sturm sequence - \def\POL@isolz@minusinf@SV{0}% - \edef\POL@isolz@lastsign{\xintiiSgn{\PolLeadingCoeff{\POL@sturmname _0}}}% - \ifodd\PolDegree{\POL@sturmname _0} - \edef\POL@isolz@lastsign{\xintiiOpp{\POL@isolz@lastsign}}% - \fi - \let\POL@isolz@minusinf@sign\POL@isolz@lastsign - \POL@count\@ne - \xintloop - \edef\POL@isolz@newsign - {\xintiiSgn{\PolLeadingCoeff{\POL@sturmname _\the\POL@count}}}% - \ifodd\PolDegree{\POL@sturmname _\the\POL@count} - \edef\POL@isolz@newsign{\xintiiOpp{\POL@isolz@newsign}}% - \fi - \unless\ifnum\POL@isolz@newsign=\POL@isolz@lastsign - \edef\POL@isolz@minusinf@SV{\the\numexpr\POL@isolz@minusinf@SV+\@ne}% - \fi - \let\POL@isolz@lastsign=\POL@isolz@newsign - \ifnum\POL@sturmlength>\POL@count - \advance\POL@count\@ne - \repeat -}% -% utility macro for a priori bound on root decimal exponent, via Float Rounding -\def\POL@isolz@updateE #1e#2;% - {\unless\ifnum#2<\POL@isolz@E\space\edef\POL@isolz@E{\the\numexpr#2+\@ne}\fi}% -\def\POL@isolz@getaprioribound{% - \PolAssign{\POL@sturmname _0}\toarray\POL@arrayA - \edef\POL@isolz@leading{\POL@arrayA{\POL@arrayA{0}}}% - \POL@count\z@ - \xintloop - \advance\POL@count\@ne - \ifnum\POL@arrayA{0}>\POL@count - \expandafter\edef\csname POL@arrayA\the\POL@count\endcsname - {\xintDiv{\POL@arrayA\POL@count}\POL@isolz@leading}% - \repeat - \def\POL@isolz@E{1}% WE SEEK SMALLEST E SUCH HAT -10^E < roots < +10^E - \advance\POL@count\m@ne - \xintloop - \ifnum\POL@count>\z@ - \expandafter\POL@isolz@updateE - % use floating point to get decimal exponent - \romannumeral0\xintfloat[4]% should I use with [2] rather? (should work) - {\xintAdd{1/1[0]}{\xintAbs{\POL@arrayA\POL@count}}};% - \advance\POL@count\m@ne - \repeat - % \ifxintverbose\xintMessage{polexpr}{Info}% - % {Roots a priori bounded in absolute value by 10 to the \POL@isolz@E.}% - % \fi -}% -\def\POL@IsoRight@raw{\POL@IsoRight@Int/1[\POL@isolz@E]}% -\def\POL@IsoLeft@raw {\POL@IsoLeft@Int/1[\POL@isolz@E]}% -\def\POL@IsoRight@rawout{% - \ifnum\POL@IsoRightSign=\z@\expandafter\xintREZ\fi\POL@IsoRight@raw -}% -\def\POL@IsoLeft@rawout{% - \ifnum\POL@IsoRightSign=\z@ - \expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo - \fi{\xintREZ\POL@IsoRight@raw}% - {\POL@IsoLeft@Int/1[\POL@isolz@E]}% -}% -\def\POL@isolz@main {% -% NOTE 2018/02/16. THIS WILL PRESUMABLY BE RE-ORGANIZED IN FUTURE TO DO -% FIRST POSITIVE ROOTS THEN NEGATIVE ROOTS VIA CHANGE OF VARIABLE TO OPPOSITE. - \global\POL@isolz@nextwillneedrefinefalse - \def\POL@IsoRight@Int{0}% - \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV \POL@sturmchain@SV - \let\POL@IsoRightSign\POL@sturmchain@sign - \let\POL@IsoAtZeroSV \POL@IsoRightSV - \let\POL@IsoAtZeroSign\POL@IsoRightSign - \ifnum\POL@IsoAtZeroSign=\z@ - \xdef\POL@isolz@IntervalIndex - {\the\numexpr\POL@isolz@minusinf@SV-\POL@IsoRightSV}% - \POL@refine@storeleftandright % store zero root, \POL@IsoRightSign is zero - \edef\POL@IsoRightSV{\the\numexpr\POL@IsoRightSV+\@ne}% -% subtlety here if original polynomial had multiplicities, but ok. I checked! - \edef\POL@IsoRightSign % evaluated twice, but that's not so bad - {\xintiiOpp{\xintiiSgn{\POL@eval{\POL@sturmname _1}{0/1[0]}}}}% - \fi - \def\POL@IsoLeft@Int{-1}% -10^E isn't a root! - \let\POL@IsoLeftSV \POL@isolz@minusinf@SV - \let\POL@IsoLeftSign\POL@isolz@minusinf@sign - % \POL@IsoRight@SV was modified if zero is a root - \edef\POL@isolz@NbOfNegRoots{\the\numexpr\POL@IsoLeftSV-\POL@IsoRightSV}% - \gdef\POL@isolz@IntervalIndex{0}% - \let\POL@isolz@@E\POL@isolz@E - \ifnum\POL@isolz@NbOfNegRoots>\z@ -% refactored at 0.7 to fix cases leading to an intervals with zero as end-point - \POL@isolz@findroots@neg - \fi - \let\POL@isolz@E\POL@isolz@@E - \def\POL@IsoLeft@Int{0}% - \let\POL@IsoLeftSV \POL@IsoAtZeroSV % véritable SV en zéro - \let\POL@IsoLeftSign\POL@IsoAtZeroSign% véritable signe en zéro - \ifnum\POL@IsoLeftSign=\z@ - \xdef\POL@isolz@IntervalIndex{\the\numexpr\POL@isolz@IntervalIndex+\@ne}% - \fi - \let\POL@@IsoRightSV \POL@isolz@plusinf@SV - \let\POL@@IsoRightSign\POL@isolz@plusinf@sign % 10^E not a root! - \edef\POL@isolz@NbOfPosRoots - {\the\numexpr\POL@IsoLeftSV-\POL@@IsoRightSV}% attention @@ - \ifnum\POL@isolz@NbOfPosRoots>\z@ - % always do that to avoid zero as end-point whether it is a root or not - \global\POL@isolz@nextwillneedrefinetrue - \POL@isolz@findroots@pos - \fi -}% -\def\POL@isolz@findroots@neg{% - \def\POL@IsoRight@Int{-1}% - \POL@isolz@findnextzeroboundeddecade@neg - \def\POL@IsoLeft@Int{-10}% - \let\POL@@IsoRightSign\POL@IsoRightSign % a zero there is possible - \let\POL@@IsoRightSV \POL@IsoRightSV - % this will do possibly recursive \POL@isolz@check's - \POL@isolz@explorenexteightsubdecades@neg - \ifnum\POL@isolz@IntervalIndex<\POL@isolz@NbOfNegRoots\space - % above did not explore -2, -1 for this optimization (SV known at Right) - \def\POL@IsoRight@Int{-1}% - \let\POL@IsoRightSign\POL@@IsoRightSign - \let\POL@IsoRightSV \POL@@IsoRightSV - \POL@isolz@check - \ifnum\POL@isolz@IntervalIndex<\POL@isolz@NbOfNegRoots\space - \def\POL@IsoLeft@Int{-1}% - \let\POL@IsoLeftSign\POL@@IsoRightSign - \let\POL@IsoLeftSV \POL@@IsoRightSV - % I don't like being inside TeX conditionals - \expandafter\expandafter\expandafter\POL@isolz@findroots@neg - \fi - \fi -}% -\def\POL@isolz@findnextzeroboundeddecade@neg{% - \xintloop - \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}% - \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV \POL@sturmchain@SV - \let\POL@IsoRightSign\POL@sturmchain@sign - % would an \ifx test be quicker? (to be checked) - \ifnum\POL@IsoRightSV=\POL@IsoLeftSV\space - % no roots in-between, iterate - \repeat -}% -\def\POL@isolz@explorenexteightsubdecades@neg{% - \xintloop - \edef\POL@IsoRight@Int{\the\numexpr\POL@IsoLeft@Int+\@ne}% - % we could arguably do a more efficient dichotomy here - \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV \POL@sturmchain@SV - \let\POL@IsoRightSign\POL@sturmchain@sign - \POL@isolz@check % may recurse if multiple roots are to be found - \ifnum\POL@isolz@IntervalIndex=\POL@isolz@NbOfNegRoots\space - \expandafter\xintbreakloop - \fi - \let\POL@IsoLeft@Int\POL@IsoRight@Int - \let\POL@IsoLeftSign\POL@IsoRightSign - \let\POL@IsoLeftSV\POL@IsoRightSV - \ifnum\POL@IsoRight@Int < -\tw@ - \repeat -}% -\def\POL@isolz@findroots@pos{% - % remark (2018/12/08), this needs some refactoring, I hardly understand - % the logic and it hides most into the recursion done by \POL@isolz@check - % It would probably make more sense to proceed like done for the negative - % but here finding the largest roots first. - \def\POL@IsoRight@Int{1}% - \POL@isolz@findnextzeroboundeddecade@pos - \unless\ifnum\POL@IsoRightSV=\POL@IsoLeftSV\space - % this actually explores the whole of some interval (0, 10^{e-1}] - % in a context where some roots are known to be in (10^{e-1}, 10^{e}] - % and none are larger - \POL@isolz@check % will recurse inside groups if needed with modified E - \fi - % we know get the roots in the last 9 decades from 10^{e-1} to 10^{e} - % we should arguably do a more efficient dichotomy here - \def\POL@IsoLeft@Int{1}% - \let\POL@IsoLeftSV\POL@IsoRightSV - \let\POL@IsoLeftSign\POL@IsoRightSign - \xintloop - \edef\POL@IsoRight@Int{\the\numexpr\POL@IsoLeft@Int+\@ne}% - \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV \POL@sturmchain@SV - \let\POL@IsoRightSign\POL@sturmchain@sign - \POL@isolz@check % recurses in needed - \let\POL@IsoLeft@Int\POL@IsoRight@Int - \let\POL@IsoLeftSign\POL@IsoRightSign - \let\POL@IsoLeftSV\POL@IsoRightSV - \ifnum\POL@isolz@IntervalIndex=\POL@isolz@NbOfRoots\space - \expandafter\xintbreakloop - \fi - \ifnum\POL@IsoLeft@Int < \xint_c_ix - \repeat - \ifnum\POL@isolz@IntervalIndex<\POL@isolz@NbOfRoots\space - % get now the last, rightmost, root (or roots) - \def\POL@IsoRight@Int{10}% - \let\POL@IsoRightSign\POL@@IsoRightSign - \let\POL@IsoRightSV\POL@@IsoRightSV - \POL@isolz@check - \fi -}% -\def\POL@isolz@findnextzeroboundeddecade@pos{% - \xintloop - \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}% - \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV \POL@sturmchain@SV - \let\POL@IsoRightSign\POL@sturmchain@sign - \ifnum\POL@IsoRightSV=\POL@@IsoRightSV\space - \let\POL@@IsoRightSign\POL@IsoRightSign % root here possible! - \repeat -}% -\def\POL@isolz@check{% \POL@IsoRightSign must be ready for use here -% \ifxintverbose -% \xintMessage{polexpr}{Info}% -% {\the\numexpr\POL@IsoLeftSV-\POL@IsoRightSV\relax\space roots -% in (\POL@IsoLeft@raw,\POL@IsoRight@raw] (E = \POL@isolz@E)}% -% \fi - \ifcase\numexpr\POL@IsoLeftSV-\POL@IsoRightSV\relax - % no root in ]left, right] - \global\POL@isolz@nextwillneedrefinefalse - \or - % exactly one root in ]left, right] - \xdef\POL@isolz@IntervalIndex{\the\numexpr\POL@isolz@IntervalIndex+\@ne}% - \ifnum\POL@IsoRightSign=\z@ - % if right boundary is a root, ignore previous flag - \global\POL@isolz@nextwillneedrefinefalse - \fi - % if left boundary is known to have been a root we refine interval - \ifPOL@isolz@nextwillneedrefine - \expandafter\expandafter\expandafter\POL@isolz@refine - \else - % \POL@IsoRightSign is zero iff root now exactly known - \POL@refine@storeleftandright - \ifnum\POL@IsoRightSign=\z@ - \global\POL@isolz@nextwillneedrefinetrue - \fi - \fi - \else - % more than one root, we need to recurse - \expandafter\POL@isolz@recursedeeper - \fi -}% -\def\POL@isolz@recursedeeper{% -% NOTE 2018/02/16. I SHOULD DO A REAL BINARY DICHOTOMY HERE WHICH ON AVERAGE -% SHOULD BRING SOME GAIN (LIKE WHAT IS ALREADY DONE FOR THE "refine" MACROS. -% THUS IN FUTURE THIS MIGHT BE REFACTORED. -\begingroup - \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}% - \edef\POL@@IsoRight@Int{\xintDSL{\POL@IsoRight@Int}}% - \let\POL@@IsoRightSign \POL@IsoRightSign - \let\POL@@IsoRightSV \POL@IsoRightSV - \edef\POL@IsoLeft@Int {\xintDSL{\POL@IsoLeft@Int}}% - \xintiloop[1+1] - \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% - \POL@sturmchain@getSV@at\POL@IsoRight@raw - \let\POL@IsoRightSV \POL@sturmchain@SV - \let\POL@IsoRightSign\POL@sturmchain@sign - \POL@isolz@check - \let\POL@IsoLeft@Int\POL@IsoRight@Int - \let\POL@IsoLeftSV\POL@IsoRightSV - \let\POL@IsoLeftSign\POL@IsoRightSign% not used, actually - \ifnum\POL@IsoLeftSV=\POL@@IsoRightSV\space - \expandafter\xintbreakiloop - \fi - \ifnum\xintiloopindex < \xint_c_ix - \repeat - \let\POL@IsoRight@Int\POL@@IsoRight@Int - \let\POL@IsoRightSign\POL@@IsoRightSign - \let\POL@IsoRightSV \POL@@IsoRightSV - % if we exited the loop via breakiloop this is superfluous - % but it only costs one \ifnum - \POL@isolz@check -\endgroup -}% -\def\POL@isolz@refine{% - % starting point is first root = left < unique second root < right - % even if we hit exactly via refinement second root, we set flag false as - % processing will continue with original right end-point, which isn't a root - \global\POL@isolz@nextwillneedrefinefalse -\begingroup - \let\POL@@IsoRightSign\POL@IsoRightSign % already evaluated - \xintloop - \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}% - \edef\POL@IsoLeft@Int {\xintDSL{\POL@IsoLeft@Int}}% - \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% - \edef\POL@IsoRightSign - {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% - \ifnum\POL@IsoRightSign=\POL@@IsoRightSign\space - \repeat - % now second root has been separated from the one at left end point -% we update the storage of the root at left for it to have the same number -% of digits in mantissa. No, I decided not to do that to avoid complications. - % \begingroup - % \let\POL@IsoRight@Int\POL@IsoLeft@Int - % \def\POL@IsoRightSign{0}% - % \edef\POL@isolz@IntervalIndex{\the\numexpr\POL@isolz@IntervalIndex-\@ne}% - % \POL@refine@storeleftandright - % \endgroup - \edef\POL@@IsoRight@Int{\xintDSL{\xintInc{\xintDSR{\POL@IsoLeft@Int}}}}% - \let\POL@IsoLeft@Int\POL@IsoRight@Int - \let\POL@IsoLeftSign\POL@IsoRightSign - \ifnum\POL@IsoRightSign=\z@ % check if new Left is actually a root - \else - \edef\POL@IsoRight@Int{\xintDec{\POL@@IsoRight@Int}}% - \edef\POL@IsoRightSign - {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% - \ifnum\POL@IsoRightSign=\POL@@IsoRightSign\space - \POL@refine@doonce % we need to locate in interval (1, 9) in local scale - \else - \let\POL@IsoLeft@Int\POL@IsoRight@Int - \ifnum\POL@IsoRightSign=\z@ - \def\POL@IsoLeftSign{0}% - \else - \let\POL@IsoRight@Int\POL@@IsoRight@Int - % the IsoRightSign is now wrong but here we don't care - \fi\fi - \fi - % on exit, exact root found iff \POL@IsoRightSign is zero - \POL@refine@storeleftandright -\endgroup -}% -\def\POL@refine@doonce{% if exact root is found, always in IsoRight on exit -% NOTE: FUTURE REFACTORING WILL GET RID OF \xintiiAdd WHICH ARE A BIT COSTLY -% BUT BASICALLY NEEDED TO HANDLE BOTH NEGATIVE AND POSITIVE HERE. -% I WILL RE-ORGANIZE THE WHOLE THING IN FUTURE TO GET ROOTS STARTING FROM -% THE ORIGIN AND SIMPLY RE-LABEL THE NEGATIVE ONE AT THE END. 2018/02/16. - \let\POL@@IsoRight@Int\POL@IsoRight@Int % 9 - \let\POL@@IsoRightSign\POL@IsoRightSign - \edef\POL@IsoRight@Int{\xintiiAdd{4}{\POL@IsoLeft@Int}}% 5 - \edef\POL@IsoRightSign - {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% - \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space - \let\POL@IsoLeft@Int\POL@IsoRight@Int % 5 - \edef\POL@IsoRight@Int{\xintiiAdd{2}{\POL@IsoLeft@Int}}% - \edef\POL@IsoRightSign - {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% - \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space - \let\POL@IsoLeft@Int\POL@IsoRight@Int % 7 - \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% - \edef\POL@IsoRightSign - {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% - \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space - \let\POL@IsoLeft@Int\POL@IsoRight@Int % 8 - \let\POL@IsoRight@Int\POL@@IsoRight@Int % 9 - \let\POL@IsoRightSign\POL@@IsoRightSign % opposite of one at left - \fi % else 7, 8 with possible root at 8 - \else - \ifnum\POL@IsoRightSign=\z@ - \let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 7 - \def\POL@IsoLeftSign{0}% - \else - \let\POL@@IsoRight@Int\POL@IsoRight@Int % 7 - \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% 6 - \edef\POL@IsoRightSign - {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% - \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space - \let\POL@IsoLeft@Int\POL@IsoRight@Int % 6 - \let\POL@IsoRight@Int\POL@@IsoRight@Int % 7 - \let\POL@IsoRightSign\POL@@IsoRightSign - \fi % else 5, 6 with possible root at 6 - \fi\fi - \else - \ifnum\POL@IsoRightSign=\z@ - \let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 5 - \def\POL@IsoLeftSign{0}% - \else - \let\POL@@IsoRight@Int\POL@IsoRight@Int % 5 - \edef\POL@IsoRight@Int{\xintiiAdd{2}{\POL@IsoLeft@Int}}% - \edef\POL@IsoRightSign - {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% - \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space - \let\POL@IsoLeft@Int\POL@IsoRight@Int % 3 - \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% 4 - \edef\POL@IsoRightSign - {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% - \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space - \let\POL@IsoLeft@Int\POL@IsoRight@Int % 4 - \let\POL@IsoRight@Int\POL@@IsoRight@Int % 5 - \let\POL@IsoRightSign\POL@@IsoRightSign - \fi % else 3, 4 with possible root at 4 - \else - \ifnum\POL@IsoRightSign=\z@ - \let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 3 - \def\POL@IsoLeftSign{0}% - \else - \let\POL@@IsoRight@Int\POL@IsoRight@Int % 3 - \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% 2 - \edef\POL@IsoRightSign - {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% - \ifnum\POL@IsoRightSign=\POL@IsoLeftSign\space - \let\POL@IsoLeft@Int\POL@IsoRight@Int % 2 - \let\POL@IsoRight@Int\POL@@IsoRight@Int % 3 - \let\POL@IsoRightSign\POL@@IsoRightSign - \fi % else 1, 2 with possible root at 2 - \fi\fi - \fi\fi -}% -\def\POL@refine@storeleftandright{% - \expandafter - \xdef\csname POL_ZL\POL@sturmname*\POL@isolz@IntervalIndex\endcsname - {\PolDecToString{\POL@IsoLeft@rawout}}% - \expandafter - \xdef\csname POL_ZR\POL@sturmname*\POL@isolz@IntervalIndex\endcsname - {\PolDecToString{\POL@IsoRight@rawout}}% - % added at 0.6 - \ifnum\POL@IsoRightSign=\z@ - \global - \expandafter - \let\csname POL_ZK\POL@sturmname*\POL@isolz@IntervalIndex\endcsname - \xint_stop_atfirstoftwo - \fi - \begingroup\xintglobaldefstrue - % skip some overhead of \xintdefvar... - \XINT_expr_defvar_one{\POL@sturmname L_\POL@isolz@IntervalIndex}% - {\POL@IsoLeft@rawout}% - \XINT_expr_defvar_one{\POL@sturmname R_\POL@isolz@IntervalIndex}% - {\POL@IsoRight@rawout}% - % added at 0.7 - \XINT_expr_defvar_one{\POL@sturmname Z_\POL@isolz@IntervalIndex _isknown}% - {\ifnum\POL@IsoRightSign=\z@ 1\else 0\fi}% - \endgroup -}% -%% \PolRefineInterval -\def\POL@xintexprGetVar#1{\csname XINT_expr_varvalue_#1\endcsname}% -% attention, also used by \POL@findrat@loop@a -\def\POL@get@IsoLeft@rawin{% - \edef\POL@IsoLeft@rawin - {\POL@xintexprGetVar{\POL@sturmname L_\POL@isolz@IntervalIndex}}% -}% -% attention, also used by \POL@findrat@loop@a -\def\POL@get@IsoRight@rawin{% - \edef\POL@IsoRight@rawin - {\POL@xintexprGetVar{\POL@sturmname R_\POL@isolz@IntervalIndex}}% -}% -% attention, also used by \POL@findrat@loop@a -\def\POL@get@Int@aux #1/1[#2]#3#4{\edef#3{\xintDSH{#4-#2}{#1}}}% -\def\POL@get@IsoLeft@Int{% - \expandafter\POL@get@Int@aux\POL@IsoLeft@rawin\POL@IsoLeft@Int\POL@isolz@E -}% -\newcommand\PolRefineInterval{\@ifstar\POL@srefine@start\POL@refine@start}% -\newcommand\POL@refine@start[3][1]{% - \edef\POL@isolz@IntervalIndex{\the\numexpr#3}% - \edef\POL@sturmname{#2}% - \expandafter\POL@refine@sharedbody\expandafter - {\expandafter\POL@refine@loop\expandafter{\the\numexpr#1}}% -}% -\def\POL@srefine@start#1#2{% - \edef\POL@isolz@IntervalIndex{\the\numexpr#2}% - \edef\POL@sturmname{#1}% - \POL@refine@sharedbody - {\let\POL@refine@left@next\POL@refine@main % we want to recurse if needed - \let\POL@refine@right@next\POL@refine@main % we want to recurse if needed - \POL@refine@main}% -}% -\def\POL@refine@sharedbody#1{% - \POL@get@IsoLeft@rawin - \edef\POL@IsoLeftSign - {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoLeft@rawin}}}% - \ifnum\POL@IsoLeftSign=\z@ - % do nothing if that interval was already a singleton - \else - % else both end-points are not roots and there is a single one in-between - \POL@get@IsoRight@rawin - \edef\POL@IsoRightSign{\the\numexpr-\POL@IsoLeftSign}% - \edef\POL@isolz@E{\expandafter\POL@refine@getE - % je pense que le xintrez ici est superflu - \romannumeral0\xintrez{\xintSub{\POL@IsoRight@rawin}{\POL@IsoLeft@rawin}}}% - \POL@get@IsoLeft@Int - \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% - #1% - \POL@refine@storeleftandright % \POL@IsoRightSign not zero - \fi -}% -\def\POL@refine@loop#1{% - \let\POL@refine@left@next \@empty % no recursion at end sub-intervals - \let\POL@refine@right@next\@empty - \xintiloop[1+1] - \POL@refine@main - \ifnum\POL@IsoRightSign=\z@ - \expandafter\xintbreakiloop - \fi - \ifnum\xintiloopindex<#1 - \repeat -}% -\def\POL@refine@main{% - \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}% - \edef\POL@IsoLeft@Int{\xintDSL{\POL@IsoLeft@Int}}% - \edef\POL@IsoRight@Int{\xintDSL{\POL@IsoRight@Int}}% - \let\POL@@IsoRight@Int\POL@IsoRight@Int - \let\POL@@IsoRightSign\POL@IsoRightSign - \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% - \edef\POL@IsoRightSign - {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% - \ifnum\POL@IsoRightSign=\z@ - \let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 1 - \def\POL@IsoLeftSign{0}% - \let\POL@next\@empty - \else - \ifnum\POL@IsoRightSign=\POL@@IsoRightSign\space - \let\POL@next\POL@refine@left@next % may be \@empty or \POL@refine@main for recursion - \let\POL@refine@right@next\@empty - \else - \let\POL@IsoLeft@Int\POL@IsoRight@Int - \edef\POL@IsoRight@Int{\xintDec{\POL@@IsoRight@Int}}% - \edef\POL@IsoRightSign - {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% - \ifnum\POL@IsoRightSign=\z@ - \let\POL@IsoLeft@Int\POL@IsoRight@Int % root at 9 - \def\POL@IsoLeftSign{0}% - \let\POL@next\@empty - \else - \ifnum\POL@IsoRightSign=\POL@@IsoRightSign\space - \let\POL@next\POL@refine@doonce - \else - \let\POL@IsoLeft@Int\POL@IsoRight@Int - \let\POL@IsoRight@Int\POL@@IsoRight@Int - \let\POL@IsoRightSign\POL@@IsoRightSign - \let\POL@next\POL@refine@right@next - \let\POL@refine@left@next\@empty - \fi - \fi - \fi\fi - \POL@next -}% -% lacking pre-defined xintfrac macro here (such as an \xintRawExponent) -\def\POL@refine@getE#1[#2]{#2}% \xintREZ already applied, for safety - - -\newcommand\PolIntervalWidth[2]{% -% le \xintRez est à cause des E positifs, car trailing zéros explicites -% si je travaillais à partir des variables xintexpr directement ne devrait -% pas être nécessaire, mais trop fragile par rapport à chgt internes possibles - \romannumeral0\xintrez{\xintSub{\@nameuse{POL_ZR#1*}{#2}}% - {\@nameuse{POL_ZL#1*}{#2}}} -}% - - -\newcommand\PolEnsureIntervalLengths[2]{% #1 = Sturm chain name, - % localize roots in intervals of length at most 10^{#2} - \edef\POL@sturmname{#1}% - \edef\POL@ensure@targetE{\the\numexpr#2}% - \edef\POL@nbofroots{\csname POL_ZL\POL@sturmname*0\endcsname}% - \ifnum\POL@nbofroots>\z@ - \expandafter\POL@ensureintervallengths - \fi -}% -\def\POL@ensureintervallengths{% - \POL@count\z@ - % \POL@count used by \POL@sturmchain@getSV@at but latter not used - \xintloop - \advance\POL@count\@ne - \edef\POL@isolz@IntervalIndex{\the\POL@count}% - \POL@ensure@one - \ifnum\POL@nbofroots>\POL@count - \repeat -}% -\newcommand\PolEnsureIntervalLength[3]{% #1 = Sturm chain name, - % #2 = index of interval - % localize roots in intervals of length at most 10^{#3} - \edef\POL@sturmname{#1}% - \edef\POL@ensure@targetE{\the\numexpr#3}% - \edef\POL@isolz@IntervalIndex{\the\numexpr#2}% -% peut-être autoriser -1, -2, ... ? - \ifnum\POL@isolz@IntervalIndex>\z@ -% 0.7, add this safeguard but attention means this structure must be in place - \ifnum\csname POL_ZL\POL@sturmname*0\endcsname>\z@ -% je ne fais pas les \expandafter mais je préfèrerai ne pas être à l'intérieur - \POL@ensure@one - \fi - \fi -}% -\def\POL@ensure@one{% - \POL@get@IsoLeft@rawin - \POL@get@IsoRight@rawin - \edef\POL@ensure@delta{\xintREZ{\xintSub{\POL@IsoRight@rawin}{\POL@IsoLeft@rawin}}}% - \xintiiifZero{\POL@ensure@delta} - {} - {\edef\POL@isolz@E{\expandafter\POL@refine@getE\POL@ensure@delta}% - \POL@get@IsoLeft@Int - \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% - \ifnum\POL@isolz@E>\POL@ensure@targetE\space - \edef\POL@IsoLeftSign - {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoLeft@raw}}}% - % at start left and right are not roots, and values of opposite signs - % \edef\POL@IsoRightSign{\the\numexpr-\POL@IsoLeftSign}% - \xintloop - \POL@ensure@Eloopbody % decreases E by one at each iteration - % if separation level is still too coarse we recurse at deeper level - \ifnum\POL@isolz@E>\POL@ensure@targetE\space - \repeat - % will check if right is at a zero, it needs \POL@IsoRightSign set up - \POL@refine@storeleftandright - \fi - }% -}% -\def\POL@ensure@Eloopbody {% - \edef\POL@isolz@E{\the\numexpr\POL@isolz@E-\@ne}% - \edef\POL@IsoLeft@Int{\xintDSL{\POL@IsoLeft@Int}}% - % this will loop at most ten times - \xintloop - \edef\POL@IsoRight@Int{\xintInc{\POL@IsoLeft@Int}}% - \edef\POL@IsoRightSign - {\xintiiSgn{\POL@eval{\POL@sturmname _0}{\POL@IsoRight@raw}}}% - % if we have found a zero at right boundary the \ifnum test will fail - % and we exit the loop - % else we exit the loop if sign at right boundary is opposite of - % sign at left boundary (the latter is +1 or -1, never 0) - % this is a bit wasteful if we go ten times to the right, because - % we know that there the sign will be opposite, evaluation was superfluous - \ifnum\POL@IsoLeftSign=\POL@IsoRightSign\space - \let\POL@IsoLeft@Int\POL@IsoRight@Int - \repeat - % check for case when we exited the inner loop because we actually - % found a zero, then we force exit from the main (E decreasing) loop - \ifnum\POL@IsoRightSign=\z@ - \expandafter\xintbreakloop - \fi -}% - - -\catcode`_ 8 -\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\PolPrintIntervalsTheVar{#1}% - \def\PolPrintIntervalsTheSturmName{#2}% - \ifnum\@nameuse{POL_ZL#2*}{0}=\z@ - \PolPrintIntervalsNoRealRoots - \else - \gdef\PolPrintIntervalsTheIndex{1}% - \POL@PrintIntervals@DoDefs - \begingroup\edef\POL@tmp{\endgroup - \unexpanded\expandafter{\PolPrintIntervalsBeginEnv}% - \unexpanded\expandafter{\POL@PrintIntervals@Loop}% - \unexpanded\expandafter{\PolPrintIntervalsEndEnv}% - }\POL@tmp - \fi - \POL@AfterPrintIntervals - \def\PolPrintIntervalsTheVar{#1}% - \def\PolPrintIntervalsTheSturmName{#2}% -}% -\let\POL@AfterPrintIntervals\@empty -\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 -\def\POL@PrintIntervals@Loop{% - \POL@SturmIfZeroExactlyKnown\PolPrintIntervalsTheSturmName - \PolPrintIntervalsTheIndex - \PolPrintIntervalsKnownRoot - \PolPrintIntervalsUnknownRoot - \xdef\PolPrintIntervalsTheIndex{\the\numexpr\PolPrintIntervalsTheIndex+\@ne}% - \unless\ifnum\PolPrintIntervalsTheIndex> - \@nameuse{POL_ZL\PolPrintIntervalsTheSturmName*0} - \POL@PrintIntervals@DoDefs - \xint_afterfi{\\\POL@PrintIntervals@Loop}% - \fi -}% -\def\POL@PrintIntervals@DoDefs{% - \xdef\PolPrintIntervalsTheLeftEndPoint{% - \csname POL_ZL\PolPrintIntervalsTheSturmName*\PolPrintIntervalsTheIndex - \endcsname - }% - \xdef\PolPrintIntervalsTheRightEndPoint{% - \csname POL_ZR\PolPrintIntervalsTheSturmName*\PolPrintIntervalsTheIndex - \endcsname - }% - \xdef\PolPrintIntervalsTheMultiplicity{% - \ifcsname POL_ZM\PolPrintIntervalsTheSturmName*\PolPrintIntervalsTheIndex - \endcsname - \csname POL_ZM\PolPrintIntervalsTheSturmName*\PolPrintIntervalsTheIndex - \endcsname - \else - ?% or use 0 ? - \fi - }% -}% - - -\newcommand\PolSturmIfZeroExactlyKnown[2]{% #1 = sturmname, #2=index - \romannumeral0\csname POL_ZK#1*\endcsname{#2}% -}% -\newcommand\POL@SturmIfZeroExactlyKnown[2]{% #1 = sturmname, #2=index - \romannumeral0\csname POL_ZK#1*\the\numexpr#2\endcsname -}% -\newcommand\PolSturmIsolatedZeroMultiplicity[2]{% - \romannumeral`^^@\csname POL_ZM#1*\endcsname{#2}% -}% -\newcommand\PolSturmIsolatedZeroLeft[2]{% - \romannumeral`^^@\csname POL_ZL#1*\endcsname{#2}% -}% -\newcommand\PolSturmIsolatedZeroRight[2]{% - \romannumeral`^^@\csname POL_ZR#1*\endcsname{#2}% -}% -\newcommand\PolSturmNbOfIsolatedZeros[1]{% - \romannumeral`^^@\csname POL_ZL#1*0\endcsname -}% -\newcommand\PolSturmRationalRoot[2]{% - \romannumeral`^^@\csname POL_ZL#1*% - \csname POL_RI#1*\endcsname{#2}\endcsname -}% -\newcommand\PolSturmRationalRootIndex[2]{% - \romannumeral`^^@\csname POL_RI#1*\endcsname{#2}% -}% -\newcommand\PolSturmRationalRootMultiplicity[2]{% - \romannumeral`^^@\csname POL_ZM#1% - *\csname POL_RI#1*\endcsname{#2}\endcsname -}% -\newcommand\PolSturmNbOfRationalRoots[1]{% - \romannumeral`^^@\csname POL_RI#1*0\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 - - -\newcommand\PolMakeMonic[1]{% - \edef\POL@leadingcoeff{\PolLeadingCoeff{#1}}% - \edef\POL@leadingcoeff@inverse{\xintDiv{1/1[0]}{\POL@leadingcoeff}}% - \PolMapCoeffs{\xintMul{\POL@leadingcoeff@inverse}}{#1}% -}% - - -%% CORE ALGEBRA MACROS -%% We do this non-expandably, but in a nestable way... this is the whole -%% point because \xintdeffunc as used by \poldef creates a big nested macro. -%% The idea is to execute it with another meaning given to \xintAdd etc.., -%% so that it operates on "polynomials". This is a mixture of expandable -%% and non-expandable techniques. -%% -%% And it was complicated to let it work with xintexpr 1.4 -%% -\def\POL@get#1#2#3{% - \relax %!! part de la tambouille pour fonctionner en xint 1.4 - \POL@polglobalfalse - \begingroup - \protected\def\POL@result{#3}% - #3% - \expandafter - \endgroup - \expandafter\def\expandafter#1\expandafter{\POL@result}% - \unless\ifPOL@pol - % avoid expanding more than twice #3 - % #3 must be purely numerical or at least compatible with \edef - % this is why at 0.7.5 I had to handle especially constant - % polynomial functions to remove any protection from them - % (because the protection triggers the COMPOSITION when - % the polynomial is found as argument of another one and - % this is not expandable) - \edef#1{#3}% - \xintiiifZero{#1}% - {\def#1{-1.\POL@empty{0/1[0]}}}% - {\edef#1{0.\POL@empty{#1}}}% - \fi - #2% -}% - -%% COMPOSITION -%% This did not exist before 0.7.5 and is part of its adaptation to xint 1.4 -%% We thus took up this opportunity to speed up substantially composition. -%% Very serious difficulties with constant polynomials. Had to handle them -%% especially. -%% OK, that was really tough, but advantage now is that composition -%% at 0.7.5 should be more efficient than before. However when polynomials -%% become big via composition, coefficients also are big and the time -%% taken by arithmetic dominates. No time to test really, though, relieved -%% I can release xint 1.4 at last. My basic polexpr test suite passes, -%% but it goes back already to old releases. -\protected\def\POL@applypolfunc#1#2% -{% -% This #2 may be also invoing \POL@applypolfunc... - \POL@get\POL@A\POL@applypolfunc@b#2#1% -}% -\def\POL@applypolfunc@b #1% -{% -% and now the have our Horner scheme nested macro -% which hopefully will do its job with \POL@add, \POL@mul etc... - \POL@polglobalfalse - \expandafter#1\expanded - {{\POL@polglobaltrue\protected\def\noexpand\POL@result{\POL@A}}}% - \unless\ifPOL@pol - \odef\POL@result{#1{0}}% - \xintiiifZero{\POL@result}% - {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}% - {\protected\edef\POL@result{0.\POL@empty{\POL@result}}}% - \fi -}% - -%% ADDITION -\def\POL@add {\POL@get\POL@A\POL@add@b}% -\def\POL@add@b{\POL@get\POL@B\POL@add@c}% -\def\POL@add@c{% - \POL@polglobaltrue - \POL@ifZero\POL@A - {\let\POL@result\POL@B}% - {\POL@ifZero\POL@B - {\let\POL@result\POL@A}% - {\POL@@add}}% -}% -\def\POL@@add{% - \expandafter\POL@split\POL@A;\POL@degA\POL@polA - \expandafter\POL@split\POL@B;\POL@degB\POL@polB - \ifnum\POL@degA>\POL@degB\relax - \xintAssignArray\POL@polA\to\POL@arrayA - \xintAssignArray\POL@polB\to\POL@arrayB - \else - \xintAssignArray\POL@polB\to\POL@arrayA - \xintAssignArray\POL@polA\to\POL@arrayB - \let\POL@tmp\POL@degB\let\POL@degB\POL@degA\let\POL@degA\POL@tmp - \fi - \count@\z@ - \xintloop - \advance\count@\@ne - \expandafter\edef\csname POL@arrayA\the\count@\endcsname - {\xintScalarAdd{\@nameuse{POL@arrayA\the\count@}}% - {\@nameuse{POL@arrayB\the\count@}}}% - \unless\ifnum\POL@degB<\count@ - \repeat - \count@\@nameuse{POL@arrayA0} % 1+\POL@degA - % trim zero leading coefficients (we could check for equal degrees, - % but would not bring much as anyhow loop exists immediately if not) - \xintloop - % this abuses that \POL@arrayA0 is never zero - \xintiiifZero{\@nameuse{POL@arrayA\the\count@}}% - {\iftrue}% - {\iffalse}% - \advance\count@\m@ne - \repeat - \POL@resultfromarray A% attention that \POL@arrayA0 not updated -}% - -%% MULTIPLICATION -\def\POL@mul {\POL@get\POL@A\POL@mul@b}% -\def\POL@mul@b{\POL@get\POL@B\POL@mul@c}% -\def\POL@mul@c{% - \POL@polglobaltrue - \POL@ifZero\POL@A - {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}% - {\POL@ifZero\POL@B - {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}% - {\POL@@mul}}% -}% -\def\POL@@mul{% - \expandafter\POL@split\POL@A;\POL@degA\POL@polA - \expandafter\POL@split\POL@B;\POL@degB\POL@polB - \ifnum\POL@degA>\POL@degB\relax - \xintAssignArray\POL@polA\to\POL@arrayA - \xintAssignArray\POL@polB\to\POL@arrayB - \else - \xintAssignArray\POL@polB\to\POL@arrayA - \xintAssignArray\POL@polA\to\POL@arrayB - \let\POL@tmp\POL@degB - \let\POL@degB\POL@degA - \let\POL@degA\POL@tmp - \fi - \count@\z@ - \xintloop - \POL@@mul@phaseIloopbody - \unless\ifnum\POL@degB<\count@ - \repeat - \xintloop - \unless\ifnum\POL@degA<\count@ % car attention au cas de mêmes degrés - \POL@@mul@phaseIIloopbody - \repeat - \edef\POL@degC{\the\numexpr\POL@degA+\POL@degB}% - \xintloop - \unless\ifnum\POL@degC<\count@ - \POL@@mul@phaseIIIloopbody - \repeat - %\count@\the\numexpr\POL@degC+\@ne\relax % never zero polynomial here - \POL@resultfromarray C% -}% -\def\POL@@mul@phaseIloopbody{% - \advance\count@\@ne - \def\POL@tmp{0[0]}% - \count\tw@\z@ - \xintloop - \advance\count\tw@\@ne - \edef\POL@tmp{% - \xintScalarAdd - {\POL@tmp}% - {\xintScalarMul - {\@nameuse{POL@arrayA\the\count\tw@}}% - {\@nameuse{POL@arrayB\the\numexpr\count@+\@ne-\count\tw@}}% - }% - }% - \ifnum\count\tw@<\count@ - \repeat - \expandafter\let\csname POL@arrayC\the\count@\endcsname\POL@tmp -}% -\def\POL@@mul@phaseIIloopbody{% - \advance\count@\@ne - \def\POL@tmp{0[0]}% - \count\tw@\count@ - \advance\count\tw@-\@nameuse{POL@arrayB0} % - \xintloop - \ifnum\count\tw@<\count@ - \advance\count\tw@\@ne - \edef\POL@tmp{% - \xintScalarAdd - {\POL@tmp}% - {\xintScalarMul - {\@nameuse{POL@arrayA\the\count\tw@}}% - {\@nameuse{POL@arrayB\the\numexpr\count@+\@ne-\count\tw@}}% - }% - }% - \repeat - \expandafter\let\csname POL@arrayC\the\count@\endcsname\POL@tmp -}% -\def\POL@@mul@phaseIIIloopbody{% - \advance\count@\@ne - \def\POL@tmp{0[0]}% - \count\tw@\count@ - \advance\count\tw@-\@nameuse{POL@arrayB0} % - \xintloop - \advance\count\tw@\@ne - \edef\POL@tmp{% - \xintScalarAdd{\POL@tmp}% - {\xintScalarMul - {\@nameuse{POL@arrayA\the\count\tw@}}% - {\@nameuse{POL@arrayB\the\numexpr\count@+\@ne-\count\tw@}}% - }% - }% - \ifnum\@nameuse{POL@arrayA0}>\count\tw@ - \repeat - \expandafter\let\csname POL@arrayC\the\count@\endcsname\POL@tmp -}% - -%% POWERS (SCALAR EXPONENT...) -\def\POL@pow #1#2{% - \POL@polglobalfalse - \begingroup - \protected\def\POL@result{#1}% - #1% - \expandafter - \endgroup - \expandafter\def\expandafter\POL@A\expandafter{\POL@result}% - \unless\ifPOL@pol - \edef\POL@A{\xintScalarPow{#1}{#2}}% no error check - \xintiiifZero{\POL@A}% - {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}% - {\protected\edef\POL@result{0.\POL@empty{\POL@A}}}% - \else - \edef\POL@B{\numexpr\xintNum{#2}\relax}% no check on exponent >= 0 - \ifcase\POL@B - \protected\def\POL@result{0.\POL@empty{1/1[0]}}% - \or - \let\POL@result\POL@A - \else - \POL@@pow@check - \fi - \fi - \POL@polglobaltrue -}% -\def\POL@@pow@check {% -% no problem here with leftover tokens! -% should I have used that I-don't-care technique more elsewhere? - \ifnum\@ne>\POL@A - % polynomial is a constant, must get rid of dot and \empty (\POL@empty) - \edef\POL@A{\expandafter\xintScalarPow\romannumeral`^^@% - \expandafter\xint_gob_til_dot\POL@A{\POL@B}}% - \xintiiifZero{\POL@A}% - {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}% - {\protected\edef\POL@result{0.\POL@empty{\POL@A}}}% - \else - \ifnum\@ne=\POL@A - % perhaps a constant times X, check constant term - \xintiiifZero - {\expandafter\xint_firstoftwo\romannumeral`^^@% - \expandafter\xint_gob_til_dot\POL@A} - {\protected\edef\POL@result - {\the\POL@B.% here at least 2. - \POL@empty - \romannumeral\xintreplicate{\POL@B}{{0/1[0]}}% - {\xintScalarPow - {\expandafter\xint_secondoftwo\romannumeral`^^@% - \expandafter\xint_gob_til_dot\POL@A}% - {\POL@B}}}}% - {\POL@@pow}% not constant times X, use general recursion - \else - \POL@@pow% general recursion - \fi\fi -}% -\def\POL@@pow@recurse#1#2{% - \begingroup - #1% - \expandafter - \endgroup - \expandafter\def\expandafter\POL@A\expandafter{\POL@result}% - \edef\POL@B{\numexpr\xintNum{#2}\relax}% - \ifcase\POL@B - \POL@thisshouldneverhappen - \or - \let\POL@result\POL@A - \else - \expandafter\POL@@pow - \fi -}% -\def\POL@@pow {% - \let\POL@pow@exp\POL@B - \let\POL@B\POL@A - \POL@@mul - \let\POL@sqA\POL@result - \ifodd\POL@pow@exp\space - \expandafter\POL@@pow@odd - \the\numexpr(\POL@pow@exp+\@ne)/\tw@-\@ne\expandafter.% - \else - \expandafter\POL@@pow@even - \the\numexpr(\POL@pow@exp+\@ne)/\tw@-\@ne\expandafter.% - \fi -}% -\def\POL@@pow@even#1.{% - \expandafter\POL@@pow@recurse\expandafter - {\expandafter\def\expandafter\POL@result\expandafter{\POL@sqA}}% - {#1}% -}% -\def\POL@@pow@odd#1.{% - \expandafter\POL@@pow@odd@i\expandafter{\POL@A}{#1}% -}% -\def\POL@@pow@odd@i #1#2{% - \expandafter\POL@@pow@recurse\expandafter - {\expandafter\def\expandafter\POL@result\expandafter{\POL@sqA}}% - {#2}% - \expandafter\POL@mul\expandafter - {\expandafter\def\expandafter\POL@result\expandafter - {\POL@result}\POL@polglobaltrue}% - {\protected\def\POL@result{#1}\POL@polglobaltrue}% -}% - -%% DIVISION -%% no check on divisor being non-zero -\def\POL@div {\POL@get\POL@A\POL@div@b}% -\def\POL@div@b{\POL@get\POL@B\POL@div@c}% -\def\POL@div@c{% - \POL@polglobaltrue - \expandafter\POL@split\POL@A;\POL@degA\POL@polA - \expandafter\POL@split\POL@B;\POL@degB\POL@polB - \ifnum\POL@degA<\POL@degB\space - \@namedef{POL@arrayQ1}{0/1[0]}% - \def\POL@degQ{-1}% - \else - \xintAssignArray\POL@polA\to\POL@arrayR - \xintAssignArray\POL@polB\to\POL@arrayB - \POL@@div - \fi - \count@\numexpr\POL@degQ+\@ne\relax - \POL@resultfromarray Q% -}% -\def\POL@@div{% - \xintAssignArray\POL@polA\to\POL@arrayR - \xintAssignArray\POL@polB\to\POL@arrayB - \edef\POL@B@leading{\csname POL@arrayB\the\numexpr\POL@degB+\@ne\endcsname}% - \edef\POL@degQ{\the\numexpr\POL@degA-\POL@degB}% - \count@\numexpr\POL@degA+\@ne\relax - \count\tw@\numexpr\POL@degQ+\@ne\relax - \xintloop - \POL@@div@loopbody - \ifnum\count\tw@>\z@ - \repeat - %%\expandafter\def\csname POL@arrayR0\endcsname{1}% - \xintloop - \xintiiifZero{\csname POL@arrayR\the\count@\endcsname}% - {\iftrue}% - {\iffalse}% - \advance\count@\m@ne - \repeat - \edef\POL@degR{\the\numexpr\count@-\@ne}% -}% -\def\POL@@div@loopbody{% - \edef\POL@@div@ratio{% - \xintScalarDiv{\csname POL@arrayR\the\count@\endcsname}% - {\POL@B@leading}}% - \expandafter\let\csname POL@arrayQ\the\count\tw@\endcsname - \POL@@div@ratio - \advance\count@\m@ne - \advance\count\tw@\m@ne - \count4 \count@ - \count6 \POL@degB\space - \xintloop - \ifnum\count6>\z@ - \expandafter\edef\csname POL@arrayR\the\count4\endcsname - {\xintScalarSub - {\csname POL@arrayR\the\count4\endcsname}% - {\xintScalarMul - {\POL@@div@ratio}% - {\csname POL@arrayB\the\count6\endcsname}}}% - \advance\count4 \m@ne - \advance\count6 \m@ne - \repeat -}% - -%% MINUS SIGN AS UNARY OPERATOR -\def\POL@opp #1{% - \POL@polglobalfalse - \begingroup - \protected\def\POL@result{#1}% - #1% - \expandafter - \endgroup - \expandafter\def\expandafter\POL@A\expandafter{\POL@result}% - \unless\ifPOL@pol - \edef\POL@A{\xintScalarOpp{#1}}% - \xintiiifZero{\POL@A}% - {\protected\def\POL@result{-1.\POL@empty{0/1[0]}}}% - {\protected\edef\POL@result{0.\POL@empty{\POL@A}}}% - \else - \edef\POL@B{0.\POL@empty{-1/1[0]}}% - \POL@@mul - \fi - \POL@polglobaltrue -}% - - -%% EXPANDABLE MACROS -\def\POL@eval@fork#1\At#2#3\krof{#2}% -\newcommand\PolEval[3]{\romannumeral`^^@\POL@eval@fork - #2\PolEvalAt - \At\PolEvalAtExpr\krof {#1}{#3}% -}% -\newcommand\PolEvalAt[2] - {\xintpraw{\csname XINT_expr_polfunc_#1\endcsname{#2}}}% -\newcommand\POL@eval[2] - {\csname XINT_expr_polfunc_#1\endcsname{#2}}% -\newcommand\PolEvalAtExpr[2]{\xinttheexpr #1(#2)\relax}% -% -\newcommand\PolEvalReduced[3]{\romannumeral`^^@\POL@eval@fork - #2\PolEvalReducedAt - \At\PolEvalReducedAtExpr\krof {#1}{#3}% -}% -\newcommand\PolEvalReducedAt[2]{% - \xintpraw % in order not to print denominator if the latter equals 1 - {\xintIrr{\csname XINT_expr_polfunc_#1\endcsname{#2}}[0]}% -}% -\newcommand\PolEvalReducedAtExpr[2]{% - \xintpraw - {\expandafter\xintIrr\romannumeral`^^@\xintthebareeval#1(#2)\relax[0]}% -}% -% -\newcommand\PolFloatEval[3]{\romannumeral`^^@\POL@eval@fork - #2\PolFloatEvalAt - \At\PolFloatEvalAtExpr\krof {#1}{#3}% -}% -\newcommand\PolFloatEvalAt[2] - {\xintpfloat{\csname XINT_flexpr_polfunc_#1\endcsname{#2}}}% -\newcommand\PolFloatEvalAtExpr[2]{\xintthefloatexpr #1(#2)\relax}% - - -\newcommand\PolSturmIntervalIndex[3]{\the\numexpr\POL@eval@fork - #2\PolSturmIntervalIndexAt - \At\PolSturmIntervalIndexAtExpr\krof {#1}{#3}% -}% -\newcommand\PolSturmIntervalIndexAtExpr[2] - {\PolSturmIntervalIndexAt{#1}{\xinttheexpr#2\relax}}% -\newcommand\PolSturmIntervalIndexAt[2] - {\expandafter\POL@sturm@index@at\romannumeral`^^@#2!{#1}\xint_bye\relax}% -\def\POL@sturm@index@at#1!#2% -{% - \expandafter\POL@sturm@index@at@iloop - \romannumeral`^^@\PolSturmNbOfIsolatedZeros{#2}!{#2}{#1}% -}% -% implementation is sub-optimal as it should use some kind of binary tree -% search rather than comparing to the intervals from right to left as here -\def\POL@sturm@index@at@iloop #1!% -{% - \ifnum #1=\z@ 0\expandafter\xint_bye\fi - \POL@sturm@index@at@iloop@a #1!% -}% -\def\POL@sturm@index@at@iloop@a #1!#2#3% -{% #1 = index, #2 = sturmname, #3 value - \PolSturmIfZeroExactlyKnown{#2}{#1} - {\xintifCmp{#3}{\POL@xintexprGetVar{#2L_#1}}% - {}% - {#1\xint_bye}% - {0\xint_bye}% - }% - {\xintifGt{#3}{\POL@xintexprGetVar{#2L_#1}}% - {\xintifLt{#3}{\POL@xintexprGetVar{#2R_#1}}% - {#1\xint_bye}% - {0\xint_bye}% - }% - {}% - }% - % catcode of ! is 11 in polexpr.sty - \expandafter\POL@sturm@index@at@iloop\the\numexpr#1-\@ne !{#2}{#3}% -}% - - -\def\POL@leq@fork#1\LessThanOrEqualTo#2#3\krof{#2}% -\newcommand\PolSturmNbOfRootsOf[3]{\romannumeral`^^@\POL@leq@fork - #2\PolNbOfRootsLessThanOrEqualTo - \LessThanOrEqualTo\PolNbOfRootsLessThanOrEqualToExpr\krof {#1}{#3}% -}% -\newcommand\PolNbOfRootsLessThanOrEqualToExpr[2] - {\PolNbOfRootsLessThanOrEqualTo{#1}{\xinttheexpr#2\relax}}% -\newcommand\PolNbOfRootsLessThanOrEqualTo[1]{% - \ifnum\PolSturmNbOfIsolatedZeros{#1}=\z@ - \expandafter\xint_firstofthree\expandafter0% - \else - \expandafter\PolNbOfRootsLessThanOrEqualTo@% - \fi {#1}% -}% -\def\PolNbOfRootsLessThanOrEqualTo@ #1#2% -{% - \expandafter\POL@nbofrootsleq@prep\romannumeral`^^@#2!{#1}% -}% -\def\POL@nbofrootsleq@prep#1!#2% -{% - \expandafter\POL@nbofrootsleq@iloop\expandafter 1\expandafter !% - \romannumeral0\xintsgn{\POL@eval{#2_0}{#1}}!% - #1!{#2}% -}% -\def\POL@nbofrootsleq@iloop#1!#2!#3!#4% -{% #1 = index, #2 = sign of evaluation at value, #3 = value, #4 = sturmname - \xintifCmp{#3}{\POL@xintexprGetVar{#4L_#1}}% - {\POL@nbofrootsleq@return #1-\@ne !}% - {\POL@nbofrootsleq@return - \PolSturmIfZeroExactlyKnown{#4}{#1}{#1}{#1-\@ne}!% - }% - % in third branch we are sure that if root is exactly known - % the test \xintifLt will be negative - {\xintifLt{#3}{\POL@xintexprGetVar{#4R_#1}}% - {\POL@nbofrootsleq@return - #1\ifnum#2=\xintSgn{\POL@eval{#4_0}{\POL@xintexprGetVar{#4L_#1}}} - -\@ne\fi !% - }% - {\ifnum#1=\PolSturmNbOfIsolatedZeros{#4} - \expandafter\POL@nbofrootsleq@rightmost - \fi \expandafter\POL@nbofrootsleq@iloop \the\numexpr\@ne+% - }% - }% - #1!#2!#3!{#4}% -}% -\def\POL@nbofrootsleq@return #1!#2!#3!#4!#5{\the\numexpr #1\relax}% -\def\POL@nbofrootsleq@rightmost\expandafter\POL@nbofrootsleq@iloop - \the\numexpr\@ne+#1!#2!#3!#4{#1}% - - -\newcommand\PolSturmNbWithMultOfRootsOf[3] -{\the\numexpr0\POL@leq@fork - #2\PolNbWithMultOfRootsLessThanOrEqualTo - \LessThanOrEqualTo\PolNbWithMultOfRootsLessThanOrEqualToExpr\krof {#1}{#3}% -}% -\newcommand\PolNbWithMultOfRootsLessThanOrEqualToExpr[2] - {\PolNbWithMultOfRootsLessThanOrEqualTo{#1}{\xinttheexpr#2\relax}}% -\newcommand\PolNbWithMultOfRootsLessThanOrEqualTo[1]{% - \ifnum\PolSturmNbOfIsolatedZeros{#1}=\z@ - \expandafter\POL@nbwmofroots@noroots - \else - \expandafter\PolNbWithMultOfRootsLessThanOrEqualTo@% - \fi {#1}% -}% -\def\POL@nbwmofroots@noroots#1#2{\relax}% -\def\PolNbWithMultOfRootsLessThanOrEqualTo@ #1#2% -{% - \expandafter\POL@nbwmofrootsleq@prep\romannumeral`^^@#2!{#1}% -}% -\def\POL@nbwmofrootsleq@prep#1!#2% -{% - \expandafter\POL@nbwmofrootsleq@iloop\expandafter 1\expandafter !% - \romannumeral0\xintsgn{\POL@eval{#2_0}{#1}}!% - #1!{#2}% -}% -\def\POL@nbwmofrootsleq@iloop#1!#2!#3!#4% -{% #1 = index, #2 = sign of evaluation at value, #3 = value, #4 = sturmname - \xintifCmp{#3}{\POL@xintexprGetVar{#4L_#1}}% - {\POL@nbwmofrootsleq@return !}% - {\POL@nbwmofrootsleq@return - \PolSturmIfZeroExactlyKnown{#4}{#1}% - {+\PolSturmIsolatedZeroMultiplicity{#4}{#1}}{}!% - }% - % in third branch we are sure that if root is exactly known - % the test \xintifLt will be negative - {\xintifLt{#3}{\POL@xintexprGetVar{#4R_#1}}% - {\POL@nbwmofrootsleq@return - \unless - \ifnum#2=\xintSgn{\POL@eval{#4_0}{\POL@xintexprGetVar{#4L_#1}}} - +\PolSturmIsolatedZeroMultiplicity{#4}{#1}\fi !% - }% - {+\PolSturmIsolatedZeroMultiplicity{#4}{#1}% - \ifnum#1=\PolSturmNbOfIsolatedZeros{#4} - \expandafter\POL@nbwmofrootsleq@return\expandafter !% - \fi - \expandafter\POL@nbwmofrootsleq@iloop \the\numexpr\@ne+% - }% - }% - #1!#2!#3!{#4}% -}% -\def\POL@nbwmofrootsleq@return #1!#2!#3!#4!#5{#1\relax}% - - -\newcommand\PolLeadingCoeff[1]{% - \romannumeral`^^@\expandafter\expandafter\expandafter\xintlastitem - \expandafter\expandafter\expandafter - {\csname POLuserpol@#1\endcsname}% -}% -% -\newcommand\PolNthCoeff[2]{\romannumeral`^^@% - \expandafter\POL@nthcoeff - \romannumeral0\xintnthelt{\ifnum\numexpr#2<\z@#2\else(#2)+1\fi}% - {\expandafter\expandafter\expandafter - \xint_gob_til_dot\csname POLuserpol@#1\endcsname}@% -}% -\def\POL@nthcoeff#1@{\if @#1@\expandafter\xint_firstoftwo - \else\expandafter\xint_secondoftwo\fi - {0/1[0]}{#1}}% -% -% returns -1 for zero polynomial for context of numerical expression -% should it return -\infty? -\newcommand\PolDegree[1]{\romannumeral`^^@\expandafter\expandafter\expandafter - \POL@degree\csname POLuserpol@#1\endcsname;}% -\def\POL@degree #1.#2;{#1}% -% -\newcommand\PolToList[1]{\romannumeral`^^@\expandafter\expandafter\expandafter - \xint_gob_til_dot\csname POLuserpol@#1\endcsname}% -% -\newcommand\PolToCSV[1]{\romannumeral0\xintlistwithsep{, }{\PolToList{#1}}}% - - -\newcommand\PolToExprCmd[1]{\xintPRaw{\xintRawWithZeros{#1}}}% -\newcommand\PolToFloatExprCmd[1]{\xintFloat{#1}}% -\let\PolToExprTermPrefix\PolTypesetCmdPrefix -\newcommand\PolToExprOneTermStyleA[2]{% - \ifnum#2=\z@ - \PolToExprCmd{#1}% - \else - \xintifOne{\xintiiAbs{#1}} - {\xintiiifSgn{#1}{-}{}{}}% + from \PolToExprTermPrefix - {\PolToExprCmd{#1}\PolToExprTimes}% - \fi - \ifcase\xintiiAbs{#2} %<-- space here mandatory - \or\PolToExprVar - \else\PolToExprVar^\xintiiAbs{#2}% - \fi -}% -\let\PolToExprOneTerm\PolToExprOneTermStyleA -\newcommand\PolToExprOneTermStyleB[2]{% - \ifnum#2=\z@ - \xintNumerator{#1}% - \else - \xintifOne{\xintiiAbs{\xintNumerator{#1}}} - {\xintiiifSgn{#1}{-}{}{}}% + from \PolToExprTermPrefix - {\xintNumerator{#1}\PolToExprTimes}% - \fi - \ifcase\xintiiAbs{#2} %<-- space here mandatory - \or\PolToExprVar - \else\PolToExprVar^\xintiiAbs{#2}% - \fi - \xintiiifOne{\xintDenominator{#1}}{}{/\xintDenominator{#1}}% -}% -\newcommand\PolToFloatExprOneTerm[2]{% - \ifnum#2=\z@ - \PolToFloatExprCmd{#1}% - \else - \PolToFloatExprCmd{#1}\PolToExprTimes - \fi - \ifcase\xintiiAbs{#2} %<-- space here mandatory - \or\PolToExprVar - \else\PolToExprVar^\xintiiAbs{#2}% - \fi -}% -\newcommand\PolToExprTimes{*}% -\newcommand\PolToExprVar{x}% -\newcommand\PolToExpr[1]{% - \if*\noexpand#1\expandafter\xint_firstoftwo\else - \expandafter\xint_secondoftwo\fi - \PolToExprAscending\PolToExprDescending{#1}}% -\newcommand\PolToFloatExpr[1]{% - \if*\noexpand#1\expandafter\xint_firstoftwo\else - \expandafter\xint_secondoftwo\fi - \PolToFloatExprAscending\PolToFloatExprDescending{#1}}% -\newcommand\PolToExprAscending[2]{% - \expandafter\POL@toexpr\csname POLuserpol@#2\endcsname - \PolToExprOneTerm\POL@toexprA}% -\newcommand\PolToFloatExprAscending[2]{% - \expandafter\POL@toexpr\csname POLuserpol@#2\endcsname - \PolToFloatExprOneTerm\POL@toexprA}% -\newcommand\PolToExprDescending[1]{% - \expandafter\POL@toexpr\csname POLuserpol@#1\endcsname - \PolToExprOneTerm\POL@toexprD}% -\newcommand\PolToFloatExprDescending[1]{% - \expandafter\POL@toexpr\csname POLuserpol@#1\endcsname - \PolToFloatExprOneTerm\POL@toexprD}% -% -\def\POL@toexpr#1#2#3{\expandafter\POL@toexpr@ - \expandafter#3\expandafter#2#1\relax}% -\def\POL@toexpr@#1#2#3.{% - \ifnum#3<\z@ - #2{0/1[0]}{0}\expandafter\xint_gobble_v - \else - \expandafter#1% - \fi {#3}#2}% -% -\def\POL@toexprA #1#2\POL@empty#3{% - \ifpoltoexprall\expandafter\POL@toexprall@b - \else\expandafter\POL@toexpr@b - \fi {#3}#2{0}1.% -}% -\def\POL@toexprD #1#2#3\relax{% #3 has \empty (\POL@empty) to prevent brace removal - \expandafter\POL@toexprD@a\expandafter#2% - \the\numexpr #1\expandafter.\romannumeral0\xintrevwithbraces{#3}\relax -}% -\def\POL@toexprD@a #1#2.#3{% - \ifpoltoexprall\expandafter\POL@toexprall@b - \else\expandafter\POL@toexpr@b - \fi{#3}#1{-#2}\the\numexpr\@ne+-#2.% -}% -\def\POL@toexpr@b #1#2#3{% - \xintiiifZero{#1}% - {\expandafter\POL@toexpr@loop\expandafter\POL@toexpr@b}% - {#2{#1}{#3}% - \expandafter\POL@toexpr@loop\expandafter\POL@toexpr@c}% - \expandafter#2% -}% -\def\POL@toexpr@c #1#2#3{% - \xintiiifZero{#1}% - {}% - {\PolToExprTermPrefix{#1}#2{#1}{#3}}% - \expandafter\POL@toexpr@loop\expandafter\POL@toexpr@c - \expandafter#2% -}% -\def\POL@toexprall@b #1#2#3{% - #2{#1}{#3}% - \expandafter\POL@toexpr@loop\expandafter\POL@toexprall@c - \expandafter#2% -}% -\def\POL@toexprall@c #1#2#3{% - \PolToExprTermPrefix{#1}#2{#1}{#3}% - \expandafter\POL@toexpr@loop\expandafter\POL@toexprall@c - \expandafter#2% -}% -\def\POL@toexpr@loop#1#2#3.#4{% - \if\relax#4\expandafter\xint_gob_til_dot\fi - #1{#4}#2{#3}\the\numexpr\@ne+#3.% -}% - - -\POL@restorecatcodes -\endinput diff --git a/macros/latex/contrib/polexpr/polexpr.txt b/macros/latex/contrib/polexpr/polexpr.txt deleted file mode 100644 index 898375926b..0000000000 --- a/macros/latex/contrib/polexpr/polexpr.txt +++ /dev/null @@ -1,2598 +0,0 @@ -.. comment: -*- fill-column: 72; mode: rst; -*- - -=============================== - Package polexpr documentation -=============================== - -0.7.5 (2020/01/31) -================== - -.. contents:: - -Basic syntax ------------- - -The syntax is:: - - \poldef polname(x):= expression in variable x; - -where: - -- in place of ``x`` an arbitrary *dummy variable* is authorized, - i.e. per default any of ``[a-z|A-Z]`` (more letters can be declared - under Unicode engines.) - -- ``polname`` consists of letters, digits, and the ``_`` and - ``'`` characters. It must start with a letter. - -.. attention:: - - The ``'`` is authorized since ``0.5.1``. As a result some constructs - recognized by the ``\xintexpr`` parser, such as ``var1 'and' var2`` - will get misinterpreted and cause errors. However these constructs - are unlikely to be frequently needed in polynomial expressions, and - the ``\xintexpr`` syntax offers alternatives, so it was deemed a - small evil. Of course the ``\xintexpr`` parser is modified only - temporarily during execution of ``\poldef``. - -One can also issue:: - - \PolDef{polname}{expression in variable x} - -which admits an optional first argument to modify the variable letter -from its default ``x``. - -``\poldef f(x):= 1-x+x^2;`` - defines polynomial ``f``. Polynomial names must start with a - letter and may contain letters, digits, underscores and the right - tick character. The - variable must be a single letter. The colon character is optional. - The semi-colon at end of expression is mandatory. - -``\PolDef{f}{1-x+x^2}`` - does the same as ``\poldef f(x):= 1-x+x^2;`` To use another letter - than ``x`` in the expression, one must pass it as an extra optional - argument to ``\PolDef``. Useful if the semi-colon has been assigned - some non-standard catcode by some package. - -``\PolLet{g}={f}`` - saves a copy of ``f`` under name ``g``. Also usable without ``=``. - -``\poldef f(z):= f(z)^2;`` - redefines ``f`` in terms of itself. - -``\poldef f(T):= f(f(T));`` - again redefines ``f`` in terms of its (new) self. - -``\poldef k(z):= f(z)-g(g(z)^2)^2;`` - should now define the zero polynomial... Let's check: - ``\[ k(z) = \PolTypeset[z]{k} \]`` - -``\PolDiff{f}{f'}`` - sets ``f'`` to the derivative of ``f``. The name doesn't have to be - ``f'`` (in fact the ``'`` is licit only since ``0.5.1``). - -.. important:: - - This is not done automatically. If some new definition needs to use - the derivative of some available polynomial, that derivative - polynomial must have been defined via ``\PolDiff``: something like - ``T'(x)^2`` will not work without a prior ``\PolDiff{T}{T'}``. - -``\PolDiff{f'}{f''}`` - obtains second derivative. - -``\PolDiff[3]{f}{f'''}`` - computes the third derivative. - -:: - - $f(z) = \PolTypeset[z]{f} $\newline - $f'(z) = \PolTypeset[z]{f'} $\newline - $f''(z) = \PolTypeset[z]{f''} $\newline - $f'''(z)= \PolTypeset[z]{f'''} $\par - -.. important:: - - The package does not currently know rational functions: ``/`` in - a parsed polynomial expression does the Euclidean quotient:: - - (1-x^2)/(1-x) - - does give ``1+x`` but :: - - (1/(1-x))*(1-x^2) - - evaluates to zero. This will work as expected:: - - \poldef k(x):= (x-1)(x-2)(x-3)(x-4)/(x^2-5x+4); - -.. _warningtacit: - -.. attention:: - - ``1/2 x^2`` skips the space and is treated like ``1/(2*x^2)`` because - of the tacit multiplication rules of \xintexpr. But this means it - gives zero! Thus one must use ``(1/2)x^2`` or ``1/2*x^2`` or - ``(1/2)*x^2`` for disambiguation: ``x - 1/2*x^2 + 1/3*x^3...``. It is - even simpler to move the denominator to the right: ``x - x^2/2 + - x^3/3 - ...``. - - It is worth noting that ``1/2(x-1)(x-2)`` suffers the same issue: - xint_ tacit multiplication always "ties more", hence this gets - interpreted as ``1/(2*(x-1)*(x-2))`` which gives zero by polynomial - division. Thus, use one of ``(1/2)(x-1)(x-2)``, ``1/2*(x-1)(x-2)`` or - ``(x-1)(x-2)/2``. - -After:: - - \poldef f_1(x):= 25(x-1)(x^2-2)(x-3)(x-4)(x-5);% - \poldef f_2(x):= 37(x-1)(x^2-2)(x-6)(x-7)(x-8);% - -the macro call ``\PolGCD{f_1}{f_2}{k}`` sets ``k`` to the (unitary) GCD of -``f_1`` and ``f_2`` (hence to the expansion of ``(x-1)(x^2-2)``.) - -``\PolToExpr{k}`` - will (expandably) give in this case ``x^3-x^2-2*x+2``. This is - useful for console or file output (the syntax is Maple- and - PSTricks-compatible; the letter used in output can be - (non-expandably) changed via a redefinition of `\\PolToExprVar`_.) - -``\PolToExpr*{k}`` - gives ascending powers: ``2-2*x-x^2+x^3``. - -Examples of localization of roots ---------------------------------- - -- To make printed decimal numbers more enjoyable than via - ``\xintSignedFrac``:: - - \renewcommand\PolTypesetOne[1]{\PolDecToString{\xintREZ{#1}}}% - - ``\PolDecToString`` will use decimal notation to incorporate the power - of ten part; and the ``\xintREZ`` will have the effect to suppress - trailing zeros if present in raw numerator (if those digits end up - after decimal mark.) Notice that the above are expandable macros and - that one can also do:: - - \renewcommand\PolToExprCmd[1]{\PolDecToString{\xintREZ{#1}}}% - - to modify output of `\\PolToExpr{polname}`_. - -- For extra info in log file use ``\xintverbosetrue``. - -- Only for some of these examples is the output included here. - - -A typical example -~~~~~~~~~~~~~~~~~ - -In this example the polynomial is square-free. - -:: - - \poldef f(x) := x^7 - x^6 - 2x + 1; - - \PolToSturm{f}{f} - \PolSturmIsolateZeros{f} - The \PolTypeset{f} polynomial has \PolSturmNbOfIsolatedZeros{f} distinct real - roots which are located in the following intervals: - \PolPrintIntervals{f} - Here is the second root with ten more decimal digits: - \PolRefineInterval[10]{f}{2} - \[\PolSturmIsolatedZeroLeft{f}{2}<Z_2<\PolSturmIsolatedZeroRight{f}{2}\] - And here is the first root with twenty digits after decimal mark: - \PolEnsureIntervalLength{f}{1}{-20} - \[\PolSturmIsolatedZeroLeft{f}{1}<Z_1<\PolSturmIsolatedZeroRight{f}{1}\] - The first element of the Sturm chain has degree $\PolDegree{f_0}$. As - this is the original degreee $\PolDegree{f}$ we know that $f$ is square free. - Its derivative is up to a constant \PolTypeset{f_1} (in this example - it is identical with it). - \PolToSturm{f_1}{f_1}\PolSturmIsolateZeros{f_1}% - The derivative has \PolSturmNbOfIsolatedZeros{f_1} distinct real - roots: - \PolPrintIntervals[W]{f_1} - \PolEnsureIntervalLengths{f_1}{-10}% - Here they are with ten digits after decimal mark: - \PolPrintIntervals[W]{f_1} - \PolDiff{f_1}{f''} - \PolToSturm{f''}{f''} - \PolSturmIsolateZeros{f''} - The second derivative is \PolTypeset{f''}. - It has \PolSturmNbOfIsolatedZeros{f''} distinct real - roots: - \PolPrintIntervals[X]{f''} - Here is the positive one with 20 digits after decimal mark: - \PolEnsureIntervalLength{f''}{2}{-20}% - \[X_2 = \PolSturmIsolatedZeroLeft{f''}{2}\dots\] - The more mathematically advanced among our dear readers will be able - to give the exact value for $X_2$! - -A degree four polynomial with nearby roots -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Notice that this example is a bit outdated as ``0.7`` release has -added ``\PolSturmIsolateZeros**{sturmname}`` which would find exactly -the roots. The steps here retain their interest when one is interested -in finding isolating intervals for example to prepare some demonstration -of dichotomy method. - - -:: - - \PolDef{Q}{(x-1.050001)(x-1.105001)(x-1.110501)(x-1.111051)} - \PolTypeset{Q} - \PolToSturm{Q}{Q} % it is allowed to use same prefix for Sturm chain - \PolSturmIsolateZeros{Q} - \PolPrintIntervals{Q} - % reports 1.0 < Z_1 < 1.1, 1.10 < Z_2 < 1.11, 1.110 < Z_3 < 1.111, and 1.111 < Z_4 < 1.112 - % but the above bounds do not allow minimizing separation between roots - % so we refine: - \PolRefineInterval*{Q}{1} - \PolRefineInterval*{Q}{2} - \PolRefineInterval*{Q}{3} - \PolRefineInterval*{Q}{4} - \PolPrintIntervals{Q} - % reports 1.05 < Z_1 < 1.06, 1.105 < Z_2 < 1.106, 1.1105 < Z_3 < 1.1106, - % and 1.11105 < Z_4 < 1.11106. - \PolEnsureIntervalLengths{Q}{-6} - \PolPrintIntervals{Q} - % of course finds here all roots exactly - - -The degree nine polynomial with 0.99, 0.999, 0.9999 as triple roots -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - % define a user command (xinttools is loaded automatically by polexpr) - \newcommand\showmultiplicities[1]{% #1 = "sturmname" - \xintFor* ##1 in {\xintSeq{1}{\PolSturmNbOfIsolatedZeros{#1}}}\do{% - The multiplicity is \PolSturmIsolatedZeroMultiplicity{#1}{##1} - \PolSturmIfZeroExactlyKnown{#1}{##1}% - {at the root $x=\PolSturmIsolatedZeroLeft{#1}{##1}$} - {for the root such that - $\PolSturmIsolatedZeroLeft{#1}{##1}<x<\PolSturmIsolatedZeroRight{#1}{##1}$} - \par - }}% - \PolDef{f}{(x-0.99)^3(x-0.999)^3(x-0.9999)^3} - \renewcommand\PolTypesetOne[1]{\PolDecToString{\xintREZ{#1}}} - \PolTypeset{f}\par - \PolToSturm{f}{f}% it is allowed to use "polname" as "sturmname" too - \PolSturmIsolateZerosAndGetMultiplicities{f}% use the "sturmname" here - % or \PolSturmIsolateZeros*{f} which is exactly the same, but shorter.. - - \showmultiplicities{f} - -In this example, the output will look like this (but using math mode):: - - x^9 - 8.9667x^8 + 35.73400293x^7 - 83.070418400109x^6 + 124.143648875193123x^5 - - 123.683070924326075877x^4 + 82.149260397553075617891x^3 - - 35.07602992699900159127007x^2 + 8.7364078733314648368671733x - - 0.967100824643585986488103299 - - The multiplicity is 3 at the root x = 0.99 - The multiplicity is 3 at the root x = 0.999 - The multiplicity is 3 at the root x = 0.9999 - -On first pass, these rational roots were found (due to their relative -magnitudes, using ``\PolSturmIsolateZeros**`` was not needed here). But -multiplicity computation works also with (decimal) roots not yet -identified or with non-decimal or irrational roots. - -It is fun to modify only a tiny bit the polynomial and see if polexpr -survives:: - - \PolDef{g}{f(x)+1e-27} - \PolTypeset{g}\par - \PolToSturm{g}{g} - \PolSturmIsolateZeros*{g} - - \showmultiplicities{g} - -This produces:: - - x^9 - 8.9667x^8 + 35.73400293x^7 - 83.070418400109x^6 + 124.143648875193123x^5 - - 123.683070924326075877x^4 + 82.149260397553075617891x^3 - - 35.07602992699900159127007x^2 + 8.7364078733314648368671733x - - 0.967100824643585986488103298 - - The multiplicity is 1 for the root such that 0.98 < x < 0.99 - The multiplicity is 1 for the root such that 0.9991 < x < 0.9992 - The multiplicity is 1 for the root such that 0.9997 < x < 0.9998 - -Which means that the multiplicity-3 roots each became a real and a pair of -complex ones. Let's see them better:: - - \PolEnsureIntervalLengths{g}{-10} - - \showmultiplicities{g} - -which produces:: - - The multiplicity is 1 for the root such that 0.9899888032 < x < 0.9899888033 - The multiplicity is 1 for the root such that 0.9991447980 < x < 0.9991447981 - The multiplicity is 1 for the root such that 0.9997663986 < x < 0.9997663987 - -A degree five polynomial with three rational roots -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - \poldef Q(x) := 1581755751184441 x^5 - -14907697165025339 x^4 - +48415668972339336 x^3 - -63952057791306264 x^2 - +46833913221154895 x - -49044360626280925; - - \PolToSturm{Q}{Q} - %\begin{flushleft} - \renewcommand\PolTypesetCmdPrefix[1]{\allowbreak\xintiiifSgn{#1}{}{+}{+}}% - $Q_0(x) = \PolTypeset{Q_0}$ - %\end{flushleft} - \PolSturmIsolateZeros**{Q} - \PolPrintIntervals{Q} - - $Q_{norr}(x) = \PolTypeset{Q_norr}$ - -Here, all real roots are rational:: - - Z_1 = 833719/265381 - Z_2 = 165707065/52746197 - Z_3 = 355/113 - - Q_norr(x) = x^2 + 1 - -And let's get their decimal expansion too:: - - % print decimal expansion of the found roots - \renewcommand\PolPrintIntervalsPrintExactZero - {\xintTrunc{20}{\PolPrintIntervalsTheLeftEndPoint}\dots} - \PolPrintIntervals{Q} - - Z_1 = 3.14159265358107777120... - Z_2 = 3.14159265358979340254... - Z_3 = 3.14159292035398230088... - - -A Mignotte type polynomial -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - \PolDef{P}{x^10 - (10x-1)^2}% - \PolTypeset{P} % prints it in expanded form - \PolToSturm{P}{P} % we can use same prefix for Sturm chain - \PolSturmIsolateZeros{P} % finds 4 real roots - This polynomial has \PolSturmNbOfIsolatedZeros{P} distinct real roots: - \PolPrintIntervals{P}% - % reports -2 < Z_1 < -1, 0.09 < Z_2 < 0.10, 0.1 < Z_3 < 0.2, 1 < Z_4 < 2 - Let us refine the second and third intervals to separate the corresponding - roots: - \PolRefineInterval*{P}{2}% will refine to 0.0999990 < Z_2 < 0.0999991 - \PolRefineInterval*{P}{3}% will refine to 0.100001 < Z_3 < 0.100002 - \PolPrintIntervals{P}% - Let us now get to know all roots with 10 digits after decimal mark: - \PolEnsureIntervalLengths{P}{-10}% - \PolPrintIntervals{P}% now all roots are known 10 decimal digits after mark - Finally, we display 20 digits of the second root: - \PolEnsureIntervalLength{P}{2}{-20}% makes Z_2 known with 20 digits after mark - \[\PolSturmIsolatedZeroLeft{P}{2}<Z_2<\PolSturmIsolatedZeroRight{P}{2}\] - -The last line produces:: - - 0.09999900004999650028 < Z_2 < 0.09999900004999650029 - - -The Wilkinson polynomial -~~~~~~~~~~~~~~~~~~~~~~~~ - -See `Wilkinson polynomial`_. - -:: - - \documentclass{article} - \usepackage{polexpr} - \begin{document} - %\xintverbosetrue % for the curious... - - \poldef f(x) := mul((x - i), i = 1..20); - - \renewcommand\PolTypesetCmdPrefix[1]{\allowbreak\xintiiifSgn{#1}{}{+}{+}}% - \renewcommand\PolTypesetOne[1]{\xintDecToString{#1}}% - - \noindent\PolTypeset{f} - - \PolToSturm{f}{f} - \PolSturmIsolateZeros{f} - \PolPrintIntervals{f} - - \clearpage - - \poldef g(x) := f(x) - 2**{-23} x**19; - - % be patient! - \PolToSturm{g}{g} - \noindent\PolTypeset{g_0}% integer coefficient primitive polynomial - - \PolSturmIsolateZeros{g} - \PolEnsureIntervalLengths{g}{-10} - - \renewcommand\PolPrintIntervalsPrintMultiplicity{} - \PolPrintIntervals*{g} - - \end{document} - - -The first polynomial:: - - f(x) = x**20 - - 210 x**19 - + 20615 x**18 - - 1256850 x**17 - + 53327946 x**16 - - 1672280820 x**15 - + 40171771630 x**14 - - 756111184500 x**13 - + 11310276995381 x**12 - - 135585182899530 x**11 - + 1307535010540395 x**10 - - 10142299865511450 x**9 - + 63030812099294896 x**8 - - 311333643161390640 x**7 - + 1206647803780373360 x**6 - - 3599979517947607200 x**5 - + 8037811822645051776 x**4 - - 12870931245150988800 x**3 - + 13803759753640704000 x**2 - - 8752948036761600000 x - + 2432902008176640000 - -is handled fast enough (a few seconds), but the modified one ``f(x) - -2**-23 x**19`` takes about 20x longer (the Sturm chain polynomials -have integer coefficients with up to 321 digits, whereas (surprisingly -perhaps) those of the Sturm chain polynomials derived from ``f`` never -have more than 21 digits ...). - -Once the Sturm chain is computed and the zeros isolated, obtaining their -decimal digits is relatively faster. Here is for the ten real roots of -``f(x) - 2**-23 x**19`` as computed by the code above:: - - Z_1 = 0.9999999999... - Z_2 = 2.0000000000... - Z_3 = 2.9999999999... - Z_4 = 4.0000000002... - Z_5 = 4.9999999275... - Z_6 = 6.0000069439... - Z_7 = 6.9996972339... - Z_8 = 8.0072676034... - Z_9 = 8.9172502485... - Z_10 = 20.8469081014... - -The second Wilkinson polynomial -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - \documentclass{article} - \usepackage{polexpr} - \begin{document} - \poldef f(x) := mul(x - 2^-i, i = 1..20); - - %\PolTypeset{f} - - \PolToSturm{f}{f} - \PolSturmIsolateZeros**{f} - \PolPrintIntervals{f} - \end{document} - -This takes more time than the polynomial with 1, 2, .., 20 as roots but -less than the latter modified by the ``2**-23`` change in one -coefficient. - -Here is the output (with release 0.7.2):: - - Z_1 = 0.00000095367431640625 - Z_2 = 0.0000019073486328125 - Z_3 = 0.000003814697265625 - Z_4 = 0.00000762939453125 - Z_5 = 0.0000152587890625 - Z_6 = 0.000030517578125 - Z_7 = 0.00006103515625 - Z_8 = 0.0001220703125 - Z_9 = 1/4096 - Z_10 = 1/2048 - Z_11 = 1/1024 - Z_12 = 1/512 - Z_13 = 1/256 - Z_14 = 1/128 - Z_15 = 0.015625 - Z_16 = 0.03125 - Z_17 = 0.0625 - Z_18 = 0.125 - Z_19 = 0.25 - Z_20 = 0.5 - -There is some incoherence in output format which has its source in the -fact that some roots are found in branches which can only find decimal -roots, whereas some are found in branches which could find general -fractions and they use ``\xintIrr`` before storage of the found root. -This may evolve in future. - - -The degree 41 polynomial with -2, -1.9, -1.8, ..., 0, 0.1, ..., 1.9, 2 as roots -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - \PolDef{P}{mul((x-i*1e-1), i=-20..20)}% i/10 is same but less efficient - -In the defining expression we could have used ``i/10`` but this gives -less efficient internal form for the coefficients (the ``10``'s end up -in denominators). Using ``\PolToExpr{P}`` after having done - -:: - - \renewcommand\PolToExprCmd[1]{\PolDecToString{\xintREZ{#1}}} - -we get this expanded form:: - - x^41 - -28.7*x^39 - +375.7117*x^37 - -2975.11006*x^35 - +15935.28150578*x^33 - -61167.527674162*x^31 - +173944.259366417394*x^29 - -373686.963560544648*x^27 - +613012.0665016658846445*x^25 - -771182.31133138163125495*x^23 - +743263.86672885754888959569*x^21 - -545609.076599482896371978698*x^19 - +301748.325708943677229642930528*x^17 - -123655.8987669450434698869844544*x^15 - +36666.1782054884005855608205864192*x^13 - -7607.85821367459445649518380016128*x^11 - +1053.15135918687298508885950223794176*x^9 - -90.6380005918141132650786081964032*x^7 - +4.33701563847327366842552218288128*x^5 - -0.0944770968420804735498178265088*x^3 - +0.00059190121813899276854174416896*x - -which shows coefficients with up to 36 significant digits... - -Stress test: not a hard challenge to ``xint + polexpr``, but be a bit patient! - -:: - - \PolDef{P}{mul((x-i*1e-1), i=-20..20)}% - \PolToSturm{P}{S} % dutifully computes S_0, ..., S_{41} - % the [1] optional argument limits the search to interval (-10,10) - \PolSturmIsolateZeros[1]{S} % finds *exactly* (but a bit slowly) all 41 roots! - \PolPrintIntervals{S} % nice, isn't it? - -.. note:: - - Release ``0.5`` has *experimental* addition of optional argument - ``E`` to ``\PolSturmIsolateZeros``. It instructs to search roots only - in interval ``(-10^E, 10^E)``. Important: the extremities are - *assumed to not be roots*. In this example, the ``[1]`` in - ``\PolSturmIsolateZeros[1]{S}`` gives some speed gain; without it, it - turns out in this case that ``polexpr`` would have started with - ``(-10^6, 10^6)`` interval. - - Please note that this will probably get replaced in future by the - specification of a general interval. Do not rely on meaning of this - optional argument keeping the same. - -Roots of Chebyshev polynomials -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:: - - \newcount\mycount - \poldef T_0(x) := 1; - \poldef T_1(x) := x; - \mycount 2 - \xintloop - \poldef T_\the\mycount(x) := - 2x*T_\the\numexpr\mycount-1(x) - - T_\the\numexpr\mycount-2(x); - \ifnum\mycount<15 - \advance\mycount 1 - \repeat - - \[T_{15} = \PolTypeset[X]{T_15}\] - \PolToSturm{T_15}{T_15} - \PolSturmIsolateZeros{T_15} - \PolEnsureIntervalLengths{T_15}{-10} - \PolPrintIntervals{T_15} - - -Non-expandable macros ---------------------- - -.. _poldef;: - -``\poldef polname(letter):= expression in letter;`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This evaluates the *polynomial expression* and stores the coefficients - in a private structure accessible later via other package macros, - under the user-chosen ``polname``. Of course the *expression* can - use other previously defined polynomials. Names must start with a - letter and are constituted of letters, digits, underscores and - (since ``0.5.1``) the right tick ``'``. - The whole xintexpr_ syntax is authorized:: - - \poldef sin(z) := add((-1)^i z^(2i+1)/(2i+1)!, i = 0..10); - - With fractional coefficients, beware the `tacit multiplication issue - <warningtacit_>`_. - - As a side effect the function ``polname()`` is recognized as a - genuine ``\xintexpr...\relax`` function for (exact) numerical - evaluation (or within an ``\xintdefvar`` assignment.) It computes - values not according to the original expression but via the Horner - scheme corresponding to the polynomial coefficients. - - .. attention:: - - Release ``0.3`` also did the necessary set-up to let the - polynomial be known to the ``\xintfloatexpr`` (or - ``\xintdeffloatvar``) parser. - - Since ``0.4`` this isn't done automatically. Even more, a - previously existing floating point variant of the same name will - be let undefined again, to avoid hard to debug mismatches between - exact and floating point polynomials. This also applies when the - polynomial is produced not via ``\poldef`` or ``\PolDef`` but as - a product of the other package macros. - - See `\\PolGenFloatVariant{polname}`_. - - The original expression is lost after parsing, and in particular - the package provides no way to typeset it. This has to be done - manually, if needed. - -.. _PolDef: - -``\PolDef[letter]{polname}{expression in letter}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Does the same as `\\poldef <poldef;>`_ in an undelimited macro - format (thus avoiding potential problems with the catcode of the - semi-colon in presence of some packages.) In absence of the - ``[letter]`` optional argument, the variable is assumed to be ``x``. - -.. _PolGenFloatVariant: - -``\PolGenFloatVariant{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Makes the polynomial also usable in the ``\xintfloatexpr`` parser. - It will therein evaluates via an Horner scheme with coefficients - already pre-rounded to the float precision. - - See also `\\PolToFloatExpr{polname}`_. - - .. attention:: - - Release ``0.3`` did this automatically on ``\PolDef`` and - ``\poldef`` but this was removed at ``0.4`` for optimization. - - Any operation, for example generating the derivative polynomial, - or dividing two polynomials or using the ``\PolLet``, **must** be - followed by explicit usage of ``\PolGenFloatVariant{polname}`` if - the new polynomial is to be used in ``\xintfloatexpr`` or alike - context. - -.. _PolLet: - -``\PolLet{polname_2}={polname_1}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Makes a copy of the already defined polynomial ``polname_1`` to a - new one ``polname_2``. Same effect as - ``\PolDef{polname_2}{polname_1(x)}`` but with less overhead. The - ``=`` is optional. - -.. _PolGlobalLet: - -``\PolGlobalLet{polname_2}={polname_1}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Acts globally. - -.. _PolAssign: - -``\PolAssign{polname}\toarray\macro`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Defines a one-argument expandable macro ``\macro{#1}`` which expands - to the (raw) #1th polynomial coefficient. - - - Attention, coefficients here are indexed starting at 1. - - - With #1=-1, -2, ..., ``\macro{#1}`` returns leading coefficients. - - - With #1=0, returns the number of coefficients, i.e. ``1 + deg f`` - for non-zero polynomials. - - - Out-of-range #1's return ``0/1[0]``. - - See also `\\PolNthCoeff{polname}{number}`_. The main difference is that - with ``\PolAssign``, ``\macro`` is made a prefix to ``1 + deg f`` - already defined (hidden to user) macros holding individually the - coefficients but `\\PolNthCoeff{polname}{number}`_ does each time the job - to expandably recover the ``Nth`` coefficient, and due to - expandability can not store it in a macro for future usage (of course, - it can be an argument in an ``\edef``.) The other difference - is the shift by one in indexing, mentioned above (negative - indices act the same in both.) - -.. _PolGet: - -``\PolGet{polname}\fromarray\macro`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Does the converse operation to - ``\PolAssign{polname}\toarray\macro``. Each individual - ``\macro{number}`` gets expanded in an ``\edef`` and then normalized - via xintfrac_\ 's macro ``\xintRaw``. - - The leading zeros are removed from the polynomial. - - (contrived) Example:: - - \xintAssignArray{1}{-2}{5}{-3}\to\foo - \PolGet{f}\fromarray\foo - - This will define ``f`` as would have ``\poldef f(x):=1-2x+5x^2-3x^3;``. - - .. note:: - - Prior to ``0.5``, coefficients were not normalized via - ``\xintRaw`` for internal storage. - -.. _PolFromCSV: - -``\PolFromCSV{polname}{<csv>}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Defines a polynomial directly from the comma separated list of values - (or a macro expanding to such a list) of its coefficients, the *first - item* gives the constant term, the *last item* gives the leading - coefficient, except if zero, then it is dropped (iteratively). List - items are each expanded in an ``\edef`` and then put into normalized - form via xintfrac_\ 's macro ``\xintRaw``. - - As leading zero coefficients are removed:: - - \PolFromCSV{f}{0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - - defines the zero polynomial, which holds only one coefficient. - - See also expandable macro `\\PolToCSV <\\PolToCSV{polname}_>`_. - - .. note:: - - Prior to ``0.5``, coefficients were not normalized via - ``\xintRaw`` for internal storage. - -.. _PolTypeset: - -``\PolTypeset{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~ - - Typesets in descending powers in math mode. It uses letter ``x`` but - this can be changed via an optional argument:: - - \PolTypeset[z]{polname} - - By default zero coefficients are skipped (issue ``\poltypesetalltrue`` - to get all of them in output). - - These commands (whose meanings will be found in the package code) - can be re-defined for customization. Their default definitions are - expandable, but this is not a requirement. - -.. _PolTypesetCmd: - -``\PolTypesetCmd{raw_coeff}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Checks if the coefficient is ``1`` or ``-1`` and then skips printing - the ``1``, except for the constant term. Also it sets conditional - `\\PolIfCoeffIsPlusOrMinusOne{A}{B}`_. - - The actual printing of the coefficients, when not equal to plus or - minus one is handled by `\\PolTypesetOne{raw_coeff}`_. - -.. _PolTypesetOne: - -``\PolTypesetOne{raw_coeff}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - The default is ``\xintSignedFrac`` but this macro is annoying as it - insists to use a power of ten, and not decimal notation. - - One can do things such as for example: [#]_ - - :: - - \renewcommand\PolTypesetOne[1]{\num{\xintPFloat[5]{#1}}} - \renewcommand\PolTypesetOne[1]{\num{\xintRound{4}{#1}}} - - where e.g. we used the ``\num`` macro of ``siunitx`` as it - understands floating point notation. - - .. [#] the difference in the syntaxes of ``\xintPFloat`` and - ``\xintRound`` is explained from the fact that - ``\xintPFloat`` by default uses the prevailing precision - hence the extra argument like here ``5`` is an optional one. - - One can also give a try to using `\\PolDecToString{decimal number}`_ - which uses decimal notation (at least for the numerator part). - -.. _PolTypesetMonomialCmd: - -``\PolTypesetMonomialCmd`` -^^^^^^^^^^^^^^^^^^^^^^^^^^ - - This decides how a monomial (in variable ``\PolVar`` and with - exponent ``\PolIndex``) is to be printed. The default does nothing - for the constant term, ``\PolVar`` for the first degree and - ``\PolVar^{\PolIndex}`` for higher degrees monomials. Beware that - ``\PolIndex`` expands to digit tokens and needs termination in - ``\ifnum`` tests. - -.. _PolTypesetCmdPrefix: - -``\PolTypesetCmdPrefix{raw_coeff}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Expands to a ``+`` if the ``raw_coeff`` is zero or positive, and to - nothing if ``raw_coeff`` is negative, as in latter case the - ``\xintSignedFrac`` used by `\\PolTypesetCmd{raw_coeff}`_ will put - the ``-`` sign in front of the fraction (if it is a fraction) and - this will thus serve as separator in the typeset formula. Not used - for the first term. - -.. _PolTypeset*: - -``\PolTypeset*{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~ - - Typesets in ascending powers. Use e.g. ``[h]`` optional argument - (after the ``*``) to use letter ``h`` rather than ``x``. - -.. _PolDiff: - -``\PolDiff{polname_1}{polname_2}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_2`` to the first derivative of ``polname_1``. It - is allowed to issue ``\PolDiff{f}{f}``, effectively replacing ``f`` - by ``f'``. - - Coefficients of the result ``polname_2`` are irreducible fractions - (see `Technicalities`_ for the whole story.) - -.. _PolDiff[N]: - -``\PolDiff[N]{polname_1}{polname_2}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_2`` to the ``N``-th derivative of ``polname_1``. - Identical arguments is allowed. With ``N=0``, same effect as - ``\PolLet{polname_2}={polname_1}``. With negative ``N``, switches to - using ``\PolAntiDiff``. - -.. _PolAntiDiff: - -``\PolAntiDiff{polname_1}{polname_2}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_2`` to the primitive of ``polname_1`` vanishing - at zero. - - Coefficients of the result ``polname_2`` are irreducible fractions - (see `Technicalities`_ for the whole story.) - -.. _PolAntiDiff[N]: - -``\PolAntiDiff[N]{polname_1}{polname_2}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_2`` to the result of ``N`` successive integrations on - ``polname_1``. With negative ``N``, it switches to using ``\PolDiff``. - -.. _PolDivide: - -``\PolDivide{polname_1}{polname_2}{polname_Q}{polname_R}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_Q`` and ``polname_R`` to be the quotient and - remainder in the Euclidean division of ``polname_1`` by - ``polname_2``. - -.. _PolQuo: - -``\PolQuo{polname_1}{polname_2}{polname_Q}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_Q`` to be the quotient in the Euclidean division - of ``polname_1`` by ``polname_2``. - -.. _PolRem: - -``\PolRem{polname_1}{polname_2}{polname_R}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_R`` to be the remainder in the Euclidean division - of ``polname_1`` by ``polname_2``. - -.. _PolGCD: - -``\PolGCD{polname_1}{polname_2}{polname_GCD}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This sets ``polname_GCD`` to be the (monic) GCD of the two first - polynomials. It is a unitary polynomial except if both ``polname_1`` - and ``polname_2`` vanish, then ``polname_GCD`` is the zero - polynomial. - -.. ``\PolIGCD{polname_1}{polname_2}{polname_iGCD}`` - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - **NOT YET** - - This **assumes** that the two polynomials have integer coefficients. - It then computes the greatest common divisor in the integer - polynomial ring, normalized to have a positive leading coefficient - (if the inputs are not both zero). - - ``\PolIContent{polname}`` - ~~~~~~~~~~~~~~~~~~~~~~~~~ - - **NOT YET** - - This computes a positive rational number such that dividing the - polynomial with it returns an integer coefficients polynomial with - no common factor among the coefficients. - -.. _PolToSturm: - -``\PolToSturm{polname}{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - With ``polname`` being for example ``P``, the macro starts by - computing polynomials ``P`` and ``P'``, then computes the (opposite - of the) remainder in euclidean division, iteratively. - - The last non-zero remainder ``P_N_`` (where ``N`` is obtainable as - `\\PolSturmChainLength{sturmname}`_) is up to a factor - the GCD of ``P`` and ``P'`` hence it is a constant if and only if - ``P`` is square-free. - - .. note:: - - - Since ``0.5`` all these polynomials are divided by their rational - content, so they have integer coefficients with no common factor, - and the last one if a constant is either ``1`` or ``-1``. - - - After this normalization to primitive polynomials, they are - stored internally as ``sturmname_k_``, ``k=0,1, ...``. - - - These polynomials are used internally only. To keep them as - genuine declared polynomials also after the macro call, use the - starred variant `PolToSturm*`_. - - .. note:: - - It is perfectly allowed to use the polynomial name as Sturm chain name: - ``\PolToSturm{f}(f}``. - - The macro then declares ``sturmname_0``, ``sturmname_1``, ..., which are - the (non-declared) ``sturmname_k_`` divided by the last one. Division is - not done if this last one is the constant ``1`` or ``-1``, i.e. if the - original polynomial was square-free. These polynomials are primitive - polynomials too, i.e. with integer coefficients having no common factor. - - Thus ``sturmname_0`` has exactly the same real and complex roots as - polynomial ``polname``, but with each root now of multiplicity one: - i.e. it is the "square-free part" of original polynomial ``polname``. - - Notice that ``sturmname_1`` isn't necessarily the derivative of - ``sturmname_0`` due to the various normalizations. - - The polynomials ``sturmname_k`` main utility is for the execution of - `\\PolSturmIsolateZeros{sturmname}`_. Be careful not to use these - names ``sturmname_0``, ``sturmname_1``, etc... for defining other - polynomials after having done ``\PolToSturm{polname}{sturmname}`` and - before executing ``\PolSturmIsolateZeros{sturmname}`` else the - latter will behave erroneously. - - `\\PolSturmChainLength{sturmname}`_ gives the index of the last - element of the Sturm chain. - -.. _PolToSturm*: - -``\PolToSturm*{polname}{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Does the same as `un-starred version <PolToSturm_>`_ and additionally it - keeps for user usage the memory of the *un-normalized* Sturm chain - polynomials ``sturmname_k_``, ``k=0,1, ..., N``, with - ``N`` being `\\PolSturmChainLength{sturmname}`_. - - .. note:: - - This behaviour was modified at ``0.6``, anyhow the macro was - broken at ``0.5``. - - .. hint:: - - The square-free part of ``polname`` is ``sturmname_0``, and their - quotient is the polynomial with name - ``sturname_\PolSturmChainLength{sturmname}_``. It thus easy to - set-up a loop iteratively computing the latter until the last one - is a constant, thus obtaining the decomposition of an ``f`` as - a product ``c f_1 f_2 f_3 ...`` of a constant and square-free (primitive) - polynomials, where each ``f_i`` divides its predecessor. - -.. _PolSetToSturmChainSignChangesAt: - -``\PolSetToSturmChainSignChangesAt{\macro}{sturmname}{fraction}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Sets macro ``\macro`` to the number of sign changes in the Sturm - chain with name prefix ``sturmname``, at location ``fraction`` - (which must be in format as acceptable by the xintfrac_ macros.) - - .. note:: - - The author was lazy and did not provide rather an expandable - variant, where one would do ``\edef\macro{\PolNbOf...}``. - - This will presumably get added in a future release. - - After some hesitation it was decided the macro would by default - act globally. To make the scope of its macro definition local, - use ``[\empty]`` as extra optional argument. - -.. _PolSetToNbOfZerosWithin: - -``\PolSetToNbOfZerosWithin{\macro}{sturmname}{value_a}{value_b}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Applies the `Sturm Theorem`_ to set ``\macro`` to the exact number - of **distinct** roots of ``sturmname_0`` in the interval ``(value_a, - value_b]`` (the macro first re-orders the value for ``value_a <= - value_b`` to hold). - - .. note:: - - The author was lazy and did not provide rather an expandable - variant, where one would do ``\edef\macro{\PolNbOf...}``. - - This will presumably get added in future. - - After some hesitation it was decided the macro would by default - act globally. To make the scope of its macro definition local, - use ``[\empty]`` as extra optional argument. - - See also the expandable - `\\PolSturmNbOfRootsOf{sturmname}\\LessThanOrEqualTo{value}`_, from - which it is immediate (with ``\numexpr``) to create an expandable - variant of this macro. However the difference is that this macro - requires only `\\PolToSturm <PolToSturm_>`_ to have been executed, - whereas the expandable variant requires prior execution of - `\\PolSturmIsolateZeros <PolSturmIsolateZeros_>`_. - - See also the expandable - `\\PolSturmNbWithMultOfRootsOf{sturmname}\\LessThanOrEqualTo{value}`_ - which requires prior execution of - `\\PolSturmIsolateZeros* <PolSturmIsolateZeros*_>`_. - - -.. _PolSturmIsolateZeros: - -``\PolSturmIsolateZeros{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The macros locates, using `Sturm theorem`_, as many disjoint - intervals as there are (real) roots. - - .. important:: - - The Sturm chain must have been produced by an earlier - `\\PolToSturm{polname}{sturmname}`_. - - Why does this macro ask for argument the name of Sturm chain, - rather than the name of a polynomial? well this is mainly for - legacy reason, and because it is accompanied by other macros for - which it is simpler to assume the argument will be the name of an - already computed Sturm chain. - - Notice that ``\PolToSturm{f}{f}`` is perfectly legal (the - ``sturmname`` can be same as the ``polname``): it defines - polynomials ``f_0``, ``f_1``, ... having ``f`` has name prefix. - - Such a prior call - to ``\PolToSturm`` must have been made at any rate for - ``\PolSturmIsolateZeros`` to be usable. - - After its execution they are two types of such intervals (stored in - memory and accessible via macros or xintexpr_ variables, see below): - - - singleton ``{a}``: then ``a`` is a root, (necessarily a decimal - number, but not all such decimal numbers are exactly identified yet). - - - open intervals ``(a,b)``: then there is exactly one root ``z`` - such that ``a < z < b``, and the end points are guaranteed to not - be roots. - - The interval boundaries are decimal numbers, originating - in iterated decimal subdivision from initial intervals - ``(-10^E, 0)`` and ``(0, 10^E)`` with ``E`` chosen initially large - enough so that all roots are enclosed; if zero is a root it is always - identified as such. The non-singleton intervals are of the - type ``(a/10^f, (a+1)/10^f)`` with ``a`` an integer, which is - neither ``0`` nor ``-1``. Hence either ``a`` and ``a+1`` are both positive - or they are both negative. - - One does not *a priori* know what will be the lengths of these - intervals (except that they are always powers of ten), they - vary depending on how many digits two successive roots have in - common in their respective decimal expansions. - - .. important:: - - If some two consecutive intervals share an end-point, no - information is yet gained about the separation between the two - roots which could at this stage be arbitrarily small. - - See `\\PolRefineInterval*{sturmname}{index}`_ which addresses - this issue. - - .. This procedure is covariant - with the independent variable ``x`` becoming ``-x``. - Hmm, pas sûr et trop fatigué - - The interval boundaries (and exactly found roots) are made available - for future computations in ``\xintexpr``-essions or polynomial - definitions as variables ``<sturmname>L_1``, - ``<sturmname>L_2``, etc..., for the left end-points and - ``<sturmname>R_1``, ``<sturmname>R_2``, ..., for the right - end-points. - - Thus for example, if ``sturmname`` is ``f``, one can use the - xintexpr_ variables ``fL_1``, ``fL_2``, ... to refer in expressions - to the left end-points (or to the exact root, if left and right end - points coincide). Additionally, xintexpr_ variable ``fZ_1_isknown`` - will have value ``1`` if the root in the first interval is known, - and ``0`` otherwise. And similarly for the other intervals. - - Also, macros `\\PolSturmIsolatedZeroLeft{sturmname}{index}`_ and - `\\PolSturmIsolatedZeroRight{sturmname}{index}`_ are provided which - expand to these same values, written in decimal notation (i.e. - pre-processed by `\\PolDecToString <PolDecToString_>`_.) And there - is also `\\PolSturmIfZeroExactlyKnown{sturmname}{index}{A}{B}`_. - - .. important:: - - Trailing zeroes in the stored decimal numbers accessible via the - macros are significant: they are also present in the decimal - expansion of the exact root. - - These variables and macros are automatically updated when one next - uses macros such as `\\PolRefineInterval*{sturmname}{index}`_. - - The start of decimal expansion of a positive ``k``-th root is given - by `\\PolSturmIsolatedZeroLeft{sturmname}{k} - <PolSturmIsolatedZeroLeft_>`_, and for a negative root it is given - by `\PolSturmIsolatedZeroRight{sturmname}{k} - <PolSturmIsolatedZeroRight_>`_. These two decimal - numbers are either both zero or both of the same sign. - - The number of distinct roots is obtainable expandably as - `\\PolSturmNbOfIsolatedZeros{sturmname}`_. - - Furthermore - `\\PolSturmNbOfRootsOf{sturmname}\\LessThanOrEqualTo{value}`_ and - `\\PolSturmNbOfRootsOf{sturmname}\\LessThanOrEqualToExpr{expression}`_. - will expandably compute respectively the number of real roots at - most equal to ``value`` or ``expression``, and the same but with - multiplicities. - - .. note:: - - In the current implementation the xintexpr_ variables - and xinttools_ arrays are globally defined. On the - other hand the Sturm sequence polynomials obey the current scope. - - .. note:: - - As all computations are done *exactly* there can be no errors... - apart those due to bad coding by author. The results are exact - bounds for the mathematically exact real roots. - - Future releases will perhaps also provide macros based on Newton - or Regula Falsi methods. Exact computations with such methods - lead however quickly to very big fractions, and this forces usage - of some rounding scheme for the abscissas if computation times - are to remain reasonable. This raises issues of its own, which - are studied in numerical mathematics. - -.. _PolSturmIsolateZeros*: - -``\PolSturmIsolateZeros*{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The macro does the same as `\\PolSturmIsolateZeros{sturmname}`_ and - then in addition it does the extra work to determine all - multiplicities (of the real roots): - after executing this macro, - `\\PolSturmIsolatedZeroMultiplicity{sturmname}{index}`_ will expand - to the multiplicity of the root located in the ``index``\ -th - interval (intervals are enumerated from left to right, with index - starting at ``1``). - - Furthermore, if for example the ``sturmname`` is ``f``, xintexpr_ - variables ``fM_1``, ``fM_2``... hold the multiplicities thus - computed. - - .. note:: - - It is **not** necessary to have executed the `PolToSturm*`_ starred - variant, as the non-starred variant keeps internally the memory of the - original GCD (and even of the full non-normalized original Sturm - chain), even though it does not make the declarations as *user-level* - genuine polynomials. - - See `The degree nine polynomial with 0.99, 0.999, 0.9999 as triple - roots`_ for an example. - -.. _PolSturmIsolateZeros**: - -``\PolSturmIsolateZeros**{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The macro does the same as `\\PolSturmIsolateZeros*{sturmname}`_ and - in addition it does the extra work to determine all the *rational* - roots. - - .. note:: - - After execution of this macro, a root is "known" if and only if - it is rational. - - Furthermore, primitive polynomial ``sturmname_sqf_norr`` is created - to match the (square-free) ``sturmname_0`` from which all rational - roots have been removed (see `\\polexprsetup`_ for customizing this - name). The number of distinct rational roots is thus the difference - between the degrees of these two polynomials (see also - `\\PolSturmNbOfRationalRoots{sturmname}`_). - - And ``sturmname_norr`` is ``sturmname_0_`` from which all rational - roots have been removed (see `\\polexprsetup`_), i.e. it contains - the irrational roots of the original polynomial, with the same - multiplicities. - - See `A degree five polynomial with three rational - roots`_ for an example. - -.. _PolSturmIsolateZerosAndGetMultiplicities: - -``\PolSturmIsolateZerosAndGetMultiplicities{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This is another name for `\\PolSturmIsolateZeros*{sturmname}`_. - -.. _PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots: - -``\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This is another name for `\\PolSturmIsolateZeros**{sturmname}`_. - - -``\PolSturmIsolateZerosAndFindRationalRoots{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This works exactly like `\\PolSturmIsolateZeros**{sturmname}`_ - (inclusive of declaring the polynomials ``sturmname_sqf_norr`` and - ``sturmname_norr`` with no rational roots) except that it does *not* - compute the multiplicities of the *non-rational* roots. - - .. note:: - - There is no macro to find the rational roots but not compute - their multiplicities at the same time. - - .. attention:: - - This macro does *not* define xintexpr_ variables - ``sturmnameM_1``, ``sturmnameM_2``, ... holding the - multiplicities and it leaves the multiplicity array (whose accessor - is `\\PolSturmIsolatedZeroMultiplicity{sturmname}{index}`_) into - a broken state, as all non-rational roots will supposedly have - multiplicity one. This means that the output of - `\\PolPrintIntervals* <PolPrintIntervals*_>`_ for example will be - erroneous for the intervals with irrational roots. - - I decided to document it because finding multiplicities of the - non rational roots is somewhat costly, and one may be interested - only into finding the rational roots (of course random - polynomials with integer coefficients will not have *any* - rational root anyhow). - - -.. _PolRefineInterval*: - -``\PolRefineInterval*{sturmname}{index}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The ``index``\ -th interval (starting indexing at one) is further - subdivided as many times as is necessary in order for the newer - interval to have both its end-points distinct from the end-points of - the original interval. This means that the ``k``\ th root is then - strictly separated from the other roots. - -.. _PolRefineInterval[N]: - -``\PolRefineInterval[N]{sturmname}{index}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The ``index``\ -th interval (starting count at one) is further - subdivided once, reducing its length by a factor of 10. This is done - ``N`` times if the optional argument ``[N]`` is present. - -.. _PolEnsureIntervalLength: - -``\PolEnsureIntervalLength{sturmname}{index}{E}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The ``index``\ -th interval is subdivided until its length becomes at - most ``10^E``. This means (for ``E<0``) that the first ``-E`` digits - after decimal mark of the ``k``\ th root will then be known exactly. - -.. _PolEnsureIntervalLengths: - -``\PolEnsureIntervalLengths{sturmname}{E}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The intervals as obtained from ``\PolSturmIsolateZeros`` are (if - necessary) subdivided further by (base 10) dichotomy in order for - each of them to have length at most ``10^E`` (length will be shorter - than ``10^E`` in output only if it did not change or became zero.) - - This means that decimal expansions of all roots will be known with - ``-E`` digits (for ``E<0``) after decimal mark. - -.. _PolPrintIntervals: - -``\PolPrintIntervals[varname]{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This is a convenience macro which prints the bounds for the roots - ``Z_1``, ``Z_2``, ... (the optional argument ``varname`` allows to - specify a replacement for the default ``Z``). This will be done (by - default) in a - math mode ``array``, one interval per row, and pattern ``rcccl``, - where the second and fourth column hold the ``<`` sign, except when - the interval reduces to a singleton, which means the root is known - exactly. - - .. attention:: - - This macro was refactored at 0.7, its default output remained - identical but the ways to customize it got completely - modified. - - See next macros which govern its output. - -``\PolPrintIntervalsNoRealRoots`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Executed in place of an ``array`` environment, when there are no - real roots. Default definition:: - - \newcommand\PolPrintIntervalsNoRealRoots{} - -``\PolPrintIntervalsBeginEnv`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Default definition:: - - \newcommand\PolPrintIntervalsBeginEnv{\[\begin{array}{rcccl}} - -``\PolPrintIntervalsEndEnv`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Default definition:: - - \newcommand\PolPrintIntervalsEndEnv{\end{array}\]} - -``\PolPrintIntervalsKnownRoot`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Default definition:: - - \newcommand\PolPrintIntervalsKnownRoot{% - &&\PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}% - &=&\PolPrintIntervalsPrintExactZero - } - -``\PolPrintIntervalsUnknownRoot`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Default definition:: - - \newcommand\PolPrintIntervalsUnknownRoot{% - \PolPrintIntervalsPrintLeftEndPoint&<&% - \PolPrintIntervalsTheVar_{\PolPrintIntervalsTheIndex}&<&% - \PolPrintIntervalsPrintRightEndPoint - } - - -.. _PolPrintIntervalsPrintExactZero: - -``\PolPrintIntervalsPrintExactZero`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Default definition:: - - \newcommand\PolPrintIntervalsPrintExactZero{\PolPrintIntervalsTheLeftEndPoint} - - -.. _PolPrintIntervalsPrintLeftEndPoint: - -``\PolPrintIntervalsPrintLeftEndPoint`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Default definition:: - - \newcommand\PolPrintIntervalsPrintLeftEndPoint{\PolPrintIntervalsTheLeftEndPoint} - -.. _PolPrintIntervalsPrintRightEndPoint: - -``\PolPrintIntervalsPrintRightEndPoint`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Default definition is:: - - \newcommand\PolPrintIntervalsPrintRightEndPoint{\PolPrintIntervalsTheRightEndPoint} - -.. _PolPrintIntervals*: - -``\PolPrintIntervals*[varname]{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This starred variant produces an alternative output (which - displays the root multiplicity), and is provided as an - example of customization. - - As replacement for `\\PolPrintIntervalsKnownRoot`_, - `\\PolPrintIntervalsPrintExactZero`_, - `\\PolPrintIntervalsUnknownRoot`_ it uses its own - ``\POL@@PrintIntervals...`` macros. We only reproduce here one - definition:: - - \newcommand\POL@@PrintIntervalsPrintExactZero{% - \displaystyle - \xintSignedFrac{\PolPrintIntervalsTheLeftEndPoint}% - }% - - Multiplicities are printed using this auxiliary macro: - -``\PolPrintIntervalsPrintMultiplicity`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - whose default definition is:: - - \newcommand\PolPrintIntervalsPrintMultiplicity{(\mbox{mult. }\PolPrintIntervalsTheMultiplicity)} - - -.. _PolMapCoeffs: - -``\PolMapCoeffs{\macro}{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - It modifies ('in-place': original coefficients get lost) each - coefficient of the defined polynomial via the *expandable* macro - ``\macro``. The degree is adjusted as necessary if some leading - coefficients vanish after the operation. In replacement text of - ``\macro``, ``\index`` expands to the coefficient index (which is - defined to be zero for the constant term). - - Notice that ``\macro`` will have to handle inputs of the shape - ``A/B[N]`` (xintfrac_ internal notation). This means that it probably - will have to be expressed in terms of macros from xintfrac_ package. - - Example:: - - \def\foo#1{\xintMul{#1}{\the\numexpr\index*\index\relax}} - - (or with ``\xintSqr{\index}``) to replace ``n``-th coefficient - ``f_n`` by ``f_n*n^2``. - -.. _PolReduceCoeffs: - -``\PolReduceCoeffs{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - About the same as ``\PolMapCoeffs{\xintIrr}{polname}`` (but - maintaining a ``[0]`` postfix for speedier xintfrac_ parsing when - polynomial function is used for computations.) This is a - one-argument macro, working 'in-place'. - -.. _PolReduceCoeffs*: - -``\PolReduceCoeffs*{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This starred variant leaves un-touched the decimal exponent in the - internal representation of the fractional coefficients, i.e. if a - coefficient is internally ``A/B[N]``, then ``A/B`` is reduced to - smallest terms, but the ``10^N`` part is kept as is. Note: if the - polynomial is freshly defined directly via `\\PolFromCSV - <PolFromCSV_>`_ its coefficients might still be internally in some - format like ``1.5e7``; the macro will anyhow always first do the - needed conversion to strict format ``A/B[N]``. - - Evaluations with polynomials treated by this can be much faster than - with those handled by the non-starred variant - `\\PolReduceCoeffs{polname}`_: as the numerators and denominators - remain smaller, this proves very beneficial in favorable cases - (especially when the coefficients are decimal numbers) to the - expansion speed of the xintfrac_ macros used internally by - `\\PolEval <PolEvalAt_>`_. - -.. _PolMakeMonic: - -``\PolMakeMonic{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Divides by the leading coefficient. It is recommended to execute - `\\PolReduceCoeffs*{polname}`_ immediately afterwards. This is not - done automatically, due to the case the original polynomial had integer - coefficients and we want to keep the leading one as common - denominator. - -.. _PolMakePrimitive: - -``\PolMakePrimitive{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Divides by the integer content see (`\\PolIContent - <PolIContent_>`_). This thus produces a polynomial with integer - coefficients having no common factor. The sign of the leading - coefficient is not modified. - -Expandable macros ------------------ - -All these macros expand completely in two steps except ``\PolToExpr`` -and ``\PolToFloatExpr`` (and their auxiliaries) which need a -``\write``, ``\edef`` or a ``\csname...\endcsname`` context. - -.. _PolEvalAtExpr: - -``\PolEval{polname}\AtExpr{numerical expression}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - It boils down to - ``\xinttheexpr polname(numerical expression)\relax``. - -.. _PolEvalAt: - -``\PolEval{polname}\At{fraction}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Evaluates the polynomial at value ``fraction`` which must be in (or - expand to) a format acceptable to the xintfrac_ macros. - -.. _PolEvalReducedAtExpr: - -``\PolEvalReduced{polname}\AtExpr{numerical expression}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Boils down to ``\xinttheexpr reduce(polname(numerical expression))\relax``. - -.. _PolEvalReducedAt: - -``\PolEvalReduced{polname}\At{fraction}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Evaluates the polynomial at value ``fraction`` which must be in (or - expand to) a format acceptable to the xintfrac_ macros, and produce - an irreducible fraction. - -.. _PolFloatEvalAtExpr: - -``\PolFloatEval{polname}\AtExpr{numerical expression}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Boils down to ``\xintthefloatexpr polname(numerical expression)\relax``. - - This is done via a Horner Scheme (see `\\poldef <poldef;_>`_ and - `\\PolGenFloatVariant{polname}`_), with already rounded - coefficients. [#]_ To use the *exact coefficients* with *exactly - executed* additions and multiplications, just insert it in the float - expression as in this example: [#]_ - - :: - - \xintthefloatexpr 3.27*\xintexpr f(2.53)\relax^2\relax - - The ``f(2.53)`` is exactly computed then rounded at the time of - getting raised to the power ``2``. Moving the ``^2`` inside, that - operation would also be treated exactly. - - - .. [#] Anyway each floating point operation starts by rounding its - operands to the floating point precision. - - .. [#] The ``\xintexpr`` here could be ``\xinttheexpr`` but that - would be less efficient. Cf. xintexpr_ documentation about - nested expressions. - -.. _PolFloatEvalAt: - -``\PolFloatEval{polname}\At{fraction}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Evaluates the polynomial at value ``fraction`` which must be in (or - expand to) a format acceptable to the xintfrac_ macros, and produces - a floating point number. - -.. _PolIfCoeffIsPlusOrMinusOne: - -``\PolIfCoeffIsPlusOrMinusOne{A}{B}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This macro is a priori undefined. - - It is defined via the default `\\PolTypesetCmd{raw_coeff}`_ to be - used if needed in the execution of `\\PolTypesetMonomialCmd`_, - e.g. to insert a ``\cdot`` in front of ``\PolVar^{\PolIndex}`` if - the coefficient is not plus or minus one. - - The macro will execute ``A`` if the coefficient has been found to be - plus or minus one, and ``B`` if not. - -.. _PolLeadingCoeff: - -``\PolLeadingCoeff{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the leading coefficient. - -.. _PolNthCoeff: - -``\PolNthCoeff{polname}{number}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - It expands to the raw ``N``-th coefficient (``0/1[0]`` if the index - number is out of range). With ``N=-1``, ``-2``, ... expands to the - leading coefficients. - -.. _PolDegree: - -``\PolDegree{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~ - - It expands to the degree. This is ``-1`` if zero polynomial but this - may change in future. Should it then expand to ``-\infty`` ? - -.. _PolIContent: - -``\PolIContent{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~ - - It expands to the contents of the polynomial, i.e. to the positive - fraction such that dividing by this fraction produces a polynomial - with integer coefficients having no common prime divisor. - - See `\\PolMakePrimitive <PolMakePrimitive_>`_. - -.. _PolToExpr: - -``\PolToExpr{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~ - - Expands [#]_ to ``coeff_N*x^N+...`` (descending powers.) - - .. [#] in a ``\write``, ``\edef``, or ``\csname...\endcsname``, but - not under ``\romannumeral-`0``. - - By default zero coefficients are skipped (issue ``\poltoexpralltrue`` to - get all of them in output). - - By default, no ``+`` sign before negative coefficients, for - compliance with Maple input format (but see - `\\PolToExprTermPrefix{raw_coeff}`_.) Also, like the default - behaviour of `\\PolTypeset{polname}`_, does not print (for the non - constant terms) coefficients equal to plus or minus one. The degree - one monomial is output as ``x``, not ``x^1``. Complete customization is - possible, see next macros. - - Of course ``\PolToExpr{f}`` can be inserted in a ``\poldef``, as the - latter expands token by token, hence will force complete expansion - of ``\PolToExpr{f}``, but a simple ``f(x)`` is more efficient for - the identical result. - -.. _PolToExprOneTerm: - -``\PolToExprOneTerm{raw_coeff}{number}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - This two argument expandable command takes care of the monomial and - its coefficient. The default definition is done in order for - coefficients of absolute value ``1`` not be printed explicitely - (except of course for the constant term). Also by default, the - monomial of degree one is ``x`` not ``x^1``, and ``x^0`` is skipped. - - For compatibility with Maple input requirements, by default a ``*`` - always precedes the ``x^number``, except if the coefficient is a one - or a minus one. See `\\PolToExprTimes`_. - -.. _PolToExprOneTermStyleA: - -``\PolToExprOneTermStyleA{raw_coeff}{number}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Holds the default package meaning of - `\\PolToExprOneTerm{raw_coeff}{number}`_. - -.. _PolToExprOneTermStyleB: - -``\PolToExprOneTermStyleB{raw_coeff}{number}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - For output in this style:: - - 2*x^11/3+3*x^8/7-x^5-x^4/4-x^3-x^2/2-2*x+1 - - issue ``\let\PolToExprOneTerm\PolToExprOneTermStyleB`` before usage of - ``\PolToExpr``. Note that then ``\PolToExprCmd`` isn't used at all. - To revert to package default, issue - ``\let\PolToExprOneTerm\PolToExprOneTermStyleA``. - - To suppress the ``*``'s, cf. `\\PolToExprTimes`_. - -.. _PolToExprCmd: - -``\PolToExprCmd{raw_coeff}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - It is the one-argument macro used by the package definition of - ``\PolToExprOneTerm`` for the coefficients themselves (when not - equal to plus or minus one), and it defaults to - ``\xintPRaw{\xintRawWithZeros{#1}}``. One will have to redefine it - to ``\xintIrr{#1}`` or to ``\xintPRaw{\xintIrr{#1}}`` to obtain in the - output forcefully reduced coefficients. - -.. _PolToExprTermPrefix: - -``\PolToExprTermPrefix{raw_coeff}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Defined identically as `\\PolTypesetCmdPrefix{raw_coeff}`_. It - prefixes with a plus sign for non-negative coefficients, because - they don't carry one by themselves. - -.. _PolToExprVar: - -``\PolToExprVar`` -^^^^^^^^^^^^^^^^^ - - This expands to the variable to use in output (it does not have to - be a single letter, may be an expandable macro.) Initial definition - is ``x``. - -.. _PolToExprTimes: - -``\PolToExprTimes`` -^^^^^^^^^^^^^^^^^^^ - - This expands to the symbol used for multiplication of an - ``x^{number}`` by the corresponding coefficient. The default is - ``*``. Redefine the macro to expand to nothing to get rid of it (but - this will give output incompatible with some professional computer - algebra software). - -.. _PolToExpr*: - -``\PolToExpr*{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to ``coeff_0+coeff_1*x+coeff_2*x^2+...`` (ascending powers). - Customizable like `\\PolToExpr{polname}`_ via the same macros. - -.. _PolToFloatExpr: - -``\PolToFloatExpr{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Similar to `\\PolToExpr{polname}`_ but uses `\\PolToFloatExprCmd - <\\PolToFloatExprCmd{raw_coeff}>`_ - which by default rounds and converts the coefficients to floating - point format. - - .. note:: - - It is not necessary to have issued - `\\PolGenFloatVariant{polname}`_. The rounded coefficients are - not easily recoverable from the ``\xintfloatexpr`` polynomial - function hence ``\PolToFloatExprCmd`` operates from the *exact* - coefficients anew. - - Attention that both macros obey the prevailing float precision. - If it is changed between those macro calls, then a mismatch - exists between the coefficients as used in ``\xintfloatexpr`` and - those output by ``\PolToFloatExpr{polname}``. - -.. _PolToFloatExprOneTerm: - -``\PolToFloatExprOneTerm{raw_coeff}{number}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Similar to `\\PolToExprOneTerm - <\\PolToExprOneTerm{raw_coeff}{number}>`_. But does not treat - especially coefficients equal to plus or minus one. - -.. _PolToFloatExprCmd: - -``\PolToFloatExprCmd{raw_coeff}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - It is the one-argument macro used by ``\PolToFloatExprOneTerm``. - Its package definition is ``\xintFloat{#1}``. - - .. caution:: - - Currently (xint_ ``1.3c``) ``\xintFloat{0}`` outputs ``0.e0`` - which is perfectly acceptable input for Python, but not for - Maple. Thus, one should better leave the `\\poltoexprallfalse`_ - toggle to its default ``\iffalse`` state, if one intends to use - the output in a Maple worksheet. - - But even then the zero polynomial will cause a problem. Workaround:: - - \renewcommand\PolToFloatExprCmd[1]{\xintiiifZero{#1}{0.0}{\xintFloat{#1}}} - - Usage of ``\xintiiifZero`` and not ``\xintifZero`` is only for - optimization (I can't help it) because ``#1`` is known to be - in ``xintfrac`` raw format. - -.. _PolToFloatExpr*: - -``\PolToFloatExpr*{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Typesets in ascending powers. - -.. _PolToList: - -``\PolToList{polname}`` -~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to ``{coeff_0}{coeff_1}...{coeff_N}`` with ``N`` = degree, and - ``coeff_N`` the leading coefficient - (the zero polynomial does give ``{0/1[0]}`` and not an - empty output.) - -.. _PolToCSV: - -``\PolToCSV{polname}`` -~~~~~~~~~~~~~~~~~~~~~~ - - Expands to ``coeff_0, coeff_1, coeff_2, ....., coeff_N``, starting - with constant term and ending with leading coefficient. Converse - to `\\PolFromCSV <\\PolFromCSV{polname}{\<csv\>}_>`_. - -.. _PolSturmChainLength: - -``\PolSturmChainLength{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Returns the integer ``N`` such that ``sturmname_N`` is the last one - in the Sturm chain ``sturmname_0``, ``sturmname_1``, ... - - See `\\PolToSturm{polname}{sturmname}`_. - -.. _PolSturmIfZeroExactlyKnown: - -``\PolSturmIfZeroExactlyKnown{sturmname}{index}{A}{B}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Executes ``A`` if the ``index``\ -th interval reduces to a singleton, - i.e. the root is known exactly, else ``B``. - - .. note:: - - ``index`` is allowed to be something like ``1+2*3`` as it is fed - to ``\the\numexpr...\relax``. - -.. _PolSturmIsolatedZeroLeft: - -``\PolSturmIsolatedZeroLeft{sturmname}{index}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the left end-point for the ``index``\ -th interval, as - computed by some earlier `\\PolSturmIsolateZeros{sturmname}`_. - - .. note:: - - Of course, this is kept updated by macros such as - `\\PolRefineInterval{sturmname}{index} <PolRefineInterval[N]_>`_. - - The value is pre-formatted using `\\PolDecTostring - <PolDecToString_>`_. - -.. _PolSturmIsolatedZeroRight: - -``\PolSturmIsolatedZeroRight{sturmname}{index}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the right end-point for the ``index``\ -th interval as - computed by some earlier `\\PolSturmIsolateZeros{sturmname}`_ and - possibly refined afterwards. - - The value is pre-formatted using `\\PolDecTostring - <PolDecToString_>`_. - -.. _PolSturmIsolatedZeroMultiplicity: - -``\PolSturmIsolatedZeroMultiplicity{sturmname}{index}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the multiplicity of the unique root contained in the - ``index``\ -th interval. - - .. attention:: - - A prior execution of `\\PolSturmIsolateZeros*{sturmname}`_ is mandatory. - - See `The degree nine polynomial with 0.99, 0.999, 0.9999 as triple - roots`_ for an example of use. - -.. _PolSturmNbOfIsolatedZeros: - -``\PolSturmNbOfIsolatedZeros{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the number of real roots of the polynomial - ``<sturmname>_0``, i.e. the number of distinct real roots of the - polynomial originally used to create the Sturm chain via - `\\PolToSturm{polname}{sturmname}`_. - -.. warning:: - - The next few macros counting roots, with or without multiplicities, - less than or equal to some value, are under evaluation and may be - removed from the package if their utility is judged to be not high - enough. They can be re-coded at user level on the basis of the other - documented package macros anyway. - -``\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualTo{value}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Expands to the number of distinct roots (of the polynomial used to - create the Sturm chain) less than or equal to the ``value`` (i.e. a - number of fraction recognizable by the xintfrac_ macros). - - .. attention:: - - `\\PolSturmIsolateZeros{sturmname}`_ must have been executed - beforehand. - - And the argument is a ``sturmname``, not a ``polname`` (this is - why the macro contains Sturm in its name), simply to be reminded - of the above constraint. - -``\PolSturmNbOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Expands to the number of distinct roots (of the polynomial - used to create the Sturm chain) which are less than or equal to the - given ``expression``. - - .. attention:: - - `\\PolSturmIsolateZeros{sturmname}`_ must have been executed - beforehand. - -``\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualTo{value}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Expands to the number counted with multiplicities of the roots (of - the polynomial used to create the Sturm chain) which are less than - or equal to the given ``value``. - - .. attention:: - - `\\PolSturmIsolateZeros*{sturmname}`_ (or the double starred - variant) must have been executed beforehand. - -``\PolSturmNbWithMultOfRootsOf{sturmname}\LessThanOrEqualToExpr{expression}`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Expands to the total number of roots (counted with multiplicities) - which are less than or equal to the given ``expression``. - - .. attention:: - - `\\PolSturmIsolateZeros*{sturmname}`_ (or the double starred - variant) must have been executed beforehand. - -``\PolSturmNbOfRationalRoots{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the number of rational roots (without multiplicities). - - .. attention:: - - `\\PolSturmIsolateZeros**{sturmname}`_ must have been executed - beforehand. - -``\PolSturmNbOfRationalRootsWithMultiplicities{sturmname}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the number of rational roots (counted with multiplicities). - - .. attention:: - - `\\PolSturmIsolateZeros**{sturmname}`_ must have been executed - beforehand. - -``\PolSturmRationalRoot{sturmname}{k}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the ``k``\ th rational root (they are ordered and indexed - starting at 1 for the most negative). - - .. attention:: - - `\\PolSturmIsolateZeros**{sturmname}`_ must have been executed - beforehand. - -``\PolSturmRationalRootIndex{sturmname}{k}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to ``index`` of the ``k``\ th rational root as part of the - ordered real roots (without multiplicities). I.e., above macro - `\\PolSturmRationalRoot{sturmname}{k}`_ is equivalent to this - nested call:: - - \PolSturmIsolatedZeroLeft{sturmname}{\PolSturmRationalRootIndex{sturmname}{k}} - - .. attention:: - - `\\PolSturmIsolateZeros**{sturmname}`_ must have been executed - beforehand. - -``\PolSturmRationalRootMultiplicity{sturmname}{k}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Expands to the multiplicity of the ``k``\ th rational root. - - .. attention:: - - `\\PolSturmIsolateZeros**{sturmname}`_ must have been executed - beforehand. - -.. _PolIntervalWidth: - -``\PolIntervalWidth{sturmname}{index}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - The ``10^E`` width of the current ``index``\ -th root localization - interval. Output is in xintfrac_ raw ``1/1[E]`` format (if not zero). - -Expandable macros for use within execution of ``\PolPrintIntervals`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -These macros are for usage within custom user redefinitions of -`\\PolPrintIntervalsKnownRoot`_, `\\PolPrintIntervalsUnknownRoot`_, or -in redefinitions of `\PolPrintIntervalsPrintExactZero`_ (used in the -default for the former) and of `\\PolPrintIntervalsPrintLeftEndPoint`_, -`\\PolPrintIntervalsPrintRightEndPoint`_ (used in the default for the -latter). - -.. attention:: - - Some macros formerly mentioned here got removed at 0.7: - ``\PolPrintIntervalsTheEndPoint``, - ``\PolIfEndPointIsPositive{A}{B}``, - ``\PolIfEndPointIsNegative{A}{B}``, - ``\PolIfEndPointIsZero{A}{B}``. - -``\PolPrintIntervalsTheVar`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Expands to the name (default ``Z``) used for representing the roots, - which was passed as optional argument ``varname`` to - `\\PolPrintIntervals[varname]{sturmname}`_. - -``\PolPrintIntervalsTheIndex`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Expands to the index of the considered interval (indexing starting - at 1 for the leftmost interval). - -``\PolPrintIntervalsTheSturmName`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Expands to the argument which was passed as ``sturmname`` to - `\\PolPrintIntervals[varname]{sturmname}`_. - -``\PolPrintIntervalsTheLeftEndPoint`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - The left end point of the interval, as would be produced by - `\\PolSturmIsolatedZeroLeft <PolSturmIsolatedZeroLeft_>`_ if it was - used with arguments the Sturm chain name and interval index returned - by `\\PolPrintIntervalsTheSturmName`_ and - `\\PolPrintIntervalsTheIndex`_. - -``\PolPrintIntervalsTheRightEndPoint`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - The right end point of the interval, as would be produced by - `\\\PolSturmIsolatedZeroRight <PolSturmIsolatedZeroRight_>`_ for - this Sturm chain name and index. - -``\PolPrintIntervalsTheMultiplicity`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - The multiplicity of the unique root within the interval of index - `\\PolPrintIntervalsTheIndex`_. Makes sense only if the starred (or - double-starred) variant of `\\PolSturmIsolateZeros - <PolSturmIsolateZeros_>`_ was used earlier. - -.. _PolDecToString: - -``\PolDecToString{decimal number}`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - This is a utility macro to print decimal numbers. It has been - backported to xintfrac_ (release ``1.3`` of ``2018/03/01``) under - the name ``\xintDecToString``, and the ``polexpr`` macro is simply - now an alias to it. - - For example - ``\PolDecToString{123.456e-8}`` will expand to ``0.00000123456`` - and ``\PolDecToString{123.450e-8}`` to ``0.00000123450`` which - illustrates that trailing zeros are not trimmed. To trim trailing - zeroes, one can use ``\PolDecToString{\xintREZ{#1}}``. - - The precise behaviour of this macro may evolve in future releases of - xint_. - -Booleans (with default setting as indicated) --------------------------------------------- - -``\xintverbosefalse`` -~~~~~~~~~~~~~~~~~~~~~ - - This is actually an xintexpr_ configuration. Setting it to - ``true`` triggers the writing of information to the log when new - polynomials are defined. - - .. caution:: - - The macro meanings as written to the log are to be considered - unstable and undocumented internal structures. - -``\poltypesetallfalse`` -~~~~~~~~~~~~~~~~~~~~~~~ - - If ``true``, `\\PolTypeset{polname}`_ will also typeset the vanishing - coefficients. - - -``\poltoexprallfalse`` -~~~~~~~~~~~~~~~~~~~~~~ - - If ``true``, `\\PolToExpr{polname}`_ and `\\PolToFloatExpr{polname}`_ will - also include the vanishing coefficients in their outputs. - -``\polexprsetup`` ------------------ - - Serves to customize the package. Currently only two keys are - recognized: - - - ``norr``: the postfix that `\\PolSturmIsolateZeros**{sturmname}`_ - should append to ``sturmname`` to declare the primitive polynomial - obtained from original one after removal of all rational roots. - The default value is ``_norr`` (standing for “no rational roots”). - - - ``sqfnorr``: the postfix that `\\PolSturmIsolateZeros**{sturmname}`_ - should append to ``sturmname`` to declare the primitive polynomial - obtained from original one after removal of all rational roots and - suppression of all multiplicities. - The default value is ``_sqf_norr`` (standing for “square-free with - no rational roots”). - - The package executes ``\polexprsetup{norr=_norr, - sqfnorr=_sqf_norr}`` as default. - -Technicalities --------------- - -- The catcode of the semi-colon is reset temporarily by `\\poldef - <poldef;_>`_ macro in case some other package (for example the French - babel module) may have made it active. This will fail though if the - whole thing was already part of a macro argument, in such cases one - can use `\\PolDef{f}{P(x)} <PolDef_>`_ - rather. The colon in ``:=`` may be active with no consequences. - -- As a consequence of xintfrac_ addition and subtraction always using - least common multiples for the denominators [#]_, user-chosen common - denominators survive additions and multiplications. For example, this:: - - \poldef P(x):= 1/2 + 2/2*x + 3/2*x^3 + 4/2*x^4; - \poldef Q(x):= 1/3 + (2/3)x + (3/3)x^3 + (4/3)x^4; - \poldef PQ(x):= P(x)Q(x); - - gives internally the polynomial:: - - 1/6+4/6*x^1+4/6*x^2+6/6*x^3+20/6*x^4+16/6*x^5+9/6*x^6+24/6*x^7+16/6*x^8 - - where all coefficients have the same denominator 6. Notice though that - ``\PolToExpr{PQ}`` outputs the ``6/6*x^3`` as ``x^3`` because (by - default) it recognizes and filters out coefficients equal to one or - minus one (since release ``0.3``). One can use for example - ``\PolToCSV{PQ}`` to see the internally stored coefficients. - - .. [#] prior to ``0.4.1``, ``polexpr`` used to temporarily patch - during the parsing of polynomials the xintfrac_ macros. This - patch was backported to xint_ at release ``1.3``. - -- `\\PolDiff{polname_1}{polname_2}`_ always applies ``\xintIrr`` to the - resulting coefficients, except that the *power of ten* part ``[N]`` - (for example an input in scientific notation such as ``1.23e5`` gives - ``123/1[3]`` internally in xintfrac) is not taken into account in the - reduction of the fraction. This is tentative and may change. - - Same remark for `\\PolAntiDiff{polname_1}{polname_2}`_. - -- Currently, the package stores all coefficients from index ``0`` to - index equal to the polynomial degree inside a single macro, as a list. - This data structure is obviously very inefficient for polynomials of - high degree and few coefficients (as an example with ``\poldef - f(x):=x^1000 + x^500;`` the subsequent definition ``\poldef g(x):= - f(x)^2;`` will do of the order of 1,000,000 multiplications and - additions involvings only zeroes... which does take time). This - may change in the future. - -- As is to be expected internal structures of the package are barely - documented and unstable. Don't use them. - - -CHANGE LOG ----------- - -- v0.1 (2018/01/11): initial release. Features: - - * The `\\poldef <poldef;_>`_ parser itself, - * Differentiation and anti-differentiation, - * Euclidean division and GCDs, - * Various utilities such as `\\PolFromCSV <PolFromCSV_>`_, - `\\PolMapCoeffs <PolMapCoeffs_>`_, - `\\PolToCSV <PolToCSV_>`_, `\\PolToExpr <PolToExpr_>`_, ... - - Only one-variable polynomials so far. - -- v0.2 (2018/01/14) - - * Fix: ``"README thinks \numexpr recognizes ^ operator"``. - * Convert README to reStructuredText markup. - * Move main documentation from README to separate ``polexpr.txt`` file. - * Provide ``polexpr.html`` as obtained via DocUtils_ ``rst2html.py``. - * Convert README to (CTAN compatible) Markdown markup. - - Due to lack of available time the test suite might not be extensive - enough. Bug reports are very welcome! - -- v0.3 (2018/01/17) - - * bug fixes: - - - the ``0.1`` `\\PolEval <PolEvalAt_>`_ accepted expressions for its second - argument, but this was removed by mistake at ``0.2``. Restored. - - **Attention**: at ``0.4`` this has been reverted again, and - `\\PolEval{P}\\AtExpr{foo} <PolEvalAtExpr_>`_ syntax is needed for - using expressions in the second argument. - * incompatible or breaking changes: - - - `\\PolToExpr <PolToExpr_>`_ now by default uses *descending* - powers (it also treats differently coefficients equal to 1 or -1.) - Use `\\PolToExpr* <PolToExpr*_>`_ for *ascending* powers. - - `\\PolEval <PolEvalAt_>`_ reduced the output to smallest terms, - but as this is costly with big fractions and not needed if e.g. - wrapped in an ``\xintRound`` or ``\xintFloat``, this step has been - removed; the former meaning is available as `\\PolEvalReduced - <PolEvalReducedAt_>`_. - * new (or newly documented) macros: - - - `\\PolTypesetCmd <PolTypesetCmd_>`_ - - `\\PolTypesetCmdPrefix <PolTypesetCmdPrefix_>`_ - - `\\PolTypesetMonomialCmd <PolTypesetMonomialCmd_>`_ - - `\\PolEvalReducedAt <PolEvalReducedAt_>`_ - - `\\PolToFloatExpr <PolToFloatExpr_>`_ - - `\\PolToExprOneTerm <PolToExprOneTerm_>`_ - - `\\PolToFloatExprOneTerm <PolToFloatExprOneTerm_>`_ - - `\\PolToExprCmd <PolToExprCmd_>`_ - - `\\PolToFloatExprCmd <PolToFloatExprCmd_>`_ - - `\\PolToExprTermPrefix <PolToExprTermPrefix_>`_ - - `\\PolToExprVar <PolToExprVar_>`_ - - `\\PolToExprTimes <PolToExprTimes_>`_ - * improvements: - - - documentation has a table of contents, internal hyperlinks, - standardized signature notations and added explanations. - - one can do ``\PolLet{g}={f}`` or ``\PolLet{g}{f}``. - - ``\PolToExpr{f}`` is highly customizable. - - `\\poldef <poldef;_>`_ and other defining macros prepare the polynomial - functions for usage within ``\xintthefloatexpr`` (or - ``\xintdeffloatvar``). Coefficients are pre-rounded to the - floating point precision. Indispensible for numerical algorithms, - as exact fractions, even reduced, quickly become very big. See the - documentation about how to use the exact polynomials also in - floating point context. - - **Attention**: this has been reverted at ``0.4``. The macro - `\\PolGenFloatVariant <PolGenFloatVariant_>`_ must be used for - generation floating point polynomial functions. - -- v0.3.1 (2018/01/18) - - Fixes two typos in example code included in the documentation. - -- v0.4 (2018/02/16) - - * bug fixes: - - - when Euclidean division gave a zero remainder, the internal - representation of this zero polynomial could be faulty; this - could cause mysterious bugs in conjunction with other package - macros such as `\\PolMapCoeffs <PolMapCoeffs_>`_. - - `\\PolGCD <PolGCD_>`_ was buggy in case of first polynomial being - of lesser degree than the second one. - * breaking changes: - - - formerly `\\PolEval{P}\\At{foo} <PolEvalAt_>`_ allowed ``foo`` to - be an expression, which was transparently handled via - ``\xinttheexpr``. Now, ``foo`` must be a fraction (or a macro - expanding to such) in the format acceptable by ``xintfrac.sty`` - macros. Use `\\PolEval{P}\\AtExpr{foo} <PolEvalAtExpr_>`_ for more - general arguments using expression syntax. E.g., if ``foo`` is the - name of a variable known to ``\xintexpr``. - - The same holds for `\\PolEvalReduced <PolEvalReducedAt_>`_ - and `\\PolFloatEval <PolFloatEvalAt_>`_. - - the ``3.0`` automatic generation of floating point variants has - been reverted. Not only do *not* the package macros automatically - generate floating point variants of newly created polynomials, - they actually make pre-existing such variant undefined. - - See `\\PolGenFloatVariant <PolGenFloatVariant_>`_. - * new non-expandable macros: - - - `\\PolGenFloatVariant <PolGenFloatVariant_>`_ - - `\\PolGlobalLet <PolGlobalLet_>`_ - - `\\PolTypesetOne <PolTypesetOne_>`_ - - `\\PolQuo <PolQuo_>`_ - - `\\PolRem <PolRem_>`_ - - `\\PolToSturm <PolToSturm_>`_ - - `\\PolToSturm\* <PolToSturm*_>`_ - - `\\PolSetToSturmChainSignChangesAt <PolSetToSturmChainSignChangesAt_>`_ - - `\\PolSetToNbOfZerosWithin <PolSetToNbOfZerosWithin_>`_ - - `\\PolSturmIsolateZeros <PolSturmIsolateZeros_>`_ - - `\\PolRefineInterval* <PolRefineInterval*_>`_ - - `\\PolRefineInterval[N] <PolRefineInterval[N]_>`_ - - `\\PolEnsureIntervalLength <PolEnsureIntervalLength_>`_ - - `\\PolEnsureIntervalLengths <PolEnsureIntervalLengths_>`_ - - `\\PolPrintIntervals <PolPrintIntervals_>`_ - - `\\PolPrintIntervalsPrintExactZero <PolPrintIntervalsPrintExactZero_>`_ - - `\\PolPrintIntervalsPrintLeftEndPoint <PolPrintIntervalsPrintLeftEndPoint_>`_ - - `\\PolPrintIntervalsPrintRightEndPoint <PolPrintIntervalsPrintRightEndPoint_>`_ - - `\\PolReduceCoeffs* <PolReduceCoeffs*_>`_ - - `\\PolMakeMonic <PolMakeMonic_>`_ - * new expandable macros: - - - `\\PolToExprOneTermStyleA <PolToExprOneTermStyleA_>`_ - - `\\PolIfCoeffIsPlusOrMinusOne <PolIfCoeffIsPlusOrMinusOne_>`_ - - `\\PolLeadingCoeff <PolLeadingCoeff_>`_ - - `\\PolSturmChainLength <PolSturmChainLength_>`_ - - `\\PolSturmNbOfIsolatedZeros <PolSturmNbOfIsolatedZeros_>`_ - - `\\PolSturmIfZeroExactlyKnown <PolSturmIfZeroExactlyKnown_>`_ - - `\\PolSturmIsolatedZeroLeft <PolSturmIsolatedZeroLeft_>`_ - - `\\PolSturmIsolatedZeroRight <PolSturmIsolatedZeroRight_>`_ - - ``\PolPrintIntervalsTheEndPoint`` (removed at 0.7) - - `\\PolPrintIntervalsTheIndex`_ - - ``\PolIfEndPointIsPositive`` (removed at 0.7) - - ``\PolIfEndPointIsNegative`` (removed at 0.7) - - ``\PolIfEndPointIsZero`` (removed at 0.7) - - `\\PolIntervalWidth <PolIntervalWidth_>`_ - - `\\PolDecToString <PolDecToString_>`_ - * improvements: - - The main new feature is implementation of the `Sturm algorithm`_ - for localization of the real roots of polynomials. - -- v0.4.1 (2018/03/01) - - Synced with xint 1.3. - -- v0.4.2 (2018/03/03) - - Documentation fix. - -- v0.5 (2018/04/08) - - * bug fixes: - - - `\\PolGet{polname}\\fromarray\\macro`_ crashed when ``\macro`` was - an xinttools_ array macro with no items. It now produces the zero - polynomial. - * breaking changes: - - - `\\PolToSturm`_ creates primitive integer coefficients polynomials. - This speeds up localization of roots via - `\\PolSturmIsolateZeros`_. In case of user protests the author - will make available again the code producing the bona fide Sturm - polynomials as used formerly. - - polynomials created from `\\PolFromCSV`_ or `\\PolGet <PolGet_>`_ - get their coefficients normalized via xintfrac_\ 's ``\xintRaw``. - * experimental change: - - - optional argument to `\\PolSturmIsolateZeros`_ (see `The - degree 41 polynomial with -2, -1.9, -1.8, ..., 0, 0.1, ..., 1.9, 2 - as roots`_ for usage). It will presumably be replaced in future by - an interval specification. - * new non-expandable macro: - - - `\\PolMakePrimitive`_ - * new expandable macro: - - - `\\PolIContent`_ - -- v0.5.1 (2018/04/22) - - * new feature: - - - the character ``'`` can be used in polynomial names. - -- v0.6 (2018/11/20) - - * bugfix: - - - the starred variant `\\PolToSturm*{polname}{sturmname}`_ was - broken. On the occasion of the fix, its meaning has been modified, - see its documentation. - - - using `\\PolToSturm <PolToSturm_>`_ with a constant polynomial - caused a division by zero error. - - * new macro: - - - `\\PolSturmIsolateZeros* <PolSturmIsolateZeros*_>`_ - acts like the `non-starred variant - <PolSturmIsolateZeros_>`_ then computes all the multiplicities. - - * new expandable macros: - - - `\\PolSturmIsolatedZeroMultiplicity{sturmname}{index}`_ - - `\\PolSturmNbOfRootsOf{sturmname}\\LessThanOrEqualTo{value}`_ - - `\\PolSturmNbOfRootsOf{sturmname}\\LessThanOrEqualToExpr{expression}`_ - - `\\PolSturmNbWithMultOfRootsOf{sturmname}\\LessThanOrEqualTo{value}`_ - - `\\PolSturmNbWithMultOfRootsOf{sturmname}\\LessThanOrEqualToExpr{expression}`_ - -- v0.7 (2018/12/08), v0.7.1 (bugfix), v0.7.2 (2nd bugfix) (2018/12/09) - - * breaking changes: - - - although `\\PolPrintIntervals[varname]{sturmname}`_ default output - remains the same, some auxiliary macros for user-customization - have been removed: ``\PolPrintIntervalsTheEndPoint``, - ``\PolIfEndPointIsPositive{A}{B}``, - ``\PolIfEndPointIsNegative{A}{B}``, and - ``\PolIfEndPointIsZero{A}{B}``. - - * bugfix: - - - it could happen that, contrarily to documentation, an interval - computed by `\\PolSturmIsolateZeros{sturmname}`_ had zero as an - endpoint, - - `\\PolEnsureIntervalLength{sturmname}{index}{E}`_ could under - certain circumstances erroneously replace a non-zero root by - zero, - - `\\PolEnsureIntervalLengths{sturmname}{E}`_ crashed when used with - a polynomial with no real roots, hence for which no isolation intervals - existed (thanks to Thomas Söll for report). - - * new macros: - - - `\\PolSturmIsolateZeros**{sturmname}`_ - - `\\PolSturmIsolateZerosGetMultiplicitiesAndRationalRoots{sturmname}`_ - - `\\PolSturmIsolateZerosAndFindRationalRoots{sturmname}`_ - - `\\polexprsetup`_ - - `\\PolPrintIntervals* <PolPrintIntervals*_>`_ - - `\\PolPrintIntervalsNoRealRoots`_ - - `\\PolPrintIntervalsBeginEnv`_ - - `\\PolPrintIntervalsEndEnv`_ - - `\\PolPrintIntervalsKnownRoot`_ - - `\\PolPrintIntervalsUnknownRoot`_ - - `\\PolPrintIntervalsPrintMultiplicity`_ - - * new expandable macros: - - - `\\PolSturmNbOfRationalRoots{sturmname}`_ - - `\\PolSturmNbOfRationalRootsWithMultiplicities{sturmname}`_ - - `\\PolSturmRationalRoot{sturmname}{k}`_ - - `\\PolSturmRationalRootIndex{sturmname}{k}`_ - - `\\PolSturmRationalRootMultiplicity{sturmname}{k}`_ - - `\\PolPrintIntervalsTheVar`_ - - `\\PolPrintIntervalsTheSturmName`_ - - `\\PolPrintIntervalsTheMultiplicity`_ - -- v0.7.3 (2019/02/04) - - * bugfix: - - - Debugging information not destined to user showed in log if root - finding was done under ``\xintverbosetrue`` regime. - - `\\PolPrintIntervalsTheVar`_ remained defined after - `\\PolPrintIntervals`_ but was left undefined after - `\\PolPrintIntervals*`_ (reported by Jürgen Gilg). Now remains - defined in both cases, and `\\PolPrintIntervalsTheSturmName`_ - also. - - Polynomial names ending in digits caused errors (reported by Thomas - Söll). - -- v0.7.4 (2019/02/12) - - * bugfix: - - - 20000000000 is too big for ``\numexpr``, shouldn't I know that? - Thanks to Jürgen Gilg for report. - -- v0.7.5 (2020/01/31) - - Synced with xint 1.4. Requires it. - - -Acknowledgments ---------------- - -Thanks to Jürgen Gilg whose question about xint_ usage for -differentiating polynomials was the initial trigger leading to this -package, and to Jürgen Gilg and Thomas Söll for testing it on some -concrete problems. - -Renewed thanks to them on occasion of the ``0.6`` and ``0.7`` releases for their -continued interest. - -See README.md for the License. - -.. _xinttools: -.. _xintfrac: -.. _xintexpr: -.. _xint: http://www.ctan.org/pkg/xint - -.. _Wilkinson polynomial: https://en.wikipedia.org/wiki/Wilkinson%27s_polynomial - -.. _Sturm algorithm: -.. _Sturm Theorem: https://en.wikipedia.org/wiki/Sturm%27s_theorem - -.. _DocUtils: http://docutils.sourceforge.net/docs/index.html diff --git a/macros/latex/contrib/srdp-mathematik/README.txt b/macros/latex/contrib/srdp-mathematik/README.txt index 98bf90021a..af803dd1eb 100644 --- a/macros/latex/contrib/srdp-mathematik/README.txt +++ b/macros/latex/contrib/srdp-mathematik/README.txt @@ -1,28 +1,28 @@ -__________________________________
-
- The
- srdp-mathematik package
- v1.8
-
- 2021/03/18
-___________________________________
-
-Maintainer: Christoph Weberndorfer
-E-mail : c.weberndorfer@gmail.com
- Comments, bug reports and suggestions are welcome.
-Licence : Released under the LaTeX Project Public License 1.3c or
- later, see http://www.latex-project.org/lppl.txt
-
-----------------------------------------------------------------------
-
-This package provides basic commands for the defined formats of the Austrian sRDP in mathematics.
-Furthermore, it includes ways to implement answers in the tex file, which can be voluntarily displayed in the pdf file and
-it offers a way of varying the answers in order to create different groups (e.g. for tests) easily.
-
-----------------------------------------------------------------------
-
-Dieses Paket bietet grundlegende Befehle für die vorgegebenen Formate der österreichischen, standardisierten
-Reife- und Diplomprüfung (sRDP) in Mathematik.
-Es bietet darüber hinaus die Möglichkeit, Antworten in die tex Datei zu implentieren und diese bei Bedarf in der pdf Datei anzuzeigen.
-Außerdem können die eingegeben Antwortmöglichkeiten variiert werden, um mehrere Gruppe für zum Beispiel Schularbeiten einfach zu erstellen.
-
+__________________________________ + + The + srdp-mathematik package + v1.9.0 + + 2021/03/29 +___________________________________ + +Maintainer: Christoph Weberndorfer +E-mail : c.weberndorfer@gmail.com + Comments, bug reports and suggestions are welcome. +Licence : Released under the LaTeX Project Public License 1.3c or + later, see http://www.latex-project.org/lppl.txt + +---------------------------------------------------------------------- + +This package provides basic commands for the defined formats of the Austrian sRDP in mathematics. +Furthermore, it includes ways to implement answers in the tex file, which can be voluntarily displayed in the pdf file and +it offers a way of varying the answers in order to create different groups (e.g. for tests) easily. + +---------------------------------------------------------------------- + +Dieses Paket bietet grundlegende Befehle für die vorgegebenen Formate der österreichischen, standardisierten +Reife- und Diplomprüfung (sRDP) in Mathematik. +Es bietet darüber hinaus die Möglichkeit, Antworten in die tex Datei zu implentieren und diese bei Bedarf in der pdf Datei anzuzeigen. +Außerdem können die eingegeben Antwortmöglichkeiten variiert werden, um mehrere Gruppe für zum Beispiel Schularbeiten einfach zu erstellen. + diff --git a/macros/latex/contrib/srdp-mathematik/srdp-mathematik.pdf b/macros/latex/contrib/srdp-mathematik/srdp-mathematik.pdf Binary files differindex 610ae58130..81b5cbc449 100644 --- a/macros/latex/contrib/srdp-mathematik/srdp-mathematik.pdf +++ b/macros/latex/contrib/srdp-mathematik/srdp-mathematik.pdf diff --git a/macros/latex/contrib/srdp-mathematik/srdp-mathematik.sty b/macros/latex/contrib/srdp-mathematik/srdp-mathematik.sty index 6176e19db1..09bf9fd8ab 100644 --- a/macros/latex/contrib/srdp-mathematik/srdp-mathematik.sty +++ b/macros/latex/contrib/srdp-mathematik/srdp-mathematik.sty @@ -10,7 +10,7 @@ % \NeedsTeXFormat{LaTeX2e}[1996/12/26] -\ProvidesPackage{srdp-mathematik}[2021/03/18 v1.8 Standard-Schularbeitsformate] +\ProvidesPackage{srdp-mathematik}[2021/03/29 v1.9.0 Standard-Schularbeitsformate] \usepackage{color} @@ -309,54 +309,38 @@ % %%%%%%%%%%%% NOTENSCHLUESSEL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% -\newcommand{\notenschluessel}[5][]{ -\vfill +% + +\NewDocumentCommand{\notenschluessel}{ O{} O{} O{} m m m m}{ +\null\vfill \STautoround{3}\renewcommand{\arraystretch}{0}\tiny \begin{spreadtab}[\STsavecell\gutgenau{b2} \STsavecell\befriedigendgenau{c2} \STsavecell\genuegendgenau{d2} \STsavecell\nichtgenuegendgenau{e2} \STsavecell\gut{b3} \STsavecell\befriedigend{c3} \STsavecell\genuegend{d3} \STsavecell\nichtgenuegend{e3} \STsavecell\gutpluseins{b4} \STsavecell\befriedigendpluseins{c4} \STsavecell\genuegendpluseins{d4} \STsavecell\nichtgenuegendpluseins{e4} \STsavecell\gutminuseins{b5} \STsavecell\befriedigendminuseins{c5} \STsavecell\genuegendminuseins{d5} \STsavecell\nichtgenuegendminuseins{e5}]{{tabular}{ccccc}} - \SThidecol\thepunkte &\SThidecol 1 &\SThidecol2 &\SThidecol 3 &\SThidecol 4 \\ - & a1*#2 &a1*#3 & a1*#4 & a1*#5 \\ - &trunc(a1*#2,0) & trunc(a1*#3,0) &trunc(a1*#4,0) &trunc(a1*#5,0) \\ - &b3+1 &c3+1 &d3+1 & e3+1\\ - &b3-1 &c3-1 &d3-1 & e3-1\\ + \SThidecol\thepunkte &\SThidecol 1 &\SThidecol2 &\SThidecol 3 &\SThidecol 4 \\ + & a1*#4 &a1*#5 & a1*#6 & a1*#7 \\ + &trunc(a1*#4,0) & trunc(a1*#5,0) &trunc(a1*#6,0) &trunc(a1*#7,0) \\ + &b3+1 &c3+1 &d3+1 & e3+1\\ + &b3-1 &c3-1 &d3-1 & e3-1\\ \end{spreadtab} \footnotesize\renewcommand{\arraystretch}{1} \begin{center} \begin{tabular}{|C{3cm}C{3cm}C{3cm}C{3cm}C{3cm}|} \hline +\ifthenelse{\equal{#2}{prozent}}{% Erreichte Punkte & Prozent & Gesamt & \multicolumn{2}{c|}{Note} \\ -&& \multirow{2}{*}{\thepunkte} && \\ -&&&& \\ \hline \hline -\scriptsize{Sehr gut} & \scriptsize{Gut} & \scriptsize{Befriedigend} & \scriptsize{Gen\"ugend} & \scriptsize{Nicht gen\"ugend} \\ -\scriptsize{\thepunkte ~ - \ifdim\gut pt=\gutgenau pt \gut\else\gutpluseins\fi}& \scriptsize{\ifdim\gut pt=\gutgenau pt \gutminuseins\else\gut\fi \ifthenelse{\equal{#1}{1/2}}{,5}{} ~ - \ifdim\befriedigend pt=\befriedigendgenau pt \befriedigend\else\befriedigendpluseins\fi} & \scriptsize{\ifdim\befriedigend pt=\befriedigendgenau pt \befriedigendminuseins\else\befriedigend\fi \ifthenelse{\equal{#1}{1/2}}{,5}{} ~ - \ifdim\genuegend pt=\genuegendgenau pt \genuegend\else\genuegendpluseins\fi} & \scriptsize{\ifdim\genuegend pt=\genuegendgenau pt \genuegendminuseins\else\genuegend\fi \ifthenelse{\equal{#1}{1/2}}{,5}{} ~ - \ifdim\nichtgenuegend pt=\nichtgenuegendgenau pt \nichtgenuegend\else\nichtgenuegendpluseins\fi} & \scriptsize{unter \ifdim\nichtgenuegend pt=\nichtgenuegendgenau pt \nichtgenuegend\else\nichtgenuegendpluseins\fi} \\ \hline -\end{tabular} -\end{center}\STautoround{}\normalsize} - -\newcommand{\notenschluesselop}[5][]{ -\vfill -\STautoround{3}\renewcommand{\arraystretch}{0}\tiny -\begin{spreadtab}[\STsavecell\gutgenau{b2} \STsavecell\befriedigendgenau{c2} \STsavecell\genuegendgenau{d2} -\STsavecell\gut{b3} \STsavecell\befriedigend{c3} \STsavecell\genuegend{d3} \STsavecell\nichtgenuegend{e3} -\STsavecell\gutpluseins{b4} \STsavecell\befriedigendpluseins{c4} \STsavecell\genuegendpluseins{d4} \STsavecell\gutminuseins{b5} \STsavecell\befriedigendminuseins{c5} \STsavecell\genuegendminuseins{d5}]{{tabular}{ccccc}} - \SThidecol \thepunkte &\SThidecol 1 &\SThidecol 2 &\SThidecol 3 &\SThidecol 4 \\ - & a1*#2 &a1*#3 & a1*#4 & a1*#5 \\ - &trunc(a1*#2,0) & trunc(a1*#3,0) &trunc(a1*#4,0) &trunc(a1*#5,0) \\ - &b3+1 &c3+1 &d3+1 & e3+1\\ - &b3-1 &c3-1 &d3-1 & e3-1\\ -\end{spreadtab} -\footnotesize\renewcommand{\arraystretch}{1} -\begin{center} -\begin{tabular}{|C{3cm}C{3cm}C{3cm}C{3cm}C{3cm}|} \hline +&& \multirow{2}{*}{\thepunkte} && \\% +}{% Erreichte Punkte &Gesamt&\multicolumn{2}{c}{Note}& \\ -&\multirow{2}{*}{\thepunkte} &&& \\ +&\multirow{2}{*}{\thepunkte} &&& \\} &&&& \\ \hline \hline -\scriptsize{Sehr gut} & \scriptsize{Gut} & \scriptsize{Befriedigend} & \scriptsize{Gen\"ugend} & \scriptsize{Nicht gen\"ugend} \\ -\scriptsize{\thepunkte ~ - \ifdim\gut pt=\gutgenau pt \gut\else\gutpluseins\fi}& \scriptsize{\ifdim\gut pt=\gutgenau pt \gutminuseins\else\gut\fi \ifthenelse{\equal{#1}{1/2}}{,5}{} ~ - \ifdim\befriedigend pt=\befriedigendgenau pt \befriedigend\else\befriedigendpluseins\fi} & \scriptsize{\ifdim\befriedigend pt=\befriedigendgenau pt \befriedigendminuseins\else\befriedigend\fi \ifthenelse{\equal{#1}{1/2}}{,5}{} ~ - \ifdim\genuegend pt=\genuegendgenau pt \genuegend\else\genuegendpluseins\fi} & \scriptsize{\ifdim\genuegend pt=\genuegendgenau pt \genuegendminuseins\else\genuegend\fi \ifthenelse{\equal{#1}{1/2}}{,5}{} ~ - \ifdim\nichtgenuegend pt=\nichtgenuegendgenau pt \nichtgenuegend\else\nichtgenuegendpluseins\fi} & \scriptsize{unter \ifdim\nichtgenuegend pt=\nichtgenuegendgenau pt \nichtgenuegend\else\nichtgenuegendpluseins\fi} \\ \hline +\ifthenelse{\equal{#3}{ms}}{}{\scriptsize{Sehr gut}} & \ifthenelse{\equal{#3}{ms}}{}{\scriptsize{Gut}} & \scriptsize{Befriedigend} & \scriptsize{Gen\"ugend} & \scriptsize{Nicht gen\"ugend} \\ +\ifthenelse{\equal{#3}{ms}}{}{\scriptsize{\thepunkte ~ - \ifdim\gut pt=\gutgenau pt \gut\else\gutpluseins\fi}}& \ifthenelse{\equal{#3}{ms}}{}{\scriptsize{\ifdim\gut pt=\gutgenau pt \gutminuseins\else\gut\fi \ifthenelse{\equal{#1}{1/2}}{,5}{} ~ - \ifdim\befriedigend pt=\befriedigendgenau pt \befriedigend\else\befriedigendpluseins\fi}} & \scriptsize{\ifdim\befriedigend pt=\befriedigendgenau pt \befriedigendminuseins\else\befriedigend\fi \ifthenelse{\equal{#1}{1/2}}{,5}{} ~ - \ifdim\genuegend pt=\genuegendgenau pt \genuegend\else\genuegendpluseins\fi} & \scriptsize{\ifdim\genuegend pt=\genuegendgenau pt \genuegendminuseins\else\genuegend\fi \ifthenelse{\equal{#1}{1/2}}{,5}{} ~ - \ifdim\nichtgenuegend pt=\nichtgenuegendgenau pt \nichtgenuegend\else\nichtgenuegendpluseins\fi} & \scriptsize{unter \ifdim\nichtgenuegend pt=\nichtgenuegendgenau pt \nichtgenuegend\else\nichtgenuegendpluseins\fi} \\ \hline \end{tabular} \end{center}\STautoround{}\normalsize} - +% for legacy reason +\newcommand{\notenschluesselop}[5][1]{\notenschluessel[#1]{#2}{#3}{#4}{#5}} +%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%% GAP DEFINITION diff --git a/macros/latex/contrib/srdp-mathematik/srdp-mathematik.tex b/macros/latex/contrib/srdp-mathematik/srdp-mathematik.tex index 8dbc5baae6..1df75d3560 100644 --- a/macros/latex/contrib/srdp-mathematik/srdp-mathematik.tex +++ b/macros/latex/contrib/srdp-mathematik/srdp-mathematik.tex @@ -55,7 +55,7 @@ hidelinks \vfill -\Huge The \textit{srdp-mathematik} package v1.8\\[1cm] +\Huge The \textit{srdp-mathematik} package v1.9.0\\[1cm] Documentation \\ [1cm] @@ -93,7 +93,7 @@ Die \textit{allgemeinen Befehle} erleichtern das Erstellen von Tests, Schularbei Jedes Beispiel sollte innerhalb einer Beispielumgebung gesetzt werden, welche bei der Formatierung und der Verarbeitung der Punkte unterstützt. Dabei werden zwei Beispiel-Typen unterschieden: \texttt{beispiel} und \texttt{langesbeispiel}. \vspace{1cm} -\subsubsection{\texttt{beispiel}-Umbgebung} +\subsubsection{\texttt{\textbackslash begin\{beispiel\} \ldots\ \textbackslash end\{beispiel\}}} Die \texttt{beispiel}-Umgebung dient zur Erstellung eines Beispiels einer Schularbeit, einer Prüfung, usw. Dabei sind praktisch alle Funktionen von \LaTeX, wie Text, Formeln oder Grafiken möglich. Diese Umgebung erlaubt jedoch keinen Seitenumbruch! Die Beispiele werden automatisch nummeriert. @@ -127,7 +127,7 @@ $\frac{x^2+x+5}{\sqrt{x^3}}$ \vspace{1cm} -\subsubsection{\texttt{langesbeispiel}-Umbgebung} +\subsubsection{\texttt{\textbackslash begin\{langesbeispiel\} \ldots\ \textbackslash end\{langesbeispiel\}}} Die \texttt{langesbeispiel}-Umgebung dient ebenso zur Erstellung eines Beispiels, funktioniert analog, erlaubt aber im Gegensatz zur \texttt{beispiel}-Umgebung Seitenumbrüche. Auch lange Beispiele werden weiterführend nummeriert. @@ -159,48 +159,83 @@ $\frac{x^2+x+5}{\sqrt{x^3}}$. -\subsubsection{Notenschlüssel} +\subsubsection{\texttt{\textbackslash notenschluessel}} Werden für alle Beispiele die \texttt{beispiel}- oder die \texttt{langesbeispiel}-Umgebung verwendet, wird die Gesamtpunktezahl sowie der Notenschlüssel automatisch berechnet. Die Werte in Klammer geben dabei den prozentualen Notenschlüssel vor und können beliebig variiert werden: \vspace{0.4cm} +\setcounter{punkte}{48} + + +\vspace{0.3cm} + +\textsc{Ausgabe:} +\notenschluessel{0.91}{0.8}{0.64}{0.5} +\vfill + +Der Befehl \texttt{notenschluessel} bietet auch die Eingabe von drei unterschiedlichen Optionen, die alle einzeln oder gemeinsam verwendet werden können. Wichtig: Wird Option 3 benötigt (jedoch Option 1 \& 2 nicht) müssen die Optionen 1 \& 2 jeweils mit leerer Klammer \texttt{[]} angegeben werden. + +\subsubsection*{\texttt{\textbackslash notenschluessel} -- Option 1: Halbe Punkte-Schritte} + +Durch die Option 1 \texttt{[1/2]} wird die Anzeige auf halbe Punkte-Schritten geändert. \textsc{Eingabe:} \begin{verbatim} -\notenschluessel{0.91}{0.8}{0.64}{0.5} +\notenschluessel[1/2]{0.91}{0.8}{0.64}{0.5} \end{verbatim} -\vspace{0.3cm} - \textsc{Ausgabe:} -\notenschluessel{0.91}{0.8}{0.64}{0.5} +\notenschluessel[1/2]{0.91}{0.8}{0.64}{0.5} + -\normalsize +\subsubsection*{\texttt{\textbackslash notenschluessel} -- Option 2: Prozentanzeige} -\paragraph{Notenschlüssel - Ohne Prozentangabe} -Analog zum \texttt{notenschluessel} funktioniert auch der Befehl \texttt{notenschluesselop}. Es wird dabei jedoch die Prozentspalte nicht angezeigt. +Die Option 2 \texttt{[prozent]} ergänzt die erste Zeile des Notenschlüssel mit einer prozentuellen Angabe. \textsc{Eingabe:} \begin{verbatim} -\notenschluesselop{0.91}{0.8}{0.64}{0.5} +\notenschluessel[][prozent]{0.91}{0.8}{0.64}{0.5} \end{verbatim} \textsc{Ausgabe:} -\notenschluessel{0.91}{0.8}{0.64}{0.5} +\notenschluessel[][prozent]{0.91}{0.8}{0.64}{0.5} -\paragraph{Notenschlüssel - Option: [1/2]} +\subsubsection*{\texttt{\textbackslash notenschluessel} -- Option 3: Standard der Mittelschule} -Die Option 1/2 ermöglicht die Anzeige des Notenschlüssel (mit oder ohne Prozentspalte) mit halben Punkten. +Die option 3 \texttt{ms} ermöglicht die Darstellung des Notenschlüssels entsprechend des Standards der Mittelschule. \textsc{Eingabe:} \begin{verbatim} -\notenschluessel[1/2]{0.91}{0.8}{0.64}{0.5} +\notenschluessel[][][ms]{0.91}{0.8}{0.64}{0.5} \end{verbatim} \textsc{Ausgabe:} -\notenschluessel[1/2]{0.91}{0.8}{0.64}{0.5} +\notenschluessel[][][ms]{0.91}{0.8}{0.64}{0.5} + +%\paragraph{Notenschlüssel - Ohne Prozentangabe} +%Analog zum \texttt{notenschluessel} funktioniert auch der Befehl \texttt{notenschluesselop}. Es wird dabei jedoch die Prozentspalte nicht angezeigt. +% +%\textsc{Eingabe:} +%\begin{verbatim} +%\notenschluesselop{0.91}{0.8}{0.64}{0.5} +%\end{verbatim} +% +%\textsc{Ausgabe:} +%\notenschluessel{0.91}{0.8}{0.64}{0.5} + +%\paragraph{Notenschlüssel - Option: [1/2]} +% +%Die Option 1/2 ermöglicht die Anzeige des Notenschlüssel (mit oder ohne Prozentspalte) mit halben Punkten. +% +%\textsc{Eingabe:} +%\begin{verbatim} +%\notenschluessel[1/2]{0.91}{0.8}{0.64}{0.5} +%\end{verbatim} +% +%\textsc{Ausgabe:} +%\notenschluessel[1/2]{0.91}{0.8}{0.64}{0.5} -\subsubsection{Beurteilungsraster} +\subsubsection{\texttt{\textbackslash beurteilungsraster}} Der Befehl \texttt{beurteilungsraster} entspricht der aktuellen Vorgabe der Beurteilung der standardisierten Reifeprüfung (Stand 2019). Dabei müssen die Punkte für Teil 1, Ausgleichspunkte und Teil 2 angegeben werden. Die in Klammer angegebenen Werte entsprechen der bei der Reifeprüfung verwendeten prozentuellen Notenverteilung, können jedoch jederzeit verändert werden. \leer @@ -227,7 +262,7 @@ siehe nächste Seite \newpage \newpage -\subsection{Lösungseingabe -- Option: \texttt{[solution\_on/off]}} +\subsection{Paketoption -- Lösungseingabe: \texttt{[solution\_on/off]}} Es besteht die Möglichkeit, die Lösung in der erstellten \texttt{tex}-Datei zu implementieren und diese bei Bedarf in der \texttt{PDF}-Datei ein- bzw. auszublenden. Um diese Funktion nutzen zu können, muss die \texttt{solution\_on/off} Option im \texttt{srdp-mathematik}-Paket geladen werden. Diese kann durch hinzufügen durch "`\texttt{solution\_on}"' bzw. "`\texttt{solution\_off}"' aktiviert bzw. deaktiviert werden. Also: @@ -245,11 +280,11 @@ oder Die korrekte Lösungseingabe der vorformatierten Typ-1-Aufgaben wird bei den entsprechenden Befehlen direkt erklärt. Unabhängig davon, gibt es die Möglichkeit mithilfe des \texttt{antwort}-Befehls, beliebige Abschnitte als \textit{Antwort} zu deklarieren. (verwendeter counter: \texttt{Antworten=0, 1}) -\subsubsection{\texttt{antwort}-Befehl} +\subsubsection{\texttt{\textbackslash antwort}} Für offene Antworten kann der \texttt{\textbackslash antwort\{\}}-Befehl verwendet werden. Darin können Textpassagen, mathematische Formeln oder Grafiken angegeben werden, die ausschließlich bei aktivierter Lösung (\texttt{[solution\_on]}) und in \textcolor[rgb]{1,0,0}{rot} angegeben werden. \leer -\subsubsection{Zusatz: Optionales Argument} +\subsubsection*{\texttt{\textbackslash antwort} -- Option: Anzeige nur bei \texttt{solution\_off}} Der \texttt{antwort}-Befehl erlaubt ein optionales Argument. Es können dadurch zusätzliche Textpassagen angegeben werden, die \underline{ausschließlich} angezeigt werden, wenn die Lösungsanzeige deaktiviert (\texttt{[solution\_off])} ist. Das heißt: \leer @@ -278,7 +313,7 @@ wird.] \texttt{'solution\_on'} eingestellt ist.} -\subsection{Erstellung von Gruppen -- Option: \texttt{[random=0,1,2,\ldots]}} +\subsection{Paketoption -- Erstellung von Gruppen: \texttt{[random=0,1,2,\ldots]}} Das \texttt{srdp-mathematik}-Paket ermöglicht auch die automatische Erstellung von Gruppen für Schularbeiten, durch Vertauschung der Antwortmöglichkeiten aller Typ-1-Aufgaben. Dazu kann die \texttt{random}-Option im \texttt{srdp-mathematik}-Paket eingebunden geladen werden. Also: \begin{verbatim} @@ -299,93 +334,9 @@ Durch das Ersetzen der Zahl "`0"' durch die Zahlen $1, 2, 3, \ldots$ (und anschl Die Erstellung der Gruppen ist dabei reproduzierbar. Die Reihenfolge der Antwortmöglichkeiten einer Gruppe bleibt daher immer gleich. Mithilfe des Befehls \texttt{\textbackslash Gruppe} kann die Gruppennummer innerhalb der \texttt{PDF}-Datei (z.B. am Deckblatt) angezeigt werden. (verwendeter counter: \texttt{Zufall=0, 1, 2, \ldots}) -%Dieses Prinzip wird exemplarisch am Multiplechoice-Format gezeigt:\leer -% -%\textsc{Eingabe:} -%\begin{verbatim} -%\multiplechoice[5]{ %Anzahl der Antwortmoeglichkeiten, Standard: 5 - %L1={Antwort 1}, %1. Antwortmoeglichkeit - %L2={Antwort 2}, %2. Antwortmoeglichkeit - %L3={Antwort 3}, %3. Antwortmoeglichkeit - %L4={Antwort 4}, %4. Antwortmoeglichkeit - %L5={Antwort 5}, %5. Antwortmoeglichkeit - %L6={}, %6. Antwortmoeglichkeit - %L7={}, %7. Antwortmoeglichkeit - %L8={}, %8. Antwortmoeglichkeit - %L9={}, %9. Antwortmoeglichkeit - %%% LOESUNG: %% - %A1=2, % 1. Antwort - %A2=4, % 2. Antwort - %A3=0, % 3. Antwort - %A4=0, % 4. Antwort - %A5=0, % 5. Antwort - %} -%\end{verbatim} -% -%\setcounter{Zufall}{0} -%\textsc{Ausgabe:}, bei \texttt{\textbackslash setcounter\{Zufall\}\{0\}}: -% -%\multiplechoice[5]{ %Anzahl der Antwortmoeglichkeiten, Standard: 5 - %L1={Antwort 1}, %1. Antwortmoeglichkeit - %L2={Antwort 2}, %2. Antwortmoeglichkeit - %L3={Antwort 3}, %3. Antwortmoeglichkeit - %L4={Antwort 4}, %4. Antwortmoeglichkeit - %L5={Antwort 5}, %5. Antwortmoeglichkeit - %L6={}, %6. Antwortmoeglichkeit - %L7={}, %7. Antwortmoeglichkeit - %L8={}, %8. Antwortmoeglichkeit - %L9={}, %9. Antwortmoeglichkeit - %%% LOESUNG: %% - %A1=2, % 1. Antwort - %A2=4, % 2. Antwort - %A3=0, % 3. Antwort - %A4=0, % 4. Antwort - %A5=0, % 5. Antwort - %} - % -%\setcounter{Zufall}{1} -%\textsc{Ausgabe:}, bei \texttt{\textbackslash setcounter\{Zufall\}\{1\}}: -% -%\multiplechoice[5]{ %Anzahl der Antwortmoeglichkeiten, Standard: 5 - %L1={Antwort 1}, %1. Antwortmoeglichkeit - %L2={Antwort 2}, %2. Antwortmoeglichkeit - %L3={Antwort 3}, %3. Antwortmoeglichkeit - %L4={Antwort 4}, %4. Antwortmoeglichkeit - %L5={Antwort 5}, %5. Antwortmoeglichkeit - %L6={}, %6. Antwortmoeglichkeit - %L7={}, %7. Antwortmoeglichkeit - %L8={}, %8. Antwortmoeglichkeit - %L9={}, %9. Antwortmoeglichkeit - %%% LOESUNG: %% - %A1=2, % 1. Antwort - %A2=4, % 2. Antwort - %A3=0, % 3. Antwort - %A4=0, % 4. Antwort - %A5=0, % 5. Antwort - %} -% -%\setcounter{Zufall}{2} -%\textsc{Ausgabe:}, bei \texttt{\textbackslash setcounter\{Zufall\}\{2\}}: -% -%\multiplechoice[5]{ %Anzahl der Antwortmoeglichkeiten, Standard: 5 - %L1={Antwort 1}, %1. Antwortmoeglichkeit - %L2={Antwort 2}, %2. Antwortmoeglichkeit - %L3={Antwort 3}, %3. Antwortmoeglichkeit - %L4={Antwort 4}, %4. Antwortmoeglichkeit - %L5={Antwort 5}, %5. Antwortmoeglichkeit - %L6={}, %6. Antwortmoeglichkeit - %L7={}, %7. Antwortmoeglichkeit - %L8={}, %8. Antwortmoeglichkeit - %L9={}, %9. Antwortmoeglichkeit - %%% LOESUNG: %% - %A1=2, % 1. Antwort - %A2=4, % 2. Antwort - %A3=0, % 3. Antwort - %A4=0, % 4. Antwort - %A5=0, % 5. Antwort - %} - -\subsection{Informationseingabe -- Option: \texttt{[info\_on/off]}} + + +\subsection{Paketoption -- Informationseingabe: \texttt{[info\_on/off]}} Es ist darüber hinaus möglich zusätzliche Informationen (Erläuterungen, Hilfestellungen, \ldots) hinzuzufügen und einzublenden. Dazu kann die Option \texttt{info\_on/off} im \texttt{srdp-mathematik}-Paket eingebunden werden. Die Infos werden in \textcolor[rgb]{0,0,1}{blau} angegeben und nur dann angezeigt, wenn die Option \texttt{info\_on} gewählt wurde (verwendeter counter: \texttt{info=0,1}). Also: @@ -403,13 +354,13 @@ oder \subsection{Weitere allgemeine Befehle} Außerdem gibt es noch weitere Befehle, die die Formatierung erleichtern. -\subsubsection*{\texttt{\textbackslash leer} - Befehl} +\subsubsection{\texttt{\textbackslash leer}} Eine Leerzeile, etwa zwischen zwei Beispielen. \\ (Nach dem Befehl \texttt{\textbackslash leer} muss in der \texttt{.tex}-Datei ein Leerzeile eingefügt werden!) \leer -\subsubsection*{\texttt{\textbackslash meinlr} - Befehl} +\subsubsection{\texttt{\textbackslash meinlr}} \begin{verbatim} \meinlr{Dieser Teil steht links. Wenn dieser Text länger sein sollte, geht er automatisch in der nächsten Zeile weiter ohne auf die andere @@ -426,7 +377,7 @@ geht er automatisch in der nächsten Zeile weiter ohne auf die andere Seite über zu gehen.}{Dieser Teil steht rechts.} -\subsubsection*{Zusatz: Variable Spaltenbreiten bei \texttt{\textbackslash meinlr}} +\subsubsection*{\texttt{\textbackslash meinlr} -- Option: Variable Spaltenbreiten} Der Befehl \texttt{\textbackslash meinlr} erlaubt durch die optionale Eingabe eine Abänderung der beiden Spaltenbreiten. Durch die Eingabe zwischen ca. -0.3 und 0.3 kann die Spaltenmitte nach links oder rechts verschoben und somit die Spaltenbreite variiert werden. @@ -446,7 +397,7 @@ die Spaltenbreiten nach Belieben zu variieren.} \leer -\subsubsection*{\texttt{\textbackslash meinlcr} - Befehl} +\subsubsection{\texttt{\textbackslash meinlcr}} \begin{verbatim} \meinlcr{Text ganz links}{Text in der Mitte. Auch hier sind längere Texte möglich.}{Text auf der rechten Seite.} @@ -459,15 +410,54 @@ Teilt die Seite in drei gleich große Teile \meinlcr{Text ganz links. Was passiert hier wenn dieser Teil länger ist?}{Text in der Mitte. Auch hier sind längere Texte möglich.}{Text auf der rechten Seite.} + +\subsubsection{\texttt{\textbackslash dint} und \texttt{\textbackslash dx}} +Die Befehle \texttt{\textbackslash dint} und \texttt{\textbackslash dx} vereinfacht die Eingabe eines Integrals (bestimmt oder unbestimmt).\leer + +\textsc{Eingabe:} + +\begin{verbatim} +$\dint_1^3 x^2 \dx$ +\end{verbatim} + +\textsc{Ausgabe:}\leer + +$\dint_1^3 x^2 \dx$ \leer +Wird eine Variable ungleich $x$ integriert, kann diese mithilfe der Option \texttt{\textbackslash{dx[Variable]}} dargestellt werden.\leer + +\textsc{Eingabe:} + +\begin{verbatim} +$\dint t^2 \dx[t]$ +\end{verbatim} + +\textsc{Ausgabe:}\leer + +$\dint t^2 \dx[t]$ + +\subsubsection{\texttt{\textbackslash degre}} + +Der \texttt{\textbackslash degre} Befehl stellt das Einheitszeichen für Grad dar. Er kann im Text- und im Mathematik-Modus verwendet werden. + +\textsc{Eingabe:} + +\begin{verbatim} +Der Winkel Alpha ist 30\degre. ($\alpha = 30 \degre$) +\end{verbatim} + +\textsc{Ausgabe:}\leer + +Der Winkel Alpha ist 30\degre. ($\alpha = 30 \degre$) + \section{Typ-1-Aufgaben} Das \texttt{srdp-mathematik}-Paket ermöglicht die Verwendung vorgefertigter Aufgabenformate, die bei der österreichischen, standardisierten Reifeprüfung Anwendung finden. -\subsection{\texttt{multiplechoice}-Befehl} +\subsection{\texttt{\textbackslash multiplechoice}} Dieser Befehl liefert eine vollständige Formatierung für eine Multiplechoice-Aufgabe. Die Anzahl der Antwortmöglichkeiten kann dabei frei (max. 9) gewählt werden. Als Standard ist dabei das Format mit fünf Antwortmöglichkeiten eingestellt. \leer @@ -669,7 +659,7 @@ Die Eingabe in eckiger Klammer ist dabei optional. Wird sie nicht angegeben, wir \leer \newpage -\subsubsection{Add-on: \texttt{langmultiplechoice}-Befehl} +\subsubsection{Add-on: \texttt{\textbackslash langmultiplechoice}} Der \texttt{langmultiplechoice}-Befehl ist analog zum \texttt{multiplechoice}-Befehl zu verwenden. Der Unterschied besteht darin, dass Antwortmöglichkeiten auf zwei Spalten aufgeteilt werden. Dies ist vor allem dann sinnvoll, wenn Geogebra-Grafiken importiert werden, um eine bessere Lesbarkeit zu ermöglichen. @@ -790,7 +780,7 @@ Der \texttt{langmultiplechoice}-Befehl ist analog zum \texttt{multiplechoice}-Be \newpage -\subsection{\texttt{lueckentext}-Befehl} +\subsection{\texttt{\textbackslash lueckentext}} Dieser Befehl dient zur Erstellung eines Lückentexts, basierend auf dem standardisierten Format des BIFIE. Der einleitenden Satz: \textit{"`Ergänze die Textlücken im folgenden Satz durch Ankreuzen der jeweils richtigen Satzteile so, dass eine mathematisch korrekte Aussage entsteht!"'} wird als Standard angenommen und automatisch angegeben. Im Bereich \texttt{\textbackslash text=\{\}} wird der Lückentext angegeben, wobei die Lücken immer mit \texttt{\textbackslash gap} eingefügt werden und automatisch nummeriert werden. Analog zu den Lösungsangaben der Multiplechoice-Aufgabe, werden die korrekten Antworten bei A1, A2 oder A3 mit 1,2 oder 3 angegeben. (hier: Lösung links: 3 und rechts: 2) \vspace{0.35cm} @@ -829,7 +819,7 @@ die \gap, die Lücke zwei hat die \gap.}, %Lueckentext Luecke=\gap } -\subsubsection{Zusatz: Variable Breiten der Boxen} +\subsubsection{\texttt{\textbackslash lueckentext} -- Option: Variable Breiten der Boxen} Der \texttt{lueckentext}-Befehl erlaubt ein optionales Argument, um die Größen der beiden Boxen zu variieren. Dabei werden in den eckigen Klammern $[~]$ die Veränderung der linken Box (Änderung ca. zwischen -0.3 und 0.3) angegeben und die rechte Box wird automatisch angepasst. Will man etwa die linke Box vergrößern, gilt:\leer @@ -877,7 +867,7 @@ die \gap, die Lücke zwei hat die \gap.}, %Lueckentext Luecke=\gap Analog funktioniert die Verkleinerung der linken Box. Dazu müssen Werte kleiner 0 angegeben werden. -\subsubsection{\texttt{Zusatz}: Englischer Lückentext} +\subsubsection{\texttt{\textbackslash lueckentext} -- Option: Englischer Lückentext} Der Befehl \texttt{englueckentext} ist analog zum \texttt{lueckentext}-Befehl zu verwenden. Jedoch wird der als Standard angenommene, einleitende Satz bei Lückentextaufgaben in Englisch angezeigt. \textsc{Eingabe:} @@ -911,7 +901,7 @@ Der Befehl \texttt{englueckentext} ist analog zum \texttt{lueckentext}-Befehl zu A2=3 % Antwort rechts } -\subsection{\texttt{zuordnen}-Befehl} +\subsection{\texttt{\textbackslash zuordnen}} Dieser Befehl dient zum Erstellen des Zuordnungsformats von vier aus sechs Möglichkeiten. Die korrekten Antworten können hier frei als Buchstaben eingegeben werden. (hier: F, C, A, D) @@ -961,7 +951,7 @@ Die korrekten Antworten können hier frei als Buchstaben eingegeben werden. (hie A4={D}, % 4. richtige Zuordnung } -\subsubsection{Zusatz: Variable Breiten der Boxen} +\subsubsection{\texttt{\textbackslash zuordnen} -- Option: Variable Breiten der Boxen} Der \texttt{zuordnen}-Befehl erlaubt ein optionales Argument, um die Größen der beiden Boxen zu variieren. Dabei werden in den eckigen Klammern $[~]$ die Veränderung der linken Box (Änderung ca. zwischen -0.3 und 0.3) angegeben und die rechte Box wird automatisch angepasst. Will man etwa die linke Box vergrößern, gilt: @@ -1019,16 +1009,16 @@ Analog funktioniert die Verkleinerung der linken Box. Dazu müssen Werte kleiner \section{Typ-2-Aufgaben} Um die Struktur der Teil-2-Aufgaben ähnlich jener bei der standardisierten Reifeprüfung einhalten zu können, beinhaltet das Paket einige Befehle, die die Erstellung von Typ-2-Aufagben erleichtern. -\subsection{\texttt{aufgabenstellung}-Umgebung} +\subsection{\texttt{\textbackslash begin\{aufgabenstellung\} \ldots\ \textbackslash end\{aufgabenstellung\}}} Typ-2-Aufgaben sollten innerhalb einer Prüfung mithilfe der \texttt{langesbeispiel}-Umgebung eingegeben werden, um die volle Funktionalität (wie \texttt{notenschluessel}) des Pakets zu ermöglichen. Der einleitenden Aufgabentext kann dann eingegeben werden. Für die Eingabe der Aufgabenstellung kann dann die \texttt{aufgabenstellung}-Umgebung verwendet werden.\leer \subsubsection{\texttt{\textbackslash item} und \texttt{\textbackslash Subitem\{\}}} Innerhalb dieser Umgebung können dann mithilfe von \texttt{\textbackslash item} (nummeriert mit a), b) ,c), \ldots) und \texttt{\textbackslash Subitem\{\}} (nummeriert mit 1), 2), \ldots) die jeweiligen Items und Subitems der Aufgabe eingegeben werden. \leer -\subsubsection{Ausgleichspunkte} +\subsubsection{Ausgleichspunkte -- \texttt{\textbackslash Aitem} und \texttt{\textbackslash ASubitem\{\}}} Um die notwendigen Ausgleichspunkte in den Typ-2-Aufgaben zu markieren, können die Befehle \texttt{item} und \texttt{Subitem} durch \texttt{\textbackslash Aitem} und \texttt{\textbackslash ASubitem\{\}} ersetzt werden. Dabei wird vor den geschriebenen Text noch ein \fbox{A} eingefügt -- die Nummerierung wird aber wie gewohnt fortgesetzt. -\subsection{\texttt{loesung}-Umgebung} +\subsection{\texttt{\textbackslash begin\{loesung\} \ldots\ \textbackslash end\{loesung\}}} Mithilfe der \texttt{loesung}-Umgebung kann die Lösungserwartung sowie der Lösungsschlüssel eingegeben werden. Analog zur Aufgabenstellung können \texttt{\textbackslash item} und \texttt{\textbackslash Subitem\{\}} verwendet werden. Die Eingabe innerhalb der \texttt{loesung}-Umgebung werden nur dann angezeigt, wenn die Lösungsanzeige aktiviert wurde. Die Nummerierung der Subitems kann man mit folgender Eingabe zurücksetzen: \texttt{\textbackslash setcounter{subitemcounter}{0}}.\leer Eine vollständige Typ-2-Aufgabe könnte also wie folgt aussehen: @@ -1063,7 +1053,7 @@ Hier steht der einleitende Text der Typ-2-Aufgabe. \end{langesbeispiel} \end{verbatim} -\newpage + \textsc{Ausgabe:} \setcounter{Antworten}{1} |