diff options
author | Karl Berry <karl@freefriends.org> | 2020-02-19 22:11:40 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2020-02-19 22:11:40 +0000 |
commit | 4701e1a772599af5699534ae4090999a79e04ecf (patch) | |
tree | 5454e5ee585903dcb6ebe8724e674d53039e4e02 /Master/texmf-dist/source | |
parent | f7fa7c5e6558b4fdff8eebb64a21cdf138d96929 (diff) |
xint (19feb20)
git-svn-id: svn://tug.org/texlive/trunk@53846 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source')
-rw-r--r-- | Master/texmf-dist/source/generic/xint/Makefile | 2 | ||||
-rw-r--r-- | Master/texmf-dist/source/generic/xint/xint.dtx | 6740 |
2 files changed, 3544 insertions, 3198 deletions
diff --git a/Master/texmf-dist/source/generic/xint/Makefile b/Master/texmf-dist/source/generic/xint/Makefile index c8bdeb9bf21..0c18379fe15 100644 --- a/Master/texmf-dist/source/generic/xint/Makefile +++ b/Master/texmf-dist/source/generic/xint/Makefile @@ -1,5 +1,5 @@ # Makefile for building and installing xint -# (C) 2014-2019 Jean-Francois Burnol +# (C) 2014-2020 Jean-Francois Burnol # distributed under LPPL 1.3c. # Tested with GNU Make 3.81 on Mac OS X Mavericks, diff --git a/Master/texmf-dist/source/generic/xint/xint.dtx b/Master/texmf-dist/source/generic/xint/xint.dtx index 0962cf0553e..49fbd503512 100644 --- a/Master/texmf-dist/source/generic/xint/xint.dtx +++ b/Master/texmf-dist/source/generic/xint/xint.dtx @@ -3,27 +3,27 @@ % Extract all files via "etex xint.dtx" and do "make help" % or follow instructions from extracted README.md. %<*dtx> -\def\xintdtxtimestamp {Time-stamp: <31-01-2020 at 16:51:45 CET>} +\def\xintdtxtimestamp {Time-stamp: <19-02-2020 at 09:09:07 CET>} %</dtx> %<*drv> %% --------------------------------------------------------------- -\def\xintdocdate {2020/01/31} -\def\xintbndldate{2020/01/31} -\def\xintbndlversion {1.4} +\def\xintdocdate {2020/02/19} +\def\xintbndldate{2020/02/19} +\def\xintbndlversion {1.4a} %</drv> %<readme>% README %<changes>% CHANGE LOG -%<readme|changes>% xint 1.4 -%<readme|changes>% 2020/01/31 +%<readme|changes>% xint 1.4a +%<readme|changes>% 2020/02/19 %<readme|changes> -%<readme|changes> Source: xint.dtx 1.4 2020/01/31 (doc 2020/01/31) +%<readme|changes> Source: xint.dtx 1.4a 2020/02/19 (doc 2020/02/19) %<readme|changes> Author: Jean-Francois Burnol %<readme|changes> Info: Expandable operations on big integers, decimals, fractions %<readme|changes> License: LPPL 1.3c %<readme|changes> %<*!readme&!changes&!dohtmlsh&!makefile> %% --------------------------------------------------------------- -%% The xint bundle 1.4 2020/01/31 +%% The xint bundle 1.4a 2020/02/19 %% Copyright (C) 2013-2020 by Jean-Francois Burnol %<xintkernel>%% xintkernel: Paraphernalia for the xint packages %<xinttools>%% xinttools: Expandable and non-expandable utilities @@ -123,8 +123,8 @@ Documentation Requirements ============ -Attention, release `1.4` requires the `\expanded` primitive available -in all major TeX engines since TeXLive 2019. +Attention, since release `1.4` `xintexpr` requires the `\expanded` +primitive (it is provided by all major TeX engines since TeXLive 2019). License ======= @@ -153,6 +153,37 @@ See `xint.pdf` for contact information. %</readme>-------------------------------------------------------- %<*changes>------------------------------------------------------- +`1.4a (2020/02/19)` +---- + +### Breaking changes + + - **xintexpr**: the macros implementing customization of + `\xintthealign` have modified meanings and names. + +### New features + + - **xintexpr**: `\xintthespaceseparated` (serves to provide + suitable input to PS-Tricks `\listplot`). + + - **xintexpr**: the optional argument `[D]` to `\xintieval/\xintiexpr` + can be negative, with the same meaning as the non-negative case, i.e. + *quantization* to an integer multiple of `10^(-D)`. + + The same applies to the functions `trunc()` and `round()`. And to + the `\xintTrunc`, `\xintRound`, `\xintiTrunc`, and `\xintiRound` macros + of **xintfrac**. + +### Bug fixes + + - **xintexpr**: usage of `round()` and `trunc()` within `\xintdeffunc` + got broken at `1.4`. + + - **xintexpr**: `add()` and `mul()` were supposedly accepting the + `omit`, `abort` and `break()` keywords since `1.4` but this was + broken. + + `1.4 (2020/01/31)` ---- @@ -2559,6 +2590,13 @@ pandoc -o CHANGES.html -s --toc -V highlighting-css=' body{margin-left : 10%; \definecolor{JOLI}{RGB}{225,95,0} \definecolor{BLUE}{RGB}{0,0,255} \definecolor{niceone}{RGB}{38,128,192} +\definecolor{sedate}{RGB}{193,132,1} +\definecolor{saddlebrown}{rgb}{.545,.27,.075} +\definecolor{jfbrown}{RGB}{165,100,10}% + + + + \usepackage{eso-pic}% après xcolor sinon Option clash for package xcolor. \ifnum\dosourcexint=1 @@ -2843,6 +2881,8 @@ pdfpagemode=UseNone,% % Margin Notes % ============ +% Nothing here can be used in vertical mode directly. + \makeatletter \def\MyMarginNote {\@ifnextchar[\@MyMarginNote{\@MyMarginNote[]}}% \let\inmarg\MyMarginNote @@ -2914,6 +2954,22 @@ pdfpagemode=UseNone,% \vtop{\noindent Changed at #1!}\ }}}% \vskip\dp\strutbox }\strut\@esphack} +\def\DNU#1{\@bsphack + \vadjust{\vskip-\dp\strutbox + \hbox{\smash{\hbox to 0pt {\hss\color[named]{Red}% + \normalfont\small\bfseries + \hsize 1.5cm\rightskip.5cm minus.5cm + \vtop{\noindent Do not use! #1}\ }}}% + \vskip\dp\strutbox }\strut\@esphack} + +\def\UNSTABLE#1{\@bsphack + \vadjust{\vskip-\dp\strutbox + \hbox{\smash{\hbox to 0pt {\hss\color[named]{Red}% + \normalfont\small\bfseries + \hsize 1.5cm\rightskip.5cm minus.5cm + \vtop{\noindent Unstable! #1}\ }}}% + \vskip\dp\strutbox }\strut\@esphack} + \def\DEPRECATED #1{\@bsphack \vadjust{\vskip-\dp\strutbox \hbox{\smash{\hbox to 0pt {\hss\color[named]{PineGreen}% @@ -3008,7 +3064,11 @@ pdfpagemode=UseNone,% % ========================= \def\restoreMicroFont {\def\MicroFont {\ttbfamily\makestarlowast - \ifinlefted\else\ifineverb\else\color[named]{Blue}\fi\fi}} +% \ifinlefted\else\ifineverb\else\color[named]{verbatim}\fi\fi +% \ifinlefted\else\color[named]{saddlebrown}\fi +% \ifinlefted\else\color[named]{sedate}\fi + \ifinlefted\else\color[named]{jfbrown}\fi +}} \restoreMicroFont % Notice that \macrocode uses \macro@font which stores the \MacroFont meaning @@ -3016,7 +3076,11 @@ pdfpagemode=UseNone,% % not the meaning at \begin{document}. Comprenne qui pourra... \def\restoreMacroFont {\def\MacroFont {\ttbfamily - \ifinlefted\else\ifineverb\else\color[named]{Blue}\fi\fi}} +% \ifinlefted\else\ifineverb\else\color[named]{Blue}\fi\fi +% \ifinlefted\else\color[named]{Blue}\fi +% \ifinlefted\else\color[named]{sedate}\fi + \ifinlefted\else\color[named]{Brown}\fi +}} \restoreMacroFont % \verb @@ -3122,12 +3186,14 @@ pdfpagemode=UseNone,% \makeatletter \catcode`_ 11 -\def\everbatimtop {\MacroFont\small } +% Je modifie Mardi 18 février 2020 \MacroFont +% pour essayer couleur de foreground, +% je supprime donc le \ifineverb de \MacroFont. +% \newif\ifineverb +\def\everbatimtop {\MacroFont \small} \let\everbatimbottom\relax \let\everbatimhook\relax -\newif\ifineverb - \def\everbatim {\s@everbatim\@everbatim } \@namedef{everbatim*}{\s@everbatim\expandafter\@everbatimx\expandafter {\the\newlinechar}} @@ -3143,7 +3209,7 @@ pdfpagemode=UseNone,% \expandafter\let\csname endeverbatim*\endcsname \endeverbatim \def\s@everbatim {% - \ineverbtrue +% \ineverbtrue \everbatimtop % put there size changes \topsep \z@skip \partopsep \z@skip @@ -3337,8 +3403,8 @@ pdfpagemode=UseNone,% {{\char92\mbox{xint}\-\endlinechar-1 \makestarlowast \scantokens\expandafter{\detokenize{#1}}}}} -% \func, \funcdesc, \keyword, \keyworddesc, \prec, \precdesc -% ========================================================== +% \func, \funcdesc, \keyword, \keyworddesc, \prec, \precdesc, \oper, \operdesc +% ============================================================================ \newcommand\func[1]{\hyperlink{\detokenize{func-#1}}{#1}()} \newcommand\funcdesc[2][x]{\item[#2({#1})]\hypertarget{\detokenize{func-#2}}{}}% @@ -3348,17 +3414,21 @@ pdfpagemode=UseNone,% \let\prec\relax % sinon, c'est \mathchar"321E \newcommand\prec[1]{\hyperlink{\detokenize{prec-#1}}{#1}} -\newcommand\precdesc[1]{\item[$#1$]\hypertarget{\detokenize{prec-$#1$}}{}}% +\newcommand\precdesc[1]{\item[\texttt{#1}]\hypertarget{\detokenize{prec-#1}}{}\leavevmode}% \newcommand\var[1]{\hyperlink{\detokenize{var-#1}}{#1}} \newcommand\vardesc[1]{\item[#1]\hypertarget{\detokenize{var-#1}}{}}% +\newcommand\oper[1]{\hyperlink{\detokenize{oper-#1}}{#1}} +\newcommand\operdesc[1]{\item[\texttt{#1}]\hypertarget{\detokenize{oper-#1}}{}}% + + % \xintname, \xintnameimp etc... % ============================== \xintForpair #1#2 in -{(xintbundle,bundle), +{(xint bundle,bundle), (xintkernel,kernel), (xinttools,tools), (xintcore,core),(xint,xint),(xintbinhex,binhex),(xintgcd,gcd),% @@ -3455,22 +3525,22 @@ pdfpagemode=UseNone,% % 31 janvier 2020 - \def\DOCuserguide + \def\DOCxintexprintro {\texorpdfstring - {\hyperref[sec:xintexprsyntax]{\relax{\color{joli}\MakeNameUp{Syntax reference}}}}% - {Syntax reference}% + {\hyperref[part:1]{\relax{\color{joli}\MakeNameUp{Start here}}}}% + {Start here}% \xspace }% \def\DOCxintexprmacros {\texorpdfstring - {\hyperref[sec:oldxintexpr]{\relax{\color{joli}\MakeNameUp{Older macros and doc}}}}% - {Older macros and doc}% + {\hyperref[sec:oldxintexpr]{\relax{\color{joli}\MakeNameUp{xintexpr}}}}% + {xintexpr}% \xspace }% \def\DOCexamples {\texorpdfstring - {\hyperref[sec:examples]{\relax{\color{joli}\MakeNameUp{Old examples}}}}% - {Old examples}% + {\hyperref[sec:examples]{\relax{\color{joli}\MakeNameUp{Examples}}}}% + {Examples}% \xspace }% % Vendredi 15 juin 2018 @@ -3479,13 +3549,11 @@ pdfpagemode=UseNone,% % tokens, so it fails to recognize the commas which of course are of catcode12 \def\xintRunningHeader{{\inheadertrue\catcode`,12\relax \DOCxintfrontpage, + \DOCxintexprintro, \xintexprname, - \DOCuserguide, - \DOCxintexprmacros, \xinttrigname, \xintlogname, - \DOCexamples, - \xintbundlename}} + \csname xint bundlename\endcsname}} \markboth{\makebox[0pt]{\xintRunningHeader}}{\makebox[0pt]{\xintRunningHeader}} % Skips safely. @@ -3724,47 +3792,33 @@ pdfpagemode=UseNone,% \etocdepthtag.toc {part1A} -\csname xintexprnameUp\endcsname +\csname Start herenameUp\endcsname \part{The \xintexprname package} -\RaisedLabel[12]{sec:expr} +\RaisedLabel[12]{part:1} \etocsetnexttocdepth{section} \localtableofcontents -\section {Release \texttt{\xintbndlversion } of \texttt{\xintbndldate}} - -\subsection{Start here} +\section {Start here} -To use with |etex|, |pdftex|, ..., i.e. with \TeX{} engines activating the -e\TeX{} extensions: +\begin{itemize} +\item To use with |etex|, |pdftex|, ..., i.e. with \TeX{} engines activating + the e\TeX{} extensions: \begin{everbatim} \input xintexpr.sty +\xinteval{sqrt(13, 60)}% get it with 60 digits (correctly rounded) \end{everbatim} -To use with the \LaTeX{} macro layer (|latex|, |pdflatex|, ...): +\item To use with the \LaTeX{} macro layer (|latex|, |pdflatex|, ...): \begin{everbatim} \usepackage{xintexpr} +% and here you have to wait for \begin{document}... +% or rather you can start playing immediately: +\typeout{\xinteval{sqrt(13, 60)}} \end{everbatim} +\end{itemize} -\medskip - -|1.4| is a major release with new features and breaking changes. They are -summarized at top of |CHANGES.html| file (|texdoc --list xint|) and it is -recommended to read it as it may contain information which will not be -duplicated here. - -\medskip - -The formatted source code is available in file |sourcexint.pdf| -(|texdoc sourcexint|). - -\begin{framed} - The main breaking change is that \xintexprname |1.4| requires the - |\expanded| primitive, available with all major \TeX{} engines since \TeX - Live 2019. But the supporting macro packages \xintcorename, \xintname, - \xintfracname, \xinttoolsname do not (yet). -\end{framed} - -\xintexprname is a package to do expandable computations, either exactly or in +\xintexprname is a package to do expandable computations, either exactly +(i.e.\@ with fractions) or in the sense of floating point numbers at an arbitrary (reasonable% % \footnote{Trigonometrical functions are currently supported only up to about @@ -3775,18 +3829,28 @@ the sense of floating point numbers at an arbitrary (reasonable% will not attempt to support floating point calculations efficiently beyond that limit.}% ) precision. It supports user definition of variables and functions. Its -interface allows multiple comma separated expressions. +interface allows multiple comma separated expressions and nested structures: +\begin{everbatim*} +\xinteval{1, 2, [3, [4, 5]], 6} +\end{everbatim*}is impressive. No? + + \medskip +I am thinking about providing a console interface (using |rlwrap etex| as +sadly the e-\TeX{} binaries are not linked with the |readline| library) which +would mimick sessions with Maple or Python. -Iterated commas are like only one. The parentheses serve only to disambiguate -operator precedences or to hand-over variables to functions. One can add 100 -paired parentheses to |1, 2, 3| and it will not change anything. On the -other hand brackets |[|, |]| allow to define nested \emph{lists}, for example -\begin{everbatim*} -\xinteval{1, 2, [3, [4, 5]], 6} -\end{everbatim*} -is a pretty impressive feast. +\medskip + +For a quick impression of the package abilities, check (not yet, else you will +never come back here) the tables of its built-in +\hyperref[tab:precedences]{operators} and \hyperref[tab:functions]{functions}. + + +\medskip +The formatted source code is available in file |sourcexint.pdf| +(|texdoc sourcexint|). \medskip @@ -3797,7 +3861,35 @@ sections, which was a hard decision to take, almost breaking the palimpsest quality of the document). Reports welcome.% % \footnote{Thanks to Jürgen Gilg for keeping the author motivated and - helping proof-reading the documentation.} + helping proof-read the documentation.} + +\subsection{The \texttt{1.4a} release of \texttt{2020/02/19}} + +It is mainly a bugfix release. Check |CHANGES.html| file (|texdoc --list +xint|). + +\subsection{The \texttt{1.4} release of \texttt{2020/01/31}} + +|1.4| was a major release with new features and breaking changes. See +|CHANGES.html| file (|texdoc --list xint|) which may contain information +not yet included in the PDF documentation. + +The main new feature was (initial) support for nested structures. For a quick +idea of already available related abilities check for example \func{ndseq} or +\csbxint{defufunc}. See also \csbxint{thealign}. However, please grant the +author a few decades to finish absorbing Python/NumPy. + +\begin{framed} + The main breaking change is that \xintexprname |1.4| requires the + |\expanded| primitive. It is available with all major \TeX{} engines + since \TeX Live 2019. + + The macro packages \xintcorename, \xintname, + \xintfracname, \xinttoolsname et al. do not (yet) require |\expanded|. + + It is probable also |\pdfstrcmp| (|\strcmp|) will be required at some point + but it has been provided by major \TeX{} engines for a long time already. +\end{framed} \subsection{License and installation instructions} @@ -3819,101 +3911,6 @@ will offer to display one of those files: \item |CHANGES.html|. \end{itemize} - - -\subsection{Quick overview of syntax elements} - -Here is a (partial) list of the recognized syntax elements: -\begin{itemize} -\item the comma (to separate distinct computations or arguments to a - function), -\item parentheses, -\item square brackets,\NewWith{1.4} -\item \hyperref[tab:precedences]{operators}: - \begin{itemize}[nosep] -\item |+|, |-|, |*|, |/|, -\item powers via |^| or equivalently |**|, see \xintlogname for allowing usage of - them with fractional exponents (half-integer exponents are allowed by - default by \csbxint{floateval}), -\item |//| for floored division (attention that |-3//2| is computed as - |-(3//2)|) and |/:| its associated modulo, -\item branching via |(x)?{x non zero}{x zero}| and |(x)??{x<0}{x=0}{x>0}| - syntax, -\item Boolean logic |!()|, |?()| (truth values), |&&| (equivalently |'and'|), \verb+||+ (equivalently - |'or'|), |'xor'|, -\item comparison operators |==|, |!=|, |<|, |>|, |<=|, |>=|, -\item factorial (exact or floating point, but only for integer arguments) via - the postfix operator |!|. - \end{itemize} -\item the |"| is used to prefix hexadecimal (only uppercase) input. This is - NOT activated by default: package \xintbinhexname \fbox{must} be explicitly - loaded, -%\item |'| for octal input (\emph{not yet}), -\item various \hyperref[tab:functions]{functions}: - \begin{itemize}[nosep] - \item rounding and truncating \func{round}, \func{trunc} to a given fixed - point precision or with \func{float} to a given floating point precision, - \item the square-root \func{sqrt} achieves correct rounding in arbitrary - precision, - \item \func{binomial}, \func{factorial}, \func{pfactorial}, - \item \func{gcd} and \func{lcm} both work with general fractions as input, - \item randomness related functions such as \func{random} and - \func{randrange} for random floats or integers; they require that \TeX\ - engine provides \csa{pdfuniformdeviate} or \csa{uniformdeviate} primitive, - \item trigonometrical functions \xinttrigname, - \item logarithm and exponential functions \xintlogname. - \item pseudo-functions whose syntax involves usage of dummy variables: - \xintFor #1 in {subs, subsm, subsn, rseq, seq, add, mul, iter, rrseq, iterr, - ndseq, ndmap}\do - {\func{#1}\xintifForLast{.}{, }} - \end{itemize} -\item built-in and user-defined \hyperref[ssec:uservariables]{variables} and \hyperref[ssec:userfunctions]{functions}. -\end{itemize} - - -The normal mode of operation of the parsers is to unveil the parsed material -token by token. Unveiling is a process combining brace removal (one level -generally) and \fexpan sion (think of it as a kind of adaptative |\edef|). -Thus all tokens may arise from expansion of macros or active characters. For -example a closing parenthesis does not have generally to be immediately -visible, it may arise later from expansion. Even the ending |\relax| may -arise from expansion. Even though the \csbxint{eval} user interface means that -the package has at some point the entire expression in its hands, it -immediately re-inserts it into token stream with an additional postfixed -|\relax| and from this point on has lost any ways to manipulate formally again -the whole thing; it can only re-discover it piece per piece. - -This general behaviour has significative exceptions mostly related to -«pseudo»-functions. A «pseudo»-function will grab some of its arguments via -delimited macros. For example |subs(expr1,x=expr2)| needs to see the comma, -equal sign and closing parenthesis. But it has mechanisms to allow |expr1| and -|expr2| to possess their own commas and parentheses. - -Inner semi-colons on the currently always can originate from expansion. -Defining functions or variables requires a visible semi-colon acting as -delimiter of the expression, but inner semi-colons do not need to be -hidden within braces or macros\NewWith{1.4}. The semi-colon catcode will be -set at the start of the process but of course this is too late if the whole -thing has already been grabbed in a macro. - -The expansion stops only when the ending |\relax| has been found; -it is then removed from the token stream, and the final computation result is -inserted. - -Some examples with dummy variables: -\begin{everbatim*} -\xintiiexpr add(i^5, i=100..200)\relax\par -\noindent\xintexpr add(x/(x+1), x = 1000..1014)\relax\par -\noindent\xintexpr reduce(add(x/(x+1), x = 1000..1014))\relax -\end{everbatim*} -\newline In this example, the fraction obtained by addition was thus already -irreducible, but this is not always the case: -\begin{framed} - By default, basic operations on fractions do not automatically reduce to - smallest terms the output: |A/B| multiplied by |C/D| - returns |AC/BD|, and |A/B| added to |C/D| uses |lcm(B, D)| as denominator. -\end{framed} - \subsection{Printing big numbers on the page}\label{ssec:printnumber} When producing very long numbers there is the question of printing them on the page, without going beyond the page limits. In this document, I have most @@ -3931,11 +3928,22 @@ It may be used like this: % \begin{everbatim*} \printnumber{\xintiieval{100!^3}}\newline -\end{everbatim*} +\end{everbatim*}% The rendering here uses extra decoration. +\clearpage +\expandafter\let\csname Start herenameUp\endcsname\undefined +\csname xintexprnameUp\endcsname +\section{\xintexprname syntax reference and user guide} +\RaisedLabel{sec:expr} + +\localtableofcontents + \subsection{Oples and nut-ples: terminology for a new \xintname generation} +\emph{Skip this on first reading, else you will never start using the + package.} \fbox{SKIP THIS!} (understood?) + In this section I will describe a mathematical terminology appropriate to understand the core functioning of the package in so far as it regards its numerical mode of operation. The description requires some adaptations to @@ -4098,7 +4106,7 @@ For example when applied to the \emph{not-ple} we always obtain the |nil|. Whereas as we saw slicing the \emph{not-ple} always gives back the \emph{not-ple}. Indexing is denoted in the syntax by postfixing by |[N]|. Thus for \emph{nut-ples} (which are analogous to Python objects), there is genuine -diffence between the |[N]| extractor and the |[N:N+1]| slicer. But for +difference between the |[N]| extractor and the |[N:N+1]| slicer. But for \emph{oples} which are either |nil|, a \emph{number}, or of length at least 2, there is no difference. @@ -4169,7 +4177,7 @@ $\{\{A_{00}A_{01}\}\{A_{10}A_{11}\}\}$ with atoms $A_{00}=\{1\}$, ..., being the \emph{leaves} of the tree associated to (or which is) the \emph{ople}. Numbers may be called the \emph{leaves} of the \textbf{input}, but once -converted to a structure in memory, the input becomes an \emph{ople} which is +parsed, the input becomes an \emph{ople} which is (morally) a tree whose leaves are \emph{atoms} (and the empty set). \medskip @@ -4178,15 +4186,6 @@ absolutely not needed to understand the rest of the manual, but I needed to write it for my own satisfaction. Believe me, you need this section if you want to write the underlying software! -\clearpage -\let\xintexprnameUp\undefined -\csname Syntax referencenameUp\endcsname -\section{\xintexprname syntax reference and user guide} -\RaisedLabel{sec:xintexprsyntax} - -\localtableofcontents - - \subsection{The three parsers} \xintexprname provides three numerical expression parsers and two subsidiary @@ -4205,28 +4204,63 @@ any pre-parsing. \item \csbxint{eval}\marg{expression} handles integers, decimal numbers, numbers in scientific notation and fractions. The algebraic computations are done \emph{exactly.} +\begin{everbatim*} +\xinteval{add(x/(x+1), x = 1000..1014)}\par +\end{everbatim*} +In this example, the fraction obtained by addition is already +irreducible, but this is not always the case: +\begin{snugframed} + By default, basic operations on fractions do not automatically reduce to + smallest terms the output: |A/B| multiplied by |C/D| + returns |AC/BD|, and |A/B| added to |C/D| uses |lcm(B, D)| as denominator. +\end{snugframed} + \item \csbxint{iieval}\marg{expression} does exact computations \emph{on (big) integers only.} The forward slash \dtt{/} does the \emph{rounded} integer division to match behaviour of |\numexpr|. +\begin{everbatim*} +\xintiieval{add((i/:7)?{omit}{i^5}, i=1000..1020)}% only add fifth powers of multiples of 7 +\end{everbatim*} + \item \csbxint{floateval}\marg{expression} does floating point computations with a given precision \dtt{P}, as specified via a prior assignment - |\xintDigits:=P\relax |. The default is \dtt{P=16} digits. The four basic + |\xintDigits:=P\relax |. +\begin{everbatim*} +\begingroup +\xintDigits:=64; +\xintfloateval{sqrt(3)} +\endgroup +\end{everbatim*} + + The default is with \dtt{P=16} digits. The four basic operations and the square root realize \emph{correct rounding.}\footnote{when the inputs are already floating point numbers with at most |P|-digits mantissas.} - It can be used with an optional argument |[Q]| and then do a float rounding - to mantissas of |Q| digits as the final step (this makes sense only if - |Q<P|). ATTENTION: the optional argument - |[Q]| is to be located \emph{within} the braces at the start of the expression. + It can be used with an optional argument |[Q]| which means to do a final + float rounding to mantissas of |Q| digits (this makes + sense only if |Q<P|). ATTENTION: the optional argument |[Q]| is to be + located \emph{within} the braces at the start of the expression. + + When |Q| is negative it means to round to |P+Q| digits only. Current + implementation of trigonometrical functions (\xinttrigname) is provisory and + does not use guard digits, using |[-2]| will trim the last two, probably + wrong, digits. \end{itemize} Two derived parsers: \begin{itemize} \item \csbxint{ieval}\marg{expression} does all computations like \csbxint{eval} but rounds the result to the nearest integer. If there is an optional - positive argument |[D]|, the rounding is to the nearest fixed point number - with |D| digits after the decimal mark. ATTENTION: the optional argument + positive argument |[D]|, the rounding is to: + \begin{itemize} + \item if |D>0|: the nearest fixed point number with |D| digits after the + decimal mark, + \item if |D=0|: the nearest integer, + \item if |D<0|: the nearest multiple of |10^(-D)| (i.e. \emph{quantization}, + this case is new with |1.4a|).\NewWith{1.4a} + \end{itemize} + ATTENTION: the optional argument |[D]| is to be located \emph{within} the braces at the start of the expression. \item \csbxint{theboolexpr}\meta{expression}|\relax| does all computations like \csbxint{eval} but converts the (itemwise) results to |True| or |False|. This @@ -4241,14 +4275,14 @@ These macros are wrappers for a more core syntax: \item \csbxint{iexpr}\meta{expression}|\relax|, \item \csbxint{boolexpr}\meta{expression}|\relax|. \end{itemize} -This core syntax can be used directly in typesetting flow. But in an |\edef| they -expand to some braced nested data prefixed with some non-expandable -«typesetting» macros. When using \csbxint{eval} in an |\edef|, the -\csa{XINTexprprint} typesetter is activated and the expansion gives explicit -digits and other characters such as those of scientific notation or -brackets. - -It is possible to use the core syntax +This core syntax can be used directly in typesetting flow.\NewWith{1.4} But in an |\edef| +they expand to some braced nested data prefixed with some |\protected| +«typesetter» macros. When using \csbxint{eval} (in contrast to +\csbxint{expr}), the protection of the «typesetter» is removed and the expansion +gives explicit digits and other characters such as those of scientific +notation or brackets. + +It is possible to use the core syntax\NewWith{1.4} \csbxint{expr}\marg{expression}|\relax| also in so-called moving arguments, because when written out to a file they use only standard catcodes and the output will get retokenized and will expand as expected. @@ -4261,28 +4295,56 @@ As alternative to \csbxint{eval}\marg{expression}, an equivalent is can prefix all other core parsers. And one can also use \csbxint{theexpr} as shortcut for \csbxint{the}\csbxint{expr}. -Notice that in this documentation I will most of the time refer to -\csbxint{eval} and \csbxint{expr}. But beware that doing exact computations -with fractions leads very quickly to very big results (and furthermore one -needs to use explicitly the |reduce()| function to convert the fractions into -smallest terms). Thus most probably what you want is \csbxint{floateval} and +Throughout this documentation I will most of the time refer to \csbxint{eval} +and \csbxint{expr}. But beware that doing exact computations with fractions +leads very quickly to very big results (and furthermore one needs to use +explicitly the |reduce()| function to convert the fractions into smallest +terms). Thus most probably what you want is \csbxint{floateval} and \csbxint{floatexpr}. +\subsection{Expansion} + +As mentioned already, the parsers are compatible with expansion-only +context. + +Also, they expand the expression piece by piece: +the normal mode of operation of the parsers is to unveil the parsed material +token by token. Unveiling is a process combining brace removal (one level +generally) and \fexpan sion. + +For example a closing parenthesis does not have generally to be immediately +visible, it may arise later from expansion. Even the ending |\relax| may +arise from expansion. Even though the \csbxint{eval} user interface means that +the package has at some point the entire expression in its hands, it +immediately re-inserts it into token stream with an additional postfixed +|\relax| and from this point on has lost any ways to manipulate formally again +the whole thing; it can only re-discover it piece per piece. + +This general behaviour has significative exceptions mostly related to +«pseudo»-functions. A «pseudo»-function will grab some of its arguments via +delimited macros. For example |subs(expr1,x=expr2)| needs to see the comma, +equal sign and closing parenthesis. But it has mechanisms to allow |expr1| and +|expr2| to possess their own commas and parentheses. + +Inner semi-colons on the other hand currently always can originate from expansion. +Defining functions or variables requires a visible semi-colon acting as +delimiter of the expression, but inner semi-colons do not need to be +hidden within braces or macros\NewWith{1.4}. + +The expansion stops only when the ending |\relax| has been found +(it is then removed from the token stream). + +For catcode related matters see \csbxint{exprSafeCatcodes}. + A word of warning on the bracketed optional argument of respectively -\csbxint{floatexpr} and \csbxint{iexpr}. If defining macros handing over an -argument to one of these two parsers, the argument may accidentally start with -a left square bracket |[| and this will break the parser. The fix is to use in -the macro definition |\xintfloatexpr\empty| for example. The extra |\empty| -token will prevent the parser thinking there is an optional argument and it -will then disappear during expansion. +\csbxint{floatexpr} and \csbxint{iexpr}. When defining macros which will hand +over some argument to one of these two parsers, the argument may potentially +start with a left square bracket |[| (e.g. argument could be |[1, 2, 3]|) and +this will break the parser. The fix is to use in the macro definition +|\xintfloatexpr\empty|. This extra |\empty| token will prevent the parser +thinking there is an optional argument and it will then disappear during +expansion. -With \csbxint{thealign} one can get nested data use a \TeX{} alignment in the -output. Attention, this must be followed by \csbxint{expr} et al., never by -\csbxint{theexpr} or \csbxint{eval}. -Here is an example : -\begin{everbatim*} -\xintthealign\xintexpr ndseq(1/(i+j), i = 1..10; j=1..10)\relax -\end{everbatim*} \subsection{\csh{xintthealign} and output related customizations} \label{xintthealign} @@ -4292,46 +4354,96 @@ Here is an example : \label{xintfloatexprPrintOne} \label{xintboolexprPrintOne} +With \csbxint{thealign} one can get nested data use a \TeX{} alignment in the +output. Attention, this must be followed by \csbxint{expr} et al., never by +\csbxint{theexpr} or \csbxint{eval}. +Here is an example : +\begin{everbatim*} +\xintthealign\xintexpr ndseq(1/(i+j), i = 1..10; j=1..10)\relax +\end{everbatim*} -This is hopefully more or less self-explanatory: +It is possible to customize the behaviour of |\xintthealign|.\CHANGED{1.4a} +The helper macros, apart from |\xintexpralignbegin| and |\xintexpralignend| +will be subjected to a complete (|\expanded|) expansion (once). The package +uses here |\protected| with no strong reason, as the replacement tokens are +not expanding anyhow, but the idea is that this allows to define a macro in an +|\edef| and later change the meaning of the auxiliary macros depending on what +one wants to do with the expansion result. See also further down the \LaTeX{} +example with a matrix environment, where |\noexpand| rather than |\protected| +is used. \begin{everbatim} -\def\xintexprEmptyItem{[]} -% this is a macro from xintfrac.sty, must understand its raw format -\let\xintexprPrintOne\xintFracToSci -\def\xintiiexprPrintOne #1{#1} -% this is a macro from xintfrac.sty, must understand its raw format -\def\xintfloatexprPrintOne#1#2{\xintPFloat[#1]{#2}} -\def\xintboolexprPrintOne#1{\xintiiifNotZero{#1}{True}{False}} -% The package uses \protected here for no strong reason, but why not \protected\def\xintexpralignbegin {\halign\bgroup\tabskip2ex\hfil##&&##\hfil\cr}% \protected\def\xintexpralignend {\crcr\egroup}% -\protected\def\xintexpraligncr {\cr}% +\protected\def\xintexpralignlinesep {,\cr}% separates "lines" +\protected\def\xintexpralignleftsep {&}% at left of first item in a "line" (after brackets) +\protected\def\xintexpraligninnersep {,&}% at the left of non-first items +\protected\def\xintexpralignrightsep {&}% at right of last item in a "line" (before brackets) \protected\def\xintexpralignleftbracket {[}% \protected\def\xintexpralignrightbracket{]}% -\protected\def\xintexpraligninnercomma {,}% -\protected\def\xintexpralignoutercomma {,}% -\protected\def\xintexpraligntab {&}% -% Use for example this for outputting to a file. Better then without \protected. +\end{everbatim} +Although we will try to keep stable the way «regular arrays» are +rendered,\UNSTABLE{} the |\xintthealign| macro (and its associated customizability) is +considered work-in-progress and may experience breaking changes. + +Use for example this for outputting to a file or a terminal: +\begin{everbatim} +% Better here without \protected. % We assume here \newlinechar has the LaTeX setting. \def\xintexpralignbegin {}% \def\xintexpralignend {}% -\def\xintexpraligncr {^^J}% +\def\xintexpralignlinesep {,^^J}% separates "lines" +\def\xintexpralignleftsep { }% at left of first item in a "line" (after brackets) +\def\xintexpraligninnersep {, }% at the left of non-first items +\def\xintexpralignrightsep { }% at right of last item in a "line" (before brackets) \def\xintexpralignleftbracket {[}% \def\xintexpralignrightbracket{]}% -\def\xintexpraligninnercomma {,}% -\def\xintexpralignoutercomma {,}% -\def\xintexpraligntab { }% \end{everbatim} +And here is an example using a |pmatrix| environment. +\begin{everbatim*} +\[ +\def\xintexpralignbegin {\begin{pmatrix}}% +\def\xintexpralignend {\end{pmatrix}}% +\def\xintexpralignlinesep {\noexpand\\}% needed to counteract an internal \expanded +\def\xintexpraligninnersep {&}% +\let\xintexpralignleftbracket\empty \let\xintexpralignleftsep\empty +\let\xintexpralignrightbracket\empty \let\xintexpralignrightsep\empty +% by default amsmath matrices can have 10 columns at most +% (cf amsmath documentation for what to do to allow more) +l.c.m.=\xintthealign\xintiiexpr ndmap(lcm, 1..12; 1..10)\relax +\] +\end{everbatim*} + +The way individual items are formatted (whether or not using +|\xintthealign|) is also customizable: +\begin{everbatim} +\def\xintexprEmptyItem{[]} +% The used macro (here \xintFracToSci) must understand the xintfrac.sty raw format +\let\xintexprPrintOne\xintFracToSci +\def\xintFracToSciE{e} +% In the integer-only parser, internal format coincides simply with the digit tokens +% Attention this may change in future +\def\xintiiexprPrintOne #1{#1} +% The used macro (here \xintPFloat) must understand the xintfrac.sty raw format +\def\xintfloatexprPrintOne#1#2{\xintPFloat[#1]{#2}} +% Same here +\def\xintboolexprPrintOne#1{\xintiiifNotZero{#1}{True}{False}} +\end{everbatim} +Attention! The above macros convert from \xintexprname internal numeric data +format to «printed» output; they are thus susceptible to require adjustments +if the internal data format changes, which may happen at each release. Of course +the default for |\xintexprPrintOne| etc... will be adjusted accordingly, but +user custom definitions may break. + \subsection{Built-in operators and their precedences} -\def\MicroFont{\ttbfamily\makestarlowast\color[named]{DarkOrchid}} \makeatletter \def\@floatboxreset{\@setminipage}% faudra contrôler celui-là \makeatother \begin{table}[htbp] +\edef\Ampersand{\string&}% \edef\restorehtdpstrutbox {\ht\strutbox\the\ht\strutbox\dp\strutbox\the\dp\strutbox} \ht\strutbox12pt\dp\strutbox5pt @@ -4339,54 +4451,73 @@ This is hopefully more or less self-explanatory: \centering\begin{tabular}{|c|p{.5\textwidth}|} \hline \multicolumn{2}{|p{.6\textwidth}|}{\prec{$\infty$}: - at this top level the non-operator syntax elements whose parsing - is always done prior to executing operators preceding them: + at this top level the syntax elements whose + execution + is done prior to operators preceding them: \begin{itemize}[nosep] \item \hyperref[ssec:builtinfunctions]{built-in} or \hyperref[ssec:userfunctions]{user-defined} functions, \item \hyperref[ssec:uservariables]{variables}, - \item the |*| unpacking operator, - \item and the intrinsic constituents of numbers: decimal mark |.|, |e| and |E| of scientific notation, hexadecimal prefix |"|. + \item the \oper{\empty*} unpacking operator, + \item and intrinsic constituents of numbers: decimal mark \oper{\strut.}, + \oper{e} and \oper{E} of scientific notation, hexadecimal prefix + \oper{"}. \end{itemize}\par\kern-\baselineskip\relax}% \\\hline\hline - Precedence&``Operators'' at this level\strut\\ - \hline - \prec{$20$}& the factorial (postfix) operator |!| and the conditional branching operators |?| and |??|\strut\\\hline - \prec{$=$}& the minus sign |-| as unary operator acquires the - precedence level of the previous infix operator\strut\\\hline - \prec{$18$}&the power |^|, |**| operators\strut\\\hline - \prec{$16$}&the action of tacit multiplication\strut\\\hline - \prec{$14$}&the multiplication, division, and modulo operators |*|, |/|, - |//|, |/:| (aka |'mod'|)\strut - \\\hline - \prec{$12$}&the addition and subtraction |+|, |-|\strut\\\hline - \prec{$10$}&the comparison operators |<|, |>|, |==|, |<=|, |>=|, |!=|\strut\\\hline - \prec{$8$}&Boolean conjunction |&&| and its alias |'and'|\strut\\\hline - \prec{$6$}&Boolean disjunction \verb+||+ and |'or'|, and |'xor'|; also the - sequence generators |..|, |..[|, |]..|, and the Python slicer |:| have - this precedence\strut\\\hline - \prec{$4$}& the brackets for |NumPy| slicing syntax |[|, |]|\strut\\\hline - \prec{$3$}& the comma |,|\strut\\\hline - \prec{$2$}& the bracketers |[|, |]|\strut\\\hline - \prec{$1$}& the parentheses |(|, |)|, and the semi-colon |;| in the - \func{iter}, - \func{rseq}, etc... constructs\strut\\\hline\hline + Precedence&``Operators'' at this level\strut\\ + \hline + \prec{20}& postfix \oper{!} and branching \oper{?}, \oper{??} operators\strut\\\hline +% + \prec{-}& minus sign as unary operator\strut\\\hline +% + \prec{18}& \oper{\string^} and \oper{**} are a priori synonymous (but see + \xintlogname)\strut\\\hline +% + \prec{16}& \hyperref[ssec:tacit multiplication]{Tacit + multiplication} has an elevated precedence\strut\\\hline +% + \prec{14}& \oper{*}, \oper{/}, \oper{//} (floored division), + and \oper{/:} (associated modulo, alias + \oper{'mod'})\strut\\\hline +% + \prec{12}& \oper{+}, \oper{-}\strut\\\hline +% + \prec{10}& \oper{<}, \oper{>}, \oper{==}, \oper{<=}, \oper{>=}, + \oper{!=}\strut\\\hline +% + \prec{8}& Boolean conjunction \oper{\Ampersand\Ampersand} and + its alias \oper{'and'}\strut\\\hline +% + \prec{6}& Boolean disjunction \oper{\string|\string|} and + its alias \oper{'or'}. Also \oper{'xor'} and + \oper{\strut..}, \oper{..[}, + \oper{{]..}}, and \oper{:} have + this precedence\strut\\\hline +% + \prec{4}& the brackets for slicers and extractors \oper{\empty[}, + \oper{\empty]}\strut\\\hline +% + \prec{3}& the comma \oper{,}\strut\\\hline +% + \prec{2}& the bracketers \oper{[}, \oper{]} construct nestable «arrays»\strut\\\hline +% + \prec{1}& the parentheses \oper{(}, \oper{)}, and the semi-colon + \oper{;} in \func{iter}, \func{rseq}, and further structures\strut\\\hline +% +\hline +% \multicolumn{2}{|p{.6\textwidth}|}{% \begin{itemize}[nosep] \item Actually operators have a left and a right precedence, which for most coincide. But for some there is a crucial distinction. The above - table is indicative, see |sourcexint.pdf|. Roughly all precedence levels - were doubled at |1.4| to make room. + table is indicative, and the actual numerical levels used internally may change. \item In case of equal precedence, the rule is left-associativity: the first encountered operation is executed first. \hyperref[ssec:tacit multiplication]{Tacit multiplication} has an elevated precedence level hence seemingly breaks left-associativity: |(1+2)/(3+4)5| is computed as |(1+2)/((3+4)*5)| and |x/2y| is interpreted as |x/(2*y)| when using variables. - % \item List variants |^[|, |**[|, |]^|, |]**|, - % |*[|, |/[|, |]*|, |]/|, |+[|, |-[|, |]+|, |]-|, share the precedence - % level of their respective associated operators on numbers. \end{itemize} }\\\hline \end{tabular} @@ -4396,199 +4527,283 @@ when using variables. \restorehtdpstrutbox \end{table} -The \autoref{tab:precedences} is hyperlinked to the more detailed discussion -at each level. - -\begin{description}[parsep=0pt,align=left,itemindent=0pt, - leftmargin=\leftmarginii, labelwidth=\leftmarginii, labelsep=0pt, - labelindent=0pt, listparindent=\leftmarginiii] - -\precdesc{\infty} At this highest level of precedence, one finds: -\begin{itemize}[parsep=0pt,align=left,itemindent=0pt, - leftmargin=\leftmarginii, labelwidth=\leftmarginii, labelsep=0pt, - labelindent=0pt, listparindent=\leftmarginiii] -\item \hyperref[ssec:builtinfunctions]{functions} and - \hyperref[ssec:uservariables]{variables}: - we approximately describe the situation as - saying they have highest precedence. Functions (even the logic functions +The entries of \autoref{tab:precedences} are hyperlinked to the more detailed +discussion at each level. + +\begin{description} +% [parsep=0pt,align=left,itemindent=0pt, +% leftmargin=\leftmarginii, labelwidth=\leftmarginii, labelsep=0pt, +% labelindent=0pt, listparindent=\leftmarginiii] +\edef\Ampersand{\string&}% + +\precdesc{$\infty$} At this highest level of precedence, one finds: +\begin{description} +\item[{\hyperref[ssec:builtinfunctions]{functions} and + \hyperref[ssec:uservariables]{variables}}] + Functions (even the logic functions \func{!} and \func{?} whose names consists of a single non-letter character) must be used with parentheses. These parentheses may arise from expansion after the function name is parsed (there are exceptions which are documented at the relevant locations.) -\item The |*| as Python-like «unpacking» prefix operator. Sometimes one needs - to use it as function |*()| (but I can't find an example right now) but most - of the time parentheses are unneeded, -\item the |.| as decimal mark; the number scanner treats it as - an inherent, optional and unique component of a being formed number. One can - do things such as - % - \leftedline{\restoreMicroFont|\xintexpr 0.^2+2^.0\relax|} - % - which is |0^2+2^0| and produces \dtt{\xintexpr 0.^2+2^.0\relax}. - - Since release |1.2| an isolated decimal mark |"."| is illegal - input in |\xintexpr..\relax|, although it remains legal as argument to the - macros of \xintfracname. -\item the |e| and |E|, for scientific notation are intrinsic constituents of - number denotations, - like the decimal mark. -\item the |"| for hexadecimal numbers: it is allowed only at locations where - the parser expects to start forming a numeric operand, once encountered it - triggers the hexadecimal scanner which looks for successive hexadecimal - digits as usual skipping spaces and expanding forward everything; letters - (only |ABCDEF|, not |abcdef|), an optional dot - (allowed directly in front) and an optional (possibly empty) fractional - part. The |"| functionality - \fbox{requires to load package \xintbinhexname}.% -% -\begin{everbatim*} -\xinttheexpr "FEDCBA9876543210\relax\newline -\xinttheiexpr 16^5-("F75DE.0A8B9+"8A21.F5746+16^-5)\relax + + \operdesc{\empty*} Python-like «unpacking» prefix operator. Sometimes one + needs to use it as function |*()| (but I can't find an example right now) + but most of the time parentheses are unneeded. + + \operdesc{\strut.} is decimal mark; the number scanner treats it as an inherent, + optional and unique component of a being formed number. + |\xintexpr 0.^2+2^.0\relax| is interpreted as |0^2+2^0| and + thus produces \dtt{\xintexpr 0.^2+2^.0\relax}. + + Since release |1.2| an isolated decimal mark is illegal + input in the \xintexprname parsers (it remains legal as argument to the + macros of \xintfracname). + + \operdesc{e} scientific notation. + + \operdesc{E} scientific notation. For output, see \csbxint{FracToSciE}. + + \operdesc{"} prefix for hexadecimal input. Only uppercase letters, and + one optional |.| separating integer and fractional hexadecimal parts. + This functionality + \centeredline{\fbox{requires to load explicitly package \xintbinhexname.}}% + +\begin{everbatim*} +\xintexpr "FEDCBA9876543210\relax\newline +\xintexpr ".FEDCBA9876543210\relax\newline +\xintexpr 16^5-("F75DE.0A8B9+"8A21.F5746+16^-5)\relax \end{everbatim*} -\end{itemize} -\precdesc{20} The postfix operators |!| and the branching conditionals |?|, |??|. - \begin{description}[parsep=0pt,align=left,itemindent=0pt, - leftmargin=\leftmarginii, labelwidth=\leftmarginii, labelsep=0pt, - labelindent=0pt, listparindent=\leftmarginiii] - - \item[{\color[named]{DarkOrchid}!}] computes the factorial of an integer. - Attention that the boolean equality test |==| must not follow directly - such a |<digits or variable>!| because the parser will handle |!=| as the - boolean inequality test... the remaining |=| then causes a parsing error. - It is even worse if one uses a single |=| following the |!| because no - error arises but an un-intended interpretation. Use parentheses: + It is possible that in future the |"| prefix could be dropped in favour of + |0x| prefix. This would free |"| to be used for input of «string»-like + entities. +\end{description} + + +\precdesc{20} + The postfix operators |!| and the branching conditionals |?|, |??|. +\begin{description} + \operdesc{!} computes the factorial of an integer. + Attention that the boolean equality test |==| confuses + the parser if following directly |!| (e.g. |3! == 10|) + as spaces are ignored and \oper{!=} will be intepreted as + boolean inequality test, the second |=| causing then a low-level error. + Use parentheses in such cases: |(3!)==10|. - \item[{\color[named]{DarkOrchid}?}] is used as |(stuff)?{yes}{no}|. It + \operdesc{?} is used as |(stuff)?{yes}{no}|. It evaluates |stuff| and chooses the |yes| branch if the result is non-zero, else it executes |no|. After evaluation of |stuff| it acts as a macro with two mandatory arguments within braces, chooses the correct branch \emph{without evaluating the wrong one}. Once the braces - are removed, the parser scans and expands the uncovered material so for - example - % - \leftedline{|\xinttheiexpr (3>2)?{5+6}{7-1}2^3\relax|} - % - is legal and computes - |5+62^3=|\dtt{\xinttheiexpr(3>2)?{5+(6}{7-(1}2^3)\relax}. It would be - better practice to include here the |2^3| inside the branches. The - contents of the branches may be arbitrary as long as once glued to what is - next the syntax is respected: {|\xintexpr (3>2)?{5+(6}{7-(1}2^3)\relax| - also works.} - - - \item[{\color[named]{DarkOrchid}??}] is used as |(stuff)??{<0}{=0}{>0}|, + are removed, the parser scans and expands the uncovered material. + % so for + % example + % % + % \leftedline{|\xinttheiexpr (3>2)?{5+6}{7-1}2^3\relax|} + % % + % is legal and computes + % |5+62^3=|\dtt{\xinttheiexpr(3>2)?{5+(6}{7-(1}2^3)\relax}. It would be + % better practice to include here the |2^3| inside the branches. The + % contents of the branches may be arbitrary as long as once glued to what is + % next the syntax is respected: {|\xintexpr (3>2)?{5+(6}{7-(1}2^3)\relax| + % also works.} + + \operdesc{??} is used as |(stuff)??{<0}{=0}{>0}|, where |stuff| is anything, its sign is evaluated and depending on the sign the correct branch is un-braced, the two others are discarded with no - evaluation of their contents. The un-braced branch will then be parsed as - usual. - % - \leftedline{|\def\x{0.33}\def\y{1/3}|} - % - \leftedline{|\xinttheexpr (\x-\y)??{sqrt}{0}{1/}(\y-\x)\relax|% - \dtt{=\def\x{0.33}\def\y{1/3}% - \xinttheexpr (\x-\y)??{sqrt}{0}{1/}(\y-\x)\relax }} - % + evaluation of their contents. + % The un-braced branch will then be parsed as + % usual. + % % + % \leftedline{|\def\x{0.33}\def\y{1/3}|} + % % + % \leftedline{|\xinttheexpr (\x-\y)??{sqrt}{0}{1/}(\y-\x)\relax|% + % \dtt{=\def\x{0.33}\def\y{1/3}% + % \xinttheexpr (\x-\y)??{sqrt}{0}{1/}(\y-\x)\relax }} + % % \end{description} -\precdesc{=} The minus sign |-| as prefix unary operator inherits the - precedence of the infix operator it follows. |\xintexpr -3-4*-5^-7\relax| - evaluates as |(-3)-(4*(-(5^(-7))))| and |-3^-4*-5-7| as - |(-((3^(-4))*(-5)))-7|. +\precdesc{-} As prefix unary operator it inherits the precedence of + the infix operator it follows. +\begin{everbatim*} +\xintexpr -3-4*-5^-7, (-3)-(4*(-(5^(-7))))\relax\newline +\xintexpr -3^-4*-5-7, (-((3^(-4))*(-5)))-7\relax\par +\end{everbatim*} + |2^-10| is perfectly accepted input, no need for parentheses. + +\precdesc{18} +\begin{description} +\operdesc{\string^} +\operdesc{**} Both compute powers in left associative way. +\begin{everbatim*} +\xintiiexpr 2^2^3\relax +\end{everbatim*} - |2^-10| is perfectly accepted input, no need for parentheses + Half-integer exponents are allowed in \csbxint{floateval} and use + \func{sqrt}. It is possible to allow arbitrary fractional exponents + (\autoref{ssec:poormanloghack}) but this currently achieves only a + reduced precision. See \csbxint{FloatPower} and \xintlogname for + additional information. +\end{description} +\precdesc{16} see \hyperref[ssec:tacit multiplication]{Tacit multiplication}. +\precdesc{14} +\begin{description} +\operdesc{*} multiplication +\operdesc{/} division: exact in \csbxint{eval}, correctly rounded in + \csbxint{floateval} (numerator and denominator are rounded before the + division is done), and rounded to an integer (like |\numexpr| does: + half-integers are rounded towards infinity of same sign) in + \csbxint{iieval}. The division is left-associative: +\begin{everbatim*} +\xintexpr reduce(100/50/2)\relax +\end{everbatim*} - \precdesc{18} The power operator |^|, or equivalently |**|. It is left - associative: {\restoreMicroFont|\xinttheiexpr 2^2^3\relax|} evaluates to - \xinttheiexpr 2^2^3\relax, not \xinttheiexpr 2^(2^3)\relax. See - \csbxint{FloatPower} for additional information. +\operdesc{//} floored division -\precdesc{16} see \hyperref[ssec:tacit multiplication]{Tacit multiplication}. +\operdesc{/:} the associated modulo -\precdesc{14} Multiplication and division |*|, |/|. The - division is left associative, too: - % - \begingroup\restoreMicroFont - % - |\xinttheiexpr 100/50/2\relax| evaluates to \xinttheiexpr 100/50/2\relax, - not \xinttheiexpr 100/(50/2)\relax. - % - \endgroup + Left-associativity applies generally to operators of same precedence. +\begin{everbatim*} +\xintexpr 100000/:13, 100000 'mod' 13\relax\newline +\xintexpr 100000/:13/13\relax +\end{everbatim*} - Also the floored division |//| and its associated modulo |/:| (equivalently |'mod'|, - quotes mandatory). +\operdesc{'mod'} is same as \oper{/:} - Also at this level the list operators |*[|, |/[|, |]*| and |]/|. +\end{description} - In an \csbxint{iiexpr}-ession, |/| does \emph{rounded} division, to behave - like the |/| of |\numexpr|. +\precdesc{12} +\begin{description} +\operdesc{+} addition - Infix operators all at the same level of precedence are - left-associative.\footnote{i.e. the first two operands are operated upon - first.} - Apply parentheses for disambiguation. +\operdesc{-} subtraction. According to the general left-associativity rule in +case of equal precedence, it is + left associative: \begin{everbatim*} -\xinttheexpr 100000//13, 100000/:13, 100000 'mod' 13, trunc(100000/13,10), - trunc(100000/:13/13,10)\relax +\xintiiexpr 100-50-2\relax \end{everbatim*} +\end{description} -\precdesc{12} Addition and subtraction |+|, |-|. According to the rule above, |-| - is left associative: - % - \begingroup\restoreMicroFont - % - |\xinttheiexpr 100-50-2\relax| evaluates to \xinttheiexpr 100-50-2\relax, - not \xinttheiexpr 100-(50-2)\relax. - % - \endgroup +\precdesc{10} Comparison operators are currently all at the same level of +precedence, use parentheses for disambiguation. + \begin{description} + \operdesc{<} |a<b| evaluates to \dtt{1} if the strict inequality holds to \dtt{0} + if not. - Also the list operators |+[|, |-[|, |]+|, |]-| are at this precedence level. + \operdesc{>} |a>b| evaluates to \dtt{1} if the strict inequality holds to \dtt{0} + if not. -\precdesc{10} Comparison operators |<|, |>|, |==|, |<=|, |>=|, |!=| all - at the same level of precedence, use parentheses for disambiguation. + \operdesc{==} |a==b| evaluates to \dtt{1} if equality holds to \dtt{0} + if not. -\precdesc{8} Conjunction (logical and) |&&| or equivalently - |'and'| (quotes mandatory).% -% -\footnote{with releases earlier than |1.1|, only single - character operators |&| and \verb+|+ were available, because the parser - did not handle multi-character operators. Their usage in this rôle is now - deprecated,\IMPORTANT{} and they may be assigned some new meaning in the - future.} + \operdesc{<=} |a<=b| evaluates to \dtt{1} if left hand side is at most equal + to right hand side, to \dtt{0} + if not. -\precdesc{6} Inclusive disjunction (logical or) \verb+||+ - and equivalently |'or'| (quotes mandatory). + \operdesc{>=} |a>=b| evaluates to \dtt{1} if left hand side is at least equal + to right hand side, to \dtt{0} + if not. - Also the |'xor'| operator (quotes mandatory) is at this level. + \operdesc{!=} |a!=b| evaluates to \dtt{1} if they differ, to \dtt{0} + if not. + \end{description} + +\precdesc{8} +\begin{description} + \operdesc{\Ampersand\Ampersand} logical conjunction. Evaluates to \dtt{1} if + both sides are non-zero, to \dtt{0} if not. + + \operdesc{'and'} idem. The (right) ticks are mandatory. See also the + \func{all} multi-arguments function. +\end{description} - Also the list generation operators |..|, |..[|, |]..| are at this level. +\precdesc{6} +\begin{description} + \operdesc{\string|\string|} logical (inclusive) disjunction. Evaluates to + \dtt{1} if one or both sides are non-zero, to \dtt{0} if not. + + \operdesc{'or'} idem. See also the \func{any} multi-arguments function. + + \operdesc{'xor'} logical (exclusive) disjunction. See also the \func{xor} + multi-arguments function. - Also the |:| for Python/NumPy nested slicing of nested lists. + \operdesc{\strut..} + \operdesc{..[} + \operdesc{{]..}} Syntax for arithmetic + progressions. See \autoref{ssec:arithseq}. + + \operdesc{:} This is a separator involved in |[a:b]| Python-like slicing syntax. +\end{description} -\precdesc{4} The square brackets as involved in NumPy like slicing. The step -is not implemented yet. -\precdesc{3} The comma: {\restoreMicroFont with |\xinttheexpr 2^3,3^4,5^6\relax| - one obtains as output \xinttheexpr 2^3,3^4,5^6\relax{}.}\footnote{The comma +\precdesc{4} +\begin{description} + \operdesc{\empty[} + \operdesc{\empty]} + Involved in Python-like slicing |[a:b]| and extracting |[N]| syntax. And its + extension à la NumPy |[a:b,N,c:d,...,:]|. Ellipsis |...| is not yet implemented. + The «step» parameter as in |[a:b:step]| is not yet implemented. +\end{description} + +\precdesc{3} +\begin{description} + \operdesc{,} + The comma separates expressions (or function arguments).% +% + \footnote{The comma is really like a binary operator, which may be called ``join''. It has lowest precedence of all (apart the parentheses) because when it is encountered all postponed operations are executed in order to finalize its \emph{first} operand; only a new comma or a closing parenthesis or the end of the expression will finalize its \emph{second} operand.} -\precdesc{2} The square brackets as |nut-ple| constructors. -\precdesc{1} The parentheses. The semi-colon |;| in an |iter| or - |rseq| has the same precedence as a closing parenthesis.\footnote{It is not - apt to describle the opening parenthesis as an operator, but the closing - parenthesis is more closely like a postfix unary operator. It has lowest - precedence because when it is encountered all postponed operations are - executed to finalize its operand. The start of this operand was decided by - the opening parenthesis.} +% +\begin{everbatim*} +\xintiiexpr 2^3,3^4,5^6\relax +\end{everbatim*} +\end{description} + +\precdesc{2} +\begin{description} + \operdesc{[} + \operdesc{]} The bracketers construct nestable «array-like» + structures. Arbitrary (heterogeneous) nesting is allowed. For output related + matters see \csbxint{thealign} (its usage is optional, without it rendering + is «one-dimensional»). Output shape of non-homogeneous arrays is to + be considered unstable at this time. \end{description} +\precdesc{1} +\begin{description} + \operdesc{(} + \operdesc{)} + The parentheses serve as mandatory part of the syntax for functions, and to + disambiguate precedences.% +% + \footnote{It is not apt to describle the + opening parenthesis as an operator, but the closing parenthesis is analogous + to a postfix unary operator. It has lowest precedence which means + that when it is encountered all postponed operations are executed to finalize + its operand. The start of this operand was decided by the opening + parenthesis.} +% + They do not construct any nested structure. + + \operdesc{;} The semi-colon as involved as part of the syntax of \func{iter}, + \func{rseq}, \func{ndseq}, \func{ndmap} has the same + precedence as a closing parenthesis. It also serves as syntax terminator for + \csbxint{defvar} and \csbxint{deffunc}. Inner semi-colons do not need to be + braced to avoid being mistaken for the terminator (but they may be which + speeds up by micro-second the parsing). +\end{description} + +\item[|\relax|] This is the expression terminator for \csbxint{expr} et al. + It may arise from expansion during the parsing itself. As alternative use + \csbxint{eval} et al. which proceed as macros expecting one mandatory + argument. +\end{description} -\restoreMicroFont \subsection{Built-in functions}\label{ssec:builtinfunctions} @@ -4907,8 +5122,8 @@ $\xintthefloatexpr subs(((x-1)/x, x/x, (x+1)/x), x=2**30)\relax definitions done via \csbxint{deffunc} (see explanations there) to functions usable in \csbxint{floateval}. - \funcdesc{nuple} (WIP) is currently same as |[...]|. Do not use. Reserved - for possible alternative meaning in future.\NewWith{1.4} + \funcdesc{nuple} is currently same as |[...]|.\DNU{(1.4)} Reserved for + possible alternative meaning in future. \begin{everbatim*} \xinteval{nuple(1,2,3)} \end{everbatim*} @@ -5007,28 +5222,34 @@ $\xintthefloatexpr subs(((x-1)/x, x/x, (x+1)/x), x=2**30)\relax % labelwidth=-\fontdimen2\font, labelsep=\fontdimen2\font, labelindent=0pt, % listparindent=\leftmarginiii] - \funcdesc[{x[, n]}]{round} Rounds its first argument to a fixed point number, having a - number of digits - after decimal mark given by the second argument. For example - |round(-2^9/3^5,12)=|\dtt{\xinttheexpr round(-2^9/3^5,12)\relax.} - \funcdesc[{x[, n]}]{trunc} Truncates its first argument to a fixed point number, having - a number of digits - after decimal mark given by the second argument. For example - |trunc(-2^9/3^5,12)=|\dtt{\xinttheexpr trunc(-2^9/3^5,12)\relax.} + \funcdesc[{x[, n]}]{round} Rounds its first argument to an integer multiple + of |10^(-n)| (i.e. it \emph{quantizes}). The case of negative |n| is new with + |1.4a|. Positive |n| corresponds to conversion to a fixed point number with + |n| digits after decimal mark. +\begin{everbatim*} +\xinteval{round(-2^30/3^5,12), round(-2^30/3^5,-3)} +\end{everbatim*} + \funcdesc[{x[, n]}]{trunc} Truncates its first argument to an integer + multiple of |10^(-n)|. The case of negative |n| is new with + |1.4a|. +\begin{everbatim*} +\xinteval{trunc(-2^30/3^5,12), trunc(-2^30/3^5,-3)} +\end{everbatim*} + \funcdesc[{x[, n]}]{float} Rounds its first argument to a floating point number, with a - precision given by the second argument. - |float(-2^9/3^5,12)=|\dtt{\xinttheexpr float(-2^9/3^5,12)\relax.} + precision given by the second argument, which must be positive. +\begin{everbatim*} +\xinteval{float(-2^30/3^5,12), float(-2^30/3^5, 1)} +\end{everbatim*} % AUCTeX EXTREMEMENT PENIBLE AVEC L'INDENTATION FORCEE SOUS M-q - Note for this example and the earlier ones that when the surrounding - parser is \csbxint{floatexpr}|...\relax| the fraction first argument (here - |2^9/3^5|) will already have been computed as floating point number (with - numerator and denominator handled separately first), even before the - second argument is seen and a fortiori before the |round|, |trunc| or - |float| is executed. The general float precision is the one governing - these initial steps. To avoid that, use |\xintexpr2^9/3^5\relax| wrapper. - Then the rounding or truncation will be applied on the exact fraction. + For this example and earlier ones if the parser had been + \csbxint{floateval}, not \csbxint{eval}, the first argument (here + |2^30/3^5|) would already have been computed as floating point number with + numerator and denominator rounded separately first to the prevailing + precision. To avoid that, use |\xintexpr2^9/3^5\relax| wrapper. + Then the rounding or truncation will be applied to the exact fraction. \funcdesc[{x[, n]}]{sfloat} It is the same as \func{float}, but in case of a short (non-fractional) input it gets stored internally @@ -5242,14 +5463,26 @@ The arguments must be (expand to) short integers. The arguments must (expand to) short integers. See \autoref{xintiiPFactorial} for the behaviour if the arguments are negative. -\funcdesc[macro, n-uple]{ndfillraw} (WIP) DO NOT USE.\NewWith{1.4} The second argument is -|[N1, N2, ..., Nk]|. The construct fills an |N1xN2x...xNk| hyperrectangular -nested list by evaluating the |macro| as many times as needed. Useful to generate either -constant or random -arrays. But, attention, |macro| is any \TeX{} macro, if one wants to evaluate -some expression one needs explicitly adding |\xinteval{..}|. Beware spaces or -other things this goes directly into internal data storage. - \end{description} +\funcdesc[\TeX-macro, n-uple]{ndfillraw} The second argument is |[N1, N2, ..., +Nk]|.\NewWith{1.4} The construct fills an |N1xN2x...xNk| hyperrectangular +nested list by evaluating the given |macro| as many times as needed. The +expansion result goes directly into internal data and must thus comply with +what is expected internally for an individual numeric leaf (at |1.4|, +\xintfracname raw format worked for |\xintexpr| or |\xintfloatexpr|, but not +|\xintiiexpr|, and this may have changed since).\DNU{} This is an experimental +function serving to generate either constant or random arrays. Attention that +% +% BORDEL \textbf{\sffamily...} NON, {\bfseries\sffamily ...} NON +% LaTeX Font Warning: Font shape `T1/cmss/b/n' undefined +% (Font) using `T1/cmss/m/n' instead on input line 1826. +% +% ceci est ok {\fontseries{bx}\sffamily\TeX-macro} +% https://github.com/latex3/latex2e/issues/277 +{\fontseries{bx}\sffamily \TeX-macro} +stands here for any expandable \TeX{} +\emph{macro}, and an |\xintexpr|-ession at this location thus requires an +explicit |\xinteval| wrapping. +\end{description} \subsubsection{Functions with 3 or 4 arguments} @@ -5307,9 +5540,9 @@ depending on internal data representation). % labelwidth=-\fontdimen2\font, labelsep=\fontdimen2\font, labelindent=0pt, % listparindent=\leftmarginiii] - \funcdesc[stuff]{qraw} DO NOT USE. It allows to inject directly a nested \TeX-braced - list conforming to internal data structures manipulated by the package. Can - break at any release. + \funcdesc[stuff]{qraw} It\DNU{} injects directly tokens to represent + internally numerical data. Will break at any release modifying the internal + data format specifications (which are not always documented). \funcdesc[x, y, ...]{all} inserts a logical |AND| in-between its arguments and evaluates the resulting logical assertion (as with all functions, all arguments are @@ -5407,31 +5640,34 @@ the case here. \subsubsection{Functions requiring dummy variables} \hypertarget{ssec:dummies}{} -The pseudo-functions \xintFor #1 in {add, mul, seq, subs, subsm, subsn, ndmap, ndseq, rseq, iter, rrseq, - iterr} \do {\func{#1}\xintifForLast{}{, }} use delimited macros to -identify the ``|,<letter>=|'' part. This is done in a way -allowing nesting via correctly balanced parentheses. The |<letter>| must not -have been assigned a value before via \csbxint{defvar}. - -This |,<letter>=| must be visible when the parser has finished absorbing the -function name and the opening parenthesis. For \func{rseq}, \func{iter}, -\func{rrseq} and \func{iterr} this is delayed to after the parser has -assimilated a starting part delimited by a semi-colon; this mandatory segment -may be generated entirely by expansion and the |,<letter>=| may appear during -this expansion. - -After |,<letter>=|, the expansion and parsing will generate a list of values -(for example from an |a..b| specification, there may be multiple ones -themselves separated by commas). After this step is complete the parser will -know the values which will be assigned to |<letter>|. The special -|<letter>=<integer>++| syntax offers a variant not pre-computing the iterated -over list (which currently must thus proceed by steps of one.) +The pseudo-functions \xintFor #1 in {subs, seq, subsm, subsn, iter, add, mul, + rseq, iterr, rrseq, iterr, ndseq, ndmap, ndfillraw} \do +{\func{#1}\xintifForLast{}{, }} use delimited macros for some tasks: +\begin{itemize} +\item for all of them, whenever a |<varname>=| chunk must be parsed into a + (non-assigned) variable name, then the equal sign must be visible, +\item and if the syntax is with «|,<varname>=|» the initial comma also must be + visible (spaces do not matter), +\item for all of them but \func{ndmap} and \func{ndfillraw} the final closing + parenthesis must be visible. +\end{itemize} +Although delimited macros involving commas are used to locate «|,<varname=|» +this is done in a way which will ignore commas located inside correctly +balanced parentheses. And the semi-colons involved in the syntax can +always arise from expansion alone. For \func{rseq}, \func{iter}, \func{rrseq} +and \func{iterr} the |,<varname>=| part may also be created from the expansion +which will generate the initial comma separated values delimited by a +semi-colon. + +Prior to |1.4|, semi-colons needed to be braced or otherwise hidden when +located in an expression parsed by \csbxint{defvar} or \csbxint{deffunc},\NewWith{1.4} to +not be confused with the expression terminator. This is not needed anymore. + \func{seq}, \func{rseq}, \func{iter}, \func{rrseq}, \func{iterr} and also \func{add}, \func{mul}, but not \func{subs} admit the \keyword{omit}, \keyword{abort}, and \keyword{break}|()| keywords. This is a -new feature for \func{add} and \func{mul}.\NewWith{1.4} - +new feature for \func{add} and \func{mul}. In the case of a potentially infinite list generated by the |<integer>++| syntax, use of @@ -5441,8 +5677,8 @@ All lowercase and uppercase Latin letters are pre-configured for usage as dummy variables. In Unicode engines one can use \csbxint{newdummy} to turn any letter into a usable dummy variable. -Further, since |1.4|, \csbxint{newdummy} works to turn a multi-letter word -into a dummy variable.\NewWith{1.4} +Since |1.4|,\NewWith{1.4} \csbxint{newdummy} works (in all engines) to turn a multi-letter +word into a dummy variable. \begin{description} % [parsep=0pt,align=left, @@ -5470,21 +5706,41 @@ results. Or one can use \func{seq}. See the documentation of \funcdesc[expr, letter=values]{add} addition \begin{everbatim*} -\xinttheiiexpr add(x^3,x=1..50), add(x(x+1), x=1,3,19)\relax +\xintiiexpr add(x^3,x=1..20), add(x(x+1), x=1,3,19)\relax\newline +\xintiiexpr add((odd(x))?{x^3}{omit}, x = 1..20)\relax\par % add only odd cubes +\end{everbatim*} + +\noindent At |1.4|,\NewWith {1.4a} the keywords \keyword{omit}, \keyword{abort} and +\keyword{break}|()| are allowed. But this was broken and got fixed at |1.4a|. +The |@| special variable holds the so-far accumulated value. Initially its +value is zero. +\begin{everbatim*} +\xintiiexpr add(1 + @, i=1..10)\relax % iterates x <- 2x+1 +\end{everbatim*} + +The meaning of \keyword{break}|()| is specific: its argument serves as last +operand for the addition, not as ultimate value. +\begin{everbatim*} +\xintiiexpr add((x>10)?{break(1000)}{x}, x = 1..15)\relax \end{everbatim*} -\noindent At |1.4|, the keywords \keyword{omit}, \keyword{abort} and -\keyword{break}|()| are allowed.\NewWith {1.4} - See |`+`| for syntax without a dummy variable. \funcdesc[expr, letter=values]{mul} multiplication \begin{everbatim*} -\xinttheiiexpr mul(x^2, x=1,3,19), mul(2n+1,n=1..10)\relax +\xintiiexpr mul(x^2, x=1,3,19), mul(2n+1,n=1..10)\relax \end{everbatim*} -\noindent At |1.4|, the keywords \keyword{omit}, \keyword{abort} and -\keyword{break}|()| are allowed.\NewWith {1.4} +\noindent At |1.4|,\NewWith {1.4a} the keywords \keyword{omit}, \keyword{abort} and +\keyword{break}|()| are allowed. But this was broken and got fixed at |1.4a|. +The |@| special variable holds the so-far accumulated value. Initially its +value is one. + +The meaning of \keyword{break}|()| is specific: its argument serves as last +operand for the multiplication, not as ultimate value. +\begin{everbatim*} +\xintiieval{mul((i==100)?{break(i^4)}{i}, i = 98, 99, 100)} +\end{everbatim*} See |`*`| for syntax without a dummy variable. @@ -5652,8 +5908,15 @@ legal. The |<integer>| must be a \TeX-allowable integer. \begin{everbatim*} First Fibonacci number at least |2^31| and its index % we use iterr to refer via @1 and @2 to the previous and previous to previous. -\xinttheiiexpr iterr(0,1; (@1>=2^31)?{break(i)}{@2+@1}, i=1++)\relax +\xinttheiiexpr iterr(0,1; (@1>=2^31)?{break(@1, i)}{@2+@1}, i=1++)\relax \end{everbatim*} + +Note: the above example, up to |1.3f| used |break(i)| in place of current +|break(@1, i)|. This syntax looks in retrospect as having been a bug. +Starting with |1.4| the example does have to be written with |break(@1, i)|, +as |break(i)| conforming to intuition will only print the last |i| value. And +if one also wants the previous Fibonacci number one only has to use |break(@2, +@1, i)| for example. \end{description} @@ -5669,8 +5932,8 @@ major modern \TeX{} installations since more than ten years now. -\subsection{One-dimensional sequence generators} - +\subsection{Generators of arithmetic progressions} +\label{ssec:arithseq} \begin{itemize} \item |a..b| constructs the \textbf{small} integers from the ceil $\lceil @@ -5817,7 +6080,7 @@ NumPy's concepts (of basic slicing/indexing): \item slicing and itemizing apply also to non-bracketed objects i.e. \emph{oples}, \item the leaves do not have to be all at the same depth, \item there are never any out-of-range index errors: out-of-range indices - generate the |nil| variable (at the suitable depth). + are silently ignored. \end{itemize} \begin{everbatim*} @@ -6141,9 +6404,6 @@ with the (already evaluated) function arguments, and the parser \emph{will substitution, but with parentheses and comma separated arguments (which can be arbitrary expressions themselves). - - - \subsubsection{\csh{xintdeffunc}} \label{xintdeffunc} @@ -6174,9 +6434,9 @@ have gained experience in using this interface...): signs. A function name must start with a letter. It may be a single letter (see \autoref{sssec:overload}). \item The variable names used in the function signature may be multi-letter - words. It is also allowed for them to already be in use for previously + words.\NewWith{1.4} It is also allowed for them to already be in use for previously declared variables. Their meanings will get restored for usage after the - function declaration.\NewWith{1.4} + function declaration. \item A function can have at most nine arguments. It can be defined as a function with no arguments. \item Recursive definitions are possible; for them to not generate error or @@ -6184,9 +6444,9 @@ have gained experience in using this interface...): |??| is \emph{mandatory}.\CHANGED{1.4} \item If a function is used in another definition it will check if it is applied to numerical arguments and if this is the case will expand - fully. Prior to |1.4| one needed deprecated \csa{xintdefefunc} for this. But + fully.\CHANGED{1.4} Prior to |1.4| one needed deprecated \csa{xintdefefunc} for this. But the latter is now but an alias for \csa{xintdeffunc}, the two have been - merged.\CHANGED{1.4} + merged. \item The previous item has an exception for functions with no arguments; they never expand immediately in other function definitions (else they would be almost like variables). This provides a way to define functions with @@ -6531,7 +6791,7 @@ $$ For some hair-raising experience check the \csbxint{verbosetrue} output in the log... here is an alternative with two (three, counting |dprod()|) helper functions: -\begin{everbatim} +\begin{everbatim*} % annoying that Tr also starts Trace, but Spur is available % well Sp also starts Spectrum. Big problems. \xintdeffunc Tr(M) := @@ -6545,25 +6805,27 @@ functions: [dprod(r3, c1), dprod(r3, c2), dprod(r3, c3)]]; \xintdeffunc MatMul(A, B) := MatMul_a(*A, *Tr(B)); -\end{everbatim} +\end{everbatim*} And once we have the transpose and the scalar product of vectors, we can simply use \func{ndmap} for a lean syntax (this would extend to arbitrary dimension): \begin{everbatim*} -\xintdeffunc Tr(M) := - [[M[0,0], M[1,0], M[2,0]], - [M[0,1], M[1,1], M[2,1]], - [M[0,2], M[1,2], M[2,2]]]; \xintdeffunc MatMul(A, B) = ndmap(dprod, *A; *Tr(B)); \xintdefvar mat1212 = MatMul(mat12, mat12); -$$ - M_1\cdot M_2 \cdot M_1 \cdot M_2 = - \vcenter{\xintthealign \xintexpr mat1212\relax} -$$ -$$ - \det(M_1\cdot M_2 \cdot M_1 \cdot M_2) = \xinteval{reduce(DetMat(mat1212))} -$$ +\begingroup +\def\xintexprPrintOne #1{\xintFrac{#1}}% (no need for \protected with \xintFrac) +\def\xintexpralignbegin {\begin{pmatrix}}% +\def\xintexpralignend {\end{pmatrix}}% +\def\xintexpralignlinesep {\noexpand\\[2\jot]}% needed to counteract an internal \expanded +\def\xintexpraligninnersep {&}% +\let\xintexpralignleftbracket\empty \let\xintexpralignleftsep\empty +\let\xintexpralignrightbracket\empty \let\xintexpralignrightsep\empty +$$ \xintthealign \xintexpr mat1\relax \cdot \xintthealign \xintexpr mat2\relax \cdot + \xintthealign \xintexpr mat1\relax \cdot \xintthealign \xintexpr mat2\relax = + \xintthealign \xintexpr mat12\relax ^2 = \xintthealign \xintexpr mat1212\relax$$ +$$ \det(M_1\cdot M_2 \cdot M_1 \cdot M_2) = \xinteval{reduce(DetMat(mat1212))}$$ +\endgroup \end{everbatim*} \subsubsection{Example with the \textsc{Rump} test} @@ -6647,7 +6909,7 @@ If function |A| needs function |B| which needs function |A| start by giving to |B| some dummy definition, define |A|, then define |B| properly. TODO: add some example here... -\subsection {Links to some advanced (but old) examples within this document} +\subsection {Links to some (old) examples within this document} \label{sec:awesome} \begin{itemize} @@ -6695,1124 +6957,9 @@ run.% \clearpage -\def\n{|{N}|} -\def\m{|{M}|} -\def\x{|{x}|} - \etocdepthtag.toc {part1B} -\expandafter\let\csname Syntax referencenameUp\endcsname\undefined -\csname Older macros and docnameUp\endcsname -\section{Macros of the \xintexprname package (legacy documentation)}% -\RaisedLabel{sec:oldxintexpr} - -\localtableofcontents - -The \xintexprname package was first released with version |1.07| -(|2013/05/25|) of the \xintname bundle. It was substantially enhanced with -release |1.1| from |2014/10/28|. - -The |1.4| release from |2020/01/31| maintains the same general architecture -but needed adapting all the code base for the switch from |\csname| to -|\expanded| techniques. On this occasion the mechanism for defining functions -was substantially strengthened. The parser core mechanisms were improved too. - -The package loads automatically \xintfracname and \xinttoolsname. - -This section is limited to some information which has not already been covered -in \autoref{sec:xintexprsyntax}. - -\subsection{The \csh{xintexpr} expressions} -\label{xintexpr} -\label{xinttheexpr} -\label{thexintexpr} -\label{xintthe} - -An \xintexprname{}ession is a construct -\csbxint{expr}\meta{expandable\_expression}|\relax|\etype{x} where the -expandable expression is read and completely expanded from left to right. - -An |\xintexpr...\relax| \emph{must} end in a |\relax| (which will be absorbed). -Contrarily to a |\numexpr| expression, it is printable\CHANGED{1.4} as is without a prefix -|\the| or |\number| (don't use them with |\xintexpr| this will raise an -error). - -But one can use |\xintthe| prefix if one does need the explicit digits and -other characters as in the final typesetted result. - -As an alternative and equivalent syntax to -\begin{everbatim} -\xintexpr round(<expression>, D)\relax -\end{everbatim} -there is -\begin{everbatim} -\xintiexpr [D] <expression> \relax -\end{everbatim} -The parameter |D| must be zero or positive.\footnote{|D=0| - corresponds to using |round(<expression>)| not |round(<expression>,0)| which - would leave a trailing dot. Same for |trunc|. There is also function |float| - for floating point rounding to \csbxint{theDigits} or the given number of - significant digits as second argument.} Perhaps some future version will -give a meaning to using a negative |D|.\footnote{Thanks to KT for this - suggestion. Sorry for the delay in implementing it... matter of formatting - the output and corresponding choice of user interface are still in need of - some additional thinking.} - -\begin{itemize} -\item the expression may contain arbitrarily many levels of nested parenthesized - sub-expressions, -\item the expression may contain explicitely or from a macro expansion a - sub-expression |\xintexpr...\relax|, which itself may contain a - sub-expressions etc\dots -\item to let sub-contents evaluate as a sub-unit it should thus be either - \begin{enumerate} - \item parenthesized, - \item or a sub-expression |\xintexpr...\relax|. - \end{enumerate} - \item to use an expression as argument to macros from \xintfracname, - or more generally to macros which expand their arguments, one must use the - |\xinttheexpr...\relax| or |\xintthe\xintexpr...\relax| forms. - \item one should not use |\xintthe\xintexpr...\relax| as a sub-constituent of - another expression but only the - |\xintexpr...\relax| form which is more efficient in this context. - \item each \xintexprname{}ession, whether prefixed or not with |\xintthe|, is - completely expandable and obtains its result in two expansion steps. -\end{itemize} - -The information now following is possibly in need of updates. - -\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, - itemindent=0pt, listparindent=\leftmarginiii, leftmargin=\leftmarginii] -\item An expression is built the standard way with opening and closing - parentheses, infix operators, and (big) numbers, with possibly a fractional - part, and/or scientific notation (except for \csbxint{iiexpr} which only - admits big integers). All variants work with comma separated expressions. On - output each comma will be followed by a space. A decimal number must have - digits either before or after the decimal mark. - -\item As everything gets expanded, the characters |.|, |+|, |-|, |*|, |/|, |^|, - |!|, |&|, \verb+|+, |?|, |:|, |<|, |>|, |=|, |(|, |)|, |"|, |]|, |[|, |@| - and the comma |,| should not (if used in the expression) be active. For - example, the French language in |Babel| system, for pdf\LaTeX, activates |!|, - |?|, |;| and |:|. Turn off the activity before expressions using such characters. - - Alternatively the macro \csbxint{exprSafeCatcodes} resets all - characters potentially needed by \csbxint{expr} to their standard catcodes - and \csbxint{exprRestoreCatcodes} restores the former status. - -\item Count registers and |\numexpr|-essions are accepted (LaTeX{}'s counters - can be inserted using |\value|) natively without |\the| or |\number| as - prefix. Also dimen registers and control sequences, skip registers and - control sequences (\LaTeX{}'s lengths), |\dimexpr|-essions, - |\glueexpr|-essions are automatically unpacked using |\number|, discarding - the stretch and shrink components and giving the dimension value in |sp| - units ($1/65536$th of a \TeX{} point). Furthermore, tacit multiplication is - implied, when the (count or dimen or glue) register or variable, or the - (|\numexpr| or |\dimexpr| or |\glueexpr|) expression is immediately prefixed - by a (decimal) number. See \autoref{ssec:tacit multiplication} for the complete rules - of tacit multiplication.\IMPORTANT - -\item With a macro |\x| defined like this: - % - \leftedline{|\def\x {\xintexpr \a + \b \relax}| or |\edef\x {\xintexpr - \a+\b\relax}|} - % - one may then do |\xintthe\x|, either for printing the result on the page or - to use it in some other macros expanding their arguments. The |\edef| does - the computation immediately but keeps it in a protected form. - Naturally, the |\edef| is only possible if |\a| and |\b| are already - defined. With both approaches the |\x| can be inserted in other expressions, - as for example (assuming naturally as we use an |\edef| that in the - `yet-to-be computed' case the |\a| and |\b| now have some suitable meaning): - % - \leftedline {|\edef\y {\xintexpr \x^3\relax}|} - -\item There is also \csbxint{boolexpr}| ... \relax| and - \csbxint{theboolexpr}| ... \relax|. - -\item See also - \csbxint{ifboolexpr} (\autoref{xintifboolexpr}) and the - \func{bool} and \func{togl} functions - in \autoref{sec:expr}. Here is an example. Well in fact the - example ended up using only \csbxint{boolexpr} so it - was modified to use \csbxint{ifboolexpr}. -\catcode`| 12 % -\begin{everbatim*} -\xintdeffunc A(p,q,r) = p && (q || r) ; -\xintdeffunc B(p,q,r) = p || (q && r) ; -\xintdeffunc C(p,q,r) = xor(p, q, r) ; - -{\centering\normalcolor -\begin{tabular}{ccrclcl} - \xintFor* #1 in {{False}{True}} \do {% - \xintFor* #2 in {{False}{True}} \do {% - \xintFor* #3 in {{False}{True}} \do {% - #1 &AND &(#2 &OR )&is&\textcolor[named]{OrangeRed} - {\xintifboolexpr{A(#1,#2,#3)}{true}{false}}\\ - #1 &OR &(#2 &AND )&is&\textcolor[named]{OrangeRed} - {\xintifboolexpr{B(#1,#2,#3)}{yes}{no}}\\ - #1 &XOR & #2 &XOR  &is&\textcolor[named]{OrangeRed} - {\xintifboolexpr{C(#1,#2,#3)}{oui}{non}}\\ -}}} -\end{tabular} -} -\end{everbatim*}\catcode`| 13 - -\item See also \csbxint{ifsgnexpr}. - -\item There is \csbxint{floatexpr}| ... \relax| where the algebra is done - in floating point approximation (also for each intermediate result). Use the - syntax |\xintDigits:=N\relax| to set the precision. Default: $16$ digits. - % - \leftedline{|\xintthefloatexpr 2^100000\relax:| \dtt{\xintthefloatexpr - 2^100000\relax }} - % - The square-root operation can be used in |\xintexpr|, it is computed - as a float with the precision set by |\xintDigits| or by the optional - second argument: - % -\begin{everbatim*} -\xinttheexpr sqrt(2,60)\relax\newline -Here the [60] is to avoid truncation to |\xinttheDigits| of precision on output.\newline -\printnumber{\xintthefloatexpr [60] sqrt(2,60)\relax} -\end{everbatim*} - - Floats are quickly indispensable when using the power function, as exact - results will easily have hundreds, even thousands of digits. - % -\begin{everbatim*} -\xintDigits:=48\relax \xintthefloatexpr 2^100000\relax -\end{everbatim*} - - Only integer and (in |\xintfloatexpr...\relax|) half-integer exponents are - allowed. - -\item if one uses \emph{macros} within |\xintexpr..\relax| one should - obviously take into account that the parser will \emph{not} see the macro - arguments, hence one cannot use the syntax there, except if the arguments - are themselves wrapped as |\xinttheexpr...\relax| and assuming the macro - \fexpan ds these arguments. -\end{itemize} -\subsection{\texorpdfstring{\texttt{\protect\string\numexpr}}{\textbackslash - numexpr} or \texorpdfstring{\texttt{\protect\string\dimexpr}}{\textbackslash - dimexpr} expressions, count and dimension registers and variables} -\label{ssec:countinexpr} - -Count registers, count control sequences, dimen registers, dimen control -sequences (like |\parindent|), skips and skip control sequences, |\numexpr|, -|\dimexpr|, |\glueexpr|, |\fontdimen| can be inserted directly, they will be -unpacked using |\number| which gives the internal value in terms of scaled -points for the dimensional variables: $1$\,|pt|${}=65536$\,|sp| (stretch and -shrink components are thus discarded). - -Tacit multiplication (see \autoref{ssec:tacit multiplication}) is implied, -when a number or decimal number prefixes such a register or control sequence. -\LaTeX{} lengths are skip control sequences and \LaTeX{} counters should be -inserted using |\value|. - -Release |1.2| of the |\xintexpr| parser also recognizes and prefixes with -|\number| the |\ht|, |\dp|, and |\wd| \TeX{} primitives as well as the -|\fontcharht|, |\fontcharwd|, |\fontchardp| and |\fontcharic| \eTeX{} -primitives. - -In the case of numbered registers like |\count255| or |\dimen0| (or |\ht0|), -the resulting digits will be re-parsed, so for example |\count255 0| is like -|100| if |\the\count255| would give |10|. The same happens with inputs such -as |\fontdimen6\font|. And |\numexpr 35+52\relax| will be exactly as if |87| -as been encountered by the parser, thus more digits may follow: |\numexpr -35+52\relax 000| is like |87000|. If a new |\numexpr| follows, it is treated -as what would happen when |\xintexpr| scans a number and finds a non-digit: it -does a tacit multiplication. -\begin{everbatim*} -\xinttheexpr \numexpr 351+877\relax\numexpr 1000-125\relax\relax{} is the same -as \xinttheexpr 1228*875\relax. -\end{everbatim*} - -Control sequences however (such as |\parindent|) are picked up as a whole by -|\xintexpr|, and the numbers they define cannot be extended extra digits, a -syntax error is raised if the parser finds digits rather than a legal -operation after such a control sequence. - -A token list variable must be prefixed by |\the|, it will not be unpacked -automatically (the parser will actually try |\number|, and thus fail). Do not -use |\the| but only |\number| with a dimen or skip, as the |\xintexpr| parser -doesn't understand |pt| and its presence is a syntax error. To use a dimension -expressed in terms of points or other \TeX{} recognized units, incorporate it in -|\dimexpr...\relax|. - -Regarding how dimensional expressions are converted by \TeX{} into scaled points -see also \autoref{sec:Dimensions}. - -\subsection{Catcodes and spaces} - -Active characters may (and will) break the functioning of \csbxint{expr}. -Inside an expression one may prefix, for example a |:| with |\string|. Or, for -a more radical way, there is \csbxint{exprSafeCatcodes}. This is a -non-expandable step as it changes catcodes. - -\subsubsection{\csh{xintexprSafeCatcodes}} -\label{xintexprSafeCatcodes} - -This macro sets the catcodes of many characters to safe values. This is used -internally by \csbxint{NewExpr} (restoring the catcodes on exit), hence it -does not have to be protected against active characters when used at -top-level. - -Also \csbxint{defvar}, \csbxint{deffunc}, ..., use it before fetching their -semi-colon delimited arguments, so they can be used (also in the document -body) for example with Babel+French which makes the semi-colon active in the -(\LaTeX) document body. - -As \csbxint{NewExpr} and \csbxint{deffunc} and variants use internally some -|\scantokens|, they will (reasonably) succeed in sanitizing catcodes in the -expressions, even if all is from the replacement text of some macro whose -definition was done under some special catcode regime. - -But \csbxint{deffunc}, \csbxint{defvar} and variants need the (catcode other) -semi-colon as delimiter. Thus make sure the semi-colon has its normal catcode -when using \csbxint{deffunc} inside some macro definition. - -The macros \csbxint{deffunc} and variants ignore completely the colon in |:=| -(which furthermore is optional) so it can have any (reasonable) frozen catcode. - -The macros \csbxint{defvar} and variants are also compatible with any -reasonable frozen catcode of the colon |:| in |:=|, and the colon presence is -only optional. - -\begin{framed} - It is important to ALWAYS shortly let \csbxint{exprSafeCatcodes} be followed - by \csbxint{exprRestoreCatcodes}.\IMPORTANTf{} If one uses twice - \csbxint{exprSafeCatcodes} then the next \csbxint{exprRestoreCatcodes} will - restore the ancient catcode regime at time of the first one. -\end{framed} - -\subsubsection{\csh{xintexprRestoreCatcodes}} -\label{xintexprRestoreCatcodes} - -Restores the catcodes to the earlier state. More precisely, -\csbxint{exprSafeCatcodes} sets a toggle (with local scope). If the toggle is -set already it does not restore the current catcodes. The next -\csa{xintexprRestoreCatcodes} unsets the toggle. -So, in case of nesting, the -catcodes are restored to what they were when the \emph{first} un-paired -\csbxint{exprSafeCatcodes} got executed. - -\bigskip - -Spaces inside an |\xinttheexpr...\relax| should mostly be -innocuous (except inside macro arguments). - -|\xintexpr| and |\xinttheexpr| are for the most part agnostic regarding -catcodes: (unbraced) digits, binary operators, minus and plus signs as -prefixes, dot as decimal mark, parentheses, may be indifferently of catcode -letter or other or subscript or superscript, ..., it doesn't matter.% -% -\footnote{Furthermore, although \csbxint{expr} uses \csa{string}, it is - escape-char agnostic. It should work with any \csa{escapechar} setting - including -1.} - -The characters |+|, |-|, |*|, |/|, |^|, |!|, |&|, \verb+|+, |?|, |:|, |<|, |>|, -|=|, |(|, |)|, |"|, |[|, |]|, |;|, the dot and the comma should not be active if -in the expression, as everything is expanded along the way. If one of them is -active, it should be prefixed with |\string|. - -The exclamation mark |!| should have its standard catcode: with catcode letter -it is used internally and hence will confuse the parsers if it comes from the -expression. - -Digits, slash, square brackets, minus sign, in the output from an -|\xinttheexpr| are all of catcode 12. For |\xintthefloatexpr| the `e' in the -output has its standard catcode ``letter''. - -A macro with arguments will expand and grab its arguments before the -parser may get a chance to see them, so the situation with catcodes and spaces -is not the same within such macro arguments. - - - -\subsection{Expandability, \csh{xintexpro}} - -As is the case with all other package macros |\xintexpr| \fexpan ds (in two -steps) to its final (somewhat protected) result; and |\xinttheexpr| \fexpan ds -(in two steps) to the chain of digits (and possibly minus sign |-|, decimal -mark |.|, fraction slash |/|, scientific |e|, square brackets |[|, |]|) -representing the result. - -The once expanded |\xintexpr| is |\romannumeral0\xintexpro|. is similarly -|\xintiexpro| |\xintiiexpro| and |\xintfloatexpro|. For an example see -\autoref{ssec:fibonacci}. - -An expression can only be legally finished by a |\relax| token, which -will be absorbed. - -It is quite possible to nest expressions among themselves; for example, if one -needs inside an |\xintiiexpr...\relax| to do some computations with fractions, -rounding the final result to an integer, one just has to insert -|\xintiexpr...\relax|. The functioning of the infix operators will not be in -the least affected from the fact that the outer ``environment'' is the -|\xintiiexpr| one. - - -\subsection{\csh{xintDigits*}, \csh{xintSetDigits*}} -\label{xintDigits*} -\label{xintSetDigits*} - -These starred variants of \csbxint{Digits} and \csbxint{SetDigits} execute -\csbxint{reloadxinttrig}. - -\subsection{\csh{xintiexpr}, \csh{xinttheiexpr}} -\label{xintiexpr}\label{xinttheiexpr}\label{thexintiexpr} - -Equivalent\etype{x} to doing |\xintexpr round(...)\relax| (more precisely, -|round| is applied to each item independently of its depth inside square -brackets. Intermediate calculations are exact, only the final output gets -rounded. Half integers are rounded towards $+\infty$ for positive -numbers and towards $-\infty$ for negative ones. - -An optional parameter |D>0| within brackets, immediately after |\xintiexpr| -is allowed: it instructs the expression to do its final rounding to the -nearest value with that many digits after the decimal mark, \emph{i.e.}, -|\xintiexpr [D] <expression>\relax| is equivalent (in case of a single -expression) to |\xintexpr round(<expression>, D)\relax|. - -|\xintiexpr [0] ...| is the same as |\xintiexpr ...|. - -If truncation rather than rounding is needed use (in case of a single -expression, naturally) |\xintexpr trunc(...)\relax| for truncation to an -integer or |\xintexpr trunc(...,D)\relax| for truncation to a decimal number -with |D>0| digits after the decimal mark (works only here for single scalar -value). - -Perhaps in the future some meaning will be given to using negative value for -the optional parameter |D|.\footnote{Thanks to Kpym for this suggestion.} - -\subsection{\csh{xintiiexpr}, \csh{xinttheiiexpr}} -\label{xintiiexpr}\label{xinttheiiexpr}\label{thexintiiexpr} - -This variant\etype{x} does not know fractions. It deals almost only with long -integers. Comma separated lists of expressions are allowed. - -\begin{framed} - It maps |/| to the \emph{rounded} quotient. The operator - |//| is, like in |\xintexpr...\relax|, mapped to \emph{truncated} division. - The Euclidean quotient (which for positive operands is like the truncated - quotient) was, prior to release |1.1|, associated to |/|. The function - |quo(a,b)| can still be employed. -\end{framed} - -The \csbxint{iiexpr}-essions use the `ii' macros for addition, subtraction, -multiplication, power, square, sums, products, Euclidean quotient and -remainder. - -The |round|, |trunc|, |floor|, |ceil| functions are still available, and are -about the only places where fractions can be used, but |/| within, if not -somehow hidden will be executed as integer rounded division. To avoid this one -can wrap the input in \dtt{qfrac}: this means however that none of the normal -expression parsing will be executed on the argument. - -To understand the illustrative examples, recall that |round| and |trunc| have -a second (non negative) optional argument. In a normal \csbxint{expr}-essions, -|round| and |trunc| are mapped to \csbxint{Round} and \csbxint{Trunc}, in -\csbxint{iiexpr}-essions, they are mapped to \csbxint{iRound} and -\csbxint{iTrunc}. - - -\begin{everbatim*} -\xinttheiiexpr 5/3, round(5/3,3), trunc(5/3,3), trunc(\xintDiv {5}{3},3), -trunc(\xintRaw {5/3},3)\relax{} are problematic, but -% -\xinttheiiexpr 5/3, round(qfrac(5/3),3), trunc(qfrac(5/3),3), floor(qfrac(5/3)), -ceil(qfrac(5/3))\relax{} work! -\end{everbatim*} - -On the other hand decimal numbers and scientific numbers can be used directly -as arguments to the |num|, |round|, or any function producing an integer. - -\begin{framed} - Scientific numbers will be - represented with as many zeroes as necessary, thus one does not want to - insert \dtt{num(1e100000)} for example in an \csa{xintiiexpr}ession! -\end{framed} - -% -\begin{everbatim*} -\xinttheiiexpr num(13.4567e3)+num(10000123e-3)\relax % should (num truncates) compute 13456+10000 -\end{everbatim*} -% - -The |reduce| function is not available and will raise an error. The |frac| -function also. The |sqrt| function is mapped to \csbxint{iiSqrt} which gives -a truncated square root. The |sqrtr| function is mapped to \csbxint{iiSqrtR} -which gives a rounded square root. - -One can use the Float macros if one is careful to use |num|, or |round| -etc\dots on their output. - -\begin{everbatim*} -\xinttheiiexpr \xintFloatSqrt [20]{2}, \xintFloatSqrt [20]{3}\relax % no operations - -\noindent The next example requires the |round|, and one could not put the |+| inside it: - -\xinttheiiexpr round(\xintFloatSqrt [20]{2},19)+round(\xintFloatSqrt [20]{3},19)\relax - -(the second argument of |round| and |trunc| tells how many digits from after the -decimal mark one should keep.) -\end{everbatim*} - -The whole point of \csbxint{iiexpr} is to gain some speed in -\emph{integer-only} algorithms, and the above explanations related to how to -nevertheless use fractions therein are a bit peripheral. We observed -(2013/12/18) of the order of $30$\% speed gain when dealing with numbers with -circa one hundred digits (1.2: this info may be obsolete). - - -\subsection{\csh{xintboolexpr}, \csh{xinttheboolexpr}} -\label{xintboolexpr}\label{xinttheboolexpr}\label{thexintboolexpr} - -Equivalent\etype{x} to doing |\xintexpr ...\relax| and returning $True$ if the -result does not vanish, and $False$ if the result is zero. As |\xintexpr|, this -can be used on comma separated lists of expressions, and even bracketed lists. -\CHANGED{1.4} - -It can be customized, one only needs to modify the following: -\begin{everbatim} -\def\xintboolexprPrintOne#1{\xintiiifNotZero{#1}{True}{False}}% -\end{everbatim} -Not only are |True| and |False| usable in input, also |true| and |false| are -pre-declared variables. - -Maybe obsolete: - -There is slight quirk in case it is used as a sub-expression: the boolean -expression needs at least one logic operation else the value is not -standardized to |1| or |0|, for example we get from -\begin{everbatim*} -\xinttheexpr \xintboolexpr 1.23\relax\relax\newline -\end{everbatim*}which is to be compared with -\begin{everbatim*} -\xinttheboolexpr 1.23\relax -\end{everbatim*} - -% A related issue existed with -% |\xinttheexpr \xintiexpr 1.23\relax\relax|, which was fixed with |1.1| -% release, and I decided back then not to add the needed overhead also to the -% |\xintboolexpr| context, as one only needs to use |?(1.23)| for example or -% involve the |1.23| in any logic operation like |1.23 'and' 3.45|, or involve -% the |\xintboolexpr ..\relax | itself with any logical operation, contrarily to -% the sub-|\xintiexpr| case where |\xinttheexpr 1+\xintiexpr 1.23\relax\relax| -% did behave contrarily to expectations until |1.1|. - - -\subsection{\csh{xintfloatexpr}, - \csh{xintthefloatexpr}} -\label{xintfloatexpr}\label{xintthefloatexpr}\label{thexintfloatexpr} - -\csbxint{floatexpr}|...\relax|\etype{x} is exactly like |\xintexpr...\relax| -but with the four binary operations and the power function are mapped to -\csa{xintFloatAdd}, \csa{xintFloatSub}, \csa{xintFloatMul}, \csa{xintFloatDiv} -and \csa{xintFloatPower}, respectively.\footnote{Since |1.2f| the \string^ - handles half-integer exponents, contrarily to \csa{xintFloatPower}.} - -The target precision for the computation is from the -current setting of |\xintDigits|. Comma separated lists of expressions are -allowed. - -An optional parameter within brackets is allowed: -\begin{itemize} -\item if positive it instructs the macro to round the result to that many - digits of precision. It thus makes sense to employ it only if this parameter is - less than the \csbxint{theDigits} precision. -\item if negative it means to trim off that many digits (of course, in the - sense of rounding - the values to shorter mantissas). Don't use it to trim all digits (or more than all)! -\end{itemize} - -Since |1.2f| all float operations first round their arguments; a parsed number -is not rounded prior to its use as operand to such a float operation. - -|\thexintfloatexpr| is synonym to |\xintthefloatexpr|. - -|\xintDigits:=36\relax|\xintDigits:=36\relax -% -\leftedline{|\xintthefloatexpr - (1/13+1/121)*(1/179-1/173)/(1/19-1/18)\relax|} -% -\leftedline{\dtt{\xintthefloatexpr - (1/13+1/121)*(1/179-1/173)/(1/19-1/18)\relax}} -% 0.00564487459334466559166166079096852897 -% -\leftedline{|\xintthefloatexpr\xintexpr - (1/13+1/121)*(1/179-1/173)/(1/19-1/18)\relax\relax|} -% -\leftedline{\dtt{\xintthefloatexpr\xintexpr - (1/13+1/121)*(1/179-1/173)/(1/19-1/18)\relax\relax}} - -\xintDigits := 16; - -The latter is the rounding of the exact result. The former one has -its last three digits wrong due to the cumulative effect of rounding errors -in the intermediate computations, as compared to exact evaluations. - - - - -I recall here from \autoref{ssec:floatingpoint} that with release |1.2f| the -float macros for addition, subtraction, multiplication and division round -their arguments first to |P| significant places with |P| the asked-for -precision of the output; and similarly the power macros and the -square root macro. This does not modify anything for computations with -arguments having at most |P| significant places already. - -\subsection{\csh{xinteval}, \csh{xintieval}, \csh{xintiieval}, - \csh{xintfloateval}} -\label{xinteval}\label{xintieval}\label{xintiieval}\label{xintfloateval} - -\csbxint{eval}\etype{x} is an \fexpan dable macro which is basically defined -like this (DON'T BELIEVE THIS; it has been entirely revamped at |1.4|): -\begin{everbatim} -\def\xinteval#1{\romannumeral-`0\xinttheexpr#1\relax}% OLD DEFINITION < 1.4 -\end{everbatim} -thus expands in two steps (its exact definition differs from the one given -above in order to achieve a slight optimization). -\begin{everbatim*} -\xinteval{add(x^2, x = 100..110), add(x^3, x = 100..110)} -\end{everbatim*} - -\csbxint{ieval}\etype{x} is similarly related to \csbxint{theiexpr}. Its optional -argument must be located inside the braces: -\begin{everbatim*} -\xintieval{[7] 355/113} -\end{everbatim*} - -\csbxint{iieval}\etype{x} is similarly related to \csbxint{theiiexpr}. -\begin{everbatim*} -\xintiieval{add(x^2, x = 100..110), add(x^3, x = 100..110)} -\end{everbatim*} - -\csbxint{floateval}\etype{x} is similarly related to \csbxint{thefloatexpr}. Its optional -argument must be located inside the braces: -\begin{everbatim*} -\xintfloateval{[7] 355/113} -\end{everbatim*} - -When negative it tells how many digits to remove from the prevailing precision -(\csbxint{theDigits}): -\begin{everbatim*} -\xintfloateval{[-2] 355/113} has \xinttheDigits\ minus 2 digits. -\end{everbatim*} - -These macros are useful when one uses some extra wrapper doing some parsing of -its input, like the |\num| macro of -\href{http://ctan.org/pkg/siunitx}{siunitx}, which would choke on some of the -syntax elements allowed inside \csb{xintexpr}|...\relax| (for example -brackets). -As shown in the above examples, these macros, like the underlying parsers -accept arbitrarily many comma separated expressions. - - -\subsection{Using an expression parser within another one} - -This was already illustrated before. In the following: -\begin{everbatim*} -\xintfloatexpr \xintexpr add(1/i, i=1234..1243)\relax ^100\relax -\end{everbatim*}, -the inner sum is computed exactly. Then it will be rounded to |\xinttheDigits| -significant digits, and then its power will be evaluated as a float operation. -One should avoid the "|\xintthe|" parsers in inner positions as this induces -digit by digit parsing of the inner computation result by the outer parser. -Here is the same computation done with floats all the way: -\begin{everbatim*} -\xintfloatexpr add(1/i, i=1234..1243)^100\relax -\end{everbatim*} - -Not surprisingly this differs from the previous one which was exact until -raising to the |100|th power. - -The fact that the inner expression occurs inside a bigger one has nil -influence on its behaviour. There is the limitation though that the outputs -from \csbxint{expr} and \csbxint{floatexpr} can not be used directly in -\csbxint{theiiexpr} integer-only parser. But one can do: -\begin{everbatim*} -\xintiiexpr round(\xintfloatexpr 3.14^10\relax)\relax % or trunc -\end{everbatim*} - - -\subsection{The \csh{xintthecoords} macro} -\label{xintthecoords} - -It converts a comma separated list into the format for list of coordinates as -expected by the |TikZ| |coordinates| syntax.% -% -\footnote{The implementation had to work around the -problem that |TikZ| seemingly allows only a maximal number of about one -hundred expansion steps for the list to be entirely produced.}% -% -\begin{everbatim*} -\begin{figure}[htbp] -\centering\begin{tikzpicture}[scale=10]\xintDigits:=8\relax - \clip (-1.1,-.25) rectangle (.3,.25); - \draw [blue] (-1.1,0)--(1,0); - \draw [blue] (0,-1)--(0,+1); - \draw [red] plot[smooth] coordinates {% -%%% (\xintthecoords converts output of next expression into (x1, y1) (x2, y2)... format) - \xintthecoords\xintfloatexpr -%%% This syntax -1+[0..4]/2 is currenty dropped at xint 1.4 -%%% seq((x^2-1,mul(x-t,t=-1+[0..4]/2)),x=-1.2..[0.1]..+1.2)\relax -%%% Use this: - seq((x^2-1,mul(x-t,t=seq(-1+u/2, u=0..4))),x=-1.2..[0.1]..+1.2) - \relax - }; -\end{tikzpicture} -\caption{Coordinates with \cs{xintthecoords}.} -\end{figure} -\end{everbatim*} - -% Notice: if x goes no take exactly value 1 or -1, the origin appears slightly -% off the curve, not MY fault!!! - -As examplified above, \csbxint{thecoords} is to be used followed immediately -by either \csbxint{floatexpr} or \csbxint{iexpr} or \csbxint{iiexpr}. - - -The next\IMPORTANT{} -paragraph is probably obsoleted by |1.4| as |\xintexpr| does use -scienttific notation on output however with a possible denominator. - -As |TikZ| will not understand the |A/B[N]| format which is used on output by -|\xintexpr|, |\xintthecoords\xintexpr| has no use inside a |TikZ| picture but -may have other usages; the reason for the spaces in output is to allow if -necessary to print on the page for examination and give \TeX\ a change to -establish line-breaks. - -\begin{everbatim*} -\edef\x{\xintthecoords \xintexpr rrseq(1/2,1/3; @1+@2, x=1..20)\relax } -\meaning\x +++ -\end{everbatim*} - -\subsection{\csh{xintifboolexpr}, \csh{xintifboolfloatexpr}, \csh{xintifbooliiexpr}} -\label{xintifboolexpr} -\label{xintifboolfloatexpr} -\label{xintifbooliiexpr} - -\csh{xintifboolexpr}\marg{expr}\marg{YES}\marg{NO}\etype{xnn} does -\csbxint{theexpr}<expr>|\relax| and then executes the \meta{YES} or the -\meta{NO} branch depending on whether the outcome was non-zero or zero. Thus -one can read \emph{if bool expr} as meaning \emph{if not zero}: -\centeredline{if \meta{expr}-ession does not vanish do \meta{YES} else do - \meta{NO}} - -The expression is not limited to using only comparison operators and Boolean -logic (|<|, |>|, |==|, |!=|, |&&|, \verb+||+, \func{all}, \func{any}, -\func{xor}, \func{bool}, \func{togl}, ...), it can be the most general -computation. - -\csh{xintifboolfloatexpr}\marg{expr}\marg{YES}\marg{NO}\etype{xnn} does -\csbxint{thefloatexpr}\meta{expr}|\relax| and then executes the \meta{YES} or the -\meta{NO} branch depending on whether the outcome was non zero or zero. - -\csh{xintifbooliiexpr}\marg{expr}\marg{YES}\marg{NO}\etype{xnn} does -\csbxint{theiiexpr}\meta{expr}|\relax| and then executes the \meta{YES} or the -\meta{NO} branch depending on whether the outcome was non zero or zero. - -The expression argument must be a single one, comma separated sub-expressions -will cause low-level errors. - -\subsection{\csh{xintifsgnexpr}, \csh{xintifsgnfloatexpr}, \csh{xintifsgniiexpr}} -\label{xintifsgnexpr} -\label{xintifsgnfloatexpr} -\label{xintifsgniiexpr} - -\csh{xintifsgnexpr}\marg{expr}\marg{<0}\marg{=0}\marg{>0}\etype{xnnn} evaluates -the \csbxint{expr}ession and chooses the branch corresponding to its sign. - -\csh{xintifsgnfloatexpr}\marg{expr}\marg{<0}\marg{=0}\marg{>0}\etype{xnnn} evaluates -the \csbxint{floatexpr}ession and chooses the branch corresponding to its sign. - -\csh{xintifsgniiexpr}\marg{expr}\marg{<0}\marg{=0}\marg{>0}\etype{xnnn} evaluates -the \csbxint{iiexpr}ession and chooses the branch corresponding to its sign. - -The expression argument must be a single one, comma separated sub-expressions -will cause low-level errors. - -\subsection{The \csh{xintNewExpr}, \csh{xintNewIIExpr}, - \csh{xintNewFloatExpr}, \csh{xintNewIExpr}, and \csh{xintNewBoolExpr} - macros} -\label{xintNewExpr} -\label{xintNewIIExpr} -\label{xintNewFloatExpr} -\label{xintNewIExpr} -\label{xintNewBoolExpr} - -\csbxint{NewExpr} macro is used as: -% -\leftedline{|\xintNewExpr{\myformula}[n]|\marg{stuff}, where} -\begin{itemize} -\item \meta{stuff} will be inserted inside |\xinttheexpr . . . \relax|, -\item |n| is an integer between zero and nine, inclusive, which is the number - of parameters of |\myformula|, -\item the placeholders |#1|, |#2|, ..., |#n| are used inside \meta{stuff} in - their usual r\^ole,% -% -\catcode`# 12 -\footnote{if \csa{xintNewExpr} is used inside a macro, - the |#|'s must be doubled as usual.} - \footnote{the |#|'s will in pratice have their usual - catcode, but category code other |#|'s are accepted too.} -\catcode`# 6 -% -\item the |[n]| is \emph{mandatory}, even for |n=0|.% -\footnote{there is some use for \csa{xintNewExpr}|[0]| compared to an - \csa{edef} as \csa{xintNewExpr} has some built-in catcode protection.} -\item the macro |\myformula| is defined without checking if it already exists, - \LaTeX{} users might prefer to do first |\newcommand*\myformula {}| to get a - reasonable error message in case |\myformula| already exists, -\item the protection against active characters is done automatically (as long - as the whole thing has not already been fetched as a macro argument and - the catcodes correspondingly already frozen). -\end{itemize} - -It (if it succeeds) will be a completely expandable macro entirely built-up using |\xintAdd|, -|\xintSub|, |\xintMul|, |\xintDiv|, |\xintPow|, etc\dots as corresponds to the -expression written with the infix operators. -Macros created by |\xintNewExpr| can thus be nested. - -\begin{everbatim*} - \xintNewFloatExpr \FA [2]{(#1+#2)^10} - \xintNewFloatExpr \FB [2]{sqrt(#1*#2)} -\begin{enumerate}[nosep] - \item \FA {5}{5} - \item \FB {30}{10} - \item \FA {\FB {30}{10}}{\FB {40}{20}} -\end{enumerate} -\end{everbatim*} - -The documentation is much shortened here because \csbxint{NewExpr} and \csbxint{deffunc} -are very much related one with the other. - -\begin{framed} - ATTENTION! - - The original spirit of \csbxint{NewExpr} was to define a (possibly very big) - macro using only \xintfracname, and this means in particular that it must be - used only with arguments compatible with the \xintfracname input - format.\IMPORTANTf - - Thus an |\xintexpr| declared variable has no chance to work, it must be - wrapped explicitly in |\xinteval{...}| to be fetched as argument to a macro - constructed by \csbxint{NewExpr}. -\end{framed} - -They share essentially the same limitations. - -Notice though that \csbxint{NewFloatExpr} accepts and recognizes the optional -argument |[Q]| of \csbxint{floatexpr}, contrarily to \csbxint{deffloatfunc}. -Use an |\empty| in case the contents are not known in advance. - - -Historical note: prior to |1.4|, \xintexprname used a |\csname..\endcsname| -encapsulation technique which impacted the string pool memory. The -\csbxint{NewExpr} was designed as a method to pre-parse the expression and -produce one single, gigantic, nested usage of the relevant \xintfracname -macros. This way, only those macros were expanded which had nil impact on the -\TeX{} string pool. - -Later on it was found that this mechanism could be employed to define -functions. Basically underneath |98%| of \csbxint{NewExpr} and -\csbxint{deffunc} are using the same shared code. - -\xintDigits:= 16\relax - -\subsection{Analogies and differences of \csh{xintiiexpr} with \csh{numexpr}} - -\csbxint{iiexpr}|..\relax| is a parser of expressions knowing only (big) -integers. There are, besides the enlarged range of allowable inputs, some -important differences of syntax between |\numexpr| and |\xintiiexpr| and -variants: -\begin{itemize} -\item Contrarily to |\numexpr|, the |\xintiiexpr| parser will stop expanding - only after having encountered (and swallowed) a \emph{mandatory} |\relax| - token. -\item In particular, spaces between digits (and not only around infix - operators or parentheses) do not stop |\xintiiexpr|, contrarily to the - situation with |numexpr|: |\the\numexpr 7 + 3 5\relax| expands (in one - step)% -% -\footnote {The |\numexpr| triggers continued expansion after the space - following the |3| to check if some operator like |+| is upstream. But - after having found the |5| it treats it as and end-marker.} -% - to \dtt{\detokenize\expandafter{\the\numexpr 7 + 3 5\relax}\unskip}, whereas - |\xintthe\xintiiexpr 7 + 3 5\relax| expands (in two steps) to - \dtt{\detokenize\expandafter\expandafter\expandafter {\xintthe\xintiiexpr 7 - + 3 5\relax}}.% -% -\footnote {Since |1.2l| one can also use the underscore |_| to separate digits -for readability of long numbers.} - -\item Inside an |\edef|, an expression |\xintiiexpr...\relax| get fully - evaluated, whereas |\numexpr| without |\the| or |\number| prefix would not, - if not itself embedded in another |\the\numexpr| or similar context. -\item (ctd.) The private format to which |\xintiiexpr...\relax| (et al.) - evaluates may use |\xintthe| prefix to turn into explicit digits, - (for example in arguments to some macros which expand their arguments). The |\the| \TeX\ primitive prefix would - not work here. -\item (ctd.) One can embed a |\numexpr...\relax| (with its |\relax|!) inside an - |\xintiiexpr...\relax| without |\the| or |\number|, but the reverse situation - requires usage of |\xintthe| or \csbxint{eval} user interface, -\item |\numexpr -(1)\relax| is illegal. In contrast |\xintiiexpr -(1)\relax| is - perfectly legal and gives the expected result (what else ?). -\item |\numexpr 2\cnta\relax| is illegal (with |\cnta| a |\count| register.) - In contrast - |\xintiiexpr 2\cnta\relax| is perfectly legal and will do the tacit - multiplication. -\item |\the\numexpr| or |\number\numexpr| expands in one step, but - |\xintthe\xintiiexpr| or |\xinttheiiexpr| needs two steps. -\end{itemize} - -\subsection{Chaining expressions for expandable algorithmics} -\label{ssec:fibonacci} - -We will see in this section how to chain |\xintexpr|-essions with -|\expandafter|'s, like it is possible with |\numexpr|. For this it is -convenient to use |\romannumeral0\xintexpro| which is the once-expanded form of -|\xintexpr|, as we can then chain using only one |\expandafter| each time. - -For example, here is the code employed -on the title page to compute (expandably, of course!) the 1250th Fibonacci -number: - -\begin{everbatim*} -\catcode`_ 11 -\def\Fibonacci #1{% \Fibonacci{N} computes F(N) with F(0)=0, F(1)=1. - \expandafter\Fibonacci_a\expandafter - {\the\numexpr #1\expandafter}\expandafter - {\romannumeral0\xintiiexpro 1\expandafter\relax\expandafter}\expandafter - {\romannumeral0\xintiiexpro 1\expandafter\relax\expandafter}\expandafter - {\romannumeral0\xintiiexpro 1\expandafter\relax\expandafter}\expandafter - {\romannumeral0\xintiiexpro 0\relax}} -% -\def\Fibonacci_a #1{% - \ifcase #1 - \expandafter\Fibonacci_end_i - \or - \expandafter\Fibonacci_end_ii - \else - \ifodd #1 - \expandafter\expandafter\expandafter\Fibonacci_b_ii - \else - \expandafter\expandafter\expandafter\Fibonacci_b_i - \fi - \fi {#1}% -}% * signs are omitted from the next macros, tacit multiplications -\def\Fibonacci_b_i #1#2#3{\expandafter\Fibonacci_a\expandafter - {\the\numexpr #1/2\expandafter}\expandafter - {\romannumeral0\xintiiexpro sqr(#2)+sqr(#3)\expandafter\relax\expandafter}\expandafter - {\romannumeral0\xintiiexpro (2#2-#3)#3\relax}% -}% end of Fibonacci_b_i -\def\Fibonacci_b_ii #1#2#3#4#5{\expandafter\Fibonacci_a\expandafter - {\the\numexpr (#1-1)/2\expandafter}\expandafter - {\romannumeral0\xintiiexpro sqr(#2)+sqr(#3)\expandafter\relax\expandafter}\expandafter - {\romannumeral0\xintiiexpro (2#2-#3)#3\expandafter\relax\expandafter}\expandafter - {\romannumeral0\xintiiexpro #2#4+#3#5\expandafter\relax\expandafter}\expandafter - {\romannumeral0\xintiiexpro #2#5+#3(#4-#5)\relax}% -}% end of Fibonacci_b_ii -% code as used on title page: -%\def\Fibonacci_end_i #1#2#3#4#5{\xintthe#5} -%\def\Fibonacci_end_ii #1#2#3#4#5{\xinttheiiexpr #2#5+#3(#4-#5)\relax} -% new definitions: -\def\Fibonacci_end_i #1#2#3#4#5{{#4}{#5}}% {F(N+1)}{F(N)} in \xintexpr format -\def\Fibonacci_end_ii #1#2#3#4#5% - {\expandafter - {\romannumeral0\xintiiexpro #2#4+#3#5\expandafter\relax - \expandafter}\expandafter - {\romannumeral0\xintiiexpro #2#5+#3(#4-#5)\relax}}% idem. -% \FibonacciN returns F(N) (in encapsulated format: needs \xintthe for printing) -\def\FibonacciN {\expandafter\xint_secondoftwo\romannumeral-`0\Fibonacci }% -\catcode`_ 8 -\end{everbatim*} - - -The macro |\Fibonacci| produces not one specific value |F(N)| but a pair of -successive values |{F(N)}{F(N+1)}| which can then serve as starting point of -another routine devoted to compute a whole sequence |F(N), F(N+1), -F(N+2),....|. Each of |F(N)| and |F(N+1)| is kept in the encapsulated internal -\xintexprname format. - -|\FibonacciN| produces the single |F(N)|. It also keeps it in the private -format; thus printing it will need the |\xintthe| prefix. - -\begingroup\footnotesize\sffamily\baselineskip 10pt -Here a code snippet which -checks the routine via a \string\message\ of the first $51$ Fibonacci -numbers (this is not an efficient way to generate a sequence of such -numbers, it is only for validating \csa{FibonacciN}). -% -\begin{everbatim} -\def\Fibo #1.{\xintthe\FibonacciN {#1}}% -\message{\xintiloop [0+1] \expandafter\Fibo\xintiloopindex., - \ifnum\xintiloopindex<49 \repeat \xintthe\FibonacciN{50}.} -\end{everbatim} -\endgroup - -The way we use |\expandafter|'s to chain successive |\xintiiexpro| evaluations -is exactly analogous to what is possible with |\numexpr|. The various -|\romannumeral0\xintiiexpro| could very well all have been |\xintiiexpr|'s but -then we would have needed |\expandafter\expandafter\expandafter| each -time. - -\begin{framed} - There is a difference though: |\numexpr| does \emph{NOT} expand inside an - |\edef|, and to force its expansion we must prefix it with |\the| or - |\number| or |\romannumeral| or another |\numexpr| which is itself prefixed, - etc\dots. - - But |\xintexpr|, |\xintiexpr|, ..., expand fully in an |\edef|, with the - completely expanded - result encapsulated in a private format. - - Using |\xintthe| as prefix is necessary to print the result (like |\the| or - |\number| in the case of |\numexpr|), but it is not necessary to get the - computation done (contrarily to the situation with |\numexpr|). -\end{framed} - - -Our |\Fibonacci| expands completely under \fexpan sion, so we can use -\hyperref[fdef]{\ttfamily\char92fdef} rather than |\edef| in a situation such -as -% -\leftedline {|\fdef \X {\FibonacciN {100}}|} -% -but it is usually about as efficient to employ |\edef|. And if we want -% -\leftedline{|\edef \Y {(\FibonacciN{100},\FibonacciN{200})}|,} -% -then |\edef| is necessary. - -Allright, so let's now give the code to generate |{F(N)}{F(N+1)}{F(N+2)}...|, -using |\Fibonacci| for the first two and then using the standard recursion -|F(N+2)=F(N+1)+F(N)|: - -\catcode`_ 11 -\def\FibonacciSeq #1#2{%#1=starting index, #2>#1=ending index - \expandafter\Fibonacci_Seq\expandafter - {\the\numexpr #1\expandafter}\expandafter{\the\numexpr #2-1}% -}% -\def\Fibonacci_Seq #1#2{% - \expandafter\Fibonacci_Seq_loop\expandafter - {\the\numexpr #1\expandafter}\romannumeral0\Fibonacci {#1}{#2}% -}% -\def\Fibonacci_Seq_loop #1#2#3#4{% standard Fibonacci recursion - {#3}\unless\ifnum #1<#4 \Fibonacci_Seq_end\fi - \expandafter\Fibonacci_Seq_loop\expandafter - {\the\numexpr #1+1\expandafter}\expandafter - {\romannumeral0\xintiiexpro #2+#3\relax}{#2}{#4}% -}% -\def\Fibonacci_Seq_end\fi\expandafter\Fibonacci_Seq_loop\expandafter - #1\expandafter #2#3#4{\fi {#3}}% -\catcode`_ 8 - -\begingroup\footnotesize\baselineskip10pt -\everb|@ -\catcode`_ 11 -\def\FibonacciSeq #1#2{%#1=starting index, #2>#1=ending index - \expandafter\Fibonacci_Seq\expandafter - {\the\numexpr #1\expandafter}\expandafter{\the\numexpr #2-1}% -}% -\def\Fibonacci_Seq #1#2{% - \expandafter\Fibonacci_Seq_loop\expandafter - {\the\numexpr #1\expandafter}\romannumeral0\Fibonacci {#1}{#2}% -}% -\def\Fibonacci_Seq_loop #1#2#3#4{% standard Fibonacci recursion - {#3}\unless\ifnum #1<#4 \Fibonacci_Seq_end\fi - \expandafter\Fibonacci_Seq_loop\expandafter - {\the\numexpr #1+1\expandafter}\expandafter - {\romannumeral0\xintiiexpro #2+#3\relax}{#2}{#4}% -}% -\def\Fibonacci_Seq_end\fi\expandafter\Fibonacci_Seq_loop\expandafter - #1\expandafter #2#3#4{\fi {#3}}% -\catcode`_ 8 -| -\endgroup - -This |\FibonacciSeq| macro is -completely expandable but it is not \fexpan dable. - -This is not a problem in the next example which uses \csbxint{For*} as the -latter applies repeatedly full expansion to what comes next each time it -fetches an item from its list argument. Thus \csbxint{For*} still manages to -generate the list via iterated full expansion. - - -\begin{figure*}[ht!] - \phantomsection\label{fibonacci} - \newcounter{myindex} - \fdef\Fibxxx{\FibonacciN {30}}% - \setcounter{myindex}{30}% -\centeredline{\tabskip 1ex -\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr - \xintFor* #1 in {\FibonacciSeq {30}{59}}\do - {\themyindex &\xintthe#1 & - \xintiiRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{myindex}\cr }}% -}\vrule -\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr - \xintFor* #1 in {\FibonacciSeq {60}{89}}\do - {\themyindex &\xintthe#1 & - \xintiiRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{myindex}\cr }}% -}\vrule -\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr - \xintFor* #1 in {\FibonacciSeq {90}{119}}\do - {\themyindex &\xintthe#1 & - \xintiiRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{myindex}\cr }}% -}}% -% -\centeredline{Some Fibonacci numbers together with their residues modulo - |F(30)|\dtt{=\xintthe\Fibxxx}} -\end{figure*} - -\begingroup\footnotesize\baselineskip10pt -\everb|@ -\newcounter{myindex}% not "index", which would overwrite theindex environment! -% (many have probably been bitten by this trap) -\tabskip 1ex - \fdef\Fibxxx{\FibonacciN {30}}% - \setcounter{myindex}{30}% -\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr - \xintFor* #1 in {\FibonacciSeq {30}{59}}\do - {\themyindex &\xintthe#1 & - \xintiiRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{myindex}\cr }}% -}\vrule -\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr - \xintFor* #1 in {\FibonacciSeq {60}{89}}\do - {\themyindex &\xintthe#1 & - \xintiiRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{myindex}\cr }}% -}\vrule -\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr - \xintFor* #1 in {\FibonacciSeq {90}{119}}\do - {\themyindex &\xintthe#1 & - \xintiiRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{myindex}\cr }}% -}% -| -\endgroup - -This produces the Fibonacci numbers from |F(30)| to |F(119)|, and -computes also all the -congruence classes modulo |F(30)|. The output has -been put in a \hyperref[fibonacci]{float}, which appears -\vpageref[above]{fibonacci}. I leave to the mathematically inclined -readers the task to explain the visible patterns\dots |;-)|. - -\subsection{Acknowledgements (2013/05/25)} - -I was greatly helped in my preparatory thinking, prior to producing such an -expandable parser, by the commented source of the -\href{https://ctan.org/pkg/l3kernel}{l3fp} package, specifically the -|l3fp-parse.dtx| file (in the version of April-May 2013; I think there was in -particular a text called ``roadmap'' which was helpful). Also the source of the -|calc| package was instructive, despite the fact that here for |\xintexpr| the -principles are necessarily different due to the aim of achieving expandability. - -\clearpage -\expandafter\let\csname Older macros and docnameUp\endcsname\undefined +\let\xintexprnameUp\undefined \csname xinttrignameUp\endcsname \def\n{|{N}|} @@ -7981,46 +7128,35 @@ not really needed. It is a oneliner to add them: \begin{everbatim} \xintdeffloatefunc radians(x) := x * oneDegree; \xintdeffloatefunc degrees(x) := x * oneRadian; -\xintdefefunc radians(x) := x * oneDegree; -\xintdefefunc degrees(x) := x * oneRadian; +\xintdefefunc radians(x) := float_(x * oneDegree); +\xintdefefunc degrees(x) := float_(x * oneRadian); \end{everbatim} -The variants for \csbxint{expr} above do an exact multiplication, I did not -add a \func{float} wrapper to force rounding as anyhow the trigonometrical -functions will do this initial rounding of their arguments. But if you define -a variable for multiple later use using such a |degrees()| function, it would -be better to add a \func{float} wrapper in the variable definition so the -rounding is already done: rounding an already rounded value is unavoidable -overhead but proceeds faster as it is quicly realized the input actually needs -no rounding. - -Notice however that the conversion factors above are without guard digits. One -can do this: -\begin{everbatim} -\xintdeffloatefunc radians(x) := float(\xintexpr x * oneDegreewithmoredigits\relax); -\xintdeffloatefunc degrees(x) := float(\xintexpr x * oneRadianwithmoredigits\relax); -\end{everbatim} -But recall that |x| will normally already be a rounded value, so this is -perhaps a bit complex for not much ado. Probably better to work overall with -an elevated precision and print final results at a lower precision. +The \csbxint{expr}-variants above do an exact multiplication. The +\func{float\string_} explicit rounding is a bit superfluous as anyhow trigonometrical +functions do this initial rounding of their arguments. + +The conversion factors above are without guard digits. Probably better to work +overall with an elevated precision and print final results at a lower +precision. \subsection{Important implementation notes} \label{ssec:trignotes} \begin{itemize} \item The package is almost entirely implemented using the high level user - interface of \xintexprname, see \autoref{sec:xintexprsyntax} for - \csbxint{deffloatefunc} and \csbxint{deffloatvar}, the main two exceptions - were: + interface of \xintexprname, using + \csbxint{deffloatefunc} (and \csbxint{deffloatvar}), the main two exceptions + being for: \begin{enumerate}[nolistsep] \item the range reduction for the |sind()| and |cosd()| functions which required for optimized efficiency the coding at some more core level. - \item some changes at core level + \item some changes at core level added at |1.3e| to facilitate the transfer of the defined functions from the float parser to the exact parser. \end{enumerate} - To avoid problems if the package is reloaded at a time the user has - used some letter variables as assigned variables, I added + Also, to avoid problems if the package is reloaded at a time the user has + used some letter variables as assigned variables, |1.3e| added \csbxint{ensuredummy} and \csbxint{restorevariable}. \item It is not possible from this interface to (easily) let the computation proceed with a temporarily elevated precision (``guard digits''). Expect @@ -8115,8 +7251,6 @@ $asind(sind(25))\approx\xintfloateval{[-2] asind(sind(25))}$\par \section{Macros of the \xintlogname package} \RaisedLabel{sec:log} -\localtableofcontents - This package provides logarithms, exponentials and fractional powers for use with \xintexprname. @@ -8134,6 +7268,8 @@ has no dependencies and can be imported by any other \TeX\ macro file. Although the precision is thus limited to about \dtt{8} or \dtt{9} digits this is amply enough for plots. +\localtableofcontents + \subsection{\csh{poormanloghack}} \label{ssec:poormanloghack} @@ -8186,1209 +7322,11 @@ to 2 units in the ninth digit when computing |log10(x)| for |1<x<10| and \clearpage \let\xintlognameUp\undefined -\csname Old examplesnameUp\endcsname -\section {Additional examples using \xinttoolsname or \xintexprname or both} -\RaisedLabel{sec:examples} - -Note: \xintexprname.sty automatically loads \xinttoolsname.sty. - -The examples given here start to feel dated and are currently in need of some -rewrite to better illustrate newer features of the package. - - -\localtableofcontents - -\subsection{More examples with dummy variables} -\label{ssec:moredummies} - -These examples were first added to this manual at the time of the |1.1| -release (|2014/10/29|). - -\begin{everbatim*} -Prime numbers are always cool -\xinttheiiexpr seq((seq((subs((x/:m)?{(m*m>x)?{1}{0}}{-1},m=2n+1)) - ??{break(0)}{omit}{break(1)},n=1++))?{x}{omit}, - x=10001..[2]..10200)\relax -\end{everbatim*} - -The syntax in this last example may look a bit involved (... and it is so I -admit). First |x/:m| computes |x modulo m| (this is the modulo with respect to -floored division). The |(x)?{yes}{no}| construct checks if |x| (which -\emph{must} be within parentheses) is true or false, i.e. non zero or zero. It -then executes either the |yes| or the |no| branch, the non chosen branch is -\emph{not} evaluated. Thus if |m| divides |x| we are in the second (``false'') -branch. This gives a |-1|. This |-1| is the argument to a |??| branch which is -of the type |(y)??{y<0}{y=0}{y>0}|, thus here the |y<0|, i.e., |break(0)| is -chosen. This |0| is thus given to another |?| which consequently chooses -|omit|, hence the number is not kept in the list. The numbers which survive -are the prime numbers. - -\begin{everbatim*} -The first Fibonacci number beyond |2^64| bound is -\xinttheiiexpr subs(iterr(0,1;(@1>N)?{break(i)}{@1+@2},i=1++),N=2^64)\relax{} -and the previous number was its index. -\end{everbatim*} - -% A006877 In the `3x+1' problem, these values for the starting value set new -% records for number of steps to reach 1. (Formerly M0748) 14 1, 2, 3, 6, 7, -% 9, 18, 25, 27, 54, 73, 97, 129, 171, 231, 313, 327, 649, 703, 871, 1161, -% 2223, 2463, 2919, 3711, 6171, 10971, 13255, 17647, 23529, 26623, 34239, -% 35655, 52527, 77031, 106239, 142587, 156159, 216367, 230631, 410011, 511935, -% 626331, 837799 - -One more recursion: -\begin{everbatim*} -\def\syr #1{\xinttheiiexpr rseq(#1; (@<=1)?{break(i)}{odd(@)?{3@+1}{@//2}},i=0++)\relax} -The 3x+1 problem: \syr{231}\par -\end{everbatim*} - -OK, a final one: -\begin{everbatim*} -\def\syrMax #1{\xinttheiiexpr iterr(#1,#1;even(i)? - {(@2<=1)?{break(i/2)}{odd(@2)?{3@2+1}{@2//2}}} - {(@1>@2)?{@1}{@2}},i=0++)\relax } -With initial value 1161, the maximal number attained is \syrMax{1161} and that latter -number is the number of steps which was needed to reach 1.\par -\end{everbatim*} - -Look at the - \hyperlink{BrentSalamin}{Brent-Salamin algorithm implementation} for a more - interesting recursion. - -% \begin{everbatim*} -% \newcommand\Factors [1]{\xinttheiiexpr -% subs(seq((i/:3=1)?{omit}{[L][i]},i=0..len(L)-1), -% L=rseq(#1;(p^2>[@][0])?{([@][0]>1)?{break(1,[@][0],1)}{abort}} -% {(([@][0])/:p)?{omit} -% {iter(([@][0])//p; (@/:p)?{break(@,p,e)}{@//p},e=1++)}},p=2++))\relax } -% \Factors {41^4*59^2*29^3*13^5*17^8*29^2*59^4*37^6} -% \end{everbatim*} - -% This might look a bit scary, I admit.% -% % -% \footnote{Look at the -% \hyperlink{BrentSalamin}{Brent-Salamin algorithm implementation} for a much -% saner example.} -% % - -% \xintexprname has minimal tools and -% is obstinate about doing everything expandably! We are hampered by absence of a -% notion of ``nuple''. The algorithm divides |N| by |2| until no more possible, -% then by |3|, then by |4| (which is silly), then by |5|, then by |6| (silly -% again), \dots. - -% The variable |L=rseq(#1;...)| expands, if one follows the steps, to a comma -% separated list starting with the initial (evaluated) |N=#1| and then -% pseudo-triplets where the first item is |N| trimmed of small primes, the -% second item is the last prime divisor found, and the third item is its -% exponent in original |N|. - -% The algorithm needs to keep handy the last computed quotient by prime powers, -% hence all of them, but at the very end it will be cleaner to get rid of them -% (this corresponds to the first line in the code above). This is achieved in a -% cumbersome inefficient way; indeed each item extraction |[L][i]| is costly: it -% is not like accessing an array stored in memory, due to expandability, nothing -% can be stored in memory! Nevertheless, this step could be done here in a far -% less inefficient manner if there was a variant of |seq| which, in the spirit -% of \csbxint{iloopindex}, would know how many steps it had been through so far. -% This is a feature to be added to |\xintexpr|! (as well as a |++| construct -% allowing a non unit step). - -% Notice that in |iter(([@][0])//p;| the |@| refers to the previous triplet (or -% in the first step to |N|), but the latter |@| showing up in |(@/:p)?| refers -% to the previous value computed by |iter|. - -% \begin{snugframed} -% Parentheses are essential in |..([y][0])| else the parser will see |..[| and -% end up in ultimate confusion, and also in |([@][0])/:p| else the parser will -% see the itemwise operator |]/| on lists and again be very confused (I could -% implement a |]/:| on lists, but in this situation this would also be very -% confusing to the parser.) -% \end{snugframed} - -% See \autoref{ssec:factorize} for a routine |\Factorize| written directly with -% \xintname macros. Last time I checked |\Factors| was about seven times slower -% than |\Factorize| in test cases such as -% |16246355912554185673266068721806243461403654781833| and others. Among the -% various things explaining the speed difference, there is fact that the -% |\Factorize| algorithm step by increments of two, not one, and also it divides -% only once, obtaining quotient and remainder in one go. These two things -% already make for a speed-up factor of about four. Thus, |\Factors| is not -% completely inefficient in comparison, and was quite easier to come up with -% than |\Factorize|. - -\subsection{Completely expandable prime test} -\label{ssec:primesI} - -Let us now construct a completely expandable macro which returns $1$ if its -given input is prime and $0$ if not: -\everb|@ -\def\remainder #1#2{\the\numexpr #1-(#1/#2)*#2\relax } -\def\IsPrime #1% - {\xintANDof {\xintApply {\remainder {#1}}{\xintSeq {2}{\xintiiSqrt{#1}}}}} -| - -This uses \csbxint{iiSqrt} and assumes its input is at least $5$. Rather than -\xintname's own \csbxint{iiRem} we used a quicker |\numexpr| expression as we -are dealing with short integers. Also we used \csbxint{ANDof} which will -return $1$ only if all the items are non-zero. The macro is a bit -silly with an even input, ok, let's enhance it to detect an even input: -\everb|@ -\def\IsPrime #1% - {\xintiiifOdd {#1} - {\xintANDof % odd case - {\xintApply {\remainder {#1}} - {\xintSeq [2]{3}{\xintiiSqrt{#1}}}% - }% - } - {\xintifEq {#1}{2}{1}{0}}% - } -| - -We used the \xintname expandable tests (on big integers or fractions) -in order for |\IsPrime| to be \fexpan dable. - -Our integers are short, but without |\expandafter|'s with -|\@firstoftwo|, % @ n'est plus actif dans le dtx 1.1 ! -or some other related techniques, -direct use of |\ifnum..\fi| tests is dangerous. So to make the macro more -efficient we are going to use the expandable tests provided by the package -\href{http://ctan.org/pkg/etoolbox}{etoolbox}% -% -\footnote{\url{http://ctan.org/pkg/etoolbox}}. -% -The macro becomes: -% -\everb|@ -\def\IsPrime #1% - {\ifnumodd {#1} - {\xintANDof % odd case - {\xintApply {\remainder {#1}}{\xintSeq [2]{3}{\xintiiSqrt{#1}}}}} - {\ifnumequal {#1}{2}{1}{0}}} -| - -In the odd case however we have to assume the integer is at least $7$, as -|\xintSeq| generates an empty list if |#1=3| or |5|, and |\xintANDof| returns -$1$ when supplied an empty list. Let us ease up a bit |\xintANDof|'s work by -letting it work on only $0$'s and $1$'s. We could use: -% -\everb|@ -\def\IsNotDivisibleBy #1#2% - {\ifnum\numexpr #1-(#1/#2)*#2=0 \expandafter 0\else \expandafter1\fi} -| -\noindent -where the |\expandafter|'s are crucial for this macro to be \fexpan dable and -hence work within the applied \csbxint{ANDof}. Anyhow, now that we have loaded -\href{http://ctan.org/pkg/etoolbox}{etoolbox}, we might as well use: -% -\everb|@ -\newcommand{\IsNotDivisibleBy}[2]{\ifnumequal{#1-(#1/#2)*#2}{0}{0}{1}} -| -\noindent -Let us enhance our prime macro to work also on the small primes: -\everb|@ -\newcommand{\IsPrime}[1] % returns 1 if #1 is prime, and 0 if not - {\ifnumodd {#1} - {\ifnumless {#1}{8} - {\ifnumequal{#1}{1}{0}{1}}% 3,5,7 are primes - {\xintANDof - {\xintApply - { \IsNotDivisibleBy {#1}}{\xintSeq [2]{3}{\xintiiSqrt{#1}}}}% - }}% END OF THE ODD BRANCH - {\ifnumequal {#1}{2}{1}{0}}% EVEN BRANCH -} -| - -The input is still assumed positive. There is a deliberate blank before -\csa{IsNotDivisibleBy} to use this feature of \csbxint{Apply}: a space stops the -expansion of the applied macro (and disappears). This expansion will be done by -\csbxint{ANDof}, which has been designed to skip everything as soon as it finds -a false (i.e. zero) input. This way, the efficiency is considerably improved. - -We did generate via the \csbxint{Seq} too many potential divisors though. Later -sections give two variants: one with \csbxint{iloop} (\autoref{ssec:primesII}) -which is still expandable and another one (\autoref{ssec:primesIII}) which is a -close variant of the |\IsPrime| code above but with the \csbxint{For} loop, thus -breaking expandability. The \hyperref[ssec:primesII]{xintiloop variant} does not -first evaluate the integer square root, the \hyperref[ssec:primesIII]{xintFor - variant} still does. I did not compare their efficiencies. - - -Let us construct with this expandable primality test a table of the prime -numbers up to $1000$. We need to count how many we have in order to know how -many tab stops one shoud add in the last row.% -% -\footnote{although a tabular row may have less tabs than in the - preamble, there is a problem with the \char`\|\space\space vertical - rule, if one does that.} -% -There is some subtlety for this -last row. Turns out to be better to insert a |\\| only when we know for sure we -are starting a new row; this is how we have designed the |\OneCell| macro. And -for the last row, there are many ways, we use again |\xintApplyUnbraced| but -with a macro which gobbles its argument and replaces it with a tabulation -character. The \csbxint{For*} macro would be more elegant here. -% -\everb?@ -\newcounter{primecount} -\newcounter{cellcount} -\newcommand{\NbOfColumns}{13} -\newcommand{\OneCell}[1]{% - \ifnumequal{\IsPrime{#1}}{1} - {\stepcounter{primecount} - \ifnumequal{\value{cellcount}}{\NbOfColumns} - {\\\setcounter{cellcount}{1}#1} - {&\stepcounter{cellcount}#1}% - } % was prime - {}% not a prime, nothing to do -} -\newcommand{\OneTab}[1]{&} -\begin{tabular}{|*{\NbOfColumns}{r}|} -\hline -2 \setcounter{cellcount}{1}\setcounter{primecount}{1}% - \xintApplyUnbraced \OneCell {\xintSeq [2]{3}{999}}% - \xintApplyUnbraced \OneTab - {\xintSeq [1]{1}{\the\numexpr\NbOfColumns-\value{cellcount}\relax}}% - \\ -\hline -\end{tabular} -There are \arabic{primecount} prime numbers up to 1000. -? - -The table has been put in \hyperref[primesupto1000]{float} which appears -\vpageref{primesupto1000}. -We had to be careful to use in the last row \csbxint{Seq} with its optional -argument |[1]| so as to not generate a decreasing sequence from |1| to |0|, but -really an empty sequence in case the row turns out to already have all its -cells (which doesn't happen here but would with a number of columns dividing -$168$). -% -\newcommand{\IsNotDivisibleBy}[2]{\ifnumequal{#1-(#1/#2)*#2}{0}{0}{1}} - -\newcommand{\IsPrime}[1] - {\ifnumodd {#1} - {\ifnumless {#1}{8} - {\ifnumequal{#1}{1}{0}{1}}% 3,5,7 are primes - {\xintANDof - {\xintApply - { \IsNotDivisibleBy {#1}}{\xintSeq [2]{3}{\xintiiSqrt{#1}}}}% - }}% END OF THE ODD BRANCH - {\ifnumequal {#1}{2}{1}{0}}% EVEN BRANCH -} - -\newcounter{primecount} -\newcounter{cellcount} -\newcommand{\NbOfColumns}{13} -\newcommand{\OneCell}[1] - {\ifnumequal{\IsPrime{#1}}{1} - {\stepcounter{primecount} - \ifnumequal{\value{cellcount}}{\NbOfColumns} - {\\\setcounter{cellcount}{1}#1} - {&\stepcounter{cellcount}#1}% - } % was prime - {}% not a prime nothing to do -} -\newcommand{\OneTab}[1]{&} -\begin{figure*}[ht!] - \centering - \phantomsection\label{primesupto1000} - \begin{tabular}{|*{\NbOfColumns}{r}|} - \hline - 2\setcounter{cellcount}{1}\setcounter{primecount}{1}% - \xintApplyUnbraced \OneCell {\xintSeq [2]{3}{999}}% - \xintApplyUnbraced \OneTab - {\xintSeq [1]{1}{\the\numexpr\NbOfColumns-\value{cellcount}\relax}}% - \\ - \hline - \end{tabular} -\smallskip -\centeredline{There are \arabic{primecount} prime numbers up to 1000.} -\end{figure*} - -\subsection{Another completely expandable prime test} -\label{ssec:primesII} - -The |\IsPrime| macro from \autoref{ssec:primesI} checked expandably if a (short) -integer was prime, here is a partial rewrite using \csbxint{iloop}. We use the -|etoolbox| expandable conditionals for convenience, but not everywhere as -|\xintiloopindex| can not be evaluated while being braced. This is also the -reason why |\xintbreakiloopanddo| is delimited, and the next macro -|\SmallestFactor| which returns the smallest prime factor examplifies that. One -could write more efficient completely expandable routines, the aim here was only -to illustrate use of the general purpose \csbxint{iloop}. A little table giving -the first values of |\SmallestFactor| follows, its coding uses \csbxint{For}, -which is described later; none of this uses count registers. -% - - -\begin{everbatim*} -\let\IsPrime\undefined \let\SmallestFactor\undefined % clean up possible previous mess -\newcommand{\IsPrime}[1] % returns 1 if #1 is prime, and 0 if not - {\ifnumodd {#1} - {\ifnumless {#1}{8} - {\ifnumequal{#1}{1}{0}{1}}% 3,5,7 are primes - {\if - \xintiloop [3+2] - \ifnum#1<\numexpr\xintiloopindex*\xintiloopindex\relax - \expandafter\xintbreakiloopanddo\expandafter1\expandafter.% - \fi - \ifnum#1=\numexpr (#1/\xintiloopindex)*\xintiloopindex\relax - \else - \repeat 00\expandafter0\else\expandafter1\fi - }% - }% END OF THE ODD BRANCH - {\ifnumequal {#1}{2}{1}{0}}% EVEN BRANCH -}% -\catcode`_ 11 -\newcommand{\SmallestFactor}[1] % returns the smallest prime factor of #1>1 - {\ifnumodd {#1} - {\ifnumless {#1}{8} - {#1}% 3,5,7 are primes - {\xintiloop [3+2] - \ifnum#1<\numexpr\xintiloopindex*\xintiloopindex\relax - \xint_afterfi{\xintbreakiloopanddo#1.}% - \fi - \ifnum#1=\numexpr (#1/\xintiloopindex)*\xintiloopindex\relax - \xint_afterfi{\expandafter\xintbreakiloopanddo\xintiloopindex.}% - \fi - \iftrue\repeat - }% - }% END OF THE ODD BRANCH - {2}% EVEN BRANCH -}% -\catcode`_ 8 -{\centering - \begin{tabular}{|c|*{10}c|} - \hline - \xintFor #1 in {0,1,2,3,4,5,6,7,8,9}\do {&\bfseries #1}\\ - \hline - \bfseries 0&--&--&2&3&2&5&2&7&2&3\\ - \xintFor #1 in {1,2,3,4,5,6,7,8,9}\do - {\bfseries #1% - \xintFor #2 in {0,1,2,3,4,5,6,7,8,9}\do - {&\SmallestFactor{#1#2}}\\}% - \hline - \end{tabular}\par -} -\end{everbatim*} - -\subsection{Miller-Rabin Pseudo-Primality expandably} -\label{ssec:PrimesIV} - - -At the time of writing, the code at the link above is still the version from -April 2016 and it needed some hacks to get recursive (pseudo)-functions -defined. Since |1.2h| of |2016/11/20| there is \csbxint{NewFunction} which -allows us here to avoid such internal hacking. - -And since |1.3| of |2018/03/01|, it is possible to use \csbxint{defiifunc} -also for recursive definitions, so we use it here, but we can benefit from it -only for modular exponentiation as the rest of the code uses |iter| or |break| -statements which are not yet compatible with \csbxint{defiifunc}. - -The |isPseudoPrime(n)| is usable in \csbxint{iiexpr}-essions and establishes -if its (positive) argument is a Miller-Rabin PseudoPrime to the bases $2, 3, -5, 7, 11, 13, 17$. If this is true and $n<341550071728321$ (which has 15 -digits) then $n$ really is a prime number. - -Similarly $n=3825123056546413051$ (19 digits) is the smallest composite number -which is a strong pseudo prime for bases $2, 3, 5, 7, 11, 13, 17, 19$ and -$23$. It is easy to extend the code below to include these additional tests -(we could make the list of tested bases an argument too, now that I think -about it.) - -For more information see - \centeredline{\url{https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test#Deterministic_variants_of_the_test}} - and -\centeredline{\url{http://primes.utm.edu/prove/prove2_3.html}} - -In particular, according to \textsc{Jaeschke} \emph{On strong pseudoprimes to - several bases,} Math. Comp., 61 (1993) 915-926, if $n < 4,759,123,141$ it is -enough to establish Rabin-Miller pseudo-primality to bases $a = 2, 7, 61$ to -prove that $n$ is prime. This range is enough for \TeX\ numbers and we could -then write a very fast expandable primality test for such numbers using only -|\numexpr|. Left as an exercise\dots - -\begin{everbatim*} -% I -------------------------------- Modular Exponentiation -% Computes x^m modulo n (with m non negative). -% We will always use it with 1 < x < n - -\xintdefiifunc powmod_a(x, m, n) := - ifone(m, - % m=1, return x modulo n - x /: n, - % m > 1 test if odd or even and do recursive call - if(odd(m), (x*sqr(powmod_a(x, m//2, n))) /: n, - sqr(powmod_a(x, m//2, n)) /: n - ) - ); -\xintdefiifunc powmod(x, m, n) := if(m, powmod_a(x, m, n), 1); - - -% For comparison here are the underlying support macros defined by -% \xintdefiifunc from the code above (since 1.3a): (with linebreaks added by -% TeX when writing to the log) - -% Function powmod_a for \xintiiexpr parser associated to \XINT_iiexpr_userfun -% c_powmod_a with meaning macro:#1#2#3->\xintiiifOne {#2}{\xintiiMod {#1}{#3}}{\x -% intiiifNotZero {\xintiiOdd {#2}}{\xintiiMod {\xintiiMul {#1}{\xintiiSqr {\xintE -% xpandArgs {XINT_iiexpr_userfunc_powmod_a}{{#1}{\xintiiDivFloor {#2}{2}}{#3}}}}} -% {#3}}{\xintiiMod {\xintiiSqr {\xintExpandArgs {XINT_iiexpr_userfunc_powmod_a}{{ -% #1}{\xintiiDivFloor {#2}{2}}{#3}}}}{#3}}} - -% Function powmod for \xintiiexpr parser associated to \XINT_iiexpr_userfunc_ -% powmod with meaning macro:#1#2#3->\xintiiifNotZero {#2}{\xintExpandArgs {XINT_i -% iexpr_userfunc_powmod_a}{{#1}{#2}{#3}}}{1} - -% II ------------------------------ Miller-Rabin compositeness witness - -% n=2^k m + 1 with m odd and k at least 1 - -% Choose 1<x<n. -% compute y=x^m modulo n -% if equals 1 we can't say anything -% if equals n-1 we can't say anything -% else put j=1, and -% compute repeatedly the square, incrementing j by 1 each time, -% thus always we have y^{2^{j-1}} -% -> if at some point n-1 mod n found, we can't say anything and break out -% -> if however we never find n-1 mod n before reaching -% z=y^{2^{k-1}} with j=k -% we then have z^2=x^{n-1}. - % Suppose z is not -1 mod n. If z^2 is 1 mod n, then n can be prime only if - % z is 1 mod n, and we can go back up, until initial y, and we have already - % excluded y=1. Thus if z is not -1 mod n and z^2 is 1 then n is not prime. - % But if z^2 is not 1, then n is not prime by Fermat. Hence (z not -1 mod n) - % implies (n is composite). (Miller test) - -% let's use again xintexpr indecipherable (except to author) syntax. Of course -% doing it with macros only would be faster. - -% Here \xintdefiifunc is not usable because not compatible with iter, break, ... -% but \xintNewFunction comes to the rescue. - -\xintNewFunction{isCompositeWitness}[4]{% x=#1, n=#2, m=#3, k=#4 - subs((y==1)?{0} - {iter(y;(j=#4)?{break(!(@==#2-1))} - {(@==#2-1)?{break(0)}{sqr(@)/:#2}},j=1++)} - ,y=powmod(#1,#3,#2))} - -% added note (2018/03/07) it is possible in the above that m=#3 is never -% zero, so we should rather call powmod_a for a small gain, but I don't -% have time to re-read the code comments and settle this. - -% III ------------------------------------- Strong Pseudo Primes - -% cf -% http://oeis.org/A014233 -% <http://mathworld.wolfram.com/Rabin-MillerStrongPseudoprimeTest.html> -% <http://mathworld.wolfram.com/StrongPseudoprime.html> - -% check if positive integer <49 si a prime. -% 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47 -\def\IsVerySmallPrime #1% - {\ifnum#1=1 \xintdothis0\fi - \ifnum#1=2 \xintdothis1\fi - \ifnum#1=3 \xintdothis1\fi - \ifnum#1=5 \xintdothis1\fi - \ifnum#1=\numexpr (#1/2)*2\relax\xintdothis0\fi - \ifnum#1=\numexpr (#1/3)*3\relax\xintdothis0\fi - \ifnum#1=\numexpr (#1/5)*5\relax\xintdothis0\fi - \xintorthat 1} - -\xintNewFunction{isPseudoPrime}[1]{% n = #1 - (#1<49)?% use ? syntax to evaluate only what is needed - {\IsVerySmallPrime{\xintthe#1}}% macro needs to be fed with #1 unlocked. - {(even(#1))? - {0} - {subs(% - % L expands to two values m, k hence isCompositeWitness does get - % its four variables x, n, m, k - isCompositeWitness(2, #1, L)? - {0}% - {isCompositeWitness(3, #1, L)? - {0}% - {isCompositeWitness(5, #1, L)? - {0}% - {isCompositeWitness(7, #1, L)? - {0}% -% above enough for N<3215031751 hence all TeX numbers - {isCompositeWitness(11, #1, L)? - {0}% -% above enough for N<2152302898747, hence all 12-digits numbers - {isCompositeWitness(13, #1, L)? - {0}% -% above enough for N<3474749660383 - {isCompositeWitness(17, #1, L)? - {0}% -% above enough for N<341550071728321 - {1}% - }% not needed to comment-out end of lines spaces inside - }% \xintexpr but this is too much of a habit for me with TeX! - }% I left some after the ? characters. - }% - }% - }% this computes (m, k) such that n = 2^k m + 1, m odd, k>=1 - , L=iter(#1//2;(even(@))?{@//2}{break(@,k)},k=1++))% - }% - }% -} - -% if needed: -%\def\IsPseudoPrime #1{\xinttheiiexpr isPseudoPrime(#1)\relax} - -\noindent The smallest prime number at least equal to 3141592653589 is -\xinttheiiexpr - seq(isPseudoPrime(3141592653589+n)? - {break(3141592653589+n)}{omit}, n=0++)\relax. -% we could not use 3141592653589++ syntax because it works only with TeX numbers -\par -\end{everbatim*} - - - - - -\subsection{A table of factorizations} -\label{ssec:factorizationtable} - -As one more example with \csbxint{iloop} let us use an alignment to display the -factorization of some numbers. The loop will actually only play a minor r\^ole -here, just handling the row index, the row contents being almost entirely -produced via a macro |\factorize|. The factorizing macro does not use -|\xintiloop| as it didn't appear to be the convenient tool. As |\factorize| will -have to be used on |\xintiloopindex|, it has been defined as a delimited macro. - -To spare some fractions of a second in the compilation time of this document -(which has many many other things to do), \number"7FFFFFED{} and -\number"7FFFFFFF, which turn out to be prime numbers, are not given to -|factorize| but just typeset directly; this illustrates use of -\csbxint{iloopskiptonext}. - -The code next generates a \hyperref[floatfactorize]{table} which has -been made into a float appearing \vpageref{floatfactorize}. Here is now -the code for factorization; the conditionals use the package provided -|\xint_firstoftwo| and |\xint_secondoftwo|, one could have employed -rather \LaTeX{}'s own |\@firstoftwo| and |\@secondoftwo|, or, simpler -still in \LaTeX{} context, the |\ifnumequal|, |\ifnumless| \dots, -utilities from the package |etoolbox| which do exactly that under the -hood. Only \TeX{} acceptable numbers are treated here, but it would be -easy to make a translation and use the \xintname macros, thus extending -the scope to big numbers; naturally up to a cost in speed. - -The reason for some strange looking expressions is to avoid arithmetic overflow. - -\begin{everbatim*} -\catcode`_ 11 -\def\abortfactorize #1\xint_secondoftwo\fi #2#3{\fi} - -\def\factorize #1.{\ifnum#1=1 \abortfactorize\fi - \ifnum\numexpr #1-2=\numexpr ((#1/2)-1)*2\relax - \expandafter\xint_firstoftwo - \else\expandafter\xint_secondoftwo - \fi - {2&\expandafter\factorize\the\numexpr#1/2.}% - {\factorize_b #1.3.}}% - -\def\factorize_b #1.#2.{\ifnum#1=1 \abortfactorize\fi - \ifnum\numexpr #1-(#2-1)*#2<#2 - #1\abortfactorize - \fi - \ifnum \numexpr #1-#2=\numexpr ((#1/#2)-1)*#2\relax - \expandafter\xint_firstoftwo - \else\expandafter\xint_secondoftwo - \fi - {#2&\expandafter\factorize_b\the\numexpr#1/#2.#2.}% - {\expandafter\factorize_b\the\numexpr #1\expandafter.% - \the\numexpr #2+2.}}% -\catcode`_ 8 -\begin{figure*}[ht!] -\centering\phantomsection\label{floatfactorize}\normalcolor -\tabskip1ex -\centeredline{\vbox{\halign {\hfil\strut#\hfil&&\hfil#\hfil\cr\noalign{\hrule} - \xintiloop ["7FFFFFE0+1] - \expandafter\bfseries\xintiloopindex & - \ifnum\xintiloopindex="7FFFFFED - \number"7FFFFFED\cr\noalign{\hrule} - \expandafter\xintiloopskiptonext - \fi - \expandafter\factorize\xintiloopindex.\cr\noalign{\hrule} - \ifnum\xintiloopindex<"7FFFFFFE - \repeat - \bfseries \number"7FFFFFFF&\number "7FFFFFFF\cr\noalign{\hrule} -}}} -\centeredline{A table of factorizations} -\end{figure*} -\end{everbatim*} - -\subsection{Another table of primes} -\label{ssec:primesIII} - -As a further example, let us dynamically generate a tabular with the first $50$ -prime numbers after $12345$. First we need a macro to test if a (short) number -is prime. Such a completely expandable macro was given in \autoref{ssec:primesI}, -here we consider a variant which will be slightly more efficient. This new -|\IsPrime| has two parameters. The first one is a macro which it redefines to -expand to the result of the primality test applied to the second argument. For -convenience we use the \href{http://ctan.org/pkg/etoolbox}{etoolbox} wrappers to -various |\ifnum| tests, although here there isn't anymore the constraint of -complete expandability (but using explicit |\if..\fi| in tabulars has its -quirks); equivalent tests are provided by \xintname, but they have some overhead -as they are able to deal with arbitrarily big integers. - -\def\IsPrime #1#2% -{\edef\TheNumber {\the\numexpr #2}% positive integer - \ifnumodd {\TheNumber} - {\ifnumgreater {\TheNumber}{1} - {\edef\ItsSquareRoot{\xintiiSqrt \TheNumber}% - \xintFor ##1 in {\xintintegers [3+2]}\do - {\ifnumgreater {##1}{\ItsSquareRoot} - {\def#1{1}\xintBreakFor} - {}% - \ifnumequal {\TheNumber}{(\TheNumber/##1)*##1} - {\def#1{0}\xintBreakFor } - {}% - }} - {\def#1{0}}}% 1 is not prime - {\ifnumequal {\TheNumber}{2}{\def#1{1}}{\def#1{0}}}% -}% - -\everb|@ -\def\IsPrime #1#2% """color[named]{PineGreen}#1=\Result, #2=tested number (assumed >0).;! -{\edef\TheNumber {\the\numexpr #2}%"""color[named]{PineGreen} hence #2 may be a count or \numexpr.;! - \ifnumodd {\TheNumber} - {\ifnumgreater {\TheNumber}{1} - {\edef\ItsSquareRoot{\xintiiSqrt \TheNumber}% - \xintFor """color{red}##1;! in {"""color{red}\xintintegers;! [3+2]}\do - {\ifnumgreater {"""color{red}##1;!}{\ItsSquareRoot} """color[named]{PineGreen}% "textcolor{red}{##1} is a \numexpr.;! - {\def#1{1}\xintBreakFor} - {}% - \ifnumequal {\TheNumber}{(\TheNumber/##1)*##1} - {\def#1{0}\xintBreakFor } - {}% - }} - {\def#1{0}}}% 1 is not prime - {\ifnumequal {\TheNumber}{2}{\def#1{1}}{\def#1{0}}}% -} -| - -As we used \csbxint{For} inside a macro we had to double the |#| in its |#1| -parameter. Here is now the code which creates the prime table (the table has -been put in a \hyperref[primes]{float}, which should be found on page -\pageref{primes}): - -\everb?@ -\newcounter{primecount} -\newcounter{cellcount} -\begin{figure*}[ht!] - \centering - \begin{tabular}{|*{7}c|} - \hline - \setcounter{primecount}{0}\setcounter{cellcount}{0}% - \xintFor """color{red}#1;! in {"""color{red}\xintintegers;! [12345+2]} \do -"""color[named]{PineGreen}% "textcolor{red}{#1} is a \numexpr.;! - {\IsPrime\Result{#1}% - \ifnumgreater{\Result}{0} - {\stepcounter{primecount}% - \stepcounter{cellcount}% - \ifnumequal {\value{cellcount}}{7} - {"""color{red}\the#1;! \\\setcounter{cellcount}{0}} - {"""color{red}\the#1;! &}} - {}% - \ifnumequal {\value{primecount}}{50} - {\xintBreakForAndDo - {\multicolumn {6}{l|}{These are the first 50 primes after 12345.}\\}} - {}% - }\hline -\end{tabular} -\end{figure*} -? - -\begin{figure*}[ht!] - \centering\phantomsection\label{primes} - \begin{tabular}{|*{7}c|} - \hline - \setcounter{primecount}{0}\setcounter{cellcount}{0}% - \xintFor #1 in {\xintintegers [12345+2]} \do - {\IsPrime\Result{#1}% - \ifnumgreater{\Result}{0} - {\stepcounter{primecount}% - \stepcounter{cellcount}% - \ifnumequal {\value{cellcount}}{7} - {\the#1 \\\setcounter{cellcount}{0}} - {\the#1 &}} - {}% - \ifnumequal {\value{primecount}}{50} - {\xintBreakForAndDo - {\multicolumn {6}{l|}{These are the first 50 primes after 12345.}\\}} - {}% - }\hline -\end{tabular} -\end{figure*} - -\subsection{Factorizing again} -\label{ssec:factorize} - -Here is an \fexpan dable macro which computes the factors of an integer. It -uses the \xintname macros only. -\begin{everbatim*} -\catcode`\@ 11 -\let\factorize\relax -\newcommand\Factorize [1] - {\romannumeral0\expandafter\factorize\expandafter{\romannumeral-`0#1}}% -\newcommand\factorize [1]{\xintiiifOne{#1}{ 1}{\factors@a #1.{#1};}}% -\def\factors@a #1.{\xintiiifOdd{#1} - {\factors@c 3.#1.}% - {\expandafter\factors@b \expandafter1\expandafter.\romannumeral0\xinthalf{#1}.}}% -\def\factors@b #1.#2.{\xintiiifOne{#2} - {\factors@end {2, #1}}% - {\xintiiifOdd{#2}{\factors@c 3.#2.{2, #1}}% - {\expandafter\factors@b \the\numexpr #1+\@ne\expandafter.% - \romannumeral0\xinthalf{#2}.}}% -}% -\def\factors@c #1.#2.{% - \expandafter\factors@d\romannumeral0\xintiidivision {#2}{#1}{#1}{#2}% -}% -\def\factors@d #1#2#3#4{\xintiiifNotZero{#2} - {\xintiiifGt{#3}{#1} - {\factors@end {#4, 1}}% ultimate quotient is a prime with power 1 - {\expandafter\factors@c\the\numexpr #3+\tw@.#4.}}% - {\factors@e 1.#3.#1.}% -}% -\def\factors@e #1.#2.#3.{\xintiiifOne{#3} - {\factors@end {#2, #1}}% - {\expandafter\factors@f\romannumeral0\xintiidivision {#3}{#2}{#1}{#2}{#3}}% -}% -\def\factors@f #1#2#3#4#5{\xintiiifNotZero{#2} - {\expandafter\factors@c\the\numexpr #4+\tw@.#5.{#4, #3}}% - {\expandafter\factors@e\the\numexpr #3+\@ne.#4.#1.}% -}% -\def\factors@end #1;{\xintlistwithsep{, }{\xintRevWithBraces {#1}}}% -\catcode`@ 12 -\end{everbatim*} -The macro will be acceptably efficient only with numbers having somewhat small -prime factors. -\begin{everbatim} -\Factorize{16246355912554185673266068721806243461403654781833} -\end{everbatim} -\begingroup\fdef\Z -{\Factorize{16246355912554185673266068721806243461403654781833}} -\noindent{\small\dtt{\Z}} - - -It puts a little stress on the input save stack in order -not be bothered with previously gathered things.\footnote{2015/11/18 I have - not revisited this code for a long time, and perhaps I could improve it now - with some new techniques.} - -Its output is a comma separated list with the number first, then its prime -factors with multiplicity. Let's produce something prettier: -\begin{everbatim*} -\catcode`_ 11 -\def\ShowFactors #1{\expandafter\ShowFactors_a\romannumeral-`0\Factorize{#1},\relax,\relax,} -\def\ShowFactors_a #1,{#1=\ShowFactors_b} -\def\ShowFactors_b #1,#2,{\if\relax#1\else#1^{#2}\expandafter\ShowFactors_b\fi} -\catcode`_ 8 -\end{everbatim*} -\begin{everbatim} -$$\ShowFactors{16246355912554185673266068721806243461403654781833}$$ -\end{everbatim} -$$\csname ShowFactors_a\expandafter\endcsname\Z,\relax,\relax,$$ -\endgroup - -If we only considered small integers, we could write pure |\numexpr| methods -which would be very much faster (especially if we had a table of small primes -prepared first) but still ridiculously slow compared to any non expandable -implementation, not to mention use of programming languages directly accessing -the CPU registers\dots - -\subsection{The Quick Sort algorithm illustrated}\label{ssec:quicksort} - -First a completely expandable macro which sorts a comma separated list of -numbers.% -% -\footnote{The code in earlier versions of this manual handled inputs composed - of braced items. I have switched to comma separated inputs on the occasion - of (link removed) - The version here is like - |code 3| on - (link removed) (which is about |3x| faster - than the earlier code it replaced in this manual) with a modification to - make it more efficient if the data has many repeated values. - - A faster routine (for sorting hundreds of values) is provided as |code 6| at - the link mentioned in the footnote, it is based on Merge Sort, but limited - to inputs which one can handle as \TeX{} dimensions.% - - This |code 6| could be extended to handle more general numbers, as - acceptable by \xintfracname. I have also written a non expandable version, - which is even faster, but this matters really only when handling hundreds or - rather thousands of values.} -% - -The |\QSx| macro expands its list argument, which may thus be a macro; its -comma separated items must expand to integers or decimal numbers or fractions -or scientific notation as acceptable to \xintfracname, but if an item is -itself some (expandable) macro, this macro will be expanded each time the item -is considered in a comparison test! This is actually good if the macro expands -in one step to the digits, and there are many many digits, but bad if the macro -needs to do many computations. Thus |\QSx| should be used with either explicit -numbers or with items being macros expanding in one step to the numbers -(particularly if these numbers are very big). - -If the interest is only in \TeX{} integers, then one should replace the -|\xintifCmp| macro with a suitable conditional, possibly helped by tools such as -|\ifnumgreater|, |\ifnumequal| and |\ifnumless| from -\href{http://ctan.org/pkg/etoolbox}{etoolbox} (\LaTeX{} only; I didn't see a -direct equivalent to |\xintifCmp|.) Or, if we are dealing with decimal numbers -with at most four+four digits, then one should use suitable |\ifdim| tests. -Naturally this will boost consequently the speed, from having skipped all the -overhead in parsing fractions and scientific numbers as are acceptable by -\xintfracname macros, and subsequent treatment. - -\begin{everbatim*} -% THE QUICK SORT ALGORITHM EXPANDABLY -% \usepackage{xintfrac} in the preamble (latex) -\makeatletter -% use extra safe delimiters -\catcode`! 3 \catcode`? 3 -\def\QSx {\romannumeral0\qsx }% -% first we check if empty list (else \qsx@finish will not find a comma) -\def\qsx #1{\expandafter\qsx@a\romannumeral-`0#1,!,?}% -\def\qsx@a #1{\ifx,#1\expandafter\qsx@abort\else - \expandafter\qsx@start\fi #1}% -\def\qsx@abort #1?{ }% -\def\qsx@start {\expandafter\qsx@finish\romannumeral0\qsx@b,}% -\def\qsx@finish ,#1{ #1}% -% -% we check if empty of single and if not pick up the first as Pivot: -\def\qsx@b ,#1#2,#3{\ifx?#3\xintdothis\qsx@empty\fi - \ifx!#3\xintdothis\qsx@single\fi - \xintorthat\qsx@separate {#1#2}{}{}{#1#2}#3}% -\def\qsx@empty #1#2#3#4#5{ }% -\def\qsx@single #1#2#3#4#5?{, #4}% -\def\qsx@separate #1#2#3#4#5#6,% -{% - \ifx!#5\expandafter\qsx@separate@done\fi - \xintifCmp {#5#6}{#4}% - \qsx@separate@appendtosmaller - \qsx@separate@appendtoequal - \qsx@separate@appendtogreater {#5#6}{#1}{#2}{#3}{#4}% -}% -% -\def\qsx@separate@appendtoequal #1#2{\qsx@separate {#2,#1}}% -\def\qsx@separate@appendtogreater #1#2#3{\qsx@separate {#2}{#3,#1}}% -\def\qsx@separate@appendtosmaller #1#2#3#4{\qsx@separate {#2}{#3}{#4,#1}}% -% -\def\qsx@separate@done\xintifCmp #1% - \qsx@separate@appendtosmaller - \qsx@separate@appendtoequal - \qsx@separate@appendtogreater #2#3#4#5#6#7?% -{% - \expandafter\qsx@f\expandafter {\romannumeral0\qsx@b #4,!,?}{\qsx@b #5,!,?}{#3}% -}% -% -\def\qsx@f #1#2#3{#2, #3#1}% -% -\catcode`! 12 \catcode`? 12 -\makeatother - -% EXAMPLE -\begingroup -\edef\z {\QSx {1.0, 0.5, 0.3, 1.5, 1.8, 2.0, 1.7, 0.4, 1.2, 1.4, - 1.3, 1.1, 0.7, 1.6, 0.6, 0.9, 0.8, 0.2, 0.1, 1.9}} -\meaning\z - -\def\a {3.123456789123456789}\def\b {3.123456789123456788} -\def\c {3.123456789123456790}\def\d {3.123456789123456787} -\oodef\z {\QSx { \a, \b, \c, \d}}% -% The space before \a to let it not be expanded during the conversion from CSV -% values to List. The \oodef expands exactly twice (via a bunch of \expandafter's) -\meaning\z -\endgroup -\end{everbatim*} (the spaces after \string\d, etc... come from the use of the -|\meaning| primitive.) - -The choice of pivot as first element is bad if the list is already almost -sorted. Let's add a variant which will pick up the pivot index randomly. The -previous routine worked also internally with comma separated lists, but for a -change this one will use internally lists of braced items (the initial -conversion via \csbxint{CSVtoList} handles all potential spurious space -problems). - -\unless\ifxetex % pour tester compilation de xint.dtx avec xetex qui n'a pas - % \pdfuniformdeviate -\begin{everbatim*} -% QuickSort expandably on comma separated values with random choice of pivots -% ====> Requires availability of \pdfuniformdeviate <==== -% \usepackage{xintfrac, xinttools} in preamble -\makeatletter -\def\QSx {\romannumeral0\qsx }% This is a f-expandable macro. -% This converts from comma separated values on input and back on output. -% **** NOTE: these steps (and the other ones too, actually) are costly if input -% has thousands of items. -\def\qsx #1{\xintlistwithsep{, }% - {\expandafter\qsx@sort@a\expandafter{\romannumeral0\xintcsvtolist{#1}}}}% -% -% we check if empty or single or double and if not pick up the first as Pivot: -\def\qsx@sort@a #1% - {\expandafter\qsx@sort@b\expandafter{\romannumeral0\xintlength{#1}}{#1}}% -\def\qsx@sort@b #1{\ifcase #1 - \expandafter\qsx@sort@empty - \or\expandafter\qsx@sort@single - \or\expandafter\qsx@sort@double - \else\expandafter\qsx@sort@c\fi {#1}}% -\def\qsx@sort@empty #1#2{ }% -\def\qsx@sort@single #1#2{#2}% -\catcode`_ 11 -\def\qsx@sort@double #1#2{\xintifGt #2{\xint_exchangetwo_keepbraces}{}#2}% -\catcode`_ 8 -\def\qsx@sort@c #1#2{% - \expandafter\qsx@sort@sep@a\expandafter - {\romannumeral0\xintnthelt{\pdfuniformdeviate #1+\@ne}{#2}}#2?}% -\def\qsx@sort@sep@a #1{\qsx@sort@sep@loop {}{}{}{#1}}% -\def\qsx@sort@sep@loop #1#2#3#4#5% -{% - \ifx?#5\expandafter\qsx@sort@sep@done\fi - \xintifCmp {#5}{#4}% - \qsx@sort@sep@appendtosmaller - \qsx@sort@sep@appendtoequal - \qsx@sort@sep@appendtogreater {#5}{#1}{#2}{#3}{#4}% -}% -% -\def\qsx@sort@sep@appendtoequal #1#2{\qsx@sort@sep@loop {#2{#1}}}% -\def\qsx@sort@sep@appendtogreater #1#2#3{\qsx@sort@sep@loop {#2}{#3{#1}}}% -\def\qsx@sort@sep@appendtosmaller #1#2#3#4{\qsx@sort@sep@loop {#2}{#3}{#4{#1}}}% -% -\def\qsx@sort@sep@done\xintifCmp #1% - \qsx@sort@sep@appendtosmaller - \qsx@sort@sep@appendtoequal - \qsx@sort@sep@appendtogreater #2#3#4#5#6% -{% - \expandafter\qsx@sort@recurse\expandafter - {\romannumeral0\qsx@sort@a {#4}}{\qsx@sort@a {#5}}{#3}% -}% -% -\def\qsx@sort@recurse #1#2#3{#2#3#1}% -% -\makeatother - -% EXAMPLES -\begingroup -\edef\z {\QSx {1.0, 0.5, 0.3, 1.5, 1.8, 2.0, 1.7, 0.4, 1.2, 1.4, - 1.3, 1.1, 0.7, 1.6, 0.6, 0.9, 0.8, 0.2, 0.1, 1.9}} -\meaning\z - -\def\a {3.123456789123456789}\def\b {3.123456789123456788} -\def\c {3.123456789123456790}\def\d {3.123456789123456787} -\oodef\z {\QSx { \a, \b, \c, \d}}% -% The space before \a to let it not be expanded during the conversion from CSV -% values to List. The \oodef expands exactly twice (via a bunch of \expandafter's) -\meaning\z - -\def\somenumbers{% -3997.6421, 8809.9358, 1805.4976, 5673.6478, 3179.1328, 1425.4503, 4417.7691, -2166.9040, 9279.7159, 3797.6992, 8057.1926, 2971.9166, 9372.2699, 9128.4052, -1228.0931, 3859.5459, 8561.7670, 2949.6929, 3512.1873, 1698.3952, 5282.9359, -1055.2154, 8760.8428, 7543.6015, 4934.4302, 7526.2729, 6246.0052, 9512.4667, -7423.1124, 5601.8436, 4433.5361, 9970.4849, 1519.3302, 7944.4953, 4910.7662, -3679.1515, 8167.6824, 2644.4325, 8239.4799, 4595.1908, 1560.2458, 6098.9677, -3116.3850, 9130.5298, 3236.2895, 3177.6830, 5373.1193, 5118.4922, 2743.8513, -8008.5975, 4189.2614, 1883.2764, 9090.9641, 2625.5400, 2899.3257, 9157.1094, -8048.4216, 3875.6233, 5684.3375, 8399.4277, 4528.5308, 6926.7729, 6941.6278, -9745.4137, 1875.1205, 2755.0443, 9161.1524, 9491.1593, 8857.3519, 4290.0451, -2382.4218, 3678.2963, 5647.0379, 1528.7301, 2627.8957, 9007.9860, 1988.5417, -2405.1911, 5065.8063, 5856.2141, 8989.8105, 9349.7840, 9970.3013, 8105.4062, -3041.7779, 5058.0480, 8165.0721, 9637.7196, 1795.0894, 7275.3838, 5997.0429, -7562.6481, 8084.0163, 3481.6319, 8078.8512, 2983.7624, 3925.4026, 4931.5812, -1323.1517, 6253.0945}% - -\oodef\z {\QSx \somenumbers}% produced as a comma+space separated list -% black magic as workaround to the shrinkability of spaces in last line... -\hsize 87\fontcharwd\font`0 -\lccode`~=32 -\lowercase{\def~}{\discretionary{}{}{\kern\fontcharwd\font`0}}\catcode32 13 -\noindent\phantom{000}\scantokens\expandafter{\meaning\z}\par -\endgroup -\end{everbatim*} -\fi % fin de si pas xetex - - -All the previous examples were with numbers which could have been handled via -|\ifdim| tests rather than the \csbxint{ifCmp} macro from \xintfracname; using -|\ifdim| tests would naturally be faster. Even faster routine is |code 6| at -(link removed) which uses |\pdfescapestring| and a -Merge Sort algorithm. - -We then turn to a graphical illustration of the algorithm.% -% -\footnote{I have rewritten (2015/11/21) the routine to do only once (and not thrice) the - needed calls to \csa{xintifCmp}, up to the price of one additional |\edef|, - although due to the context execution time on our side is not an issue and - moreover is anyhow overwhelmed by the TikZ's activities. Simultaneously I - have updated the code. - The - variant with the choice of pivot on the right has more overhead: the reason - is simply that we do not convert the data into an array, but maintain a list - of tokens with self-reorganizing delimiters.} -% -For simplicity the pivot is always chosen as the first list item. Then we also -give a variant which picks up the last item as pivot. -\begin{everbatim*} -% in LaTeX preamble: -% \usepackage{xintfrac, xinttools} -% \usepackage{color} -% or, when using Plain TeX: -% \input xintfrac.sty \input xinttools.sty -% \input color.tex -% -% Color definitions -\definecolor{LEFT}{RGB}{216,195,88} -\definecolor{RIGHT}{RGB}{208,231,153} -\definecolor{INERT}{RGB}{199,200,194} -\definecolor{INERTpiv}{RGB}{237,237,237} -\definecolor{PIVOT}{RGB}{109,8,57} -% Start of macro defintions -\makeatletter -% \catcode`? 3 % a bit too paranoid. Normal ? will do. -% -% argument will never be empty -\def\QS@cmp@a #1{\QS@cmp@b #1??}% -\def\QS@cmp@b #1{\noexpand\QS@sep@A\@ne{#1}\QS@cmp@d {#1}}% -\def\QS@cmp@d #1#2{\ifx ?#2\expandafter\QS@cmp@done\fi - \xintifCmp {#1}{#2}\tw@\@ne\z@{#2}\QS@cmp@d {#1}}% -\def\QS@cmp@done #1?{?}% -% -\def\QS@sep@A #1?{\QSLr\QS@sep@L #1\thr@@?#1\thr@@?#1\thr@@?}% -\def\QS@sep@L #1#2{\ifcase #1{#2}\or\or\else\expandafter\QS@sep@I@start\fi \QS@sep@L}% -\def\QS@sep@I@start\QS@sep@L {\noexpand\empty?\QSIr\QS@sep@I}% -\def\QS@sep@I #1#2{\ifcase#1\or{#2}\or\else\expandafter\QS@sep@R@start\fi\QS@sep@I}% -\def\QS@sep@R@start\QS@sep@I {\noexpand\empty?\QSRr\QS@sep@R}% -\def\QS@sep@R #1#2{\ifcase#1\or\or{#2}\else\expandafter\QS@sep@done\fi\QS@sep@R}% -\def\QS@sep@done\QS@sep@R {\noexpand\empty?}% -% -\def\QS@loop {% - \xintloop - % pivot phase - \def\QS@pivotcount{0}% - \let\QSLr\DecoLEFTwithPivot \let\QSIr \DecoINERT - \let\QSRr\DecoRIGHTwithPivot \let\QSIrr\DecoINERT - \centerline{\QS@list}% - % sorting phase - \ifnum\QS@pivotcount>\z@ - \def\QSLr {\QS@cmp@a}\def\QSRr {\QS@cmp@a}% - \def\QSIr {\QSIrr}\let\QSIrr\relax - \edef\QS@list{\QS@list}% compare - \let\QSLr\relax\let\QSRr\relax\let\QSIr\relax - \edef\QS@list{\QS@list}% separate - \def\QSLr ##1##2?{\ifx\empty##1\else\noexpand \QSLr {{##1}##2}\fi}% - \def\QSIr ##1##2?{\ifx\empty##1\else\noexpand \QSIr {{##1}##2}\fi}% - \def\QSRr ##1##2?{\ifx\empty##1\else\noexpand \QSRr {{##1}##2}\fi}% - \edef\QS@list{\QS@list}% gather - \let\QSLr\DecoLEFT \let\QSRr\DecoRIGHT - \let\QSIr\DecoINERTwithPivot \let\QSIrr\DecoINERT - \centerline{\QS@list}% - \repeat }% -% -% \xintFor* loops handle gracefully empty lists. -\def\DecoLEFT #1{\xintFor* ##1 in {#1} \do {\colorbox{LEFT}{##1}}}% -\def\DecoINERT #1{\xintFor* ##1 in {#1} \do {\colorbox{INERT}{##1}}}% -\def\DecoRIGHT #1{\xintFor* ##1 in {#1} \do {\colorbox{RIGHT}{##1}}}% -\def\DecoPivot #1{\begingroup\color{PIVOT}\advance\fboxsep-\fboxrule\fbox{#1}\endgroup}% -% -\def\DecoLEFTwithPivot #1{\xdef\QS@pivotcount{\the\numexpr\QS@pivotcount+\@ne}% - \xintFor* ##1 in {#1} \do - {\xintifForFirst {\DecoPivot {##1}}{\colorbox{LEFT}{##1}}}}% -\def\DecoINERTwithPivot #1{\xdef\QS@pivotcount{\the\numexpr\QS@pivotcount+\@ne}% - \xintFor* ##1 in {#1} \do - {\xintifForFirst {\colorbox{INERTpiv}{##1}}{\colorbox{INERT}{##1}}}}% -\def\DecoRIGHTwithPivot #1{\xdef\QS@pivotcount{\the\numexpr\QS@pivotcount+\@ne}% - \xintFor* ##1 in {#1} \do - {\xintifForFirst {\DecoPivot {##1}}{\colorbox{RIGHT}{##1}}}}% -% -\def\QuickSort #1{% warning: not compatible with empty #1. - % initialize, doing conversion from comma separated values to a list of braced items - \edef\QS@list{\noexpand\QSRr{\xintCSVtoList{#1}}}% many \edef's are to follow anyhow -% earlier I did a first drawing of the list, here with the color of RIGHT elements, -% but the color should have been for example white, anyway I drop this first line - %\let\QSRr\DecoRIGHT - %\par\centerline{\QS@list}% -% - % loop as many times as needed - \QS@loop }% -% -% \catcode`? 12 % in case we had used a funny ? as delimiter. -\makeatother -%% End of macro definitions. -%% Start of Example -\begingroup\offinterlineskip -\small -% \QuickSort {1.0, 0.5, 0.3, 1.5, 1.8, 2.0, 1.7, 0.4, 1.2, 1.4, -% 1.3, 1.1, 0.7, 1.6, 0.6, 0.9, 0.8, 0.2, 0.1, 1.9} -% \medskip -% with repeated values -\QuickSort {1.0, 0.5, 0.3, 0.8, 1.5, 1.8, 2.0, 1.7, 0.4, 1.2, 1.4, - 1.3, 1.1, 0.7, 0.3, 1.6, 0.6, 0.3, 0.8, 0.2, 0.8, 0.7, 1.2} -\endgroup -\end{everbatim*} - -Here is the variant which always picks the pivot as the rightmost element. - -\begin{everbatim*} -\makeatletter -% -\def\QS@cmp@a #1{\noexpand\QS@sep@A\expandafter\QS@cmp@d\expandafter - {\romannumeral0\xintnthelt{-1}{#1}}#1??}% -% -\def\DecoLEFTwithPivot #1{\xdef\QS@pivotcount{\the\numexpr\QS@pivotcount+\@ne}% - \xintFor* ##1 in {#1} \do - {\xintifForLast {\DecoPivot {##1}}{\colorbox{LEFT}{##1}}}} -\def\DecoINERTwithPivot #1{\xdef\QS@pivotcount{\the\numexpr\QS@pivotcount+\@ne}% - \xintFor* ##1 in {#1} \do - {\xintifForLast {\colorbox{INERTpiv}{##1}}{\colorbox{INERT}{##1}}}} -\def\DecoRIGHTwithPivot #1{\xdef\QS@pivotcount{\the\numexpr\QS@pivotcount+\@ne}% - \xintFor* ##1 in {#1} \do - {\xintifForLast {\DecoPivot {##1}}{\colorbox{RIGHT}{##1}}}} -\def\QuickSort #1{% - % initialize, doing conversion from comma separated values to a list of braced items - \edef\QS@list{\noexpand\QSLr {\xintCSVtoList{#1}}}% many \edef's are to follow anyhow - % - % loop as many times as needed - \QS@loop }% -\makeatother -\begingroup\offinterlineskip -\small -% \QuickSort {1.0, 0.5, 0.3, 1.5, 1.8, 2.0, 1.7, 0.4, 1.2, 1.4, -% 1.3, 1.1, 0.7, 1.6, 0.6, 0.9, 0.8, 0.2, 0.1, 1.9} -% \medskip -% with repeated values -\QuickSort {1.0, 0.5, 0.3, 0.8, 1.5, 1.8, 2.0, 1.7, 0.4, 1.2, 1.4, - 1.3, 1.1, 0.7, 0.3, 1.6, 0.6, 0.3, 0.8, 0.2, 0.8, 0.7, 1.2} -\endgroup -\end{everbatim*} - -The choice of the first or last item as pivot is not a good one as nearly -ordered lists will take quadratic time. But for explaining the algorithm via a -graphical interpretation, it is not that bad. If one wanted to pick up the -pivot randomly, the routine would have to be substantially rewritten: in -particular the |\Deco..withPivot| macros need to know where the pivot is, and -currently this is implemented by using either |\xintifForFirst| or -|\xintifForLast|. - -\etocdepthtag.toc {macros} -\addtocontents{toc}{\gdef\string\sectioncouleur{{joli}}} -\addtocontents{toc}{\gdef\string\SKIPSECTIONINTERSPACE{\kern\smallskipamount}} -\renewcommand{\etocaftertochook}{\addvspace{\bigskipamount}} - -\clearpage - -\expandafter\let\csname Old examplesnameUp\endcsname\undefined -\csname xintbundlenameUp\endcsname +\csname xint bundlenameUp\endcsname \def\xintRunningHeader{{\inheadertrue\catcode`,12\relax \DOCxintfrontpage, - \xintbundlename, + \csname xint bundlename\endcsname, \xintkernelname, \xintcorename, \xintname, @@ -9397,9 +7335,16 @@ currently this is implemented by using either |\xintifForFirst| or \xintgcdname, \xintseriesname, \xintcfracname, - \xinttoolsname}} + \xinttoolsname, + \DOCxintexprmacros, + \DOCexamples}} \markboth{\makebox[0pt]{\xintRunningHeader}}{\makebox[0pt]{\xintRunningHeader}} +\etocdepthtag.toc {macros} +\addtocontents{toc}{\gdef\string\sectioncouleur{{joli}}} +\addtocontents{toc}{\gdef\string\SKIPSECTIONINTERSPACE{\kern\smallskipamount}} +\renewcommand{\etocaftertochook}{\addvspace{\bigskipamount}} + \part{The macro layer for expandable computations: \xintcorename, \xintname, \xintfracname,...} \RaisedLabel[15]{sec:bundle} @@ -9408,8 +7353,11 @@ currently this is implemented by using either |\xintifForFirst| or \begin{framed} WARNING ! - The documentation is old, although we try to keep updated the list of macros - defined by all the packages. + The documentation is getting old, and is in need of rewrites for many + sections, particularly for examples. + + We do try to keep updated the description of macros + provided by the packages. \end{framed} \etocsetnexttocdepth{section} @@ -9579,7 +7527,9 @@ an optional argument. it has an altogether different meaning: the computations are always done with the prevailing |\xinttheDigits| precision and the optional argument |Q| is used for the final rounding. This makes sense only if |Q<\xinttheDigits| and -is intended to clean up the result from dubious last digits. +is intended to clean up the result from dubious last digits (when |Q<0| it +indicates rather by how many digits one should reduce the mantissa lengths via a +final rounding). @@ -10339,90 +8289,6 @@ case of expansions leading to only a few dozen digits. identifiers which can then be used in expressions: \autoref{xintdefvar}. -\subsection{When expandability is too much} - -Let's use the macros of \autoref{ssec:fibonacci} related to Fibonacci numbers. -Notice that the $47$th Fibonacci number is \dtt{\xintthe\FibonacciN {47}} thus -already too big for \TeX{} and \eTeX{}. - - -The |\FibonacciN| macro found in \autoref{ssec:fibonacci} is completely -expandable, it is even \fexpan dable. We need a wrapper with |\xintthe| -prefix -\begin{everbatim*} -\def\theFibonacciN{\xintthe\FibonacciN} -\end{everbatim*} -to print in the document or to use within |\message| (or \LaTeX\ |typeout|) to -write to the log and terminal. - -\begingroup - \def\A {1859} \def\B {1573} - \edef\X {\theFibonacciN\A} \edef\Y {\theFibonacciN\B} - \edef\GCDAB {\xintiiGCD\A\B}\edef\Z {\theFibonacciN\GCDAB} - \edef\GCDXY{\xintiiGCD\X\Y} - - The |\xintthe| prefix also allows its use it as argument to the \xintname - macros: for example if we are interested in knowing how many digits - $F(1250)$ has, it suffices to issue |\xintLen {\theFibonacciN {1250}}| - (which expands to \dtt{\xintLen {\theFibonacciN {1250}}}). Or if we want to - check the formula $gcd(F(1859),F(1573))=F(gcd(1859,1573))=F(143)$, we only - need% -% -\footnote{The - \csa{xintiiGCD} macro is provided by both the \xintgcdname package (since - |1.0|) and by the \xintname package (since |1.3d|).} -% -\begin{everbatim} -$\xintiiGCD{\theFibonacciN{1859}}{\theFibonacciN{1573}}=% - \theFibonacciN{\xintiiGCD{1859}{1573}}$ -\end{everbatim} -% -which produces: -% -\leftedline{$\dtt{\xintiiGCD{\X}{\Y}}=\dtt{\theFibonacciN{\GCDAB}}$} - -The |\theFibonacciN| macro expanded its |\xintiiGCD{1859}{1573}| argument via the -services of |\numexpr|: this step allows only things obeying the \TeX{} bound, -naturally! (but \dtt{F(\xintiiPow2{31}}) would be rather big anyhow...). - -This is very convenient but of course it repeats the complete evaluation each -time it is done. In practice, it is often useful to store the result of such -evaluations in macros. Any |\edef| will break expandability, but if the goal -is at some point to print something to the |dvi| or |pdf| output, and not only -to the |log| file, then expandability has to be broken one day or another! - -Hence, in practice, if we want to print in the document some computation -results, we can proceed like this and avoid having to repeat identical -evaluations: -\begin{everbatim} -\begingroup - \def\A {1859} \def\B {1573} - \edef\X {\theFibonacciN\A} \edef\Y {\theFibonacciN\B} - \edef\GCDAB {\xintiiGCD\A\B}\edef\Z {\theFibonacciN\GCDAB} - \edef\GCDXY{\xintiiGCD\X\Y} -The identity $\gcd(F(\A),F(\B))=F(\gcd(\A,\B))$ can be checked via evaluation -of both sides: $\gcd(F(\A),F(\B))=\gcd(\printnumber\X,\printnumber\Y)= -\printnumber{\GCDXY} = F(\gcd(\A,\B)) = F(\GCDAB) =\printnumber\Z$.\par - % some further computations involving \A, \B, \X, \Y -\endgroup % closing the group removes assignments to \A, \B, ... -% or choose longer names less susceptible to overwrite something. -% Note: there is no LaTeX \newecommand which would be to \edef like \newcommand is to \def -\end{everbatim} -The identity $\gcd(F(\A),F(\B))=F(\gcd(\A,\B))$ can be checked via evaluation -of both sides: $\gcd(F(\A),F(\B))=\gcd(\printnumber\X,\printnumber\Y)= -\printnumber{\GCDXY} = F(\gcd(\A,\B)) = F(\GCDAB) =\printnumber\Z$.\par -\endgroup - -One may legitimately ask the author: why expandability -to such extremes, for things such as big fractions or floating point numbers -(even continued fractions...) which anyhow can not be used directly within -\TeX's primitives such as |\ifnum|? Why insist on a concept -which is foreign to the vast majority of \TeX\ users and even programmers? - -I have no answer: it made definitely sense at the start of \xintname (see -\autoref{ssec:origins}) and once started I could not stop. - - \subsection{Possible syntax errors to avoid} \edef\x{\xintMul {3}{5}/\xintMul{7}{9}} @@ -10466,19 +8332,19 @@ found in the compilation log. Here is an example interactive run: \begin{everbatim} ! Undefined control sequence. -<argument> \ ! / +<argument> \xint/ DivisionByZero (hit <RET> thrice) l.11 \xintiiDivision{123}{0} ? ! Undefined control sequence. -<argument> \ ! / +<argument> \xint/ Division of 123 by 0 l.11 \xintiiDivision{123}{0} ? ! Undefined control sequence. -<argument> \ ! / +<argument> \xint/ next: {0}{0} l.11 \xintiiDivision{123}{0} @@ -10494,13 +8360,8 @@ release.% \footnote{The related macros checking or resetting error flags are implemented in embryonic form but no user interface is provided with |1.2l| release.} % -For the good functioning of this the macro with the weird appearance -{\catcode`/ 11 \catcode`! 11 \catcode32 11 |\ ! /|} (yes, this is a single -control sequence) must be left undefined. I trust it will be |;-)|.% % -\footnote{The implementation is cloned from \LaTeX3, the - {\catcode`/ 11 \catcode`! 11 \catcode32 11 |\ ! /|} was chosen for its - shortness.} +\footnote{The implementation is cloned from \LaTeX3.} % Deprecated macros also generate an (expandable) error message. Just hit the % |RETURN| key once to proceed.\IMPORTANT\ Most deprecated macros at |1.2o| are @@ -10508,21 +8369,22 @@ control sequence) must be left undefined. I trust it will be |;-)|.% % \autoref{ssec:xintdeprecated} or \autoref{ssec:xintdeprecatedNum}. All % were removed at |1.3|. -The expression parsers are at |1.2l| still using a slightly less evolved -method which lets \TeX{} display an undefined control sequence name giving -some indication of the underlying problem (we copied this method from the -|bigintcalc| package). The name of the control sequence is the message. +% obsoleted at xint 1.4 +% The expression parsers are at |1.2l| still using a slightly less evolved +% method which lets \TeX{} display an undefined control sequence name giving +% some indication of the underlying problem (we copied this method from the +% |bigintcalc| package). The name of the control sequence is the message. -\begin{multicols}{2}\parskip0pt\relax -\begin{everbatim} -\xintError:ignored -\xintError:removed -\xintError:inserted -\xintError:unknownfunction -\xintError:we_are_doomed -\xintError:missing_xintthe! -\end{everbatim} -\end{multicols} +% \begin{multicols}{2}\parskip0pt\relax +% \begin{everbatim} +% \xintError:ignored +% \xintError:removed +% \xintError:inserted +% \xintError:unknownfunction +% \xintError:we_are_doomed +% \xintError:missing_xintthe! +% \end{everbatim} +% \end{multicols} Some constructs in \xintexprname-essions use delimited macros and there is @@ -10530,10 +8392,10 @@ thus possibility in case of an ill-formed expression to end up beyond the |\relax| end-marker. Such a situation can also occur from a non-terminated |\numexpr|: \begin{everbatim} -\xinttheexpr 3 + \numexpr 5+4\relax followed by some LaTeX code... +\xintexpr 3 + \numexpr 5+4\relax followed by some LaTeX code... \end{everbatim} as the |\numexpr| will swallow the |\relax| whose presence is mandatory for -|\xinttheexpr|, errors will inevitably arise and may +|\xintexpr|, errors will inevitably arise and may lead to very cryptic messages; but nothing unusual or especially traumatizing for the daring experienced \TeX/\LaTeX\ user, whose has seen zillions of un-helpful error messages already in her daily practice of @@ -10584,9 +8446,6 @@ temporarily turn off potentially active characters. other and letters have category code letter. Nothing else is assumed. \end{framed} -As pointed out in previous section the control sequence {\catcode`/ 11 - \catcode`! 11 \catcode32 11 |\ ! /|} must be left undefined. - \subsection{Origins of the package} \label{ssec:origins} @@ -10656,13 +8515,11 @@ the current common values of the input save stack and maximal expansion depth: $5000$ and $10000$ respectively. \clearpage -\let\xintbundlenameUp\undefined +\expandafter\let\csname xint bundlenameUp\endcsname\undefined \csname xintkernelnameUp\endcsname \section{Macros of the \xintkernelname package} \RaisedLabel{sec:kernel} -\localtableofcontents - The \xintkernelname package contains mainly the common code base for handling the load-order of the bundle packages, the management of catcodes at loading time, definition of common constants and macro utilities which are used @@ -10671,6 +8528,8 @@ bundle. It provides a few macros possibly useful in other contexts. +\localtableofcontents + \subsection{\csh{odef}, \csh{oodef}, \csh{fdef}} \label{odef} \label{oodef} @@ -10807,7 +8666,6 @@ and does nothing.% % \footnote{This behaviour may change in future.} -Note that expansion must be triggered by a |\romannumeral|. \subsection{\csh{xintGobble}, \csh{xintgobble}} @@ -10821,7 +8679,6 @@ as large as \dtt{531440}. Don't use it with |x<0|. And \csa{xintGobble}|{x}| integrates the \csa{romannumeral}.\NewWith{1.4} -Note that expansion must be triggered by a |\romannumeral|. \csbxint{gobble} looks as if it must be related to \csbxint{Trim} from \xinttoolsname, but the latter uses different code (using directly @@ -11026,8 +8883,6 @@ possibly by the range being a power of 10. \section{Macros of the \xintcorename package} \RaisedLabel{sec:core} -\localtableofcontents - Package \xintcorename is automatically loaded by \xintname. \xintcorename provides for big integers the four basic arithmetic operations @@ -11096,6 +8951,8 @@ The {\color[named]{PineGreen}$\star$}'s in the margin are there to remind of the complete expandability, even \fexpan dability of the macros, as discussed in \autoref{ssec:expansions}. +\localtableofcontents + \subsection{\csh{xintiNum}}\label{xintiNum} |\xintiNum|\n\etype{f} removes chains of plus or minus signs, followed by @@ -11352,9 +9209,6 @@ truncates the general input to an integer in strict format. This package loads automatically \xintcorename (and \xintkernelname) hence all macros described in \autoref{sec:core} are still available. -\etocsetnexttocdepth{subsubsection} -\localtableofcontents - This is \texttt{\xintbndlversion} of \texttt{\xintbndldate}. @@ -11412,6 +9266,9 @@ margin annotations. +\etocsetnexttocdepth{subsubsection} +\localtableofcontents + \subsection{\csh{xintiLen}}\label{xintiLen} |\xintiLen|\n\etype{\Numf} returns the length of the number, after its parsing @@ -12173,8 +10030,6 @@ fraction should be reduced to smallest terms. The current method allows (for example when multiplying two polynomials) to keep a well-predictable denominator among various terms, even though some may be reducible. -\localtableofcontents - \xintfracname loads automatically \xintcorename and \xintname and inherits their macro definitions. Only these two are redefined: \hyperref[xintNumFrac]{\string\xintNum} and @@ -12207,6 +10062,8 @@ user manual for various reasons, one being that it is thought few users will use directly the \xintfracname macros, the \csbxint{expr} interface being more convenient. For complete documentation refer to |sourcexint.pdf|. +\localtableofcontents + \subsection{\csh{xintNum}}\label{xintNumFrac} The original \csbxint{Num} \etype{\Ff} from \xintname is made a synonym to @@ -12354,23 +10211,29 @@ from removing the |[N]| part if |N=0| and removing the |B| if |B=1|. \xintPRaw {123e10/321e10}, \xintPRaw {123e9/321e10}, \xintPRaw {\xintIrr{861/123}} \end{everbatim*} -\subsection{\csh{xintFracToSci}}\label{xintFracToSci} +\subsection{\csh{xintFracToSci}, \csh{xintFracToSciE}}\label{xintFracToSci} +\label{xintFracToSciE} -\csa{FracToSci}\etype{\Ff} is not really part of public interface. It is a -macro used by \csbxint{expr} for output, on data which is guaranteed to be -in raw \xintfracname format (apart from lacking possibly a denominator and/or the -|[N]| postfix). It is basically like \csbxint{PRaw} but -using scientific notation in the output.\NewWith{1.4} +\csa{xintFracToSci}\etype{\Ff} is not really part of public interface. It is a +macro used by \csbxint{expr} for output. -Use with care, and always with the argument nested in at least one -\xintfracname macro, such as \csbxint{Raw} or \csbxint{Irr}. +\noindent\csa{xintFracToSciE}\NewWith{1.4} says what to use for the scientific +notation, its default definition is +\begin{everbatim} +\def\xintFracToSciE{e} +\end{everbatim} +If using directly \csa{xintFracToSci}: attention that it expects input to +already be in raw \xintfracname format, apart from denominator and |[N]| +postfix parts being optional. Its output is like \csbxint{PRaw} except for +using scientific notation in place of raw \xintfracname format. \begin{everbatim*} \xintFracToSci {\xintRaw{123e10/321e10}}, \xintFracToSci {\xintRaw{123e9/321e10}}, \xintFracToSci {\xintIrr{861/123}} \end{everbatim*} + \subsection{\csh{xintDecToString}}\label{xintDecToString} This is\etype{\Ff} a macro tailored for printing decimal numbers. It does not @@ -12390,24 +10253,27 @@ is a backport from \href{http://ctan.org/pkg/polexpr}{polexpr}'s \subsection{\csh{xintTrunc}}\label{xintTrunc} -\csa{xintTrunc}|{x}{f}|\etype{\numx\Ff} returns the integral part, a dot -(standing for the decimal mark), and -then the first |x| digits of the decimal expansion of the fraction |f|, except -when the fraction is (or evaluates to) zero, then it simply prints \dtt{0} -(with no dot). - -\begin{framed} - The argument |x| must be non-negative, the behaviour is currently undefined - when |x<0| and will provoke errors. -\end{framed} +\csa{xintTrunc}|{x}{f}|\etype{\numx\Ff} returns the start of the decimal +expansion of the fraction |f|, truncated to: +\begin{itemize} +\item if |x>0|, |x| digits after the decimal mark, +\item if |x=0|, an integer, +\item if |x<0|, an integer multiple of |10^{-x}| (in scientific notation).\NewWith{1.4a} +\end{itemize} +The output is the sole digit token \dtt{0} if and only if the input was exactly +zero; else it contains always either a decimal mark (even if |x=0|) or a +scientific part and it conserves the sign of |f| (even if the truncated value +represents the zero value). -Except when the input is (or evaluates to) exactly zero, the output contains -exactly |x| digits after the decimal mark, thus the output may be -\dtt{0.00...0} or \dtt{-0.00...0}, indicating that the original fraction was -positive, respectively negative. +Truncation is done towards zero. +\begin{everbatim*} +\xintFor* #1 in {\xintSeq[-1]{7}{-14}}:{\xintTrunc{#1}{-11e12/7}\newline}% +\xintTrunc{10}{1e-11}\newline +\xintTrunc{10}{1/65536}\par +\end{everbatim*} \begin{framed} - \textbf{Warning:} \emph{it is not yet decided is this behaviour is + \textbf{Warning:} \emph{it is not yet decided is the current behaviour is definitive.} Currently \xintfracname has no notion of a positive zero or a negative zero. @@ -12415,10 +10281,10 @@ positive, respectively negative. truncation gives on output \dtt{0.00...0} or \dtt{-0.00...0}: a second truncation to less digits will then output \dtt{0}, whereas if it had been applied directly to the initial input it would have produced \dtt{0.00...0} - or respectively \dtt{-0.00...0} (with less zeros). + or respectively \dtt{-0.00...0} (with less zeros after decimal mark). If \xintfracname distinguished zero, positive zero, and - negative zero it would be possible to maintain transitivity. + negative zero then it would be possible to maintain transitivity. The problem would also be fixed, even without distinguishing a negative zero on input, if \csbxint{Trunc} always produced \dtt{0.00...0} (with no sign) @@ -12428,16 +10294,6 @@ positive, respectively negative. I have multiple times hesitated about what to do and must postpone again final decision. \end{framed} -\begin{everbatim*} -\xintTrunc {16}{-803.2028/20905.298}\newline -\xintTrunc {20}{-803.2028/20905.298}\newline -\xintTrunc {10}{\xintPow {-11}{-11}}\newline -\xintTrunc {12}{\xintPow {-11}{-11}}\newline -\xintTrunc {50}{\xintPow {-11}{-11}}\newline -\xintTrunc {12}{\xintAdd {-1/3}{3/9}}\par -\end{everbatim*} -The digits printed are exact up to and including the last one. - \subsection{\csh{xintXTrunc}}\label{xintXTrunc} @@ -12629,18 +10485,23 @@ conversion to a floating point number with the precision as set by |\xintDigits| \subsection{\csh{xintRound}}\label{xintRound} \csa{xintRound}|{x}{f}|\etype{\numx\Ff} returns the start of the decimal -expansion of the fraction |f|, rounded to |x| digits precision after the decimal -point. The argument |x| should be non-negative. Only when |f| evaluates exactly -to zero does \csa{xintRound} return |0| without decimal point. When |f| is not -zero, its sign is given in the output, also when the digits printed are all -zero. -\begin{everbatim*} -\xintRound {16}{-803.2028/20905.298}\newline -\xintRound {20}{-803.2028/20905.298}\newline -\xintRound {10}{\xintPow {-11}{-11}}\newline -\xintRound {12}{\xintPow {-11}{-11}}\newline -\xintRound {12}{\xintAdd {-1/3}{3/9}}\par -\end{everbatim*} +expansion of the fraction |f|, rounded to: +\begin{itemize} +\item if |x>0|, |x| digits after the decimal mark, +\item if |x=0|, an integer, +\item if |x<0|, an integer multiple of |10^{-x}| (in scientific notation).\NewWith{1.4a} +\end{itemize} +The output is the sole digit token \dtt{0} if and only if the input was +exactly zero; else it contains always either a decimal mark (even if |x=0|) or +a scientific part and it conserves the sign of |f| (even if the rounded value +represents the zero value). +\begin{everbatim*} +\xintFor* #1 in {\xintSeq[-1]{7}{-14}}:{\xintRound{#1}{-11e12/7}\newline}% +\xintRound{10}{1e-11}\newline +\xintRound{10}{1/65536}\newline +\end{everbatim*}% +Rounding is done with half-way numbers going towards infinity of +the same sign. \subsection{\csh{xintFloor}}\label{xintFloor} @@ -12662,17 +10523,14 @@ Note the trailing |[0]|, see \csbxint{iFloor} if it is not desired. \subsection{\csh{xintiTrunc}}\label{xintiTrunc} \csa{xintiTrunc}|{x}{f}|\etype{\numx\Ff} returns the integer equal to |10^x| -times what \csa{xintTrunc}|{x}{f}| would produce. +times what \csa{xintTrunc}|{x}{f}| would produce. Attention that leading zeros +are automatically removed: the output is in strict integer format. \begin{everbatim*} -\xintiTrunc {16}{-803.2028/20905.298}\newline -\xintiTrunc {10}{\xintPow {-11}{-11}}\newline -\xintiTrunc {12}{\xintPow {-11}{-11}}\par +\xintFor* #1 in {\xintSeq[-1]{7}{-14}}:{\xintiTrunc{#1}{-11e12/7}\newline}% +\xintiTrunc{10}{1e-11}\newline +\xintiTrunc{10}{1/65536}\par \end{everbatim*} -In particular \csa{xintiTrunc}|{0}{f}|'s output is in strict integer format -contrarily to \csa{xintTrunc}|{0}{f}| which produces an output with a decimal -mark, except if |f| turns out to be zero. - \subsection{\csh{xintTTrunc}}\label{xintTTrunc} \csa{xintTTrunc}|{f}|\etype{\Ff} truncates to an integer (truncation towards @@ -12682,16 +10540,14 @@ zero). This is the same as |\xintiTrunc {0}{f}| and also the same as \subsection{\csh{xintiRound}}\label{xintiRound} \csa{xintiRound}|{x}{f}|\etype{\numx\Ff} returns the integer equal to |10^x| -times what \csa{xintRound}|{x}{f}| would return. +times what \csa{xintRound}|{x}{f}| would return. The output has no leading +zeroes, it is always in strict integer format. \begin{everbatim*} -\xintiRound {16}{-803.2028/20905.298}\newline -\xintiRound {10}{\xintPow {-11}{-11}}\par +\xintFor* #1 in {\xintSeq[-1]{7}{-14}}:{\xintiRound{#1}{-11e12/7}\newline}% +\xintiRound{10}{1e-11}\newline +\xintiRound{10}{1/65536}\par \end{everbatim*} -In particular \csa{xintiRound}|{0}{f}|'s output is in strict integer format -contrarily to \csa{xintRound}|{0}{f}| which produces an output with a decimal -mark, except if |f| turns out to be zero. - \subsection{\csh{xintiFloor}}\label{xintiFloor} |\xintiFloor {f}|\etype{\Ff} does the same as \csbxint{Floor} but without the @@ -13124,47 +10980,44 @@ The syntax |\xintDigits := D;| assigns the value of |D| to the number of digits to be used by floating point operations (this uses internally a |\mathchardef| assignement, and |D| stands for (or expands to) a legal \TeX\ number). The default is |16|. The maximal value is |32767|. +\begin{framed} + \xintexprname adds\IMPORTANTf{} the variant \csbxint{Digits*} which executes + \csbxint{reloadxinttrig}. +\end{framed} The expandable macro |\xinttheDigits|\etype{} serves to retrieve (internally it uses |\number|) the current value. -Spaces do not matter (but they must not occur in-between digit tokens, as such a space - would terminate the \TeX{} number): +Spaces do not matter as long as they do not occur in-between digits: \begin{everbatim*} \xintDigits := 24;\xinttheDigits, % \xintDigits:=36 ;\xinttheDigits, % \xintDigits:= 16 ;and \xinttheDigits. \end{everbatim*} -It has always been the case that an active colon |:| was allowed. -It is now even possible to drop it and to use |\xintDigits = D;| -syntax. +% It has always been the case that an active colon |:| was allowed. -An ending active semi-colon |;| is \emph{not} compatible: it can and most -probably will cause low-level \TeX{} errors at such locations (this is the -case if it is made active by |\usepackage[french]{babel}| in \LaTeX). This -restriction always applied, but never got properly documented prior to -|1.3f| release... It is possible to use |\string;| but then there can not be -any space separating it from the digits. +Also |\xintDigits = D;| (i.e.\@ without a colon) is accepted syntax. -But this problem with an active semi-colon |;| has trivial workaround: it -always applied (but was not formerly documented) that any non-expanding token -could be used in place of the ending semi-colon |;|. One has always been -allowed to use e.g. a dot character or a |\relax| token. This non-expanding -ending token will get removed from the token stream. +An ending active semi-colon |;| is \emph{not} compatible: it can and will +cause low-level \TeX{} errors. But this has a trivial workaround: any +non-expanding token can be used in place of the ending semi-colon. For +example a full stop or a |\relax| token. This +non-expanding ending token will get removed from the token stream. -The safer syntax is thus |\xintDigits := D\relax| (with or without the colon). -This is the syntax now in use in most examples from the documentation. +% This +% restriction always applied, but never got properly documented prior to +% |1.3f| release... It is possible to use |\string;| but then there can not be +% any space separating it from the digits. + +The recommended syntax is thus now |\xintDigits := D\relax| (with or without the colon). +This is the syntax in use in most examples from the documentation. \begin{everbatim*} \xintDigits = 24\def\xinttheDigits, % only for showing it works! don't do that! \xintDigits := 36.\xinttheDigits, % one can use a dot in place of semi-colon \xintDigits = 16\relax and \xinttheDigits.\par % with \relax, even better \end{everbatim*} -\begin{framed} - \xintexprname adds the variant \csbxint{Digits*} which executes \csbxint{reloadxinttrig}. -\end{framed} - \subsection{\csh{xintSetDigits}} \label{xintSetDigits} @@ -13671,8 +11524,6 @@ general tokens (or rather braced items). \section{Macros of the \xintbinhexname package} \RaisedLabel{sec:binhex} -\localtableofcontents - This package provides expandable conversions of (big) integers to and from binary and hexadecimal. @@ -13761,7 +11612,7 @@ Currently the |p| postfix notation from standard programming languages standing for an extra power of two multiplicand is not implemented. -% \clearpage +\localtableofcontents \subsection{\csh{xintDecToHex}}\label{xintDecToHex} @@ -13851,17 +11702,10 @@ $000000001111101001010001\xrightarrow{\text{\string\xintBinToHex}} \section{Macros of the \xintgcdname package} \RaisedLabel{sec:gcd} -\localtableofcontents - This package was included in the original release |1.0| (|2013/03/28|) of the \xintname bundle. -! Since release |1.09a| the macros filter their inputs through the \csbxint{Num} -! macro, so one can use count registers, or fractions as long as they reduce to -! integers. -! Since release |1.1|, the two ``|typeset|'' macros require the explicit -! loading by the user of package \xinttoolsname. At |1.3d| macros \csbxint{iiGCD} and \csbxint{iiLCM} are copied over to \xintname, hence \func{gcd} and \func{lcm} functions in \csbxint{iiexpr} were @@ -13883,6 +11727,7 @@ The macros \csbxint{iiGCD} and \csbxint{iiLCM} got relocated into general fractions and not only integers. \end{framed} +\localtableofcontents \subsection{\csh{xintBezout}}\label{xintBezout} @@ -13956,8 +11801,6 @@ macro and modify it to what is needed. \section{Macros of the \xintseriesname package} \RaisedLabel{sec:series} -\localtableofcontents - This package was first released with version |1.03| (|2013/04/14|) of the \xintname bundle. @@ -13981,6 +11824,8 @@ stage not immediately. \end{framed} %% \clearpage +\localtableofcontents + \subsection{\csh{xintSeries}}\label{xintSeries} \csa{xintSeries}|{A}{B}{\coeff}|\etype{\numx\numx\Ff} computes @@ -14906,8 +12751,6 @@ always do it on a value computed with |D+1| truncation. \section{Macros of the \xintcfracname package} \RaisedLabel{sec:cfrac} -\localtableofcontents - First version of this package was included in release |1.04| (|2013/04/25|) of the \xintname bundle. It was kept almost unchanged until |1.09m| of |2014/02/26| which brought some new macros: \csbxint{FtoC}, \csbxint{CtoF}, \csbxint{CtoCv}, @@ -14922,13 +12765,15 @@ the commas. Note: \csbxint{CstoF} and \csbxint{CstoCv} create a partial dependency on \xinttoolsname (its \csbxint{CSVtoList}.) -This section contains: -\begin{enumerate} -\item an \hyperref[ssec:cfracoverview]{overview} of the package functionalities, -\item a description of each one of the package macros, -\item further illustration of their use via the study of the - \hyperref[ssec:e-convergents]{convergents of $e$}. -\end{enumerate} +\localtableofcontents + +% This section contains: +% \begin{enumerate} +% \item an \hyperref[ssec:cfracoverview]{overview} of the package functionalities, +% \item a description of each one of the package macros, +% \item further illustration of their use via the study of the +% \hyperref[ssec:e-convergents]{convergents of $e$}. +% \end{enumerate} \subsection{Package overview}\label{ssec:cfracoverview} @@ -15662,8 +13507,6 @@ $1$ or $-1$. \RaisedLabel{sec:tools} -\localtableofcontents - These utilities used to be provided within the \xintname package; since |1.09g| (|2013/11/22|) they have been moved to an independently usable package \xinttoolsname, which has none of the \xintname facilities regarding big @@ -15676,6 +13519,8 @@ first, then the non expandable utilities. \autoref{sec:examples} gives additional (also dated) examples of use of macros of this package. +\localtableofcontents + \subsection{\csh{xintRevWithBraces}}\label{xintRevWithBraces} %{\small New in release |1.06|.\par} @@ -17162,6 +15007,2418 @@ be treated as first item) number. \clearpage \let\xinttoolsnameUp\undefined +\def\n{|{N}|} +\def\m{|{M}|} +\def\x{|{x}|} + +\csname xintexprnameUp\endcsname +\section{Macros of the \xintexprname package}% +\RaisedLabel{sec:oldxintexpr} + +\localtableofcontents + +The \xintexprname package was first released with version |1.07| +(|2013/05/25|) of the \xintname bundle. It was substantially enhanced with +release |1.1| from |2014/10/28|. + +The |1.4| release from |2020/01/31| maintains the same general architecture +but needed adapting all the code base for the switch from |\csname| to +|\expanded| techniques. On this occasion the mechanism for defining functions +was substantially strengthened. The parser core mechanisms were improved too. + +The package loads automatically \xintfracname and \xinttoolsname. + +This section should be trimmed to contain only information not +already covered in \autoref{sec:expr}. + +\subsection{The \csh{xintexpr} expressions} +\label{xintexpr} +\label{xinttheexpr} +\label{thexintexpr} +\label{xintthe} + +An \xintexprname{}ession is a construct +\csbxint{expr}\meta{expandable\_expression}|\relax|\etype{x} where the +expandable expression is read and completely expanded from left to right. + +An |\xintexpr...\relax| \emph{must} end in a |\relax| (which will be absorbed). +Contrarily to a |\numexpr| expression, it is printable\CHANGED{1.4} as is without a prefix +|\the| or |\number| (don't use them with |\xintexpr| this will raise an +error). + +But one can use |\xintthe| prefix if one does need the explicit digits and +other characters as in the final typesetted result. + +As an alternative and equivalent syntax to +\begin{everbatim} +\xintexpr round(<expression>, D)\relax +\end{everbatim} +there is +\begin{everbatim} +\xintiexpr [D] <expression> \relax +\end{everbatim} +The parameter |D| must be zero or positive.\footnote{|D=0| + corresponds to using |round(<expression>)| not |round(<expression>,0)| which + would leave a trailing dot. Same for |trunc|. There is also function |float| + for floating point rounding to \csbxint{theDigits} or the given number of + significant digits as second argument.} Perhaps some future version will +give a meaning to using a negative |D|.\footnote{Thanks to KT for this + suggestion. Sorry for the delay in implementing it... matter of formatting + the output and corresponding choice of user interface are still in need of + some additional thinking.} + +\begin{itemize} +\item the expression may contain arbitrarily many levels of nested parenthesized + sub-expressions, +\item the expression may contain explicitely or from a macro expansion a + sub-expression |\xintexpr...\relax|, which itself may contain a + sub-expressions etc\dots +\item to let sub-contents evaluate as a sub-unit it should thus be either + \begin{enumerate} + \item parenthesized, + \item or a sub-expression |\xintexpr...\relax|. + \end{enumerate} + \item to use an expression as argument to macros from \xintfracname, + or more generally to macros which expand their arguments, one must use the + |\xinttheexpr...\relax| or |\xintthe\xintexpr...\relax| forms. + \item one should not use |\xintthe\xintexpr...\relax| as a sub-constituent of + another expression but only the + |\xintexpr...\relax| form which is more efficient in this context. + \item each \xintexprname{}ession, whether prefixed or not with |\xintthe|, is + completely expandable and obtains its result in two expansion steps. +\end{itemize} + +The information now following is possibly in need of updates. + +\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, + itemindent=0pt, listparindent=\leftmarginiii, leftmargin=\leftmarginii] +\item An expression is built the standard way with opening and closing + parentheses, infix operators, and (big) numbers, with possibly a fractional + part, and/or scientific notation (except for \csbxint{iiexpr} which only + admits big integers). All variants work with comma separated expressions. On + output each comma will be followed by a space. A decimal number must have + digits either before or after the decimal mark. + +\item As everything gets expanded, the characters |.|, |+|, |-|, |*|, |/|, |^|, + |!|, |&|, \verb+|+, |?|, |:|, |<|, |>|, |=|, |(|, |)|, |"|, |]|, |[|, |@| + and the comma |,| should not (if used in the expression) be active. For + example, the French language in |Babel| system, for pdf\LaTeX, activates |!|, + |?|, |;| and |:|. Turn off the activity before expressions using such characters. + + Alternatively the macro \csbxint{exprSafeCatcodes} resets all + characters potentially needed by \csbxint{expr} to their standard catcodes + and \csbxint{exprRestoreCatcodes} restores the former status. + +\item Count registers and |\numexpr|-essions are accepted (LaTeX{}'s counters + can be inserted using |\value|) natively without |\the| or |\number| as + prefix. Also dimen registers and control sequences, skip registers and + control sequences (\LaTeX{}'s lengths), |\dimexpr|-essions, + |\glueexpr|-essions are automatically unpacked using |\number|, discarding + the stretch and shrink components and giving the dimension value in |sp| + units ($1/65536$th of a \TeX{} point). Furthermore, tacit multiplication is + implied, when the (count or dimen or glue) register or variable, or the + (|\numexpr| or |\dimexpr| or |\glueexpr|) expression is immediately prefixed + by a (decimal) number. See \autoref{ssec:tacit multiplication} for the complete rules + of tacit multiplication.\IMPORTANT + +\item With a macro |\x| defined like this: + % + \leftedline{|\def\x {\xintexpr \a + \b \relax}| or |\edef\x {\xintexpr + \a+\b\relax}|} + % + one may then do |\xintthe\x|, either for printing the result on the page or + to use it in some other macros expanding their arguments. The |\edef| does + the computation immediately but keeps it in a protected form. + Naturally, the |\edef| is only possible if |\a| and |\b| are already + defined. With both approaches the |\x| can be inserted in other expressions, + as for example (assuming naturally as we use an |\edef| that in the + `yet-to-be computed' case the |\a| and |\b| now have some suitable meaning): + % + \leftedline {|\edef\y {\xintexpr \x^3\relax}|} + +\item There is also \csbxint{boolexpr}| ... \relax| and + \csbxint{theboolexpr}| ... \relax|. + +\item See also + \csbxint{ifboolexpr} (\autoref{xintifboolexpr}) and the + \func{bool} and \func{togl} functions + in \autoref{sec:expr}. Here is an example. Well in fact the + example ended up using only \csbxint{boolexpr} so it + was modified to use \csbxint{ifboolexpr}. +\catcode`| 12 % +\begin{everbatim*} +\xintdeffunc A(p,q,r) = p && (q || r) ; +\xintdeffunc B(p,q,r) = p || (q && r) ; +\xintdeffunc C(p,q,r) = xor(p, q, r) ; + +\centeredline{\normalcolor +\begin{tabular}{ccrclcl} + \xintFor* #1 in {{False}{True}} \do {% + \xintFor* #2 in {{False}{True}} \do {% + \xintFor* #3 in {{False}{True}} \do {% + #1 &AND &(#2 &OR )&is&\textcolor[named]{OrangeRed} + {\xintifboolexpr{A(#1,#2,#3)}{true}{false}}\\ + #1 &OR &(#2 &AND )&is&\textcolor[named]{OrangeRed} + {\xintifboolexpr{B(#1,#2,#3)}{yes}{no}}\\ + #1 &XOR & #2 &XOR  &is&\textcolor[named]{OrangeRed} + {\xintifboolexpr{C(#1,#2,#3)}{oui}{non}}\\ +}}} +\end{tabular}% +} +\end{everbatim*}\catcode`| 13 + +\item See also \csbxint{ifsgnexpr}. + +\item There is \csbxint{floatexpr}| ... \relax| where the algebra is done + in floating point approximation (also for each intermediate result). Use the + syntax |\xintDigits:=N\relax| to set the precision. Default: $16$ digits. + % + \leftedline{|\xintthefloatexpr 2^100000\relax:| \dtt{\xintthefloatexpr + 2^100000\relax }} + % + The square-root operation can be used in |\xintexpr|, it is computed + as a float with the precision set by |\xintDigits| or by the optional + second argument: + % +\begin{everbatim*} +\xinttheexpr sqrt(2,60)\relax\newline +Here the [60] is to avoid truncation to |\xinttheDigits| of precision on output.\newline +\printnumber{\xintthefloatexpr [60] sqrt(2,60)\relax} +\end{everbatim*} + + Floats are quickly indispensable when using the power function, as exact + results will easily have hundreds, even thousands of digits. + % +\begin{everbatim*} +\xintDigits:=48\relax \xintthefloatexpr 2^100000\relax +\end{everbatim*} + + Only integer and (in |\xintfloatexpr...\relax|) half-integer exponents are + allowed. + +\item if one uses \emph{macros} within |\xintexpr..\relax| one should + obviously take into account that the parser will \emph{not} see the macro + arguments, hence one cannot use the syntax there, except if the arguments + are themselves wrapped as |\xinttheexpr...\relax| and assuming the macro + \fexpan ds these arguments. +\end{itemize} +\subsection{\texorpdfstring{\texttt{\protect\string\numexpr}}{\textbackslash + numexpr} or \texorpdfstring{\texttt{\protect\string\dimexpr}}{\textbackslash + dimexpr} expressions, count and dimension registers and variables} +\label{ssec:countinexpr} + +Count registers, count control sequences, dimen registers, dimen control +sequences (like |\parindent|), skips and skip control sequences, |\numexpr|, +|\dimexpr|, |\glueexpr|, |\fontdimen| can be inserted directly, they will be +unpacked using |\number| which gives the internal value in terms of scaled +points for the dimensional variables: $1$\,|pt|${}=65536$\,|sp| (stretch and +shrink components are thus discarded). + +Tacit multiplication (see \autoref{ssec:tacit multiplication}) is implied, +when a number or decimal number prefixes such a register or control sequence. +\LaTeX{} lengths are skip control sequences and \LaTeX{} counters should be +inserted using |\value|. + +Release |1.2| of the |\xintexpr| parser also recognizes and prefixes with +|\number| the |\ht|, |\dp|, and |\wd| \TeX{} primitives as well as the +|\fontcharht|, |\fontcharwd|, |\fontchardp| and |\fontcharic| \eTeX{} +primitives. + +In the case of numbered registers like |\count255| or |\dimen0| (or |\ht0|), +the resulting digits will be re-parsed, so for example |\count255 0| is like +|100| if |\the\count255| would give |10|. The same happens with inputs such +as |\fontdimen6\font|. And |\numexpr 35+52\relax| will be exactly as if |87| +as been encountered by the parser, thus more digits may follow: |\numexpr +35+52\relax 000| is like |87000|. If a new |\numexpr| follows, it is treated +as what would happen when |\xintexpr| scans a number and finds a non-digit: it +does a tacit multiplication. +\begin{everbatim*} +\xinttheexpr \numexpr 351+877\relax\numexpr 1000-125\relax\relax{} is the same +as \xinttheexpr 1228*875\relax. +\end{everbatim*} + +Control sequences however (such as |\parindent|) are picked up as a whole by +|\xintexpr|, and the numbers they define cannot be extended extra digits, a +syntax error is raised if the parser finds digits rather than a legal +operation after such a control sequence. + +A token list variable must be prefixed by |\the|, it will not be unpacked +automatically (the parser will actually try |\number|, and thus fail). Do not +use |\the| but only |\number| with a dimen or skip, as the |\xintexpr| parser +doesn't understand |pt| and its presence is a syntax error. To use a dimension +expressed in terms of points or other \TeX{} recognized units, incorporate it in +|\dimexpr...\relax|. + +Regarding how dimensional expressions are converted by \TeX{} into scaled points +see also \autoref{sec:Dimensions}. + +\subsection{Catcodes and spaces} + +The main problems are caused by active characters, because \csbxint{expr} et +al.\@ expand forward whatever comes from token stream; they apply |\string| +only in a second step. For example the catcode of |&| from |&&| Boolean +disjunction is not really important as long as it is not active, or comment, +or escape... or brace... or ignored... in brief, as long as it is reasonable, +and in particular whether |@| is of catcode letter or other does not matter. + +It is always possible to insert manually the |\string| in the expression +before a problematic (but reasonable) character catcode, or even to use +|\detokenize| for a big chunk. + +\subsubsection{\csh{xintexprSafeCatcodes}} +\label{xintexprSafeCatcodes} + +For an even more radical way, there is \csbxint{exprSafeCatcodes} which sets +the catcodes of many characters to safe values. This is a non-expandable step +as it changes catcodes. +% This is used +% internally by \csbxint{NewExpr} (restoring the catcodes on exit), hence it +% does not have to be protected against active characters when used at +% top-level. + +\csbxint{defvar}, \csbxint{deffunc}, et al., execute it before fetching their +semi-colon delimited arguments, so they can be used (also in the document +body) for example with Babel+French (which makes the semi-colon active in the +(\LaTeX) document body). This applies also to \csbxint{NewExpr}. + +% As \csbxint{NewExpr} and \csbxint{deffunc} and variants use internally some +% |\scantokens|, they will (reasonably) succeed in sanitizing catcodes in the +% expressions, even if all is from the replacement text of some macro whose +% definition was done under some special catcode regime. + +But, if used in the body of macro definitions problems may arise from the +catcode regime at that location. This applies in particular to the +semi-colon as used by \csbxint{deffunc}, \csbxint{defvar} and variants as +delimiter. Thus make sure the semi-colon has its normal catcode when issueing +\csbxint{deffunc} inside some macro definition. + +\csbxint{deffunc} is more lenient than \csbxint{defvar} regarding catcodes of +characters in expression bodies as it does some |\scantokens| which will reset +compatible catcodes. And also, characters inside the +expression may usually be prefixed with |\string|; but some aspects of the parsing +use delimited macros which need the comma, equality sign and closing +parenthesis to have standard catcodes. + +Even if used in a context where catcodes are already set, \csbxint{deffunc}, +\csbxint{defvar} and variants ignore completely the colon in |:=| so it can +have any (reasonable) catcode. Moreover it is optional. + +The semi-colon in the syntax of \csbxint{Digits} is no real problem either +(cf. \csbxint{Digits} documentation). + +\begin{framed} + It is important to ALWAYS shortly let \csbxint{exprSafeCatcodes} be followed + by \csbxint{exprRestoreCatcodes}.\IMPORTANTf{} If one uses twice + \csbxint{exprSafeCatcodes} then the next \csbxint{exprRestoreCatcodes} will + restore the ancient catcode regime at time of the first one. +\end{framed} + +\subsubsection{\csh{xintexprRestoreCatcodes}} +\label{xintexprRestoreCatcodes} + +Restores the catcodes to the earlier state. More precisely, +\csbxint{exprSafeCatcodes} sets a toggle (with local scope). If the toggle is +set already it does not restore the current catcodes. The next +\csa{xintexprRestoreCatcodes} unsets the toggle. +So, in case of nesting, the +catcodes are restored to what they were when the \emph{first} un-paired +\csbxint{exprSafeCatcodes} got executed. + +\bigskip + +Spaces inside an |\xinttheexpr...\relax| should mostly be +innocuous (except inside macro arguments). + +|\xintexpr| and |\xinttheexpr| are for the most part agnostic regarding +catcodes: (unbraced) digits, binary operators, minus and plus signs as +prefixes, dot as decimal mark, parentheses, may be indifferently of catcode +letter or other or subscript or superscript, ..., it doesn't matter.% +% +\footnote{Furthermore, although \csbxint{expr} uses \csa{string}, it is + escape-char agnostic. It should work with any \csa{escapechar} setting + including -1.} + +The characters |+|, |-|, |*|, |/|, |^|, |!|, |&|, \verb+|+, |?|, |:|, |<|, |>|, +|=|, |(|, |)|, |"|, |[|, |]|, |;|, the dot and the comma should not be active if +in the expression, as everything is expanded along the way. If one of them is +active, it should be prefixed with |\string|. + +The exclamation mark |!| should have its standard catcode: with catcode letter +it is used internally and hence will confuse the parsers if it comes from the +expression. + +Digits, slash, square brackets, minus sign, in the output from an +|\xinttheexpr| are all of catcode 12. For |\xintthefloatexpr| the `e' in the +output has its standard catcode ``letter''. + +A macro with arguments will expand and grab its arguments before the +parser may get a chance to see them, so the situation with catcodes and spaces +is not the same within such macro arguments. + + + +\subsection{Expandability, \csh{xintexpro}} + +As is the case with all other package macros |\xintexpr| \fexpan ds (in two +steps) to its final (somewhat protected) result; and |\xinttheexpr| \fexpan ds +(in two steps) to the chain of digits (and possibly minus sign |-|, decimal +mark |.|, fraction slash |/|, scientific |e|, square brackets |[|, |]|) +representing the result. + +The once expanded |\xintexpr| is |\romannumeral0\xintexpro|. is similarly +|\xintiexpro| |\xintiiexpro| and |\xintfloatexpro|. For an example see +\autoref{ssec:fibonacci}. + +An expression can only be legally finished by a |\relax| token, which +will be absorbed. + +It is quite possible to nest expressions among themselves; for example, if one +needs inside an |\xintiiexpr...\relax| to do some computations with fractions, +rounding the final result to an integer, one just has to insert +|\xintiexpr...\relax|. The functioning of the infix operators will not be in +the least affected from the fact that the outer ``environment'' is the +|\xintiiexpr| one. + + +\subsection{\csh{xintDigits*}, \csh{xintSetDigits*}} +\label{xintDigits*} +\label{xintSetDigits*} + +These starred variants of \csbxint{Digits} and \csbxint{SetDigits} execute +\csbxint{reloadxinttrig}. + +\subsection{\csh{xintiexpr}, \csh{xinttheiexpr}} +\label{xintiexpr}\label{xinttheiexpr}\label{thexintiexpr} + +Equivalent\etype{x} to doing |\xintexpr round(...)\relax| (more precisely, +|round| is applied to each leaf item of the |ople| independently of its +depth). + +Intermediate calculations are exact, only the final output gets +rounded. Half integers are rounded towards $+\infty$ for positive +numbers and towards $-\infty$ for negative ones. + +An optional parameter |D| within brackets, immediately after |\xintiexpr| is +allowed: it instructs (for |D>0|) the expression to do its final rounding to +the nearest value with that many digits after the decimal mark, \emph{i.e.}, +|\xintiexpr [D] <expression>\relax| is equivalent (in case of a single +expression) to |\xintexpr round(<expression>, D)\relax|. + +|\xintiexpr [0] ...| is the same as |\xintiexpr ...| and rounds to an integer. + +The case of negative |D| gives quantization to an integer multiple of +\dtt{1e-D}.\NewWith{1.4a} + +If truncation rather than rounding is needed on can use |\xintexpr +trunc(...)\relax| for truncation to an integer or |\xintexpr +trunc(...,D)\relax| for quantization to an integer multiple or \dtt{1eD}. But +this works only for a single scalar value. + +Already on October 20, 2015, it was suggested by \textsc{Kpym} to give some +meaning to negative |D|. The suggestion was to let it act like |-D| but +remove trailing zeroes of the output. Finally, I opted rather for +quantization. + +\subsection{\csh{xintiiexpr}, \csh{xinttheiiexpr}} +\label{xintiiexpr}\label{xinttheiiexpr}\label{thexintiiexpr} + +This variant\etype{x} does not know fractions. It deals almost only with long +integers. Comma separated lists of expressions are allowed. + +\begin{framed} + It maps |/| to the \emph{rounded} quotient. The operator + |//| is, like in |\xintexpr...\relax|, mapped to \emph{truncated} division. + The Euclidean quotient (which for positive operands is like the truncated + quotient) was, prior to release |1.1|, associated to |/|. The function + |quo(a,b)| can still be employed. +\end{framed} + +The \csbxint{iiexpr}-essions use the `ii' macros for addition, subtraction, +multiplication, power, square, sums, products, Euclidean quotient and +remainder. + +The |round|, |trunc|, |floor|, |ceil| functions are still available, and are +about the only places where fractions can be used, but |/| within, if not +somehow hidden will be executed as integer rounded division. To avoid this one +can wrap the input in \dtt{qfrac}: this means however that none of the normal +expression parsing will be executed on the argument. + +To understand the illustrative examples, recall that |round| and |trunc| have +a second (non negative) optional argument. In a normal \csbxint{expr}-essions, +|round| and |trunc| are mapped to \csbxint{Round} and \csbxint{Trunc}, in +\csbxint{iiexpr}-essions, they are mapped to \csbxint{iRound} and +\csbxint{iTrunc}. + + +\begin{everbatim*} +\xinttheiiexpr 5/3, round(5/3,3), trunc(5/3,3), trunc(\xintDiv {5}{3},3), +trunc(\xintRaw {5/3},3)\relax{} are problematic, but +% +\xinttheiiexpr 5/3, round(qfrac(5/3),3), trunc(qfrac(5/3),3), floor(qfrac(5/3)), +ceil(qfrac(5/3))\relax{} work! +\end{everbatim*} + +On the other hand decimal numbers and scientific numbers can be used directly +as arguments to the |num|, |round|, or any function producing an integer. + +\begin{framed} + Scientific numbers will be + represented with as many zeroes as necessary, thus one does not want to + insert \dtt{num(1e100000)} for example in an \csa{xintiiexpr}ession! +\end{framed} + +% +\begin{everbatim*} +\xinttheiiexpr num(13.4567e3)+num(10000123e-3)\relax % should (num truncates) compute 13456+10000 +\end{everbatim*} +% + +The |reduce| function is not available and will raise an error. The |frac| +function also. The |sqrt| function is mapped to \csbxint{iiSqrt} which gives +a truncated square root. The |sqrtr| function is mapped to \csbxint{iiSqrtR} +which gives a rounded square root. + +One can use the Float macros if one is careful to use |num|, or |round| +etc\dots on their output. + +\begin{everbatim*} +\xinttheiiexpr \xintFloatSqrt [20]{2}, \xintFloatSqrt [20]{3}\relax % no operations + +\noindent The next example requires the |round|, and one could not put the |+| inside it: + +\xinttheiiexpr round(\xintFloatSqrt [20]{2},19)+round(\xintFloatSqrt [20]{3},19)\relax + +(the second argument of |round| and |trunc| tells how many digits from after the +decimal mark one should keep.) +\end{everbatim*} + +The whole point of \csbxint{iiexpr} is to gain some speed in +\emph{integer-only} algorithms, and the above explanations related to how to +nevertheless use fractions therein are a bit peripheral. We observed +(2013/12/18) of the order of $30$\% speed gain when dealing with numbers with +circa one hundred digits (1.2: this info may be obsolete). + + +\subsection{\csh{xintboolexpr}, \csh{xinttheboolexpr}} +\label{xintboolexpr}\label{xinttheboolexpr}\label{thexintboolexpr} + +Equivalent\etype{x} to doing |\xintexpr ...\relax| and returning $True$ if the +result does not vanish, and $False$ if the result is zero. As |\xintexpr|, this +can be used on comma separated lists of expressions, and even bracketed lists. +\CHANGED{1.4} + +It can be customized, one only needs to modify the following: +\begin{everbatim} +\def\xintboolexprPrintOne#1{\xintiiifNotZero{#1}{True}{False}}% +\end{everbatim} +Not only are |True| and |False| usable in input, also |true| and |false| are +pre-declared variables. + +Maybe obsolete: + +There is slight quirk in case it is used as a sub-expression: the boolean +expression needs at least one logic operation else the value is not +standardized to |1| or |0|, for example we get from +\begin{everbatim*} +\xinttheexpr \xintboolexpr 1.23\relax\relax\newline +\end{everbatim*}which is to be compared with +\begin{everbatim*} +\xinttheboolexpr 1.23\relax +\end{everbatim*} + +% A related issue existed with +% |\xinttheexpr \xintiexpr 1.23\relax\relax|, which was fixed with |1.1| +% release, and I decided back then not to add the needed overhead also to the +% |\xintboolexpr| context, as one only needs to use |?(1.23)| for example or +% involve the |1.23| in any logic operation like |1.23 'and' 3.45|, or involve +% the |\xintboolexpr ..\relax | itself with any logical operation, contrarily to +% the sub-|\xintiexpr| case where |\xinttheexpr 1+\xintiexpr 1.23\relax\relax| +% did behave contrarily to expectations until |1.1|. + + +\subsection{\csh{xintfloatexpr}, + \csh{xintthefloatexpr}} +\label{xintfloatexpr}\label{xintthefloatexpr}\label{thexintfloatexpr} + +\csbxint{floatexpr}|...\relax|\etype{x} is exactly like |\xintexpr...\relax| +but with the four binary operations and the power function are mapped to +\csa{xintFloatAdd}, \csa{xintFloatSub}, \csa{xintFloatMul}, \csa{xintFloatDiv} +and \csa{xintFloatPower}, respectively.\footnote{Since |1.2f| the \string^ + handles half-integer exponents, contrarily to \csa{xintFloatPower}.} + +The target precision for the computation is from the +current setting of |\xintDigits|. Comma separated lists of expressions are +allowed. + +An optional parameter within brackets is allowed: +\begin{itemize} +\item if positive it instructs the macro to round the result to that many + digits of precision. It thus makes sense to employ it only if this parameter is + less than the \csbxint{theDigits} precision. +\item if negative it means to trim off that many digits (of course, in the + sense of rounding + the values to shorter mantissas). Don't use it to trim all digits (or more than all)! +\end{itemize} + +Since |1.2f| all float operations first round their arguments; a parsed number +is not rounded prior to its use as operand to such a float operation. + +|\thexintfloatexpr| is synonym to |\xintthefloatexpr|. + +|\xintDigits:=36\relax|\xintDigits:=36\relax +% +\leftedline{|\xintthefloatexpr + (1/13+1/121)*(1/179-1/173)/(1/19-1/18)\relax|} +% +\leftedline{\dtt{\xintthefloatexpr + (1/13+1/121)*(1/179-1/173)/(1/19-1/18)\relax}} +% 0.00564487459334466559166166079096852897 +% +\leftedline{|\xintthefloatexpr\xintexpr + (1/13+1/121)*(1/179-1/173)/(1/19-1/18)\relax\relax|} +% +\leftedline{\dtt{\xintthefloatexpr\xintexpr + (1/13+1/121)*(1/179-1/173)/(1/19-1/18)\relax\relax}} + +\xintDigits := 16; + +The latter is the rounding of the exact result. The former one has +its last three digits wrong due to the cumulative effect of rounding errors +in the intermediate computations, as compared to exact evaluations. + + + + +I recall here from \autoref{ssec:floatingpoint} that with release |1.2f| the +float macros for addition, subtraction, multiplication and division round +their arguments first to |P| significant places with |P| the asked-for +precision of the output; and similarly the power macros and the +square root macro. This does not modify anything for computations with +arguments having at most |P| significant places already. + +\subsection{\csh{xinteval}, \csh{xintieval}, \csh{xintiieval}, + \csh{xintfloateval}} +\label{xinteval}\label{xintieval}\label{xintiieval}\label{xintfloateval} + +\csbxint{eval}\etype{x} is an \fexpan dable macro which is basically defined +like this (DON'T BELIEVE THIS; it has been entirely revamped at |1.4|): +\begin{everbatim} +\def\xinteval#1{\romannumeral-`0\xinttheexpr#1\relax}% OLD DEFINITION < 1.4 +\end{everbatim} +thus expands in two steps (its exact definition differs from the one given +above in order to achieve a slight optimization). +\begin{everbatim*} +\xinteval{add(x^2, x = 100..110), add(x^3, x = 100..110)} +\end{everbatim*} + +\csbxint{ieval}\etype{x} is similarly related to \csbxint{theiexpr}. Its optional +argument must be located inside the braces: +\begin{everbatim*} +\xintieval{[7] 355/113} +\end{everbatim*} + +\csbxint{iieval}\etype{x} is similarly related to \csbxint{theiiexpr}. +\begin{everbatim*} +\xintiieval{add(x^2, x = 100..110), add(x^3, x = 100..110)} +\end{everbatim*} + +\csbxint{floateval}\etype{x} is similarly related to \csbxint{thefloatexpr}. Its optional +argument must be located inside the braces: +\begin{everbatim*} +\xintfloateval{[7] 355/113} +\end{everbatim*} + +When negative it tells how many digits to remove from the prevailing precision +(\csbxint{theDigits}): +\begin{everbatim*} +\xintfloateval{[-2] 355/113} has \xinttheDigits\ minus 2 digits. +\end{everbatim*} + +These macros are useful when one uses some extra wrapper doing some parsing of +its input, like the |\num| macro of +\href{http://ctan.org/pkg/siunitx}{siunitx}, which would choke on some of the +syntax elements allowed inside \csb{xintexpr}|...\relax| (for example +brackets). +As shown in the above examples, these macros, like the underlying parsers +accept arbitrarily many comma separated expressions. + + +\subsection{Using an expression parser within another one} + +This was already illustrated before. In the following: +\begin{everbatim*} +\xintfloatexpr \xintexpr add(1/i, i=1234..1243)\relax ^100\relax +\end{everbatim*}, +the inner sum is computed exactly. Then it will be rounded to |\xinttheDigits| +significant digits, and then its power will be evaluated as a float operation. +One should avoid the "|\xintthe|" parsers in inner positions as this induces +digit by digit parsing of the inner computation result by the outer parser. +Here is the same computation done with floats all the way: +\begin{everbatim*} +\xintfloatexpr add(1/i, i=1234..1243)^100\relax +\end{everbatim*} + +Not surprisingly this differs from the previous one which was exact until +raising to the |100|th power. + +The fact that the inner expression occurs inside a bigger one has nil +influence on its behaviour. There is the limitation though that the outputs +from \csbxint{expr} and \csbxint{floatexpr} can not be used directly in +\csbxint{theiiexpr} integer-only parser. But one can do: +\begin{everbatim*} +\xintiiexpr round(\xintfloatexpr 3.14^10\relax)\relax % or trunc +\end{everbatim*} + + +\subsection{The \csh{xintthecoords} macro} +\label{xintthecoords} + +It converts (in two expansion steps) the expansion result of +\csbxint{floatexpr} (or \csbxint{expr} or \csbxint{iiexpr}) into the |(a, b) +(c, d) ...| format for list of coordinates as expected by the |TikZ| +|coordinates| syntax.% +\begin{everbatim*} +\begin{figure}[htbp] +\centering\begin{tikzpicture}[scale=10]\xintDigits:=8\relax + \clip (-1.1,-.25) rectangle (.3,.25); + \draw [blue] (-1.1,0)--(1,0); + \draw [blue] (0,-1)--(0,+1); + \draw [red] plot[smooth] coordinates {% +%%% (\xintthecoords converts output of next expression into (x1, y1) (x2, y2)... format) + \xintthecoords\xintfloatexpr +%%% This syntax -1+[0..4]/2 is currenty dropped at xint 1.4 +%%% seq((x^2-1,mul(x-t,t=-1+[0..4]/2)),x=-1.2..[0.1]..+1.2)\relax +%%% Use this: + seq((x^2-1,mul(x-t,t=seq(-1+u/2, u=0..4))),x=-1.2..[0.1]..+1.2) + \relax + }; +\end{tikzpicture} +\caption{Coordinates with \cs{xintthecoords}.} +\end{figure} +\end{everbatim*} + +% Notice: if x goes not take exactly value 1 or -1, the origin appears slightly +% off the curve, not MY fault!!! +It is currently undecided how \csa{xintthecoords} should handle +bracketed data.\UNSTABLE{} + +\subsection{The \csh{xintthespaceseparated} macro} +\label{xintthespaceseparated} + +It converts (in two expansion steps)\NewWith{1.4a} the expansion result of +\csbxint{floatexpr} (or \csbxint{expr} or \csbxint{iiexpr}) into the space +separated format suitable for usage with |PS-Tricks| |\listplot| macro. +\begin{everbatim*} +\oodef\foo{\xintthespaceseparated\xintfloatexpr [4] 1..10\relax} +\meaning\foo +\end{everbatim*} + +It is currently undecided how \csa{xintthespaceseparated} should handle +bracketed data.\UNSTABLE{} + +\subsection{\csh{xintifboolexpr}, \csh{xintifboolfloatexpr}, \csh{xintifbooliiexpr}} +\label{xintifboolexpr} +\label{xintifboolfloatexpr} +\label{xintifbooliiexpr} + +\csh{xintifboolexpr}\marg{expr}\marg{YES}\marg{NO}\etype{xnn} does +\csbxint{theexpr}<expr>|\relax| and then executes the \meta{YES} or the +\meta{NO} branch depending on whether the outcome was non-zero or zero. Thus +one can read \emph{if bool expr} as meaning \emph{if not zero}: +\centeredline{if \meta{expr}-ession does not vanish do \meta{YES} else do + \meta{NO}} + +The expression is not limited to using only comparison operators and Boolean +logic (|<|, |>|, |==|, |!=|, |&&|, \verb+||+, \func{all}, \func{any}, +\func{xor}, \func{bool}, \func{togl}, ...), it can be the most general +computation. + +\csh{xintifboolfloatexpr}\marg{expr}\marg{YES}\marg{NO}\etype{xnn} does +\csbxint{thefloatexpr}\meta{expr}|\relax| and then executes the \meta{YES} or the +\meta{NO} branch depending on whether the outcome was non zero or zero. + +\csh{xintifbooliiexpr}\marg{expr}\marg{YES}\marg{NO}\etype{xnn} does +\csbxint{theiiexpr}\meta{expr}|\relax| and then executes the \meta{YES} or the +\meta{NO} branch depending on whether the outcome was non zero or zero. + +The expression argument must be a single one, comma separated sub-expressions +will cause low-level errors. + +\subsection{\csh{xintifsgnexpr}, \csh{xintifsgnfloatexpr}, \csh{xintifsgniiexpr}} +\label{xintifsgnexpr} +\label{xintifsgnfloatexpr} +\label{xintifsgniiexpr} + +\csh{xintifsgnexpr}\marg{expr}\marg{<0}\marg{=0}\marg{>0}\etype{xnnn} evaluates +the \csbxint{expr}ession and chooses the branch corresponding to its sign. + +\csh{xintifsgnfloatexpr}\marg{expr}\marg{<0}\marg{=0}\marg{>0}\etype{xnnn} evaluates +the \csbxint{floatexpr}ession and chooses the branch corresponding to its sign. + +\csh{xintifsgniiexpr}\marg{expr}\marg{<0}\marg{=0}\marg{>0}\etype{xnnn} evaluates +the \csbxint{iiexpr}ession and chooses the branch corresponding to its sign. + +The expression argument must be a single one, comma separated sub-expressions +will cause low-level errors. + +\subsection{The \csh{xintNewExpr}, \csh{xintNewIIExpr}, + \csh{xintNewFloatExpr}, \csh{xintNewIExpr}, and \csh{xintNewBoolExpr} + macros} +\label{xintNewExpr} +\label{xintNewIIExpr} +\label{xintNewFloatExpr} +\label{xintNewIExpr} +\label{xintNewBoolExpr} + +\csbxint{NewExpr} macro is used as: +% +\leftedline{|\xintNewExpr{\myformula}[n]|\marg{stuff}, where} +\begin{itemize} +\item \meta{stuff} will be inserted inside |\xinttheexpr . . . \relax|, +\item |n| is an integer between zero and nine, inclusive, which is the number + of parameters of |\myformula|, +\item the placeholders |#1|, |#2|, ..., |#n| are used inside \meta{stuff} in + their usual r\^ole,% +% +\catcode`# 12 +\footnote{if \csa{xintNewExpr} is used inside a macro, + the |#|'s must be doubled as usual.} + \footnote{the |#|'s will in pratice have their usual + catcode, but category code other |#|'s are accepted too.} +\catcode`# 6 +% +\item the |[n]| is \emph{mandatory}, even for |n=0|.% +\footnote{there is some use for \csa{xintNewExpr}|[0]| compared to an + \csa{edef} as \csa{xintNewExpr} has some built-in catcode protection.} +\item the macro |\myformula| is defined without checking if it already exists, + \LaTeX{} users might prefer to do first |\newcommand*\myformula {}| to get a + reasonable error message in case |\myformula| already exists, +\item the protection against active characters is done automatically (as long + as the whole thing has not already been fetched as a macro argument and + the catcodes correspondingly already frozen). +\end{itemize} + +It (if it succeeds) will be a completely expandable macro entirely built-up using |\xintAdd|, +|\xintSub|, |\xintMul|, |\xintDiv|, |\xintPow|, etc\dots as corresponds to the +expression written with the infix operators. +Macros created by |\xintNewExpr| can thus be nested. + +\begin{everbatim*} + \xintNewFloatExpr \FA [2]{(#1+#2)^10} + \xintNewFloatExpr \FB [2]{sqrt(#1*#2)} +\begin{enumerate}[nosep] + \item \FA {5}{5} + \item \FB {30}{10} + \item \FA {\FB {30}{10}}{\FB {40}{20}} +\end{enumerate} +\end{everbatim*} + +The documentation is much shortened here because \csbxint{NewExpr} and \csbxint{deffunc} +are very much related one with the other. + +\begin{framed} + ATTENTION! + + The original spirit of \csbxint{NewExpr} was to define a (possibly very big) + macro using only \xintfracname, and this means in particular that it must be + used only with arguments compatible with the \xintfracname input + format.\IMPORTANTf + + Thus an |\xintexpr| declared variable has no chance to work, it must be + wrapped explicitly in |\xinteval{...}| to be fetched as argument to a macro + constructed by \csbxint{NewExpr}. +\end{framed} + +They share essentially the same limitations. + +Notice though that \csbxint{NewFloatExpr} accepts and recognizes the optional +argument |[Q]| of \csbxint{floatexpr}, contrarily to \csbxint{deffloatfunc}. +Use an |\empty| in case the contents are not known in advance. + + +Historical note: prior to |1.4|, \xintexprname used a |\csname..\endcsname| +encapsulation technique which impacted the string pool memory. The +\csbxint{NewExpr} was designed as a method to pre-parse the expression and +produce one single, gigantic, nested usage of the relevant \xintfracname +macros. This way, only those macros were expanded which had nil impact on the +\TeX{} string pool. + +Later on it was found that this mechanism could be employed to define +functions. Basically underneath |98%| of \csbxint{NewExpr} and +\csbxint{deffunc} are using the same shared code. + +\xintDigits:= 16\relax + +\subsection{Analogies and differences of \csh{xintiiexpr} with \csh{numexpr}} + +\csbxint{iiexpr}|..\relax| is a parser of expressions knowing only (big) +integers. There are, besides the enlarged range of allowable inputs, some +important differences of syntax between |\numexpr| and |\xintiiexpr| and +variants: +\begin{itemize} +\item Contrarily to |\numexpr|, the |\xintiiexpr| parser will stop expanding + only after having encountered (and swallowed) a \emph{mandatory} |\relax| + token. +\item In particular, spaces between digits (and not only around infix + operators or parentheses) do not stop |\xintiiexpr|, contrarily to the + situation with |numexpr|: |\the\numexpr 7 + 3 5\relax| expands (in one + step)% +% +\footnote {The |\numexpr| triggers continued expansion after the space + following the |3| to check if some operator like |+| is upstream. But + after having found the |5| it treats it as and end-marker.} +% + to \dtt{\detokenize\expandafter{\the\numexpr 7 + 3 5\relax}\unskip}, whereas + |\xintthe\xintiiexpr 7 + 3 5\relax| expands (in two steps) to + \dtt{\detokenize\expandafter\expandafter\expandafter {\xintthe\xintiiexpr 7 + + 3 5\relax}}.% +% +\footnote {Since |1.2l| one can also use the underscore |_| to separate digits +for readability of long numbers.} + +\item Inside an |\edef|, an expression |\xintiiexpr...\relax| get fully + evaluated, whereas |\numexpr| without |\the| or |\number| prefix would not, + if not itself embedded in another |\the\numexpr| or similar context. +\item (ctd.) The private format to which |\xintiiexpr...\relax| (et al.) + evaluates may use |\xintthe| prefix to turn into explicit digits, + (for example in arguments to some macros which expand their arguments). The |\the| \TeX\ primitive prefix would + not work here. +\item (ctd.) One can embed a |\numexpr...\relax| (with its |\relax|!) inside an + |\xintiiexpr...\relax| without |\the| or |\number|, but the reverse situation + requires usage of |\xintthe| or \csbxint{eval} user interface, +\item |\numexpr -(1)\relax| is illegal. In contrast |\xintiiexpr -(1)\relax| is + perfectly legal and gives the expected result (what else ?). +\item |\numexpr 2\cnta\relax| is illegal (with |\cnta| a |\count| register.) + In contrast + |\xintiiexpr 2\cnta\relax| is perfectly legal and will do the tacit + multiplication. +\item |\the\numexpr| or |\number\numexpr| expands in one step, but + |\xintthe\xintiiexpr| or |\xinttheiiexpr| needs two steps. +\end{itemize} + +\subsection{Chaining expressions for expandable algorithmics} +\label{ssec:fibonacci} + +We will see in this section how to chain |\xintexpr|-essions with +|\expandafter|'s, like it is possible with |\numexpr|. For this it is +convenient to use |\romannumeral0\xintexpro| which is the once-expanded form of +|\xintexpr|, as we can then chain using only one |\expandafter| each time. + +For example, here is the code employed +on the title page to compute (expandably, of course!) the 1250th Fibonacci +number: + +\begin{everbatim*} +\catcode`_ 11 +\def\Fibonacci #1{% \Fibonacci{N} computes F(N) with F(0)=0, F(1)=1. + \expandafter\Fibonacci_a\expandafter + {\the\numexpr #1\expandafter}\expandafter + {\romannumeral0\xintiiexpro 1\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiiexpro 1\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiiexpro 1\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiiexpro 0\relax}} +% +\def\Fibonacci_a #1{% + \ifcase #1 + \expandafter\Fibonacci_end_i + \or + \expandafter\Fibonacci_end_ii + \else + \ifodd #1 + \expandafter\expandafter\expandafter\Fibonacci_b_ii + \else + \expandafter\expandafter\expandafter\Fibonacci_b_i + \fi + \fi {#1}% +}% * signs are omitted from the next macros, tacit multiplications +\def\Fibonacci_b_i #1#2#3{\expandafter\Fibonacci_a\expandafter + {\the\numexpr #1/2\expandafter}\expandafter + {\romannumeral0\xintiiexpro sqr(#2)+sqr(#3)\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiiexpro (2#2-#3)#3\relax}% +}% end of Fibonacci_b_i +\def\Fibonacci_b_ii #1#2#3#4#5{\expandafter\Fibonacci_a\expandafter + {\the\numexpr (#1-1)/2\expandafter}\expandafter + {\romannumeral0\xintiiexpro sqr(#2)+sqr(#3)\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiiexpro (2#2-#3)#3\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiiexpro #2#4+#3#5\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiiexpro #2#5+#3(#4-#5)\relax}% +}% end of Fibonacci_b_ii +% code as used on title page: +%\def\Fibonacci_end_i #1#2#3#4#5{\xintthe#5} +%\def\Fibonacci_end_ii #1#2#3#4#5{\xinttheiiexpr #2#5+#3(#4-#5)\relax} +% new definitions: +\def\Fibonacci_end_i #1#2#3#4#5{{#4}{#5}}% {F(N+1)}{F(N)} in \xintexpr format +\def\Fibonacci_end_ii #1#2#3#4#5% + {\expandafter + {\romannumeral0\xintiiexpro #2#4+#3#5\expandafter\relax + \expandafter}\expandafter + {\romannumeral0\xintiiexpro #2#5+#3(#4-#5)\relax}}% idem. +% \FibonacciN returns F(N) (in encapsulated format: needs \xintthe for printing) +\def\FibonacciN {\expandafter\xint_secondoftwo\romannumeral-`0\Fibonacci }% +\catcode`_ 8 +\end{everbatim*} + + +The macro |\Fibonacci| produces not one specific value |F(N)| but a pair of +successive values |{F(N)}{F(N+1)}| which can then serve as starting point of +another routine devoted to compute a whole sequence |F(N), F(N+1), +F(N+2),....|. Each of |F(N)| and |F(N+1)| is kept in the encapsulated internal +\xintexprname format. + +|\FibonacciN| produces the single |F(N)|. It also keeps it in the private +format; thus printing it will need the |\xintthe| prefix. + +\begingroup\footnotesize\sffamily\baselineskip 10pt +Here a code snippet which +checks the routine via a \string\message\ of the first $51$ Fibonacci +numbers (this is not an efficient way to generate a sequence of such +numbers, it is only for validating \csa{FibonacciN}). +% +\begin{everbatim} +\def\Fibo #1.{\xintthe\FibonacciN {#1}}% +\message{\xintiloop [0+1] \expandafter\Fibo\xintiloopindex., + \ifnum\xintiloopindex<49 \repeat \xintthe\FibonacciN{50}.} +\end{everbatim} +\endgroup + +The way we use |\expandafter|'s to chain successive |\xintiiexpro| evaluations +is exactly analogous to what is possible with |\numexpr|. The various +|\romannumeral0\xintiiexpro| could very well all have been |\xintiiexpr|'s but +then we would have needed |\expandafter\expandafter\expandafter| each +time. + +\begin{framed} + There is a difference though: |\numexpr| does \emph{NOT} expand inside an + |\edef|, and to force its expansion we must prefix it with |\the| or + |\number| or |\romannumeral| or another |\numexpr| which is itself prefixed, + etc\dots. + + But |\xintexpr|, |\xintiexpr|, ..., expand fully in an |\edef|, with the + completely expanded + result encapsulated in a private format. + + Using |\xintthe| as prefix is necessary to print the result (like |\the| or + |\number| in the case of |\numexpr|), but it is not necessary to get the + computation done (contrarily to the situation with |\numexpr|). +\end{framed} + + +Our |\Fibonacci| expands completely under \fexpan sion, so we can use +\hyperref[fdef]{\ttfamily\char92fdef} rather than |\edef| in a situation such +as +% +\leftedline {|\fdef \X {\FibonacciN {100}}|} +% +but it is usually about as efficient to employ |\edef|. And if we want +% +\leftedline{|\edef \Y {(\FibonacciN{100},\FibonacciN{200})}|,} +% +then |\edef| is necessary. + +Allright, so let's now give the code to generate |{F(N)}{F(N+1)}{F(N+2)}...|, +using |\Fibonacci| for the first two and then using the standard recursion +|F(N+2)=F(N+1)+F(N)|: + +\catcode`_ 11 +\def\FibonacciSeq #1#2{%#1=starting index, #2>#1=ending index + \expandafter\Fibonacci_Seq\expandafter + {\the\numexpr #1\expandafter}\expandafter{\the\numexpr #2-1}% +}% +\def\Fibonacci_Seq #1#2{% + \expandafter\Fibonacci_Seq_loop\expandafter + {\the\numexpr #1\expandafter}\romannumeral0\Fibonacci {#1}{#2}% +}% +\def\Fibonacci_Seq_loop #1#2#3#4{% standard Fibonacci recursion + {#3}\unless\ifnum #1<#4 \Fibonacci_Seq_end\fi + \expandafter\Fibonacci_Seq_loop\expandafter + {\the\numexpr #1+1\expandafter}\expandafter + {\romannumeral0\xintiiexpro #2+#3\relax}{#2}{#4}% +}% +\def\Fibonacci_Seq_end\fi\expandafter\Fibonacci_Seq_loop\expandafter + #1\expandafter #2#3#4{\fi {#3}}% +\catcode`_ 8 + +\begingroup\footnotesize\baselineskip10pt +\everb|@ +\catcode`_ 11 +\def\FibonacciSeq #1#2{%#1=starting index, #2>#1=ending index + \expandafter\Fibonacci_Seq\expandafter + {\the\numexpr #1\expandafter}\expandafter{\the\numexpr #2-1}% +}% +\def\Fibonacci_Seq #1#2{% + \expandafter\Fibonacci_Seq_loop\expandafter + {\the\numexpr #1\expandafter}\romannumeral0\Fibonacci {#1}{#2}% +}% +\def\Fibonacci_Seq_loop #1#2#3#4{% standard Fibonacci recursion + {#3}\unless\ifnum #1<#4 \Fibonacci_Seq_end\fi + \expandafter\Fibonacci_Seq_loop\expandafter + {\the\numexpr #1+1\expandafter}\expandafter + {\romannumeral0\xintiiexpro #2+#3\relax}{#2}{#4}% +}% +\def\Fibonacci_Seq_end\fi\expandafter\Fibonacci_Seq_loop\expandafter + #1\expandafter #2#3#4{\fi {#3}}% +\catcode`_ 8 +| +\endgroup + +This |\FibonacciSeq| macro is +completely expandable but it is not \fexpan dable. + +This is not a problem in the next example which uses \csbxint{For*} as the +latter applies repeatedly full expansion to what comes next each time it +fetches an item from its list argument. Thus \csbxint{For*} still manages to +generate the list via iterated full expansion. + + +\begin{figure*}[ht!] + \phantomsection\label{fibonacci} + \newcounter{myindex} + \fdef\Fibxxx{\FibonacciN {30}}% + \setcounter{myindex}{30}% +\centeredline{\tabskip 1ex +\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr + \xintFor* #1 in {\FibonacciSeq {30}{59}}\do + {\themyindex &\xintthe#1 & + \xintiiRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{myindex}\cr }}% +}\vrule +\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr + \xintFor* #1 in {\FibonacciSeq {60}{89}}\do + {\themyindex &\xintthe#1 & + \xintiiRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{myindex}\cr }}% +}\vrule +\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr + \xintFor* #1 in {\FibonacciSeq {90}{119}}\do + {\themyindex &\xintthe#1 & + \xintiiRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{myindex}\cr }}% +}}% +% +\centeredline{Some Fibonacci numbers together with their residues modulo + |F(30)|\dtt{=\xintthe\Fibxxx}} +\end{figure*} + +\begingroup\footnotesize\baselineskip10pt +\everb|@ +\newcounter{myindex}% not "index", which would overwrite theindex environment! +% (many have probably been bitten by this trap) +\tabskip 1ex + \fdef\Fibxxx{\FibonacciN {30}}% + \setcounter{myindex}{30}% +\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr + \xintFor* #1 in {\FibonacciSeq {30}{59}}\do + {\themyindex &\xintthe#1 & + \xintiiRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{myindex}\cr }}% +}\vrule +\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr + \xintFor* #1 in {\FibonacciSeq {60}{89}}\do + {\themyindex &\xintthe#1 & + \xintiiRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{myindex}\cr }}% +}\vrule +\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr + \xintFor* #1 in {\FibonacciSeq {90}{119}}\do + {\themyindex &\xintthe#1 & + \xintiiRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{myindex}\cr }}% +}% +| +\endgroup + +This produces the Fibonacci numbers from |F(30)| to |F(119)|, and +computes also all the +congruence classes modulo |F(30)|. The output has +been put in a \hyperref[fibonacci]{float}, which appears +\vpageref[above]{fibonacci}. I leave to the mathematically inclined +readers the task to explain the visible patterns\dots |;-)|. + +\subsection{When expandability is too much} + +Let's use the macros of \autoref{ssec:fibonacci} related to Fibonacci numbers. +Notice that the $47$th Fibonacci number is \dtt{\xintthe\FibonacciN {47}} thus +already too big for \TeX{} and \eTeX{}. + + +The |\FibonacciN| macro found in \autoref{ssec:fibonacci} is completely +expandable, it is even \fexpan dable. We need a wrapper with |\xintthe| +prefix +\begin{everbatim*} +\def\theFibonacciN{\xintthe\FibonacciN} +\end{everbatim*} +to print in the document or to use within |\message| (or \LaTeX\ |typeout|) to +write to the log and terminal. + +\begingroup + \def\A {1859} \def\B {1573} + \edef\X {\theFibonacciN\A} \edef\Y {\theFibonacciN\B} + \edef\GCDAB {\xintiiGCD\A\B}\edef\Z {\theFibonacciN\GCDAB} + \edef\GCDXY{\xintiiGCD\X\Y} + + The |\xintthe| prefix also allows its use it as argument to the \xintname + macros: for example if we are interested in knowing how many digits + $F(1250)$ has, it suffices to issue |\xintLen {\theFibonacciN {1250}}| + (which expands to \dtt{\xintLen {\theFibonacciN {1250}}}). Or if we want to + check the formula $gcd(F(1859),F(1573))=F(gcd(1859,1573))=F(143)$, we only + need% +% +\footnote{The + \csa{xintiiGCD} macro is provided by both the \xintgcdname package (since + |1.0|) and by the \xintname package (since |1.3d|).} +% +\begin{everbatim} +$\xintiiGCD{\theFibonacciN{1859}}{\theFibonacciN{1573}}=% + \theFibonacciN{\xintiiGCD{1859}{1573}}$ +\end{everbatim} +% +which produces: +% +\leftedline{$\dtt{\xintiiGCD{\X}{\Y}}=\dtt{\theFibonacciN{\GCDAB}}$} + +The |\theFibonacciN| macro expanded its |\xintiiGCD{1859}{1573}| argument via the +services of |\numexpr|: this step allows only things obeying the \TeX{} bound, +naturally! (but \dtt{F(\xintiiPow2{31}}) would be rather big anyhow...). + +This is very convenient but of course it repeats the complete evaluation each +time it is done. In practice, it is often useful to store the result of such +evaluations in macros. Any |\edef| will break expandability, but if the goal +is at some point to print something to the |dvi| or |pdf| output, and not only +to the |log| file, then expandability has to be broken one day or another! + +Hence, in practice, if we want to print in the document some computation +results, we can proceed like this and avoid having to repeat identical +evaluations: +\begin{everbatim} +\begingroup + \def\A {1859} \def\B {1573} + \edef\X {\theFibonacciN\A} \edef\Y {\theFibonacciN\B} + \edef\GCDAB {\xintiiGCD\A\B}\edef\Z {\theFibonacciN\GCDAB} + \edef\GCDXY{\xintiiGCD\X\Y} +The identity $\gcd(F(\A),F(\B))=F(\gcd(\A,\B))$ can be checked via evaluation +of both sides: $\gcd(F(\A),F(\B))=\gcd(\printnumber\X,\printnumber\Y)= +\printnumber{\GCDXY} = F(\gcd(\A,\B)) = F(\GCDAB) =\printnumber\Z$.\par + % some further computations involving \A, \B, \X, \Y +\endgroup % closing the group removes assignments to \A, \B, ... +% or choose longer names less susceptible to overwrite something. +% Note: there is no LaTeX \newecommand which would be to \edef like \newcommand is to \def +\end{everbatim} +The identity $\gcd(F(\A),F(\B))=F(\gcd(\A,\B))$ can be checked via evaluation +of both sides: $\gcd(F(\A),F(\B))=\gcd(\printnumber\X,\printnumber\Y)= +\printnumber{\GCDXY} = F(\gcd(\A,\B)) = F(\GCDAB) =\printnumber\Z$.\par +\endgroup + +One may legitimately ask the author: why expandability +to such extremes, for things such as big fractions or floating point numbers +(even continued fractions...) which anyhow can not be used directly within +\TeX's primitives such as |\ifnum|? Why insist on a concept +which is foreign to the vast majority of \TeX\ users and even programmers? + +I have no answer: it made definitely sense at the start of \xintname (see +\autoref{ssec:origins}) and once started I could not stop. + + +\subsection{Acknowledgements (2013/05/25)} + +I was greatly helped in my preparatory thinking, prior to producing such an +expandable parser, by the commented source of the +\href{https://ctan.org/pkg/l3kernel}{l3fp} package, specifically the +|l3fp-parse.dtx| file (in the version of April-May 2013; I think there was in +particular a text called ``roadmap'' which was helpful). Also the source of the +|calc| package was instructive, despite the fact that here for |\xintexpr| the +principles are necessarily different due to the aim of achieving expandability. + +\clearpage +\expandafter\let\csname xintexprnameUp\endcsname\undefined +\csname ExamplesnameUp\endcsname +\section {More examples with \xinttoolsname or \xintexprname or both} +\RaisedLabel{sec:examples} + +Note: \xintexprname.sty automatically loads \xinttoolsname.sty. + +The examples given here start to feel dated and are currently in need of some +rewrite to better illustrate newer features of the package. + + +\localtableofcontents + +\subsection{More examples with dummy variables} +\label{ssec:moredummies} + +These examples were first added to this manual at the time of the |1.1| +release (|2014/10/29|). + +\begin{everbatim*} +Prime numbers are always cool +\xinttheiiexpr seq((seq((subs((x/:m)?{(m*m>x)?{1}{0}}{-1},m=2n+1)) + ??{break(0)}{omit}{break(1)},n=1++))?{x}{omit}, + x=10001..[2]..10200)\relax +\end{everbatim*} + +The syntax in this last example may look a bit involved (... and it is so I +admit). First |x/:m| computes |x modulo m| (this is the modulo with respect to +floored division). The |(x)?{yes}{no}| construct checks if |x| (which +\emph{must} be within parentheses) is true or false, i.e. non zero or zero. It +then executes either the |yes| or the |no| branch, the non chosen branch is +\emph{not} evaluated. Thus if |m| divides |x| we are in the second (``false'') +branch. This gives a |-1|. This |-1| is the argument to a |??| branch which is +of the type |(y)??{y<0}{y=0}{y>0}|, thus here the |y<0|, i.e., |break(0)| is +chosen. This |0| is thus given to another |?| which consequently chooses +|omit|, hence the number is not kept in the list. The numbers which survive +are the prime numbers. + +\begin{everbatim*} +The first Fibonacci number beyond |2^64| bound is +\xinttheiiexpr subs(iterr(0,1;(@1>N)?{break(i)}{@1+@2},i=1++),N=2^64)\relax{} +and the previous number was its index. +\end{everbatim*} + +% A006877 In the `3x+1' problem, these values for the starting value set new +% records for number of steps to reach 1. (Formerly M0748) 14 1, 2, 3, 6, 7, +% 9, 18, 25, 27, 54, 73, 97, 129, 171, 231, 313, 327, 649, 703, 871, 1161, +% 2223, 2463, 2919, 3711, 6171, 10971, 13255, 17647, 23529, 26623, 34239, +% 35655, 52527, 77031, 106239, 142587, 156159, 216367, 230631, 410011, 511935, +% 626331, 837799 + +One more recursion: +\begin{everbatim*} +\def\syr #1{\xinttheiiexpr rseq(#1; (@<=1)?{break(i)}{odd(@)?{3@+1}{@//2}},i=0++)\relax} +The 3x+1 problem: \syr{231}\par +\end{everbatim*} + +OK, a final one: +\begin{everbatim*} +\def\syrMax #1{\xinttheiiexpr iterr(#1,#1;even(i)? + {(@2<=1)?{break(i/2)}{odd(@2)?{3@2+1}{@2//2}}} + {(@1>@2)?{@1}{@2}},i=0++)\relax } +With initial value 1161, the maximal number attained is \syrMax{1161} and that latter +number is the number of steps which was needed to reach 1.\par +\end{everbatim*} + +Look at the + \hyperlink{BrentSalamin}{Brent-Salamin algorithm implementation} for a more + interesting recursion. + +% \begin{everbatim*} +% \newcommand\Factors [1]{\xinttheiiexpr +% subs(seq((i/:3=1)?{omit}{[L][i]},i=0..len(L)-1), +% L=rseq(#1;(p^2>[@][0])?{([@][0]>1)?{break(1,[@][0],1)}{abort}} +% {(([@][0])/:p)?{omit} +% {iter(([@][0])//p; (@/:p)?{break(@,p,e)}{@//p},e=1++)}},p=2++))\relax } +% \Factors {41^4*59^2*29^3*13^5*17^8*29^2*59^4*37^6} +% \end{everbatim*} + +% This might look a bit scary, I admit.% +% % +% \footnote{Look at the +% \hyperlink{BrentSalamin}{Brent-Salamin algorithm implementation} for a much +% saner example.} +% % + +% \xintexprname has minimal tools and +% is obstinate about doing everything expandably! We are hampered by absence of a +% notion of ``nuple''. The algorithm divides |N| by |2| until no more possible, +% then by |3|, then by |4| (which is silly), then by |5|, then by |6| (silly +% again), \dots. + +% The variable |L=rseq(#1;...)| expands, if one follows the steps, to a comma +% separated list starting with the initial (evaluated) |N=#1| and then +% pseudo-triplets where the first item is |N| trimmed of small primes, the +% second item is the last prime divisor found, and the third item is its +% exponent in original |N|. + +% The algorithm needs to keep handy the last computed quotient by prime powers, +% hence all of them, but at the very end it will be cleaner to get rid of them +% (this corresponds to the first line in the code above). This is achieved in a +% cumbersome inefficient way; indeed each item extraction |[L][i]| is costly: it +% is not like accessing an array stored in memory, due to expandability, nothing +% can be stored in memory! Nevertheless, this step could be done here in a far +% less inefficient manner if there was a variant of |seq| which, in the spirit +% of \csbxint{iloopindex}, would know how many steps it had been through so far. +% This is a feature to be added to |\xintexpr|! (as well as a |++| construct +% allowing a non unit step). + +% Notice that in |iter(([@][0])//p;| the |@| refers to the previous triplet (or +% in the first step to |N|), but the latter |@| showing up in |(@/:p)?| refers +% to the previous value computed by |iter|. + +% \begin{snugframed} +% Parentheses are essential in |..([y][0])| else the parser will see |..[| and +% end up in ultimate confusion, and also in |([@][0])/:p| else the parser will +% see the itemwise operator |]/| on lists and again be very confused (I could +% implement a |]/:| on lists, but in this situation this would also be very +% confusing to the parser.) +% \end{snugframed} + +% See \autoref{ssec:factorize} for a routine |\Factorize| written directly with +% \xintname macros. Last time I checked |\Factors| was about seven times slower +% than |\Factorize| in test cases such as +% |16246355912554185673266068721806243461403654781833| and others. Among the +% various things explaining the speed difference, there is fact that the +% |\Factorize| algorithm step by increments of two, not one, and also it divides +% only once, obtaining quotient and remainder in one go. These two things +% already make for a speed-up factor of about four. Thus, |\Factors| is not +% completely inefficient in comparison, and was quite easier to come up with +% than |\Factorize|. + +\subsection{Completely expandable prime test} +\label{ssec:primesI} + +Let us now construct a completely expandable macro which returns $1$ if its +given input is prime and $0$ if not: +\everb|@ +\def\remainder #1#2{\the\numexpr #1-(#1/#2)*#2\relax } +\def\IsPrime #1% + {\xintANDof {\xintApply {\remainder {#1}}{\xintSeq {2}{\xintiiSqrt{#1}}}}} +| + +This uses \csbxint{iiSqrt} and assumes its input is at least $5$. Rather than +\xintname's own \csbxint{iiRem} we used a quicker |\numexpr| expression as we +are dealing with short integers. Also we used \csbxint{ANDof} which will +return $1$ only if all the items are non-zero. The macro is a bit +silly with an even input, ok, let's enhance it to detect an even input: +\everb|@ +\def\IsPrime #1% + {\xintiiifOdd {#1} + {\xintANDof % odd case + {\xintApply {\remainder {#1}} + {\xintSeq [2]{3}{\xintiiSqrt{#1}}}% + }% + } + {\xintifEq {#1}{2}{1}{0}}% + } +| + +We used the \xintname expandable tests (on big integers or fractions) +in order for |\IsPrime| to be \fexpan dable. + +Our integers are short, but without |\expandafter|'s with +|\@firstoftwo|, % @ n'est plus actif dans le dtx 1.1 ! +or some other related techniques, +direct use of |\ifnum..\fi| tests is dangerous. So to make the macro more +efficient we are going to use the expandable tests provided by the package +\href{http://ctan.org/pkg/etoolbox}{etoolbox}% +% +\footnote{\url{http://ctan.org/pkg/etoolbox}}. +% +The macro becomes: +% +\everb|@ +\def\IsPrime #1% + {\ifnumodd {#1} + {\xintANDof % odd case + {\xintApply {\remainder {#1}}{\xintSeq [2]{3}{\xintiiSqrt{#1}}}}} + {\ifnumequal {#1}{2}{1}{0}}} +| + +In the odd case however we have to assume the integer is at least $7$, as +|\xintSeq| generates an empty list if |#1=3| or |5|, and |\xintANDof| returns +$1$ when supplied an empty list. Let us ease up a bit |\xintANDof|'s work by +letting it work on only $0$'s and $1$'s. We could use: +% +\everb|@ +\def\IsNotDivisibleBy #1#2% + {\ifnum\numexpr #1-(#1/#2)*#2=0 \expandafter 0\else \expandafter1\fi} +| +\noindent +where the |\expandafter|'s are crucial for this macro to be \fexpan dable and +hence work within the applied \csbxint{ANDof}. Anyhow, now that we have loaded +\href{http://ctan.org/pkg/etoolbox}{etoolbox}, we might as well use: +% +\everb|@ +\newcommand{\IsNotDivisibleBy}[2]{\ifnumequal{#1-(#1/#2)*#2}{0}{0}{1}} +| +\noindent +Let us enhance our prime macro to work also on the small primes: +\everb|@ +\newcommand{\IsPrime}[1] % returns 1 if #1 is prime, and 0 if not + {\ifnumodd {#1} + {\ifnumless {#1}{8} + {\ifnumequal{#1}{1}{0}{1}}% 3,5,7 are primes + {\xintANDof + {\xintApply + { \IsNotDivisibleBy {#1}}{\xintSeq [2]{3}{\xintiiSqrt{#1}}}}% + }}% END OF THE ODD BRANCH + {\ifnumequal {#1}{2}{1}{0}}% EVEN BRANCH +} +| + +The input is still assumed positive. There is a deliberate blank before +\csa{IsNotDivisibleBy} to use this feature of \csbxint{Apply}: a space stops the +expansion of the applied macro (and disappears). This expansion will be done by +\csbxint{ANDof}, which has been designed to skip everything as soon as it finds +a false (i.e. zero) input. This way, the efficiency is considerably improved. + +We did generate via the \csbxint{Seq} too many potential divisors though. Later +sections give two variants: one with \csbxint{iloop} (\autoref{ssec:primesII}) +which is still expandable and another one (\autoref{ssec:primesIII}) which is a +close variant of the |\IsPrime| code above but with the \csbxint{For} loop, thus +breaking expandability. The \hyperref[ssec:primesII]{xintiloop variant} does not +first evaluate the integer square root, the \hyperref[ssec:primesIII]{xintFor + variant} still does. I did not compare their efficiencies. + + +Let us construct with this expandable primality test a table of the prime +numbers up to $1000$. We need to count how many we have in order to know how +many tab stops one shoud add in the last row.% +% +\footnote{although a tabular row may have less tabs than in the + preamble, there is a problem with the \char`\|\space\space vertical + rule, if one does that.} +% +There is some subtlety for this +last row. Turns out to be better to insert a |\\| only when we know for sure we +are starting a new row; this is how we have designed the |\OneCell| macro. And +for the last row, there are many ways, we use again |\xintApplyUnbraced| but +with a macro which gobbles its argument and replaces it with a tabulation +character. The \csbxint{For*} macro would be more elegant here. +% +\everb?@ +\newcounter{primecount} +\newcounter{cellcount} +\newcommand{\NbOfColumns}{13} +\newcommand{\OneCell}[1]{% + \ifnumequal{\IsPrime{#1}}{1} + {\stepcounter{primecount} + \ifnumequal{\value{cellcount}}{\NbOfColumns} + {\\\setcounter{cellcount}{1}#1} + {&\stepcounter{cellcount}#1}% + } % was prime + {}% not a prime, nothing to do +} +\newcommand{\OneTab}[1]{&} +\begin{tabular}{|*{\NbOfColumns}{r}|} +\hline +2 \setcounter{cellcount}{1}\setcounter{primecount}{1}% + \xintApplyUnbraced \OneCell {\xintSeq [2]{3}{999}}% + \xintApplyUnbraced \OneTab + {\xintSeq [1]{1}{\the\numexpr\NbOfColumns-\value{cellcount}\relax}}% + \\ +\hline +\end{tabular} +There are \arabic{primecount} prime numbers up to 1000. +? + +The table has been put in \hyperref[primesupto1000]{float} which appears +\vpageref{primesupto1000}. +We had to be careful to use in the last row \csbxint{Seq} with its optional +argument |[1]| so as to not generate a decreasing sequence from |1| to |0|, but +really an empty sequence in case the row turns out to already have all its +cells (which doesn't happen here but would with a number of columns dividing +$168$). +% +\newcommand{\IsNotDivisibleBy}[2]{\ifnumequal{#1-(#1/#2)*#2}{0}{0}{1}} + +\newcommand{\IsPrime}[1] + {\ifnumodd {#1} + {\ifnumless {#1}{8} + {\ifnumequal{#1}{1}{0}{1}}% 3,5,7 are primes + {\xintANDof + {\xintApply + { \IsNotDivisibleBy {#1}}{\xintSeq [2]{3}{\xintiiSqrt{#1}}}}% + }}% END OF THE ODD BRANCH + {\ifnumequal {#1}{2}{1}{0}}% EVEN BRANCH +} + +\newcounter{primecount} +\newcounter{cellcount} +\newcommand{\NbOfColumns}{13} +\newcommand{\OneCell}[1] + {\ifnumequal{\IsPrime{#1}}{1} + {\stepcounter{primecount} + \ifnumequal{\value{cellcount}}{\NbOfColumns} + {\\\setcounter{cellcount}{1}#1} + {&\stepcounter{cellcount}#1}% + } % was prime + {}% not a prime nothing to do +} +\newcommand{\OneTab}[1]{&} +\begin{figure*}[ht!] + \centering + \phantomsection\label{primesupto1000} + \begin{tabular}{|*{\NbOfColumns}{r}|} + \hline + 2\setcounter{cellcount}{1}\setcounter{primecount}{1}% + \xintApplyUnbraced \OneCell {\xintSeq [2]{3}{999}}% + \xintApplyUnbraced \OneTab + {\xintSeq [1]{1}{\the\numexpr\NbOfColumns-\value{cellcount}\relax}}% + \\ + \hline + \end{tabular} +\smallskip +\centeredline{There are \arabic{primecount} prime numbers up to 1000.} +\end{figure*} + +\subsection{Another completely expandable prime test} +\label{ssec:primesII} + +The |\IsPrime| macro from \autoref{ssec:primesI} checked expandably if a (short) +integer was prime, here is a partial rewrite using \csbxint{iloop}. We use the +|etoolbox| expandable conditionals for convenience, but not everywhere as +|\xintiloopindex| can not be evaluated while being braced. This is also the +reason why |\xintbreakiloopanddo| is delimited, and the next macro +|\SmallestFactor| which returns the smallest prime factor examplifies that. One +could write more efficient completely expandable routines, the aim here was only +to illustrate use of the general purpose \csbxint{iloop}. A little table giving +the first values of |\SmallestFactor| follows, its coding uses \csbxint{For}, +which is described later; none of this uses count registers. +% + + +\begin{everbatim*} +\let\IsPrime\undefined \let\SmallestFactor\undefined % clean up possible previous mess +\newcommand{\IsPrime}[1] % returns 1 if #1 is prime, and 0 if not + {\ifnumodd {#1} + {\ifnumless {#1}{8} + {\ifnumequal{#1}{1}{0}{1}}% 3,5,7 are primes + {\if + \xintiloop [3+2] + \ifnum#1<\numexpr\xintiloopindex*\xintiloopindex\relax + \expandafter\xintbreakiloopanddo\expandafter1\expandafter.% + \fi + \ifnum#1=\numexpr (#1/\xintiloopindex)*\xintiloopindex\relax + \else + \repeat 00\expandafter0\else\expandafter1\fi + }% + }% END OF THE ODD BRANCH + {\ifnumequal {#1}{2}{1}{0}}% EVEN BRANCH +}% +\catcode`_ 11 +\newcommand{\SmallestFactor}[1] % returns the smallest prime factor of #1>1 + {\ifnumodd {#1} + {\ifnumless {#1}{8} + {#1}% 3,5,7 are primes + {\xintiloop [3+2] + \ifnum#1<\numexpr\xintiloopindex*\xintiloopindex\relax + \xint_afterfi{\xintbreakiloopanddo#1.}% + \fi + \ifnum#1=\numexpr (#1/\xintiloopindex)*\xintiloopindex\relax + \xint_afterfi{\expandafter\xintbreakiloopanddo\xintiloopindex.}% + \fi + \iftrue\repeat + }% + }% END OF THE ODD BRANCH + {2}% EVEN BRANCH +}% +\catcode`_ 8 +{\centering + \begin{tabular}{|c|*{10}c|} + \hline + \xintFor #1 in {0,1,2,3,4,5,6,7,8,9}\do {&\bfseries #1}\\ + \hline + \bfseries 0&--&--&2&3&2&5&2&7&2&3\\ + \xintFor #1 in {1,2,3,4,5,6,7,8,9}\do + {\bfseries #1% + \xintFor #2 in {0,1,2,3,4,5,6,7,8,9}\do + {&\SmallestFactor{#1#2}}\\}% + \hline + \end{tabular}\par +} +\end{everbatim*} + +\subsection{Miller-Rabin Pseudo-Primality expandably} +\label{ssec:PrimesIV} + + +% At the time of writing, the code at the link above is still the version from +% April 2016 and it needed some hacks to get recursive (pseudo)-functions +% defined. Since |1.2h| of |2016/11/20| there is \csbxint{NewFunction} which +% allows us here to avoid such internal hacking. + +% And since |1.3| of |2018/03/01|, it is possible to use \csbxint{defiifunc} +% also for recursive definitions, so we use it here, but we can benefit from it +% only for modular exponentiation as the rest of the code uses |iter| or |break| +% statements which are not yet compatible with \csbxint{defiifunc}. + +The |isPseudoPrime(n)| is usable in \csbxint{iiexpr}-essions and establishes +if its (positive) argument is a Miller-Rabin PseudoPrime to the bases $2, 3, +5, 7, 11, 13, 17$. If this is true and $n<341550071728321$ (which has 15 +digits) then $n$ really is a prime number. + +Similarly $n=3825123056546413051$ (19 digits) is the smallest composite number +which is a strong pseudo prime for bases $2, 3, 5, 7, 11, 13, 17, 19$ and +$23$. It is easy to extend the code below to include these additional tests +(we could make the list of tested bases an argument too, now that I think +about it.) + +For more information see + \centeredline{\url{https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test#Deterministic_variants_of_the_test}} + and +\centeredline{\url{http://primes.utm.edu/prove/prove2_3.html}} + +In particular, according to \textsc{Jaeschke} \emph{On strong pseudoprimes to + several bases,} Math. Comp., 61 (1993) 915-926, if $n < 4,759,123,141$ it is +enough to establish Rabin-Miller pseudo-primality to bases $a = 2, 7, 61$ to +prove that $n$ is prime. This range is enough for \TeX\ numbers and we could +then write a very fast expandable primality test for such numbers using only +|\numexpr|. Left as an exercise\dots + +\begin{everbatim*} +% I -------------------------------- Modular Exponentiation +% Computes x^m modulo n (with m non negative). +% We will always use it with 1 < x < n +% +% With xint 1.4 we should use ? and ?? (although in the case at hand ifsgn() +% and if() are ok; 1.4 still converts them to short-circuit branchers). +% The 1.4 xint.pdf was still giving here the code with ifone() and if() +% functions (given below after the one here using ? as demanded by the +% documentation) +% +\xintdefiifunc powmod_a(x, m, n) := + isone(m)? + % m=1, return x modulo n + { x /: n } + % m > 1 test if odd or even and do recursive call + { odd(m)? { x*sqr(powmod_a(x, m//2, n)) /: n } + { sqr(powmod_a(x, m//2, n)) /: n } + } + ; +\xintdefiifunc powmod(x, m, n) := (m)?{powmod_a(x, m, n)}{1}; + +%% Syntax used before xint 1.4: +% \xintdefiifunc powmod_a(x, m, n) := +% ifone(m, +% % m=1, return x modulo n +% x /: n, +% % m > 1 test if odd or even and do recursive call +% if(odd(m), (x*sqr(powmod_a(x, m//2, n))) /: n, +% sqr(powmod_a(x, m//2, n)) /: n +% ) +% ); +% \xintdefiifunc powmod(x, m, n) := if(m, powmod_a(x, m, n), 1); + +% II ------------------------------ Miller-Rabin compositeness witness + +% n=2^k m + 1 with m odd and k at least 1 + +% Choose 1<x<n. +% compute y=x^m modulo n +% if equals 1 we can't say anything +% if equals n-1 we can't say anything +% else put j=1, and +% compute repeatedly the square, incrementing j by 1 each time, +% thus always we have y^{2^{j-1}} +% -> if at some point n-1 mod n found, we can't say anything and break out +% -> if however we never find n-1 mod n before reaching +% z=y^{2^{k-1}} with j=k +% we then have z^2=x^{n-1}. + % Suppose z is not -1 mod n. If z^2 is 1 mod n, then n can be prime only if + % z is 1 mod n, and we can go back up, until initial y, and we have already + % excluded y=1. Thus if z is not -1 mod n and z^2 is 1 then n is not prime. + % But if z^2 is not 1, then n is not prime by Fermat. Hence (z not -1 mod n) + % implies (n is composite). (Miller test) + +% let's use again xintexpr indecipherable (except to author) syntax. Of course +% doing it with macros only would be faster. + +% Here \xintdefiifunc is not usable because not compatible with iter, break, ... +% but \xintNewFunction comes to the rescue. + +\xintNewFunction{isCompositeWitness}[4]{% x=#1, n=#2, m=#3, k=#4 + subs((y==1)?{0} + {iter(y;(j=#4)?{break(!(@==#2-1))} + {(@==#2-1)?{break(0)}{sqr(@)/:#2}},j=1++)} + ,y=powmod(#1,#3,#2))} + +% added note (2018/03/07) it is possible in the above that m=#3 is never +% zero, so we should rather call powmod_a for a small gain, but I don't +% have time to re-read the code comments and settle this. + +% III ------------------------------------- Strong Pseudo Primes + +% cf +% http://oeis.org/A014233 +% <http://mathworld.wolfram.com/Rabin-MillerStrongPseudoprimeTest.html> +% <http://mathworld.wolfram.com/StrongPseudoprime.html> + +% check if positive integer <49 si a prime. +% 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47 +\def\IsVerySmallPrime #1% + {\ifnum#1=1 \xintdothis0\fi + \ifnum#1=2 \xintdothis1\fi + \ifnum#1=3 \xintdothis1\fi + \ifnum#1=5 \xintdothis1\fi + \ifnum#1=\numexpr (#1/2)*2\relax\xintdothis0\fi + \ifnum#1=\numexpr (#1/3)*3\relax\xintdothis0\fi + \ifnum#1=\numexpr (#1/5)*5\relax\xintdothis0\fi + \xintorthat 1} + +\xintNewFunction{isPseudoPrime}[1]{% n = #1 + (#1<49)?% use ? syntax to evaluate only what is needed + {\IsVerySmallPrime{\xintthe#1}}% macro needs to be fed with #1 unlocked. + {(even(#1))? + {0} + {subs(% + % L expands to two values m, k hence isCompositeWitness does get + % its four variables x, n, m, k + isCompositeWitness(2, #1, L)? + {0}% + {isCompositeWitness(3, #1, L)? + {0}% + {isCompositeWitness(5, #1, L)? + {0}% + {isCompositeWitness(7, #1, L)? + {0}% +% above enough for N<3215031751 hence all TeX numbers + {isCompositeWitness(11, #1, L)? + {0}% +% above enough for N<2152302898747, hence all 12-digits numbers + {isCompositeWitness(13, #1, L)? + {0}% +% above enough for N<3474749660383 + {isCompositeWitness(17, #1, L)? + {0}% +% above enough for N<341550071728321 + {1}% + }% not needed to comment-out end of lines spaces inside + }% \xintexpr but this is too much of a habit for me with TeX! + }% I left some after the ? characters. + }% + }% + }% this computes (m, k) such that n = 2^k m + 1, m odd, k>=1 + , L=iter(#1//2;(even(@))?{@//2}{break(@,k)},k=1++))% + }% + }% +} + +% if needed: +%\def\IsPseudoPrime #1{\xinttheiiexpr isPseudoPrime(#1)\relax} + +\noindent The smallest prime number at least equal to 3141592653589 is +\xinttheiiexpr + seq(isPseudoPrime(3141592653589+n)? + {break(3141592653589+n)}{omit}, n=0++)\relax. +% we could not use 3141592653589++ syntax because it works only with TeX numbers +\par +\end{everbatim*} + + + + + +\subsection{A table of factorizations} +\label{ssec:factorizationtable} + +As one more example with \csbxint{iloop} let us use an alignment to display the +factorization of some numbers. The loop will actually only play a minor r\^ole +here, just handling the row index, the row contents being almost entirely +produced via a macro |\factorize|. The factorizing macro does not use +|\xintiloop| as it didn't appear to be the convenient tool. As |\factorize| will +have to be used on |\xintiloopindex|, it has been defined as a delimited macro. + +To spare some fractions of a second in the compilation time of this document +(which has many many other things to do), \number"7FFFFFED{} and +\number"7FFFFFFF, which turn out to be prime numbers, are not given to +|factorize| but just typeset directly; this illustrates use of +\csbxint{iloopskiptonext}. + +The code next generates a \hyperref[floatfactorize]{table} which has +been made into a float appearing \vpageref{floatfactorize}. Here is now +the code for factorization; the conditionals use the package provided +|\xint_firstoftwo| and |\xint_secondoftwo|, one could have employed +rather \LaTeX{}'s own |\@firstoftwo| and |\@secondoftwo|, or, simpler +still in \LaTeX{} context, the |\ifnumequal|, |\ifnumless| \dots, +utilities from the package |etoolbox| which do exactly that under the +hood. Only \TeX{} acceptable numbers are treated here, but it would be +easy to make a translation and use the \xintname macros, thus extending +the scope to big numbers; naturally up to a cost in speed. + +The reason for some strange looking expressions is to avoid arithmetic overflow. + +\begin{everbatim*} +\catcode`_ 11 +\def\abortfactorize #1\xint_secondoftwo\fi #2#3{\fi} + +\def\factorize #1.{\ifnum#1=1 \abortfactorize\fi + \ifnum\numexpr #1-2=\numexpr ((#1/2)-1)*2\relax + \expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo + \fi + {2&\expandafter\factorize\the\numexpr#1/2.}% + {\factorize_b #1.3.}}% + +\def\factorize_b #1.#2.{\ifnum#1=1 \abortfactorize\fi + \ifnum\numexpr #1-(#2-1)*#2<#2 + #1\abortfactorize + \fi + \ifnum \numexpr #1-#2=\numexpr ((#1/#2)-1)*#2\relax + \expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo + \fi + {#2&\expandafter\factorize_b\the\numexpr#1/#2.#2.}% + {\expandafter\factorize_b\the\numexpr #1\expandafter.% + \the\numexpr #2+2.}}% +\catcode`_ 8 +\begin{figure*}[ht!] +\centering\phantomsection\label{floatfactorize}\normalcolor +\tabskip1ex +\centeredline{\vbox{\halign {\hfil\strut#\hfil&&\hfil#\hfil\cr\noalign{\hrule} + \xintiloop ["7FFFFFE0+1] + \expandafter\bfseries\xintiloopindex & + \ifnum\xintiloopindex="7FFFFFED + \number"7FFFFFED\cr\noalign{\hrule} + \expandafter\xintiloopskiptonext + \fi + \expandafter\factorize\xintiloopindex.\cr\noalign{\hrule} + \ifnum\xintiloopindex<"7FFFFFFE + \repeat + \bfseries \number"7FFFFFFF&\number "7FFFFFFF\cr\noalign{\hrule} +}}} +\centeredline{A table of factorizations} +\end{figure*} +\end{everbatim*} + +\subsection{Another table of primes} +\label{ssec:primesIII} + +As a further example, let us dynamically generate a tabular with the first $50$ +prime numbers after $12345$. First we need a macro to test if a (short) number +is prime. Such a completely expandable macro was given in \autoref{ssec:primesI}, +here we consider a variant which will be slightly more efficient. This new +|\IsPrime| has two parameters. The first one is a macro which it redefines to +expand to the result of the primality test applied to the second argument. For +convenience we use the \href{http://ctan.org/pkg/etoolbox}{etoolbox} wrappers to +various |\ifnum| tests, although here there isn't anymore the constraint of +complete expandability (but using explicit |\if..\fi| in tabulars has its +quirks); equivalent tests are provided by \xintname, but they have some overhead +as they are able to deal with arbitrarily big integers. + +\def\IsPrime #1#2% +{\edef\TheNumber {\the\numexpr #2}% positive integer + \ifnumodd {\TheNumber} + {\ifnumgreater {\TheNumber}{1} + {\edef\ItsSquareRoot{\xintiiSqrt \TheNumber}% + \xintFor ##1 in {\xintintegers [3+2]}\do + {\ifnumgreater {##1}{\ItsSquareRoot} + {\def#1{1}\xintBreakFor} + {}% + \ifnumequal {\TheNumber}{(\TheNumber/##1)*##1} + {\def#1{0}\xintBreakFor } + {}% + }} + {\def#1{0}}}% 1 is not prime + {\ifnumequal {\TheNumber}{2}{\def#1{1}}{\def#1{0}}}% +}% + +\everb|@ +\def\IsPrime #1#2% """color[named]{PineGreen}#1=\Result, #2=tested number (assumed >0).;! +{\edef\TheNumber {\the\numexpr #2}%"""color[named]{PineGreen} hence #2 may be a count or \numexpr.;! + \ifnumodd {\TheNumber} + {\ifnumgreater {\TheNumber}{1} + {\edef\ItsSquareRoot{\xintiiSqrt \TheNumber}% + \xintFor """color{red}##1;! in {"""color{red}\xintintegers;! [3+2]}\do + {\ifnumgreater {"""color{red}##1;!}{\ItsSquareRoot} """color[named]{PineGreen}% "textcolor{red}{##1} is a \numexpr.;! + {\def#1{1}\xintBreakFor} + {}% + \ifnumequal {\TheNumber}{(\TheNumber/##1)*##1} + {\def#1{0}\xintBreakFor } + {}% + }} + {\def#1{0}}}% 1 is not prime + {\ifnumequal {\TheNumber}{2}{\def#1{1}}{\def#1{0}}}% +} +| + +As we used \csbxint{For} inside a macro we had to double the |#| in its |#1| +parameter. Here is now the code which creates the prime table (the table has +been put in a \hyperref[primes]{float}, which should be found on page +\pageref{primes}): + +\everb?@ +\newcounter{primecount} +\newcounter{cellcount} +\begin{figure*}[ht!] + \centering + \begin{tabular}{|*{7}c|} + \hline + \setcounter{primecount}{0}\setcounter{cellcount}{0}% + \xintFor """color{red}#1;! in {"""color{red}\xintintegers;! [12345+2]} \do +"""color[named]{PineGreen}% "textcolor{red}{#1} is a \numexpr.;! + {\IsPrime\Result{#1}% + \ifnumgreater{\Result}{0} + {\stepcounter{primecount}% + \stepcounter{cellcount}% + \ifnumequal {\value{cellcount}}{7} + {"""color{red}\the#1;! \\\setcounter{cellcount}{0}} + {"""color{red}\the#1;! &}} + {}% + \ifnumequal {\value{primecount}}{50} + {\xintBreakForAndDo + {\multicolumn {6}{l|}{These are the first 50 primes after 12345.}\\}} + {}% + }\hline +\end{tabular} +\end{figure*} +? + +\begin{figure*}[ht!] + \centering\phantomsection\label{primes} + \begin{tabular}{|*{7}c|} + \hline + \setcounter{primecount}{0}\setcounter{cellcount}{0}% + \xintFor #1 in {\xintintegers [12345+2]} \do + {\IsPrime\Result{#1}% + \ifnumgreater{\Result}{0} + {\stepcounter{primecount}% + \stepcounter{cellcount}% + \ifnumequal {\value{cellcount}}{7} + {\the#1 \\\setcounter{cellcount}{0}} + {\the#1 &}} + {}% + \ifnumequal {\value{primecount}}{50} + {\xintBreakForAndDo + {\multicolumn {6}{l|}{These are the first 50 primes after 12345.}\\}} + {}% + }\hline +\end{tabular} +\end{figure*} + +\subsection{Factorizing again} +\label{ssec:factorize} + +Here is an \fexpan dable macro which computes the factors of an integer. It +uses the \xintname macros only. +\begin{everbatim*} +\catcode`\@ 11 +\let\factorize\relax +\newcommand\Factorize [1] + {\romannumeral0\expandafter\factorize\expandafter{\romannumeral-`0#1}}% +\newcommand\factorize [1]{\xintiiifOne{#1}{ 1}{\factors@a #1.{#1};}}% +\def\factors@a #1.{\xintiiifOdd{#1} + {\factors@c 3.#1.}% + {\expandafter\factors@b \expandafter1\expandafter.\romannumeral0\xinthalf{#1}.}}% +\def\factors@b #1.#2.{\xintiiifOne{#2} + {\factors@end {2, #1}}% + {\xintiiifOdd{#2}{\factors@c 3.#2.{2, #1}}% + {\expandafter\factors@b \the\numexpr #1+\@ne\expandafter.% + \romannumeral0\xinthalf{#2}.}}% +}% +\def\factors@c #1.#2.{% + \expandafter\factors@d\romannumeral0\xintiidivision {#2}{#1}{#1}{#2}% +}% +\def\factors@d #1#2#3#4{\xintiiifNotZero{#2} + {\xintiiifGt{#3}{#1} + {\factors@end {#4, 1}}% ultimate quotient is a prime with power 1 + {\expandafter\factors@c\the\numexpr #3+\tw@.#4.}}% + {\factors@e 1.#3.#1.}% +}% +\def\factors@e #1.#2.#3.{\xintiiifOne{#3} + {\factors@end {#2, #1}}% + {\expandafter\factors@f\romannumeral0\xintiidivision {#3}{#2}{#1}{#2}{#3}}% +}% +\def\factors@f #1#2#3#4#5{\xintiiifNotZero{#2} + {\expandafter\factors@c\the\numexpr #4+\tw@.#5.{#4, #3}}% + {\expandafter\factors@e\the\numexpr #3+\@ne.#4.#1.}% +}% +\def\factors@end #1;{\xintlistwithsep{, }{\xintRevWithBraces {#1}}}% +\catcode`@ 12 +\end{everbatim*} +The macro will be acceptably efficient only with numbers having somewhat small +prime factors. +\begin{everbatim} +\Factorize{16246355912554185673266068721806243461403654781833} +\end{everbatim} +\begingroup\fdef\Z +{\Factorize{16246355912554185673266068721806243461403654781833}} +\noindent{\small\dtt{\Z}} + + +It puts a little stress on the input save stack in order +not be bothered with previously gathered things.\footnote{2015/11/18 I have + not revisited this code for a long time, and perhaps I could improve it now + with some new techniques.} + +Its output is a comma separated list with the number first, then its prime +factors with multiplicity. Let's produce something prettier: +\begin{everbatim*} +\catcode`_ 11 +\def\ShowFactors #1{\expandafter\ShowFactors_a\romannumeral-`0\Factorize{#1},\relax,\relax,} +\def\ShowFactors_a #1,{#1=\ShowFactors_b} +\def\ShowFactors_b #1,#2,{\if\relax#1\else#1^{#2}\expandafter\ShowFactors_b\fi} +\catcode`_ 8 +\end{everbatim*} +\begin{everbatim} +$$\ShowFactors{16246355912554185673266068721806243461403654781833}$$ +\end{everbatim} +$$\csname ShowFactors_a\expandafter\endcsname\Z,\relax,\relax,$$ +\endgroup + +If we only considered small integers, we could write pure |\numexpr| methods +which would be very much faster (especially if we had a table of small primes +prepared first) but still ridiculously slow compared to any non expandable +implementation, not to mention use of programming languages directly accessing +the CPU registers\dots + +\subsection{The Quick Sort algorithm illustrated}\label{ssec:quicksort} + +First a completely expandable macro which sorts a comma separated list of +numbers.% +% +\footnote{The code in earlier versions of this manual handled inputs composed + of braced items. I have switched to comma separated inputs on the occasion + of (link removed) + The version here is like + |code 3| on + (link removed) (which is about |3x| faster + than the earlier code it replaced in this manual) with a modification to + make it more efficient if the data has many repeated values. + + A faster routine (for sorting hundreds of values) is provided as |code 6| at + the link mentioned in the footnote, it is based on Merge Sort, but limited + to inputs which one can handle as \TeX{} dimensions.% + + This |code 6| could be extended to handle more general numbers, as + acceptable by \xintfracname. I have also written a non expandable version, + which is even faster, but this matters really only when handling hundreds or + rather thousands of values.} +% + +The |\QSx| macro expands its list argument, which may thus be a macro; its +comma separated items must expand to integers or decimal numbers or fractions +or scientific notation as acceptable to \xintfracname, but if an item is +itself some (expandable) macro, this macro will be expanded each time the item +is considered in a comparison test! This is actually good if the macro expands +in one step to the digits, and there are many many digits, but bad if the macro +needs to do many computations. Thus |\QSx| should be used with either explicit +numbers or with items being macros expanding in one step to the numbers +(particularly if these numbers are very big). + +If the interest is only in \TeX{} integers, then one should replace the +|\xintifCmp| macro with a suitable conditional, possibly helped by tools such as +|\ifnumgreater|, |\ifnumequal| and |\ifnumless| from +\href{http://ctan.org/pkg/etoolbox}{etoolbox} (\LaTeX{} only; I didn't see a +direct equivalent to |\xintifCmp|.) Or, if we are dealing with decimal numbers +with at most four+four digits, then one should use suitable |\ifdim| tests. +Naturally this will boost consequently the speed, from having skipped all the +overhead in parsing fractions and scientific numbers as are acceptable by +\xintfracname macros, and subsequent treatment. + +\begin{everbatim*} +% THE QUICK SORT ALGORITHM EXPANDABLY +% \usepackage{xintfrac} in the preamble (latex) +\makeatletter +% use extra safe delimiters +\catcode`! 3 \catcode`? 3 +\def\QSx {\romannumeral0\qsx }% +% first we check if empty list (else \qsx@finish will not find a comma) +\def\qsx #1{\expandafter\qsx@a\romannumeral-`0#1,!,?}% +\def\qsx@a #1{\ifx,#1\expandafter\qsx@abort\else + \expandafter\qsx@start\fi #1}% +\def\qsx@abort #1?{ }% +\def\qsx@start {\expandafter\qsx@finish\romannumeral0\qsx@b,}% +\def\qsx@finish ,#1{ #1}% +% +% we check if empty of single and if not pick up the first as Pivot: +\def\qsx@b ,#1#2,#3{\ifx?#3\xintdothis\qsx@empty\fi + \ifx!#3\xintdothis\qsx@single\fi + \xintorthat\qsx@separate {#1#2}{}{}{#1#2}#3}% +\def\qsx@empty #1#2#3#4#5{ }% +\def\qsx@single #1#2#3#4#5?{, #4}% +\def\qsx@separate #1#2#3#4#5#6,% +{% + \ifx!#5\expandafter\qsx@separate@done\fi + \xintifCmp {#5#6}{#4}% + \qsx@separate@appendtosmaller + \qsx@separate@appendtoequal + \qsx@separate@appendtogreater {#5#6}{#1}{#2}{#3}{#4}% +}% +% +\def\qsx@separate@appendtoequal #1#2{\qsx@separate {#2,#1}}% +\def\qsx@separate@appendtogreater #1#2#3{\qsx@separate {#2}{#3,#1}}% +\def\qsx@separate@appendtosmaller #1#2#3#4{\qsx@separate {#2}{#3}{#4,#1}}% +% +\def\qsx@separate@done\xintifCmp #1% + \qsx@separate@appendtosmaller + \qsx@separate@appendtoequal + \qsx@separate@appendtogreater #2#3#4#5#6#7?% +{% + \expandafter\qsx@f\expandafter {\romannumeral0\qsx@b #4,!,?}{\qsx@b #5,!,?}{#3}% +}% +% +\def\qsx@f #1#2#3{#2, #3#1}% +% +\catcode`! 12 \catcode`? 12 +\makeatother + +% EXAMPLE +\begingroup +\edef\z {\QSx {1.0, 0.5, 0.3, 1.5, 1.8, 2.0, 1.7, 0.4, 1.2, 1.4, + 1.3, 1.1, 0.7, 1.6, 0.6, 0.9, 0.8, 0.2, 0.1, 1.9}} +\meaning\z + +\def\a {3.123456789123456789}\def\b {3.123456789123456788} +\def\c {3.123456789123456790}\def\d {3.123456789123456787} +\oodef\z {\QSx { \a, \b, \c, \d}}% +% The space before \a to let it not be expanded during the conversion from CSV +% values to List. The \oodef expands exactly twice (via a bunch of \expandafter's) +\meaning\z +\endgroup +\end{everbatim*} (the spaces after \string\d, etc... come from the use of the +|\meaning| primitive.) + +The choice of pivot as first element is bad if the list is already almost +sorted. Let's add a variant which will pick up the pivot index randomly. The +previous routine worked also internally with comma separated lists, but for a +change this one will use internally lists of braced items (the initial +conversion via \csbxint{CSVtoList} handles all potential spurious space +problems). + +\unless\ifxetex % pour tester compilation de xint.dtx avec xetex qui n'a pas + % \pdfuniformdeviate +\begin{everbatim*} +% QuickSort expandably on comma separated values with random choice of pivots +% ====> Requires availability of \pdfuniformdeviate <==== +% \usepackage{xintfrac, xinttools} in preamble +\makeatletter +\def\QSx {\romannumeral0\qsx }% This is a f-expandable macro. +% This converts from comma separated values on input and back on output. +% **** NOTE: these steps (and the other ones too, actually) are costly if input +% has thousands of items. +\def\qsx #1{\xintlistwithsep{, }% + {\expandafter\qsx@sort@a\expandafter{\romannumeral0\xintcsvtolist{#1}}}}% +% +% we check if empty or single or double and if not pick up the first as Pivot: +\def\qsx@sort@a #1% + {\expandafter\qsx@sort@b\expandafter{\romannumeral0\xintlength{#1}}{#1}}% +\def\qsx@sort@b #1{\ifcase #1 + \expandafter\qsx@sort@empty + \or\expandafter\qsx@sort@single + \or\expandafter\qsx@sort@double + \else\expandafter\qsx@sort@c\fi {#1}}% +\def\qsx@sort@empty #1#2{ }% +\def\qsx@sort@single #1#2{#2}% +\catcode`_ 11 +\def\qsx@sort@double #1#2{\xintifGt #2{\xint_exchangetwo_keepbraces}{}#2}% +\catcode`_ 8 +\def\qsx@sort@c #1#2{% + \expandafter\qsx@sort@sep@a\expandafter + {\romannumeral0\xintnthelt{\pdfuniformdeviate #1+\@ne}{#2}}#2?}% +\def\qsx@sort@sep@a #1{\qsx@sort@sep@loop {}{}{}{#1}}% +\def\qsx@sort@sep@loop #1#2#3#4#5% +{% + \ifx?#5\expandafter\qsx@sort@sep@done\fi + \xintifCmp {#5}{#4}% + \qsx@sort@sep@appendtosmaller + \qsx@sort@sep@appendtoequal + \qsx@sort@sep@appendtogreater {#5}{#1}{#2}{#3}{#4}% +}% +% +\def\qsx@sort@sep@appendtoequal #1#2{\qsx@sort@sep@loop {#2{#1}}}% +\def\qsx@sort@sep@appendtogreater #1#2#3{\qsx@sort@sep@loop {#2}{#3{#1}}}% +\def\qsx@sort@sep@appendtosmaller #1#2#3#4{\qsx@sort@sep@loop {#2}{#3}{#4{#1}}}% +% +\def\qsx@sort@sep@done\xintifCmp #1% + \qsx@sort@sep@appendtosmaller + \qsx@sort@sep@appendtoequal + \qsx@sort@sep@appendtogreater #2#3#4#5#6% +{% + \expandafter\qsx@sort@recurse\expandafter + {\romannumeral0\qsx@sort@a {#4}}{\qsx@sort@a {#5}}{#3}% +}% +% +\def\qsx@sort@recurse #1#2#3{#2#3#1}% +% +\makeatother + +% EXAMPLES +\begingroup +\edef\z {\QSx {1.0, 0.5, 0.3, 1.5, 1.8, 2.0, 1.7, 0.4, 1.2, 1.4, + 1.3, 1.1, 0.7, 1.6, 0.6, 0.9, 0.8, 0.2, 0.1, 1.9}} +\meaning\z + +\def\a {3.123456789123456789}\def\b {3.123456789123456788} +\def\c {3.123456789123456790}\def\d {3.123456789123456787} +\oodef\z {\QSx { \a, \b, \c, \d}}% +% The space before \a to let it not be expanded during the conversion from CSV +% values to List. The \oodef expands exactly twice (via a bunch of \expandafter's) +\meaning\z + +\def\somenumbers{% +3997.6421, 8809.9358, 1805.4976, 5673.6478, 3179.1328, 1425.4503, 4417.7691, +2166.9040, 9279.7159, 3797.6992, 8057.1926, 2971.9166, 9372.2699, 9128.4052, +1228.0931, 3859.5459, 8561.7670, 2949.6929, 3512.1873, 1698.3952, 5282.9359, +1055.2154, 8760.8428, 7543.6015, 4934.4302, 7526.2729, 6246.0052, 9512.4667, +7423.1124, 5601.8436, 4433.5361, 9970.4849, 1519.3302, 7944.4953, 4910.7662, +3679.1515, 8167.6824, 2644.4325, 8239.4799, 4595.1908, 1560.2458, 6098.9677, +3116.3850, 9130.5298, 3236.2895, 3177.6830, 5373.1193, 5118.4922, 2743.8513, +8008.5975, 4189.2614, 1883.2764, 9090.9641, 2625.5400, 2899.3257, 9157.1094, +8048.4216, 3875.6233, 5684.3375, 8399.4277, 4528.5308, 6926.7729, 6941.6278, +9745.4137, 1875.1205, 2755.0443, 9161.1524, 9491.1593, 8857.3519, 4290.0451, +2382.4218, 3678.2963, 5647.0379, 1528.7301, 2627.8957, 9007.9860, 1988.5417, +2405.1911, 5065.8063, 5856.2141, 8989.8105, 9349.7840, 9970.3013, 8105.4062, +3041.7779, 5058.0480, 8165.0721, 9637.7196, 1795.0894, 7275.3838, 5997.0429, +7562.6481, 8084.0163, 3481.6319, 8078.8512, 2983.7624, 3925.4026, 4931.5812, +1323.1517, 6253.0945}% + +\oodef\z {\QSx \somenumbers}% produced as a comma+space separated list +% black magic as workaround to the shrinkability of spaces in last line... +\hsize 87\fontcharwd\font`0 +\lccode`~=32 +\lowercase{\def~}{\discretionary{}{}{\kern\fontcharwd\font`0}}\catcode32 13 +\noindent\phantom{000}\scantokens\expandafter{\meaning\z}\par +\endgroup +\end{everbatim*} +\fi % fin de si pas xetex + + +All the previous examples were with numbers which could have been handled via +|\ifdim| tests rather than the \csbxint{ifCmp} macro from \xintfracname; using +|\ifdim| tests would naturally be faster. Even faster routine is |code 6| at +(link removed) which uses |\pdfescapestring| and a +Merge Sort algorithm. + +We then turn to a graphical illustration of the algorithm.% +% +\footnote{I have rewritten (2015/11/21) the routine to do only once (and not thrice) the + needed calls to \csa{xintifCmp}, up to the price of one additional |\edef|, + although due to the context execution time on our side is not an issue and + moreover is anyhow overwhelmed by the TikZ's activities. Simultaneously I + have updated the code. + The + variant with the choice of pivot on the right has more overhead: the reason + is simply that we do not convert the data into an array, but maintain a list + of tokens with self-reorganizing delimiters.} +% +For simplicity the pivot is always chosen as the first list item. Then we also +give a variant which picks up the last item as pivot. +\begin{everbatim*} +% in LaTeX preamble: +% \usepackage{xintfrac, xinttools} +% \usepackage{color} +% or, when using Plain TeX: +% \input xintfrac.sty \input xinttools.sty +% \input color.tex +% +% Color definitions +\definecolor{LEFT}{RGB}{216,195,88} +\definecolor{RIGHT}{RGB}{208,231,153} +\definecolor{INERT}{RGB}{199,200,194} +\definecolor{INERTpiv}{RGB}{237,237,237} +\definecolor{PIVOT}{RGB}{109,8,57} +% Start of macro defintions +\makeatletter +% \catcode`? 3 % a bit too paranoid. Normal ? will do. +% +% argument will never be empty +\def\QS@cmp@a #1{\QS@cmp@b #1??}% +\def\QS@cmp@b #1{\noexpand\QS@sep@A\@ne{#1}\QS@cmp@d {#1}}% +\def\QS@cmp@d #1#2{\ifx ?#2\expandafter\QS@cmp@done\fi + \xintifCmp {#1}{#2}\tw@\@ne\z@{#2}\QS@cmp@d {#1}}% +\def\QS@cmp@done #1?{?}% +% +\def\QS@sep@A #1?{\QSLr\QS@sep@L #1\thr@@?#1\thr@@?#1\thr@@?}% +\def\QS@sep@L #1#2{\ifcase #1{#2}\or\or\else\expandafter\QS@sep@I@start\fi \QS@sep@L}% +\def\QS@sep@I@start\QS@sep@L {\noexpand\empty?\QSIr\QS@sep@I}% +\def\QS@sep@I #1#2{\ifcase#1\or{#2}\or\else\expandafter\QS@sep@R@start\fi\QS@sep@I}% +\def\QS@sep@R@start\QS@sep@I {\noexpand\empty?\QSRr\QS@sep@R}% +\def\QS@sep@R #1#2{\ifcase#1\or\or{#2}\else\expandafter\QS@sep@done\fi\QS@sep@R}% +\def\QS@sep@done\QS@sep@R {\noexpand\empty?}% +% +\def\QS@loop {% + \xintloop + % pivot phase + \def\QS@pivotcount{0}% + \let\QSLr\DecoLEFTwithPivot \let\QSIr \DecoINERT + \let\QSRr\DecoRIGHTwithPivot \let\QSIrr\DecoINERT + \centerline{\QS@list}% + % sorting phase + \ifnum\QS@pivotcount>\z@ + \def\QSLr {\QS@cmp@a}\def\QSRr {\QS@cmp@a}% + \def\QSIr {\QSIrr}\let\QSIrr\relax + \edef\QS@list{\QS@list}% compare + \let\QSLr\relax\let\QSRr\relax\let\QSIr\relax + \edef\QS@list{\QS@list}% separate + \def\QSLr ##1##2?{\ifx\empty##1\else\noexpand \QSLr {{##1}##2}\fi}% + \def\QSIr ##1##2?{\ifx\empty##1\else\noexpand \QSIr {{##1}##2}\fi}% + \def\QSRr ##1##2?{\ifx\empty##1\else\noexpand \QSRr {{##1}##2}\fi}% + \edef\QS@list{\QS@list}% gather + \let\QSLr\DecoLEFT \let\QSRr\DecoRIGHT + \let\QSIr\DecoINERTwithPivot \let\QSIrr\DecoINERT + \centerline{\QS@list}% + \repeat }% +% +% \xintFor* loops handle gracefully empty lists. +\def\DecoLEFT #1{\xintFor* ##1 in {#1} \do {\colorbox{LEFT}{##1}}}% +\def\DecoINERT #1{\xintFor* ##1 in {#1} \do {\colorbox{INERT}{##1}}}% +\def\DecoRIGHT #1{\xintFor* ##1 in {#1} \do {\colorbox{RIGHT}{##1}}}% +\def\DecoPivot #1{\begingroup\color{PIVOT}\advance\fboxsep-\fboxrule\fbox{#1}\endgroup}% +% +\def\DecoLEFTwithPivot #1{\xdef\QS@pivotcount{\the\numexpr\QS@pivotcount+\@ne}% + \xintFor* ##1 in {#1} \do + {\xintifForFirst {\DecoPivot {##1}}{\colorbox{LEFT}{##1}}}}% +\def\DecoINERTwithPivot #1{\xdef\QS@pivotcount{\the\numexpr\QS@pivotcount+\@ne}% + \xintFor* ##1 in {#1} \do + {\xintifForFirst {\colorbox{INERTpiv}{##1}}{\colorbox{INERT}{##1}}}}% +\def\DecoRIGHTwithPivot #1{\xdef\QS@pivotcount{\the\numexpr\QS@pivotcount+\@ne}% + \xintFor* ##1 in {#1} \do + {\xintifForFirst {\DecoPivot {##1}}{\colorbox{RIGHT}{##1}}}}% +% +\def\QuickSort #1{% warning: not compatible with empty #1. + % initialize, doing conversion from comma separated values to a list of braced items + \edef\QS@list{\noexpand\QSRr{\xintCSVtoList{#1}}}% many \edef's are to follow anyhow +% earlier I did a first drawing of the list, here with the color of RIGHT elements, +% but the color should have been for example white, anyway I drop this first line + %\let\QSRr\DecoRIGHT + %\par\centerline{\QS@list}% +% + % loop as many times as needed + \QS@loop }% +% +% \catcode`? 12 % in case we had used a funny ? as delimiter. +\makeatother +%% End of macro definitions. +%% Start of Example +\begingroup\offinterlineskip +\small +% \QuickSort {1.0, 0.5, 0.3, 1.5, 1.8, 2.0, 1.7, 0.4, 1.2, 1.4, +% 1.3, 1.1, 0.7, 1.6, 0.6, 0.9, 0.8, 0.2, 0.1, 1.9} +% \medskip +% with repeated values +\QuickSort {1.0, 0.5, 0.3, 0.8, 1.5, 1.8, 2.0, 1.7, 0.4, 1.2, 1.4, + 1.3, 1.1, 0.7, 0.3, 1.6, 0.6, 0.3, 0.8, 0.2, 0.8, 0.7, 1.2} +\endgroup +\end{everbatim*} + +Here is the variant which always picks the pivot as the rightmost element. + +\begin{everbatim*} +\makeatletter +% +\def\QS@cmp@a #1{\noexpand\QS@sep@A\expandafter\QS@cmp@d\expandafter + {\romannumeral0\xintnthelt{-1}{#1}}#1??}% +% +\def\DecoLEFTwithPivot #1{\xdef\QS@pivotcount{\the\numexpr\QS@pivotcount+\@ne}% + \xintFor* ##1 in {#1} \do + {\xintifForLast {\DecoPivot {##1}}{\colorbox{LEFT}{##1}}}} +\def\DecoINERTwithPivot #1{\xdef\QS@pivotcount{\the\numexpr\QS@pivotcount+\@ne}% + \xintFor* ##1 in {#1} \do + {\xintifForLast {\colorbox{INERTpiv}{##1}}{\colorbox{INERT}{##1}}}} +\def\DecoRIGHTwithPivot #1{\xdef\QS@pivotcount{\the\numexpr\QS@pivotcount+\@ne}% + \xintFor* ##1 in {#1} \do + {\xintifForLast {\DecoPivot {##1}}{\colorbox{RIGHT}{##1}}}} +\def\QuickSort #1{% + % initialize, doing conversion from comma separated values to a list of braced items + \edef\QS@list{\noexpand\QSLr {\xintCSVtoList{#1}}}% many \edef's are to follow anyhow + % + % loop as many times as needed + \QS@loop }% +\makeatother +\begingroup\offinterlineskip +\small +% \QuickSort {1.0, 0.5, 0.3, 1.5, 1.8, 2.0, 1.7, 0.4, 1.2, 1.4, +% 1.3, 1.1, 0.7, 1.6, 0.6, 0.9, 0.8, 0.2, 0.1, 1.9} +% \medskip +% with repeated values +\QuickSort {1.0, 0.5, 0.3, 0.8, 1.5, 1.8, 2.0, 1.7, 0.4, 1.2, 1.4, + 1.3, 1.1, 0.7, 0.3, 1.6, 0.6, 0.3, 0.8, 0.2, 0.8, 0.7, 1.2} +\endgroup +\end{everbatim*} + +The choice of the first or last item as pivot is not a good one as nearly +ordered lists will take quadratic time. But for explaining the algorithm via a +graphical interpretation, it is not that bad. If one wanted to pick up the +pivot randomly, the routine would have to be substantially rewritten: in +particular the |\Deco..withPivot| macros need to know where the pivot is, and +currently this is implemented by using either |\xintifForFirst| or +|\xintifForLast|. + +\clearpage + +\expandafter\let\csname ExamplesnameUp\endcsname\undefined \ifnum\NoSourceCode=1 \bigskip @@ -17372,32 +17629,36 @@ be treated as first item) number. \makeatother -\section{Introduction to this document and (very much) shortened version history} +\section{History timeline} This is \expandafter|\xintbndlversion| of \expandafter|\xintbndldate|. -Please refer |CHANGES.html|.\centeredline{Internet: +Please refer |CHANGES.html| for a (much more) detailed history. +\centeredline{Internet: \url{http://mirrors.ctan.org/macros/generic/xint/CHANGES.html}} -We keep here only a brief timeline of the most important changes. \begin{itemize} -\item Release |1.4| of |2020/01/31|: this was a major release with - breaking changes, devoted to a re-write of \xintexprnameimp - with |\expanded| based expansion control rather than |\csname| storage - of intermediate computation results. Support for input and output - of nested structures, and multiple additions to \xintexprnameimp. +\item Release |1.4a| of |2020/02/19|: + fixes |1.4| known bugs. Improves documentation. +\item Release |1.4| of |2020/01/31|: \xintexprnameimp overhaul to use + |\expanded| based expansion control. Many new features, in particular support + for input and output of nested structures. Breaking changes, main ones + being the (provisory) drop of |x*[a, b,...]|, |x+[a, b,...]| et al.\@ syntax and the + requirement of |\expanded| primitive (currently required only by \xintexprnameimp). \item Release |1.3f| of |2019/09/10|: starred variant \csbxint{Digits*}. -\item Release |1.3e| of |2019/04/05|: \xinttrignameimp, \xintlognameimp, - \csa{xintdefefunc} ``non-protected'' variant of \csbxint{deffunc}. - - Indices removed from |sourcexint.pdf|. Their functionality is advantageously - made available via the search function in PDF viewers. Already the local - tables of contents are useful enough most of the time. -\item Release |1.3d| of |2019/01/06|: bugfix of |1.2p| bug for division with a +\item Release |1.3e| of |2019/04/05|: packages \xinttrignameimp, \xintlognameimp; + \csa{xintdefefunc} ``non-protected'' variant of \csbxint{deffunc} (at |1.4| + the two got merged and \csa{xintdefefunc} became a deprecated alias for + \csbxint{deffunc}). + Indices removed from |sourcexint.pdf|. +% Their functionality is advantageously + % made available via the search function in PDF viewers. Already the local + % tables of contents are useful enough most of the time. +\item Release |1.3d| of |2019/01/06|: fix of |1.2p| bug for division with a zero dividend and a one-digit divisor, \csbxint{eval} et al. wrappers, |gcd()| and |lcm()| work with fractions. \item Release |1.3c| of |2018/06/17|: documentation better hyperlinked, - |sourcexint.pdf| with indices of macros. Colon in |:=| now optional for + indices added to |sourcexint.pdf|. Colon in |:=| now optional for \csbxint{defvar} and \csbxint{deffunc}. \item Release |1.3b| of |2018/05/18|: randomness related additions (still WIP). \item Release |1.3a| of |2018/03/07|: efficiency fix of the mechanism for @@ -17406,8 +17667,8 @@ We keep here only a brief timeline of the most important changes. systematically least common multiple of denominators. Extensive under-the-hood refactoring of \csbxint{NewExpr} and \csbxint{deffunc} which now allow recursive definitions. Removal of |1.2o| deprecated macros. -\item Release |1.2q| of |2018/02/06|: bugfix release (|1.2l| subtraction bug - in special situation); tacit multiplication extended to cases such as +\item Release |1.2q| of |2018/02/06|: fix of |1.2l| subtraction bug + in special situation; tacit multiplication extended to cases such as |10!20!30!|. \item Release |1.2p| of |2017/12/05|: maps |//| and |/:| to the floored, not truncated, division. Simultaneous assignments possible with \csbxint{defvar}. @@ -17430,6 +17691,21 @@ We keep here only a brief timeline of the most important changes. Addition and subtraction do not multiply denominators blindly but sometimes produce smaller ones. Also with that release, packages \xintkernelnameimp and \xintcorenameimp got extracted from \xinttoolsnameimp and \xintnameimp. +\item Release |1.09g| of |2013/11/22|: the \xinttoolsnameimp package is + extracted from \xintnameimp; addition of \csbxint{loop} and \csbxint{iloop}. +\item Release |1.09c| of |2013/10/09|: \csbxint{For}, \csa{xintNewNumExpr} + (ancestor of \csbxint{NewExpr}/\csbxint{deffunc} mechanism). +\item Release |1.09a| of |2013/09/24|: support for functions by \xintexprnameimp. +\item Release |1.08| of |2013/06/07|: the \xintbinhexnameimp package. +\item Release |1.07| of |2013/05/25|: support for floating point numbers + added to \xintfracnameimp and first release of the \xintexprnameimp package + (provided + \csbxint{expr} and \csbxint{floatexpr}). +\item Release |1.04| of |2013/04/25|: the \xintcfracnameimp package. +\item Release |1.03| of |2013/04/14|: the \xintfracnameimp and + \xintseriesnameimp packages. +\item Release |1.0| of |2013/03/28|: initial release of the \xintnameimp and + \xintgcdnameimp packages. \end{itemize} Some parts of the code still date back to the initial release, and @@ -17638,7 +17914,7 @@ math shift catcode. \fi \XINT_providespackage \ProvidesPackage {xintkernel}% - [2020/01/31 v1.4 Paraphernalia for the xint packages (JFB)]% + [2020/02/19 v1.4a Paraphernalia for the xint packages (JFB)]% % \end{macrocode} % \subsection{Constants} % \begin{macrocode} @@ -18424,7 +18700,7 @@ math shift catcode. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xinttools}% - [2020/01/31 v1.4 Expandable and non-expandable utilities (JFB)]% + [2020/02/19 v1.4a Expandable and non-expandable utilities (JFB)]% % \end{macrocode} % \lverb|\XINT_toks is used in macros such as \xintFor. It is not used % elsewhere in the xint bundle.| @@ -20588,7 +20864,7 @@ math shift catcode. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintcore}% - [2020/01/31 v1.4 Expandable arithmetic on big integers (JFB)]% + [2020/02/19 v1.4a Expandable arithmetic on big integers (JFB)]% % \end{macrocode} % \subsection{(WIP!) Error conditions and exceptions} % \lverb|As per the Mike Cowlishaw/IBM's General Decimal Arithmetic Specification @@ -23890,7 +24166,7 @@ math shift catcode. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xint}% - [2020/01/31 v1.4 Expandable operations on big integers (JFB)]% + [2020/02/19 v1.4a Expandable operations on big integers (JFB)]% % \end{macrocode} % \subsection{More token management} % \begin{macrocode} @@ -26456,7 +26732,7 @@ math shift catcode. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintbinhex}% - [2020/01/31 v1.4 Expandable binary and hexadecimal conversions (JFB)]% + [2020/02/19 v1.4a Expandable binary and hexadecimal conversions (JFB)]% % \end{macrocode} % \subsection{Constants, etc...} % \lverb|1.2n switches to \csname-governed expansion at various places.| @@ -27052,16 +27328,16 @@ math shift catcode. % From |1.1| to |1.3f| the package loaded only \xintcorenameimp. At |1.4| it % now automatically loads both of \xintnameimp and \xinttoolsnameimp (the % latter being in fact a requirement of \csbxint{TypesetEuclideAlgorithm} and -% \csbxint{TypesetBezoutAlgorithm} since |1.09h|. +% \csbxint{TypesetBezoutAlgorithm} since |1.09h|). % % \begin{framed} % At |1.4| \csbxint{GCD}, \csbxint{LCM}, \csbxint{GCDof}, and \csbxint{LCMof} % are \emph{removed} from the package:\IMPORTANTf they are provided only by % \xintfracnameimp and they handle general fractions, not only integers. % -% The original integer-only macros have been renamed into respectively +% The original\CHANGEDf{1.4} integer-only macros have been renamed into respectively % \csbxint{iiGCD}, \csbxint{iiLCM}, \csbxint{iiGCDof}, and \csbxint{iiLCMof} -% and got relocated into \xintnameimp package.\CHANGEDf{1.4} +% and got relocated into \xintnameimp package. % \end{framed} % % \subsection{Catcodes, \protect\eTeX{} and reload detection} @@ -27128,7 +27404,7 @@ math shift catcode. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintgcd}% - [2020/01/31 v1.4 Euclide algorithm with xint package (JFB)]% + [2020/02/19 v1.4a Euclide algorithm with xint package (JFB)]% % \end{macrocode} % \subsection{\csh{xintBezout}} % \lverb|& @@ -27728,7 +28004,7 @@ math shift catcode. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintfrac}% - [2020/01/31 v1.4 Expandable operations on fractions (JFB)]% + [2020/02/19 v1.4a Expandable operations on fractions (JFB)]% % \end{macrocode} % \subsection{\csh{XINT_cntSgnFork}} % \lverb|1.09i. Used internally, #1 must expand to \m@ne, \z@, or \@ne or @@ -28835,6 +29111,9 @@ math shift catcode. % \end{macrocode} % \subsection{\csh{xintTrunc}, \csh{xintiTrunc}} % \lverb|& +% +% This of course has a long history. Only showing here some comments. +% % 1.2i release notes: ever since its inception this macro was stupid for a % decimal input: it did not handle it separately from the general fraction % case A/B[N] with B>1, hence ended up doing divisions by powers of ten. But @@ -28846,6 +29125,31 @@ math shift catcode. % is quite longer and making it f-expandable would not shorten it... I decided % for the time being to not complicate things here. % | +% \lverb|& +% +% 1.4a (2020/02/18) adds handling of a negative first argument. +% +% Zero input still gives single digit 0 output as I did not want to complicate +% the code. But if quantization gives 0, the exponent [D] will be there. Well +% actually eD because of problem that sign of original is preserved in output +% so we can have -0 and I can not use -0[D] notation as it is not legal for +% strict format. So I will use -0eD hence eD generally even though this means +% so slight suboptimality for trunc() function in \xintexpr. +% +% The idea to give a meaning to negative D (in the context of optional +% argument to \xintiexpr) was suggested a long time ago by Kpym (October 20, +% 2015). His suggestion was then to treat it as positive D but trim trailing +% zeroes. But since then, there is \xintDecToString which can be combined with +% \xintREZ, and I feel matters of formatting output require a whole module (or +% rather use existing third-party tools), and I decided to opt rather for an +% operation similar as the quantize() of Python Decimal module. I.e. we +% truncate (or round) to an integer multiple of a given power of 10. +% +% Other reason to decide to do this is that it looks as if I don't even need +% to understand the original code to hack into its ending via \XINT_trunc_G or +% \XINT_itrunc_G. For the latter it looks as if logically I simply have to do +% nothing. For the former I simply have to add some eD postfix. +% | % \begin{macrocode} \def\xintTrunc {\romannumeral0\xinttrunc }% \def\xintiTrunc {\romannumeral0\xintitrunc}% @@ -28862,16 +29166,8 @@ math shift catcode. \xint_orthat\XINT_trunc_b #1+#4.{#2}{#3}#5#4.% }% \def\XINT_trunc_zero #1.#2.{ 0}% -% \end{macrocode} -% \lverb|& -% | -% \begin{macrocode} \def\XINT_trunc_b {\expandafter\XINT_trunc_B\the\numexpr}% \def\XINT_trunc_sp_b {\expandafter\XINT_trunc_sp_B\the\numexpr}% -% \end{macrocode} -% \lverb|& -% | -% \begin{macrocode} \def\XINT_trunc_B #1% {% \xint_UDsignfork @@ -28879,10 +29175,6 @@ math shift catcode. -\XINT_trunc_D \krof #1% }% -% \end{macrocode} -% \lverb|& -% | -% \begin{macrocode} \def\XINT_trunc_sp_B #1% {% \xint_UDsignfork @@ -28890,10 +29182,6 @@ math shift catcode. -\XINT_trunc_sp_D \krof #1% }% -% \end{macrocode} -% \lverb@& -% @ -% \begin{macrocode} \def\XINT_trunc_C -#1.#2#3% {% \expandafter\XINT_trunc_CE @@ -28915,10 +29203,6 @@ math shift catcode. \def\XINT_trunc_sp_Cb #1#2.#3.% {% \expandafter\XINT_trunc_sp_Cc -% \end{macrocode} -% \lverb|& -% | -% \begin{macrocode} \romannumeral0\expandafter\XINT_split_fromright_a \the\numexpr#3-\numexpr\XINT_length_loop #2\xint:\xint:\xint:\xint:\xint:\xint:\xint:\xint:\xint: @@ -28926,10 +29210,6 @@ math shift catcode. \xint_c_iv\xint_c_iii\xint_c_ii\xint_c_i\xint_c_\xint_bye .#2\xint_bye2345678\xint_bye..#1% }% -% \end{macrocode} -% \lverb|& -% | -% \begin{macrocode} \def\XINT_trunc_sp_Cc #1% {% \if.#1\xint_dothis{\XINT_trunc_sp_Cd 0.}\fi @@ -28967,29 +29247,32 @@ math shift catcode. {\expandafter#4\romannumeral`&&@\expandafter\xint_firstoftwo \romannumeral0\XINT_div_prepare {#3}{#2}.#1}% \def\XINT_trunc_sp_F #1#2.#3{#3#2.#1}% -\def\XINT_itrunc_G #1#2.#3#4.{\if#10\xint_dothis{ 0}\fi\xint_orthat{#3#1}#2}% -\def\XINT_trunc_G #1.#2#3.% +\def\XINT_itrunc_G #1#2.#3#4.% +{% + \if#10\xint_dothis{ 0}\fi + \xint_orthat{#3#1}#2% +}% +\def\XINT_trunc_G #1.#2#3#4.% {% + \xint_gob_til_minus#3\XINT_trunc_Hc-% \expandafter\XINT_trunc_H - \the\numexpr\romannumeral0\xintlength {#1}-#3.#3.{#1}#2% + \the\numexpr\romannumeral0\xintlength {#1}-#3#4.#3#4.{#1}#2% }% +\def\XINT_trunc_Hc-\expandafter\XINT_trunc_H + \the\numexpr\romannumeral0\xintlength #1.-#2.#3#4{#4#3e#2}% \def\XINT_trunc_H #1.#2.% {% - \ifnum #1 > \xint_c_ - \xint_afterfi {\XINT_trunc_Ha {#2}}% - \else - \xint_afterfi {\XINT_trunc_Hb {-#1}}% -0,--1,--2, .... - \fi + \ifnum #1 > \xint_c_ \xint_dothis{\XINT_trunc_Ha {#2}}\fi + \xint_orthat {\XINT_trunc_Hb {-#1}}% -0,--1,--2, .... +}% +\def\XINT_trunc_Ha% +{% + \expandafter\XINT_trunc_Haa\romannumeral0\xintdecsplit }% -\def\XINT_trunc_Ha{\expandafter\XINT_trunc_Haa\romannumeral0\xintdecsplit}% \def\XINT_trunc_Haa #1#2#3{#3#1.#2}% \def\XINT_trunc_Hb #1#2#3% {% \expandafter #3\expandafter0\expandafter.% -% \end{macrocode} -% \lverb|& -% | -% \begin{macrocode} \romannumeral\xintreplicate{#1}0#2% }% % \end{macrocode} @@ -29012,7 +29295,9 @@ math shift catcode. % input is already a decimal number (denominator B=1). % % And the rounding is now done in 1.2 style (with much delay, sorry), like of -% the rewritten \xintInc and \xintDec.| +% the rewritten \xintInc and \xintDec. +% +% At 1.4a, first argument can be negative. This is handled at \XINT_trunc_G.| % \begin{macrocode} \def\xintRound {\romannumeral0\xintround }% \def\xintiRound {\romannumeral0\xintiround }% @@ -32846,7 +33131,7 @@ math shift catcode. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintseries}% - [2020/01/31 v1.4 Expandable partial sums with xint package (JFB)]% + [2020/02/19 v1.4a Expandable partial sums with xint package (JFB)]% % \end{macrocode} % \subsection{\csh{xintSeries}} % \begin{macrocode} @@ -33347,7 +33632,7 @@ math shift catcode. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintcfrac}% - [2020/01/31 v1.4 Expandable continued fractions with xint package (JFB)]% + [2020/02/19 v1.4a Expandable continued fractions with xint package (JFB)]% % \end{macrocode} % \subsection{\csh{xintCFrac}} % \begin{macrocode} @@ -34489,29 +34774,33 @@ math shift catcode. % it became possible to let the [...] syntax be associated to a true internal type of «tuple» % or «list». % -% The output of \xintexpr after expansion is thus modified at 1.4. It now looks like +% The output of \xintexpr (after \romannumeral0 or \romannumeral-`0 triggered +% expansion or double expansion) is thus modified at 1.4. It now looks like % this: % % \XINTfstop \XINTexprprint .{{<number>}} in simplest case % % \XINTfstop \XINTexprprint .{{...}...{...}} in general case % -% where ... stands for nested braces ultimately ending in {<number>} leaves. -% The <number> is some internal representation, possibly empty. -% Both on input and output from \xintthexpr an empty leaf is rendered as []. -% The $xintfracnameimp numerical macros convert this to 0, but the integer -% only parser \xintiiexpr will currently not do this and will break -% if some arithmetic operation is attempted. +% where ... stands for nested braces ultimately ending in {<num. rep.>} leaves. +% The <num. rep.> stands for some internal representation of numeric data. It +% may be empty, and currently as well as probably in future uses only catcode +% 12 tokens (no spaces currently). % -% Only normal catcodes are output, i.e. the backslash, regular braces, and the -% catcode 12 characters which are used for the internal number representations -% <number> (scientific notation is internally converted to raw -% $xintfracnameimp representation [N]). +% {{}} corresponds (in input as in output) to []. The external TeX braces also +% serve as set-theoretical braces. The comma is concatenation, so for example +% [], [] will become {{}{}}, or rather {}{} if sub-unit of something else. % -% See the user manual for changes the novel internal representation implies at -% interface level, in particular regarding the way the commas are interpreted. -% The user manual explains some terminology («ople», «oneple», «nutple»,...) whose -% meaning I don't repeat here. +% The associated vocabulary is explained in the user manual and we avoid +% too much duplication here. $xintfracnameimp numerical macros receiving an +% empty argument usually handle it as being 0, but this is not the case of the +% $xintcorenameimp macros supporting \xintiiexpr, they usually break if +% exercised on some empty argument. +% +% The above expansion result uses thus only normal catcodes are output, i.e. +% the backslash, regular braces, and catcode 12 characters (scientific +% notation is internally converted to raw $xintfracnameimp representation +% [N]). % % Additional data may be located before the dot; this is the case only for % \xintfloatexpr currently. As @@ -34519,18 +34808,16 @@ math shift catcode. % \xintfloatexpr but tries to share as much code as possible, some overhead % is induced to fit all into the same mold. % -% \XINTfstop stops \romannumeral-`0 type spanned expansion, and is invariant -% under \edef, but simply disappears in typesetting context. It is thus now -% legal to use \xintexpr directly in typesetting flow. See user manual for -% some further comments. +% \XINTfstop stops \romannumeral-`0 (or 0) type spanned expansion, and is +% invariant under \edef, but simply disappears in typesetting context. It is +% thus now legal to use \xintexpr directly in typesetting flow. % % \XINTexprprint is \protected. % -% The f-expansion (\romannumeral-`0 type of expansion) of an \xintexpr -% <expression>\relax is a complete expansion, i.e. whose result remains -% invariant under \edef. But if exposed to finitely many expansion steps (at -% least two) there is a «blinking» \noexpand upfront depending on parity of -% number of steps. +% The f-expansion of an \xintexpr <expression>\relax is a complete expansion, +% i.e. one whose result remains invariant under \edef. But if exposed to +% finitely many expansion steps (at least two) there is a «blinking» \noexpand +% upfront depending on parity of number of steps. % % \xintthe\xintexpr <expression>\relax or \xinteval{<expression>} serve as % formerly to deliver the explicit digits, or more exactly some prettifying @@ -34736,7 +35023,7 @@ math shift catcode. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintexpr}% - [2020/01/31 v1.4 Expandable expression parser (JFB)]% + [2020/02/19 v1.4a Expandable expression parser (JFB)]% \catcode`! 11 \let\XINT_Cmp \xintiiCmp \def\XINTfstop{\noexpand\XINTfstop}% @@ -34789,22 +35076,27 @@ math shift catcode. \catcode`{ 1 \catcode`} 2 \catcode`< 12 \catcode`> 12 % \end{macrocode} % \subsubsection{Braced contents rendering via a \TeX{} alignment with prettifying of leaves} -% \lverb|1.4.| +% \lverb|1.4. +% +% Breaking change at 1.4a as helper macros were renamed and their meanings +% refactored: no more \xintexpraligntab nor \xintexpraligninnercomma or +% \xintexpralignoutercomma but \xintexpraligninnersep, etc... +% .| % \begin{macrocode} \catcode`& 4 \protected\def\xintexpralignbegin {\halign\bgroup\tabskip2ex\hfil##&&##\hfil\cr}% \protected\def\xintexpralignend {\crcr\egroup}% -\protected\def\xintexpraligncr {\cr}% +\protected\def\xintexpralignlinesep {,\cr}% \protected\def\xintexpralignleftbracket {[}% \protected\def\xintexpralignrightbracket{]}% -\protected\def\xintexpraligninnercomma {,}% -\protected\def\xintexpralignoutercomma {,}% -\protected\def\xintexpraligntab {&}% +\protected\def\xintexpralignleftsep {&}% +\protected\def\xintexpralignrightsep {&}% +\protected\def\xintexpraligninnersep {,&}% \catcode`& 7 \def\XINT:expr:toalignwith#1#2% {% {\expandafter\XINT:expr:toalign_checkempty - \expanded{\noexpand#1!\expandafter}\detokenize{#2}^}% + \expanded{\noexpand#1!\expandafter}\detokenize{#2}^\expandafter}% \xintexpralignend }% \def\XINT:expr:toalign_checkempty #1!#2% @@ -34816,23 +35108,27 @@ math shift catcode. \def\XINT:expr:toalign_a #1{#2% <% \if{#2\xint_dothis<\xintexpralignleftbracket\XINT:expr:toalign_a>\fi - \xint_orthat\XINT:expr:toalign_b #1#2% + \xint_orthat<\xintexpralignleftsep\XINT:expr:toalign_b>#1#2% >% \def\XINT:expr:toalign_b #1!#2}% <% - \xintexpraligntab \if\relax#2\relax\xintexprEmptyItem\else#1<#2>\fi\XINT:expr:toalign_c #1!}% >% \def\XINT:expr:toalign_c #1}#2% <% \if ^#2\xint_dothis<\xint_gob_til_^>\fi - \if {#2\xint_dothis<\xintexpraligninnercomma\XINT:expr:toalign_a>\fi - \xint_orthat<\xintexpraligntab\xintexpralignrightbracket\XINT:expr:toalign_C>#1#2% + \if {#2\xint_dothis<\xintexpraligninnersep\XINT:expr:toalign_A>\fi + \xint_orthat<\xintexpralignrightsep\xintexpralignrightbracket\XINT:expr:toalign_C>#1#2% +>% +\def\XINT:expr:toalign_A #1{#2% +<% + \if{#2\xint_dothis<\xintexpralignleftbracket\XINT:expr:toalign_A>\fi + \xint_orthat\XINT:expr:toalign_b #1#2% >% \def\XINT:expr:toalign_C #1}#2% <% \if ^#2\xint_dothis<\xint_gob_til_^>\fi - \if {#2\xint_dothis<\xintexpralignoutercomma\xintexpraligncr\XINT:expr:toalign_a>\fi + \if {#2\xint_dothis<\xintexpralignlinesep\XINT:expr:toalign_a>\fi \xint_orthat<\xintexpralignrightbracket\XINT:expr:toalign_C>#1#2% >% \catcode`{ 1 \catcode`} 2 \catcode`< 12 \catcode`> 12 @@ -34903,6 +35199,9 @@ math shift catcode. % ATTENTION! 1.3d renamed \xinteval to \xintexpro etc... % % +% +% The 1.4a version of optional argument [D] for \xintiexpr accepts a negative +% D, with same meaning as \xintTrunc from xintfrac.sty. % | % \begin{macrocode} \def\xintexpr {\romannumeral0\xintexpro }% @@ -35042,7 +35341,7 @@ math shift catcode. % required some work...| % \begin{macrocode} \def\xintthe #1{\expanded\expandafter\xint_gobble_i\romannumeral`&&@#1}% -\def\xintthealign #1{\xintexpralignbegin +\def\xintthealign #1{\expandafter\xintexpralignbegin \expanded\expandafter\XINT:expr:toalignwith \romannumeral0\expandafter\expandafter\expandafter\expandafter \expandafter\expandafter\expandafter\xint_gob_andstop_ii @@ -35186,6 +35485,20 @@ math shift catcode. {\xint_gob_til_! #3\XINT_thecoords_c ! (#1#2, #3#4)\XINT_thecoords_b }% \def\XINT_thecoords_c #1^{}% % \end{macrocode} +% \paragraph{\csh{xintthespaceseparated}} +% \lverb|1.4a This is a utility macro which was distributed previously +% separately for usage with PSTricks \listplot| +% \begin{macrocode} +\def\xintthespaceseparated#1% + {\romannumeral`&&@\expandafter\xintthespaceseparated_a\romannumeral0#1}% +\def\xintthespaceseparated_a #1#2.#3% + {\expanded{\expandafter\xintthespaceseparated_b\expanded#2.{#3},!,!,!,!,!,!,!,!,!,^}}% +\def\xintthespaceseparated_b #1,#2,#3,#4,#5,#6,#7,#8,#9,% + {\xint_gob_til_! #9\xintthespaceseparated_c !% + #1#2#3#4#5#6#7#8#9% + \xintthespaceseparated_b}% +\def\xintthespaceseparated_c !#1!#2^{#1}% +% \end{macrocode} % \subsection{Hooks into the numeric parser for usage by the % \cshnolabel{xintdeffunc} symbolic parser} % \lverb|This is new with 1.3 and considerably refactored at 1.4. See @@ -38127,18 +38440,48 @@ math shift catcode. % \begin{macrocode} \def\XINT_expr_onliteral_add {\expandafter\XINT_allexpr_add_f\romannumeral`&&@\XINT_expr_fetch_E_comma_V_equal_E_a {}}% -\def\XINT_allexpr_add_f #1#2{\xint_c_ii^v `{opx}#2)\relax #1{+@}{0}}% +\def\XINT_allexpr_add_f #1#2{\xint_c_ii^v `{opx}#2)\relax #1{+}{0}}% \def\XINT_expr_onliteral_mul {\expandafter\XINT_allexpr_mul_f\romannumeral`&&@\XINT_expr_fetch_E_comma_V_equal_E_a {}}% -\def\XINT_allexpr_mul_f #1#2{\xint_c_ii^v `{opx}#2)\relax #1{*@}{1}}% +\def\XINT_allexpr_mul_f #1#2{\xint_c_ii^v `{opx}#2)\relax #1{*}{1}}% \def\XINT_expr_func_opx {\XINT:NEhook:opx \XINT_allexpr_opx \xintbareeval }% \def\XINT_flexpr_func_opx {\XINT:NEhook:opx \XINT_allexpr_opx \xintbarefloateval}% \def\XINT_iiexpr_func_opx {\XINT:NEhook:opx \XINT_allexpr_opx \xintbareiieval }% +% \end{macrocode} +% \lverb|1.4a In case of usage of omit (did I not test it? obviously +% I didn't as neither omit nor abort could work; and break neither), +% 1.4 code using (#6) syntax caused a +% (somewhat misleading) «missing )» error message which originated in the +% #6. This is non-obvious problem (perhaps explained why prior to 1.4 I had +% not added support for omit and break() to add() and mul()... +% +% Allowing () is not enough as it would have to be 0 or 1 depending on +% whether we are using add() or mul(). Hence the somewhat complicated +% detour (relying on precise way var_omit and var_abort work) via +% \XINT_allexpr_opx_ifnotomitted. +% +% \break() has special meaning here as it is used as last operand, not as last +% value. The code is very unsatisfactory and inefficient but this is hotfix +% for 1.4a.| +% \begin{macrocode} \def\XINT_allexpr_opx #1#2#3#4#5#6#7#8% {% \expandafter\XINT_expr_put_op_first \expanded \bgroup {\iffalse}\fi - \XINT_expr_iter:_b {#1(#6)#7\relax !#5}#4^~{{#8}}\XINT_expr_cb_and_getop + \XINT_expr_iter:_b {#1% + \expandafter\XINT_allexpr_opx_ifnotomitted + \romannumeral0#1#6\relax#7@\relax !#5}#4^~{{#8}}\XINT_expr_cb_and_getop +}% +\def\XINT_allexpr_opx_ifnotomitted #1% +{% + \ifx !#1\xint_dothis{@\relax}\fi + \ifx ^#1\xint_dothis{\XINTfstop. ^\relax}\fi + \if ?\xintFirstItem{#1}\xint_dothis{\XINT_allexpr_opx_break{#1}}\fi + \xint_orthat{\XINTfstop.{#1}}% +}% +\def\XINT_allexpr_opx_break #1#2\relax +{% + break(\expandafter\XINTfstop\expandafter.\expandafter{\xint_gobble_i#1}#2)\relax }% % \end{macrocode} % \subsubsection{\cshn{rseq()}} @@ -39773,12 +40116,12 @@ math shift catcode. \xint_dothis\XINT:NE:f:one:and:opt_a\fi \xint_orthat\XINT:NE:f:tacitzeroifone_b ##1&&A% }}\expandafter\XINT:NE:f:tacitzeroifone:direct\string#% -\def\XINT:NE:f:tacitzeroifone:direct\XINT:expr:f:tacizeroifone #1#2#3&&A#4#5% +\def\XINT:NE:f:tacitzeroifone_b\XINT:expr:f:tacitzeroifone #1#2#3&&A#4#5% {% \if\relax#3\relax\expandafter\xint_firstoftwo\else \expandafter\xint_secondoftwo\fi - {\XINT:NE:f:one:from:two#4{0}}% - {\expandafter\XINT:NE:f:one:from:two\expandafter#5% + {\XINT:NE:f:one:from:two:direct#4{0}}% + {\expandafter\XINT:NE:f:one:from:two:direct\expandafter#5% \expanded{{\XINT:NE:f:one:from:one:direct\xintNum{#2}}}}% {#1}% }% @@ -39794,12 +40137,12 @@ math shift catcode. {% \detokenize{\romannumeral`-0\expandafter#1\expanded{#2}$XINT_expr_exclam#3}%$ }% -\def\XINT:NE:f:iitacitzeroifone:direct\XINT:expr:f:iitacizeroifone #1#2#3&&A#4% +\def\XINT:NE:f:iitacitzeroifone_b\XINT:expr:f:iitacitzeroifone #1#2#3&&A#4% {% \if\relax#3\relax\expandafter\xint_firstoftwo\else \expandafter\xint_secondoftwo\fi - {\XINT:NE:f:one:from:two#4{0}}% - {\XINT:NE:f:one:from:two#4{#2}}% + {\XINT:NE:f:one:from:two:direct#4{0}}% + {\XINT:NE:f:one:from:two:direct#4{#2}}% {#1}% }% \def\XINT:NE:x:one:from:two #1#2#3{\XINT:NE:x:one:from:two_fork #2&&A#3&&A#1{#2}{#3}}% @@ -40001,7 +40344,9 @@ math shift catcode. \detokenize {% \expanded\bgroup - \expanded{\unexpanded{\XINT_expr_iter:_b{#1(#6)#7\relax $XINT_expr_exclam #5}}% + \expanded{\unexpanded{\XINT_expr_iter:_b + {#1\expandafter\XINT_allexpr_opx_ifnotomitted + \romannumeral0#1#6\relax#7@\relax $XINT_expr_exclam #5}}% #4$XINT_expr_caret$XINT_expr_tilde{{#8}}}%$ }% }% @@ -40596,10 +40941,10 @@ math shift catcode. \expandafter\xint_secondoftwo \fi {\immediate\write-1{Reloading xinttrig library using Digits=\xinttheDigits.}}% -{\expandafter\gdef\csname xintlibver@trig\endcsname{2020/01/31 v1.4}% +{\expandafter\gdef\csname xintlibver@trig\endcsname{2020/02/19 v1.4a}% \XINT_providespackage \ProvidesPackage{xinttrig}% -[2020/01/31 v1.4 Trigonometrical functions for xintexpr (JFB)]% +[2020/02/19 v1.4a Trigonometrical functions for xintexpr (JFB)]% }% % \end{macrocode} % \subsection{Ensure used letters are dummy letters} @@ -41629,7 +41974,7 @@ math shift catcode. \xintexprSafeCatcodes\catcode`_ 11 \XINT_providespackage \ProvidesPackage{xintlog}% -[2020/01/31 v1.4 Logarithms and exponentials for xintexpr (JFB)]% +[2020/02/19 v1.4a Logarithms and exponentials for xintexpr (JFB)]% % \end{macrocode} % \subsection{Loading of \cshn{poormanlog} package} % \lverb|Attention to catcode regime when loading poormanlog. It matters less @@ -41826,8 +42171,8 @@ xint.sty:205 xintbinhex.sty:53 xintcfrac.sty:183 xintcore.sty:271 -xintexpr.sty:412 -xintfrac.sty:492 +xintexpr.sty:414 +xintfrac.sty:494 xintgcd.sty:41 xintkernel.sty:17 xintlog.sty:9 @@ -41836,15 +42181,15 @@ xinttools.sty:153 xinttrig.sty:31 \fi % grep -o "^{%" xint*sty | wc -l -\def\totala{ 1915} +\def\totala{ 1919} \iffalse % grep -c -e "^}%" xint*sty xint.sty:204 xintbinhex.sty:52 xintcfrac.sty:183 xintcore.sty:268 -xintexpr.sty:400 -xintfrac.sty:495 +xintexpr.sty:402 +xintfrac.sty:497 xintgcd.sty:43 xintkernel.sty:18 xintlog.sty:9 @@ -41853,7 +42198,7 @@ xinttools.sty:152 xinttrig.sty:32 \fi % grep -o "^}%" xint*sty | wc -l -\def\totalb{ 1904} +\def\totalb{ 1908} \cleardoublepage \section{Cumulative line count} @@ -41877,7 +42222,8 @@ xinttrig.sty:32 \TeX\strut. Version {\xintbndlversion} of {\xintbndldate}.\par } -\CheckSum {34575}% 1.4 +\CheckSum {34648}% 1.4a +% 34575 pour 1.4 % 33497 pour 1.3f, 33274 pour 1.3e, 31601 pour 1.3d, 31122 pour 1.3c % 31069 pour 1.3b, 30482 pour 1.3a, 30621 pour 1.3, 30988 pour 1.2q, % 30982 pour 1.2p, 30524 pour 1.2o, 30303 pour 1.2h, 30403 pour 1.2i, |