diff options
author | Karl Berry <karl@freefriends.org> | 2015-11-16 22:23:49 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2015-11-16 22:23:49 +0000 |
commit | bfcd7527b0f8985ecc54376d0e2b1aaa9f4b53e7 (patch) | |
tree | cf8d1be2d41875fb27db260922b97ae5431ca813 /Master | |
parent | d8258d9565c2f3e2c0e2a4d6f71099f8f604bbed (diff) |
xint (16nov15)
git-svn-id: svn://tug.org/texlive/trunk@38876 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
19 files changed, 3178 insertions, 2265 deletions
diff --git a/Master/texmf-dist/doc/generic/xint/CHANGES.html b/Master/texmf-dist/doc/generic/xint/CHANGES.html index 17429ab2b08..2b8d92ead62 100644 --- a/Master/texmf-dist/doc/generic/xint/CHANGES.html +++ b/Master/texmf-dist/doc/generic/xint/CHANGES.html @@ -4,7 +4,7 @@ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <meta name="generator" content="pandoc" /> - <meta name="author" content="xint v1.2b" /> + <meta name="author" content="xint v1.2c" /> <title>CHANGE LOG</title> <style type="text/css">code{white-space: pre;}</style> <style type="text/css"> @@ -17,11 +17,12 @@ <body> <div id="header"> <h1 class="title">CHANGE LOG</h1> -<h2 class="author">xint v1.2b</h2> -<h3 class="date">2015/10/29</h3> +<h2 class="author">xint v1.2c</h2> +<h3 class="date">2015/11/16</h3> </div> <div id="TOC"> <ul> +<li><a href="#c-20151116"><code>1.2c (2015/11/16)</code></a></li> <li><a href="#b-20151029"><code>1.2b (2015/10/29)</code></a></li> <li><a href="#a-20151019"><code>1.2a (2015/10/19)</code></a></li> <li><a href="#section"><code>1.2 (2015/10/10)</code></a></li> @@ -55,10 +56,16 @@ <li><a href="#section-8"><code>1.0 (2013/03/28)</code></a></li> </ul> </div> -<pre><code>Source: xint.dtx v1.2b 2015/10/29 (doc 2015/10/29) +<pre><code>Source: xint.dtx v1.2c 2015/11/16 (doc 2015/11/16) Author: Jean-Francois Burnol Info: Expandable operations on big integers, decimals, fractions License: LPPL 1.3c</code></pre> +<h2 id="c-20151116"><code>1.2c (2015/11/16)</code></h2> +<ul> +<li><p>bugfix in <strong>xintcore</strong>: recent release <code>1.2</code> introduced a bug in the subtraction (happened when 00000001 was found under certain circumstances at certain mod 8 locations).</p></li> +<li><p>new macros <code>\xintdeffunc</code>, <code>\xintdefiifunc</code>, <code>\xintdeffloatfunc</code> and boolean <code>\ifxintverbose</code>.</p></li> +<li><p>on-going code improvements and documentation enhancements, but stopped in order to issue this bugfix release.</p></li> +</ul> <h2 id="b-20151029"><code>1.2b (2015/10/29)</code></h2> <ul> <li>bugfix in <strong>xintcore</strong>: recent release <code>1.2</code> introduced a bug in the division macros, causing a crash when the divisor started with 99999999 (it was attempted to use with 1+99999999 a subroutine expecting only 8-digits numbers).</li> diff --git a/Master/texmf-dist/doc/generic/xint/CHANGES.pdf b/Master/texmf-dist/doc/generic/xint/CHANGES.pdf Binary files differindex 115eeb5810b..3f40ba7ed94 100644 --- a/Master/texmf-dist/doc/generic/xint/CHANGES.pdf +++ b/Master/texmf-dist/doc/generic/xint/CHANGES.pdf diff --git a/Master/texmf-dist/doc/generic/xint/README b/Master/texmf-dist/doc/generic/xint/README index e2137df6651..f43fff5f291 100644 --- a/Master/texmf-dist/doc/generic/xint/README +++ b/Master/texmf-dist/doc/generic/xint/README @@ -1,4 +1,4 @@ - Source: xint.dtx v1.2b 2015/10/29 (doc 2015/10/29) + Source: xint.dtx v1.2c 2015/11/16 (doc 2015/11/16) Author: Jean-Francois Burnol Info: Expandable operations on big integers, decimals, fractions License: LPPL 1.3c diff --git a/Master/texmf-dist/doc/generic/xint/README.html b/Master/texmf-dist/doc/generic/xint/README.html index 2862962528b..1eea28bc07b 100644 --- a/Master/texmf-dist/doc/generic/xint/README.html +++ b/Master/texmf-dist/doc/generic/xint/README.html @@ -4,7 +4,7 @@ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <meta name="generator" content="pandoc" /> - <meta name="author" content="xint v1.2b" /> + <meta name="author" content="xint v1.2c" /> <title>README</title> <style type="text/css">code{white-space: pre;}</style> <style type="text/css"> @@ -17,8 +17,8 @@ <body> <div id="header"> <h1 class="title">README</h1> -<h2 class="author">xint v1.2b</h2> -<h3 class="date">2015/10/29</h3> +<h2 class="author">xint v1.2c</h2> +<h3 class="date">2015/11/16</h3> </div> <div id="TOC"> <ul> @@ -36,7 +36,7 @@ <li><a href="#license">License</a></li> </ul> </div> -<pre><code>Source: xint.dtx v1.2b 2015/10/29 (doc 2015/10/29) +<pre><code>Source: xint.dtx v1.2c 2015/11/16 (doc 2015/11/16) Author: Jean-Francois Burnol Info: Expandable operations on big integers, decimals, fractions License: LPPL 1.3c</code></pre> diff --git a/Master/texmf-dist/doc/generic/xint/README.pdf b/Master/texmf-dist/doc/generic/xint/README.pdf Binary files differindex c102d9074d8..bf4f696efa7 100644 --- a/Master/texmf-dist/doc/generic/xint/README.pdf +++ b/Master/texmf-dist/doc/generic/xint/README.pdf diff --git a/Master/texmf-dist/doc/generic/xint/sourcexint.pdf b/Master/texmf-dist/doc/generic/xint/sourcexint.pdf Binary files differindex 03244be9e23..0612b4c18b7 100644 --- a/Master/texmf-dist/doc/generic/xint/sourcexint.pdf +++ b/Master/texmf-dist/doc/generic/xint/sourcexint.pdf diff --git a/Master/texmf-dist/doc/generic/xint/xint.pdf b/Master/texmf-dist/doc/generic/xint/xint.pdf Binary files differindex 6bafd0f4b7a..8736fed572e 100644 --- a/Master/texmf-dist/doc/generic/xint/xint.pdf +++ b/Master/texmf-dist/doc/generic/xint/xint.pdf diff --git a/Master/texmf-dist/source/generic/xint/xint.dtx b/Master/texmf-dist/source/generic/xint/xint.dtx index f499332f3cb..7b22a6c36bc 100644 --- a/Master/texmf-dist/source/generic/xint/xint.dtx +++ b/Master/texmf-dist/source/generic/xint/xint.dtx @@ -2,24 +2,24 @@ % N.B.: this dtx file does NOT use \DocInput, only docstrip. The user manual % latex source is NOT prefixed with percent characters. %<*dtx> -\def\xintdtxtimestamp {Time-stamp: <29-10-2015 13:19:20 CET>} +\def\xintdtxtimestamp {Time-stamp: <16-11-2015 at 14:51:00 CET>} %</dtx> %<*drv> %% --------------------------------------------------------------- -\def\xintdocdate {2015/10/29} -\def\xintbndldate{2015/10/29} -\def\xintbndlversion {1.2b} +\def\xintdocdate {2015/11/16} +\def\xintbndldate{2015/11/16} +\def\xintbndlversion {1.2c} %</drv> %<*dtx> \iffalse % meta-comment %</dtx> %<readme>% README %<changes>% CHANGE LOG -%<readme|changes>% xint v1.2b -%<readme|changes>% 2015/10/29 +%<readme|changes>% xint v1.2c +%<readme|changes>% 2015/11/16 %<*readme|changes> - Source: xint.dtx v1.2b 2015/10/29 (doc 2015/10/29) + Source: xint.dtx v1.2c 2015/11/16 (doc 2015/11/16) Author: Jean-Francois Burnol Info: Expandable operations on big integers, decimals, fractions License: LPPL 1.3c @@ -27,7 +27,7 @@ %</readme|changes> %<*!readme&!changes&!dohtmlsh&!dopdfsh&!makefile> %% --------------------------------------------------------------- -%% The xint bundle v1.2b 2015/10/29 +%% The xint bundle v1.2c 2015/11/16 %% Copyright (C) 2013-2015 by Jean-Francois Burnol %<xintkernel>%% xintkernel: Paraphernalia for the xint packages %<xinttools>%% xinttools: Expandable and non-expandable utilities @@ -237,6 +237,20 @@ pandoctpl.latex, doHTMLs.sh, doPDFs.sh, xint.dvi, xint.pdf, Makefile.mk.</div> %</readme>-------------------------------------------------------- %<*changes>------------------------------------------------------- +`1.2c (2015/11/16)` +---- + + - bugfix in **xintcore**: recent release `1.2` introduced a bug in the + subtraction (happened when 00000001 was found under certain + circumstances at certain mod 8 locations). + + - new macros `\xintdeffunc`, `\xintdefiifunc`, `\xintdeffloatfunc` and + boolean `\ifxintverbose`. + + - on-going code improvements and documentation enhancements, but + stopped in order to issue this bugfix release. + + `1.2b (2015/10/29)` ---- @@ -1691,6 +1705,7 @@ dvipdfmx CHANGES.dvi % alors qu'avant j'utilisais savedsectionline, par paresse. % 12 octobre 2014, emploi \llap, \leftmargini et aussi de \MARGEPAGENO ici aussi +% \leftmargini \dimexpr4\fontcharwd\font`X\relax \etocsetstyle{section}{} {\normalfont} {\kern\bigskipamount @@ -1710,26 +1725,39 @@ dvipdfmx CHANGES.dvi {}% % Octobre 2014: emploi de \leftmargini et ajout de \parskip\z@skip. +% \leftmargini \dimexpr4\fontcharwd\font`X\relax +% \leftmarginii\dimexpr3\fontcharwd\font`X\relax +% Samedi 07 novembre 2015 +% suite fusion, j'ai des numéros de sous-sections plus longs. +% j'en profite aussi pour intervenir sur le filet central etc... +\newdimen\margegauchetoc +\AtBeginDocument{\margegauchetoc \dimexpr 5\fontcharwd\font`X\relax} \makeatletter \etocsetstyle{subsection} {\begingroup\normalfont \setlength{\premulticols}{0pt}% \setlength{\multicolsep}{0pt}% - \setlength{\columnsep}{1em}% - \setlength{\columnseprule}{.4pt}% + \setlength{\columnsep}{\leftmarginii}% + \setlength{\columnseprule}{.4pt}% n'influence pas séparation colonnes % Octobre 2014 mes problèmes d'alors étaient liés à la glue dans \parskip \parskip\z@skip % j'avais seulement ceci avant, je laisse les deux \raggedcolumns \addvspace{\smallskipamount}% \begin{multicols}{2} - \leftskip \leftmargini % 12 octobre 2014 - \rightskip \MARGEPAGENO plus 2em minus 1em % 18 octobre 2013 + \leftskip \margegauchetoc % 12 octobre 2014 +% \rightskip \MARGEPAGENO plus 2em minus 1em % 18 octobre 2013 +% finalement Samedi 07 novembre 2015 + \ifindescription + \rightskip \MARGEPAGENO + \else + \rightskip \MARGEPAGENO plus 2em minus 1em + \fi \parfillskip -\MARGEPAGENO\relax } {} {\noindent - \llap{\makebox[\leftmargini][l]{\ttzfamily\bfseries\etoclink + \llap{\makebox[\margegauchetoc][l]{\ttzfamily\bfseries\etoclink {\ifindescription\expandafter\textcolor\sectioncouleur {\normalfont\bfseries\ETOCsectionnumber}\fi .\expandafter\gobbletodot\etocthenumber}}}% @@ -2485,6 +2513,9 @@ pdfpagemode=UseOutlines} % Septembre 2015 \def\liiibigint{\href{http://latex-project.org/svnroot/experimental/trunk/l3trial/l3bigint}{l3bigint}} +% % pour accéder à l'historique des commits: +% % https://github.com/latex3/latex3/tree/master/l3trial/l3bigint + % 20 octobre 2015 hier j'ai un peu rapidement remplacé les \romannumeral-`0 % dans le code par de mystérieux \romannumeral`<character0catcode12>, en T1, @@ -2706,7 +2737,14 @@ pdfpagemode=UseOutlines} \tableofcontents \renewcommand*\etocabovetocskip{\bigskipamount} \makeatletter -\etocmulticolstyle [2]{\parskip\z@skip\raggedcolumns }% +% modifié Samedi 07 novembre 2015 +% y'en a un peu marre du style olé olé de la doc de multicols +% bon bref \columnsep donne la séparation indépendamment du filet vertical +% (logique, j'admets) +\etocmulticolstyle [2]{\parskip\z@skip\raggedcolumns + \setlength{\columnsep}{\leftmarginii}% + \setlength{\columnseprule}{0pt}% +}% \makeatother \etocsettagdepth {description}{none} \etocsettagdepth {commands} {section} @@ -2777,6 +2815,8 @@ This section provides recommended reading on first discovering the package. x=10..20, 31, 51)\relax \end{everbatim*} +\smallskip + The reasonable range of use of the package arithmetics is with numbers of less than \emph{one hundred or perhaps two hundred digits.} Release |1.2| has significantly improved the speed of the basic operations for numbers @@ -2866,38 +2906,51 @@ Further modules: \end{description} \end{addmargin} -\subsection{Quick overview} +\subsection{Quick first overview (expressions with \xintexprname)} -This documentation was build via successive layers; a complete re-write -would be needed for a more user-friendly access. I will try to add here a -quick expos\'e of the package abilities, starting from the arithmetic -expressions handled by package \xintexprname. +This section gives a first few examples of using the expression parsers which +are provided by package \xintexprname. Loading \xintexprname automatically also +loads packages \xinttoolsname and \xintfracname. The latter loads \xintname +which loads \xintcorename. All three provide the macros which ultimately do the +computations associated in expressions with the various symbols like |+, *, ^, +!| and functions such as |max, sqrt, binomial, gcd| (the latter requires +explicit loading of \xintgcdname). The package +\xinttoolsname does not handle computations but provides some useful utilities. -There are three expression parsers and two additional derived ones. They +There are three expression parsers and two subsidiary ones. They all admit comma separated expressions, and will then output a comma separated list of results. \begin{itemize}[nosep] -\item \csbxint{theiiexpr}| ... \relax| does exact computations on integers. - The forward slash \dtt{/} does the rounded integer division. There are two - square root extractors \dtt{sqrt} and \dtt{sqrtr} for truncated, respectively - rounded square roots. +\item \csbxint{theiiexpr}| ... \relax| does exact computations \emph{only on + integers.} The forward slash \dtt{/} does the rounded integer division + (\dtt{//} does truncated division, and \dtt{/:} is the associated modulo). + There are two square root extractors \dtt{sqrt} and \dtt{sqrtr} for + truncated and rounded square roots. \item \csbxint{thefloatexpr}| ... \relax| does computations with a given - precision \dtt{P}, as specified via |\xintDigits:=P;|. The default is - \dtt{P=16} digits. An optional argument controls the precision on + precision \dtt{P}, as specified via a prior assignment |\xintDigits:=P;|. The + default is \dtt{P=16} digits. An optional argument controls the precision on \emph{output} (this is not the precision of the computations themselves). + The four basic operations realize \emph{correct rounding.} \item \csbxint{theexpr}| ... \relax| handles integers, decimal numbers, numbers in scientific notation and fractions. The algebraic computations are - done exactly. Currently, the only transcendental function implemented is - |sqrt|. It computes according to the precision specified by |\xintDigits|, - or according to its second optional argument. + done \emph{exactly.} \end{itemize} -Additional derived parsers: +\begin{framed} + Currently, the sole available non-algebraic function is the square root + extraction \dtt{sqrt}. It is allowed in |\xintexpr..\relax| but naturally + can't return an \emph{exact} value, hence computes as if it was in + |\xintfloatexpr..\relax|. The power operator |^| (equivalently |**|) only + works with integral powers (half-integers are not accepted, despite square + root extraction having been implemented). +\end{framed} + +Two derived parsers: \begin{itemize}[nosep] \item \csbxint{theiexpr}| ... \relax| does all computations like |\xinttheexpr ... \relax| but rounds the result to the nearest integer. With an optional - argument |[D]|, the rounding is to the nearest fixed point number with |D| - digits after the decimal mark. + positive argument |[D]|, the rounding is to the nearest fixed point number + with |D| digits after the decimal mark. \item \csbxint{theboolexpr}| ... \relax| does all computations like |\xinttheexpr ... \relax| but converts the result to $1$ if it is not zero (works also on comma separated expressions). @@ -2905,111 +2958,68 @@ Additional derived parsers: \csbxint{ifboolfloatexpr} (which do not handle comma separated expressions). \end{itemize} -\begin{framed} - Here is the (partial) list of recognized symbols: the comma (to separate - distinct computations or arguments to a function), the parentheses, infix - operators |+|, |-|, |*|, |/|, |^| (or |**|), branching operators |?|, |??|, - boolean operators |!|, |&&|, \verb+||+, comparison operators |=| (or |==|), - |<|, |>|, |<=|, |>=|, |!=|, factorial post-fix operator |!|, and functions - \dtt{num, reduce, abs, sgn, frac, floor, ceil, sqr, sqrt, sqrtr, float, - round, trunc, mod, quo, rem, gcd, lcm, max, min, |`+`|, |`*`|, not, all, - any, xor, if, ifsgn, even, odd, first, last, reversed, bool, togl, add, - mul, seq, subs, rseq, rrseq, iter}. And |"| may serve for hexadecimal - input (uppercase only; package \xintbinhexname required). - - |1.2| has added \dtt{qint, qfrac, qfloat} to tell the parser to skip its usual - token by token expansion when gathering the digits of a number. - - See \autoref{ssec:syntax} for the complete syntax, as well as - \autoref{sec:expr11} which focused on the extensions brought with |xintexpr - 1.1|. -\end{framed} +Here is a (partial) list of the recognized symbols: +\begin{itemize}[nosep] +\item the comma (to separate distinct computations or arguments to a + function), +\item parentheses, +\item infix operators |+|, |-|, |*|, |/|, |^| (or |**|), +% \item |//| and |/:| only in \csbxint{iiexpr}|..\relax|, +\item branching operators |(x)?{x non zero}{x zero}|, |(x)??{x<0}{x=0}{x>0}|, +\item boolean operators |!|, |&&| or |'and'|, \verb+||+ or |'or'|, +\item comparison operators |=| (or |==|), |<|, |>|, |<=|, |>=|, |!=|, +\item factorial post-fix operator |!|, +\item |"| for hexadecimal input (uppercase only; package \xintbinhexname + must be loaded additionally to \xintexprname), +\item |'| for octal input (\emph{not yet}), +\item functions \xintFor #1 in {num, reduce, abs, sgn, frac, floor, ceil, sqr, sqrt, + sqrtr, factorial, binomial, float, round, trunc, mod, quo, rem, gcd, lcm, + max, min, |`+`|, |`*`|, not, all, any, xor, if, ifsgn, even, odd, first, + last, reversed, bool, togl}\do {\dtt{#1}, } +\item functions with dummy variables \xintFor #1 in {add, mul, seq, subs, + rseq, rrseq, iter}\do {\dtt{#1}\xintifForLast{.}{, }} +\end{itemize} +See \autoref{ssec:syntax} for the complete syntax, as well as +\autoref{sec:expr11} which contains examples illustrating the features which +were introduced with \xintexprname |v1.1 2014/10/28|. + +The normal mode of operation of the parsers is to unveil the parsed material +token by token. This means that all elements may arise from expansion of +encountered macros (or active characters). For example a closing parenthesis +does not have to be immediately visible, it may arise later from expansion. +This general behavior has exceptions, in particular constructs with dummy +variables need immediately visible balanced parentheses and commas. 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. + +Release |1.2| added the (pseudo) functions \dtt{qint}, \dtt{qfrac}, +\dtt{qfloat} to allow swallowing in one-go all digits of a big number, +fraction, or float, skipping the token by token expansion. +\medskip Here is an example of a computation: \begin{everbatim*} \xinttheexpr (31.567^2 - 21.56*52)^3/13.52^5\relax \end{everbatim*} - -The result is a bit frightening but illustrates that |\xinttheexpr..\relax| -does its computations \emph{exactly}. There is a variant which emulates -floating point computations: +\newline The result is a bit frightening but illustrates that +|\xinttheexpr..\relax| does its computations \emph{exactly}. The same example +as a floating point evaluation: \begin{everbatim*} \xintthefloatexpr (31.567^2 - 21.56*52)^3/13.52^5\relax \end{everbatim*} -Such ``floating-point'' computations are done by default with 16 digits of -precision (this can be increased via a prior assignment such as -|\xintDigits:=24;|). - -\xintname has very few typesetting macros. \LaTeX{} users -can do: -\begin{everbatim*} -\[\xintFrac{\xintthefloatexpr (31.567^2 - 21.56*52)^3/13.52^5\relax }\] -\end{everbatim*}% <- il faudra que je vois ça, sinon espace en début de ligne -but it probably is better to use packages dedicated to the typesetting of -numbers in scientific format (notice that the display above is not in -scientific notation). However, when using |\xinttheexpr| rather than -|\xintthefloatexpr| the result will -typically be in |A/B[N]| format and this is unlikely to be understood by your -favorite number formatting package. - -The computations are done expandably: you can put them in an |\edef| or a -|\write| or even force complete expansion via |\romannumeral-`0| (if you don't -understand the latter sentence, this doesn't matter; this manual should -contain a description of expandability in \TeX, but this is yet to arise.) -Let's just say that such expandable macros are maximally usable in almost all -locations of \TeX{} code. However in contexts where \TeX{} expects an integer, -it will naturally not be able to digest a number in scientific notation or a -fraction. Fixed point decimal numbers however can be understood by \TeX{} in -the context of manipulation of dimensions. - -% The constraint of expandability exerces its spell on the programmer as a -% challenge to raise, and has its rewards: this is my only excuse for pretending -% that computing expandably with fractions of dozens of digits has any use. - - -% The implementation is also maximally complicated as many functionalities of -% the \TeX{} macro language can't be used in the source code of \xintname by the -% masochist author of the package. Besides, there is a speed impact, and -% although algebraic computations with numbers of up to one hundred digits are -% fine, my current implementation of multiplication needs of the order of the -% second for inputs with thousand digits. Macro \csbxint{XTrunc} is however able -% to compute and output tens of thousands of digits of a decimal expansion in -% reasonable time, still expandably, but it does not expand completely via -% |\romannumeral-`0|. As the \csbxint{theexpr}|..\relax| mechanism only needs -% the weaker type of expandability as in \csbxint{XTrunc}, perhaps some speed -% gains could be achieved via a complete rewrite of all basic macros of the -% package. - -The underlying macros to which |\xinttheexpr ...\relax| and the other parsers -map the infix operations are provided by packages \xintcorename, \xintname (for -integers) and \xintfracname (for fractions, decimal numbers, and scientific -numbers). They are nestable. For example to do something like |21+32*43|, the -syntax would be (only \xintcorename is needed): -\begin{everbatim*} -\xintiiAdd{21}{\xintiiMul{32}{43}}\par -\noindent\xintiiMul{21283978192739181739}{\xintiiSub {130938109831081320}{29810810281}} -\end{everbatim*} - -Needless to say this quickly becomes a bit painful. One more example (needs -\xintfracname): -\begin{everbatim*} -\xintIrr {\xintiiPrd{{128}{81}{125}}/\xintiiPrd{{32}{729}{100}}}\par -\noindent\xintIrr{\xintAdd{31791327893/231938201832}{19831081392/189038013988310}} -\end{everbatim*} - -This shows that package \xintfracname knows natively how to handle fractions -|A/B|. Notice that |*|, |+| and |-| contrarily to the |/| which is treated as -a special optional delimiter are not accepted in the arguments to the -\xintfracname macros (see \autoref{sec:inputs} and \autoref{sec:useofcount} -for some exceptions). There is \csbxint{Irr} to reduce to smallest terms (in -an |\xintexpr..\relax| this would be the |reduce| function). - Again, all computations done by |\xinttheexpr..\relax| are completely exact. Thus, very quickly very big numbers are created (and computation times -explode). To compute something like |1.23456789^10000| you will have to opt -for the floating point version (the braces below are to limit the scope of the -assignment to |\xintDigits|): +increase, not to say explode if one goes into handling numbers with thousands +of digits). To compute something like |1.23456789^10000| it is thus better to +opt for the floating point version: +\begin{everbatim*} +\xintthefloatexpr 1.23456789^10000\relax +\end{everbatim*} +\newline +(we can deduce that the exact value has |80000+916=80916| digits). +A bigger example (the scope of +the assignment to |\xintDigits| is limited by the braces): \begin{everbatim*} {\xintDigits:=24; \xintthefloatexpr 1.23456789123456789^123456789\relax } \end{everbatim*} @@ -3020,14 +3030,60 @@ It is also possible to do some (expandable...) computer algebra like evaluations (only numerically though): \begin{everbatim*} \xinttheiiexpr add(i^5, i=100..200)\relax\par -\noindent\xinttheexpr add(x/(x+1), x = 1000..[3]..1020)\relax +\noindent\xinttheexpr reduce(add(x/(x+1), x = 1000..1014))\relax \end{everbatim*} +\newline Were it not for the \dtt{reduce} function, the latter fraction would +not have been obtained in reduced terms: +\begin{framed} + By default, the basic operations on fractions are not followed in an + automatic manner by reduction to smallest terms: |A/B| multiplied by |C/D| + returns |AC/BD|, |A/B| added to |C/D| returns |(AD+BC)/BD| except if either + |B| divides |D| or |D| divides |B|. +% y réfléchir +% The command |\xintfracsetup{reduceall}| +\end{framed} -The latter fraction is not in reduced terms, but it would be if we had used -the \dtt{reduce} function inside the expression. +Make sure to read \autoref{ssec:userinterface}, \autoref{sec:expr11} and the +rest of \autoref{sec:expr}. -Make sure to read \autoref{ssec:userinterface}, \autoref{sec:expr11} and -\autoref{sec:expr}. +% \xintname has very few typesetting macros. \LaTeX{} users +% can do: +% \begin{everbatim*} +% \[\xintFrac{\xintthefloatexpr (31.567^2 - 21.56*52)^3/13.52^5\relax }\] +% \end{everbatim*}% <- il faudra que je vois ça, sinon espace en début de ligne +% but it probably is better to use packages dedicated to the typesetting of +% numbers in scientific format (notice that the display above is not in +% scientific notation). However, when using |\xinttheexpr| rather than +% |\xintthefloatexpr| the result will +% typically be in |A/B[N]| format and this is unlikely to be understood by your +% favorite number formatting package. + +% The computations are done expandably: you can put them in an |\edef| or a +% |\write| or even force complete expansion via |\romannumeral-`0| (if you don't +% understand the latter sentence, this doesn't matter; this manual should +% contain a description of expandability in \TeX, but this is yet to arise.) +% Let's just say that such expandable macros are maximally usable in almost all +% locations of \TeX{} code. However in contexts where \TeX{} expects an integer, +% it will naturally not be able to digest a number in scientific notation or a +% fraction. Fixed point decimal numbers however can be understood by \TeX{} in +% the context of manipulation of dimensions. + +% The underlying macros to which |\xinttheexpr ...\relax| and the other parsers +% map the infix operations are provided by packages \xintcorename, \xintname (for +% integers) and \xintfracname (for fractions, decimal numbers, and scientific +% numbers). They are nestable. For example to do something like |21+32*43|, the +% syntax would be (only \xintcorename is needed): +% \begin{everbatim*} +% \xintiiAdd{21}{\xintiiMul{32}{43}}\par +% \noindent\xintiiMul{21283978192739181739}{\xintiiSub {130938109831081320}{29810810281}} +% \end{everbatim*} + +% Needless to say this quickly becomes a bit painful. One more example (needs +% \xintfracname): +% \begin{everbatim*} +% \xintIrr {\xintiiPrd{{128}{81}{125}}/\xintiiPrd{{32}{729}{100}}}\par +% \noindent\xintIrr{\xintAdd{31791327893/231938201832}{19831081392/189038013988310}} +% \end{everbatim*} \subsection {Changes} @@ -3044,6 +3100,11 @@ early 2014) until their complete rewrite with release |1.2| from |2015/10/10|. \begin{description} +\item [|1.2a (2015/10/19), 1.2b (2015/10/29), 1.2c (2015/11/16):|] for fixing + bugs introduced (alas) in |1.2|. Release |1.2c| has the novel + \csbxint{deffunc}, \csbxint{defiifunc}, \csbxint{deffloatfunc} macros whose + purpose is to define functions recognized as such by the \xintexprname + parsers. \item [|1.2 (2015/10/10):|] complete rewrite of the core arithmetic routines. The efficiency for numbers with less than $20$ or $30$ digits is slightly compromised (for addition/subtraction) but it is increased for bigger @@ -3084,6 +3145,61 @@ It is also available on \href{http://ctan.org}{CTAN} via Or, running |etex xint.dtx| in a working repertory will extract a |CHANGES.md| file with Markdown syntax. +\subsection{Origins of the package} + +|2013/03/28.| Package |bigintcalc| by \textsc{Heiko Oberdiek} already +provides expandable arithmetic operations on ``big integers'', +exceeding the \TeX{} limits (of $2^{31}-1$), so why another% +% +\footnote{this section was written before the \xintfracname package; the + author is not aware of another package allowing expandable + computations with arbitrarily big fractions.} +% +one? + +I got started on this in early March 2013, via a thread on the +|c.t.tex| usenet group, where \textsc{Ulrich D\,i\,e\,z} used the +previously cited package together with a macro (|\ReverseOrder|) +which I had contributed to another thread.% +% +\footnote{the \csa{ReverseOrder} could be avoided in that circumstance, + but it does play a crucial r\^ole here.} +% +What I had learned in this +other thread thanks to interaction with \textsc{Ulrich D\,i\,e\,z} and +\textsc{GL} on expandable manipulations of tokens motivated me to +try my hands at addition and multiplication. + +I wrote macros \csa{bigMul} and \csa{bigAdd} which I posted to the +newsgroup; they appeared to work comparatively fast. These first +versions did not use the \eTeX{} \csa{numexpr} primitive, they worked +one digit at a time, having previously stored carry-arithmetic in +1200 macros. + +I noticed that the |bigintcalc| package used \csa{numexpr} +if available, but (as far as I could tell) not +to do computations many digits at a time. Using \csa{numexpr} for +one digit at a time for \csa{bigAdd} and \csa{bigMul} slowed them +a tiny bit but avoided cluttering \TeX{} memory with the 1200 +macros storing pre-computed digit arithmetic. I wondered if some speed +could be gained by using \csa{numexpr} to do four digits at a time +for elementary multiplications (as the maximal admissible number +for \csa{numexpr} has ten digits). + +The present package is the result of this initial questioning. + +\noindent|2015/10/10.| \xintname 1.2 also got its impulse from a fast +``reversing'' macro, which I wrote after my interest got awakened again as a +result of correspondance with Bruno \textsc{Le Floch} during September 2015: +this new reverse uses a \TeX nique which \emph{requires} the tokens to be +digits. I wrote a routine which works (expandably) in quasi-linear time, but a +less fancy |O(N^2)| variant which I developed concurrently proved to be faster +all the way up to perhaps $7000$ digits, thus I dropped the quasi-linear one. +The less fancy variant has the advantage that \xintname can handle numbers +with more than $19900$ digits (but not much more than $19950$). This is with +the current common values of the input save stack and maximal expansion depth: +$5000$ and $10000$ respectively. + \subsection{Installation instructions} \label{ssec:install} @@ -3127,67 +3243,6 @@ If you have |xint.dtx|, no internet access and can not use the Makefile method: |etex xint.dtx| extracts all files and among them the |README| as a file with name |README.md|. Further help and options will be found therein. -% \subsection{FAQ} - -% % pour accéder à l'historique des commits: -% % https://github.com/latex3/latex3/tree/master/l3trial/l3bigint - -% We are honoured to present here this interview with the author, dating back to -% late March 2014. -% \begin{description} -% \item[Will \xintexprname implement \texttt{exp}, \texttt{log}, -% \texttt{cos}, \texttt{sin} \dots at some point?] -% I guess so. - -% \item[\xintseriesname already provides generic tools.] Right, although the -% casual user of the \xintname bundle will not quite know how to do variable -% reduction expandably in order to use some series or Pad\'e approximants. -% Besides I wrote the code at the beginning of the project and perhaps I could -% do it better now (I have not looked at it for a while). Anyhow, generic things -% do not help much if one wants to optimize. - -% \item[Optimizing? isn't \TeX's macro expansion mechanism intrinsically slow?] -% Intensive use of \csa{numexpr} and some token manipulation algorithms -% exploiting to the best I could \TeX{} macros with parameters grant \xintname -% a significant speed up in expandable arithmetic on big integers compared to -% previously available implementations. You can do some comparisons with -% multiplication on numbers with $100$ digits or division of one of $100$ -% digits by another of $50$ digits, for example. However expandability is -% antagonist of speed, and I agree it is not very exciting to optimize slow -% things. And I was disappointed last year to realize the slowness of \TeX's -% mouth when it has to keep hundreds of tokens in cheek to mix them later with -% new aliments. -% % https://github.com/latex3/latex3/commit/f46e22cb772ee34aeb2fb200f7907ed3e6192bac -% % -% -% Believe me, I try not to think too much about the fact that the whole -% enterprise is made irrelevant by Lua\LaTeX's ability to access external -% libraries. - -% \item[Well, why isn't this \texttt{log} etc\dots thing done yet?] -% I have to decide on the maximal precision to achieve: $24$, $32$, $48$, -% $64$,\dots ; to settle that I would need to implement some initial versions and -% benchmark them. - -% \item[Fair enough. That's the common lot. So why not yet?] I am a bit -% overworked. It is also an opportunity to think over -% the basic underlying mathematics, and will need devoted thinking for some not -% insignificant amount of time. So far I didn't find the time, or rather I found -% out good means to waste it sillily. I also anticipate that originality could -% very -% well not pay off at all, so small is the window for the precision. - -% \item[Any chance this could be done in time for TL2014?] No, -% sorry.\newline Release |1.09m| of |[2014/02/26]| was the end of a cycle, and -% this |1.09n| of |[2014/04/01]| is only for a bug fix and inclusion of this -% |FAQ| in the documentation. - -% \footnotesize - -% \item[and in time for TL2015?] ... (indistinct mumbles, something like -% \emph{too tired}, \emph{I need a life}, \emph{get yourself a calculator}, -% \emph{we'll see}\dots) -% \end{description} \section{Introduction via examples} \label{sec:examples} @@ -3234,10 +3289,17 @@ groups of three, for example).\par \subsection{Randomly chosen examples} Here are some examples of use of the package macros. The first one uses only -the base module \xintname, the next two require the \xintfracname package, -which deals with fractions. Then two examples with the \xintgcdname package, -one with the \xintseriesname package, and finally a computation with a float. -Some inputs are simplified by the use of the \xintexprname package. +the base module \xintname, the next one requires the \xintfracname package, +which deals with decimal numbers, scientific numbers (lowercase \dtt{e}), and +also fractions (it loads automatically \xintname). Then some examples with +expressions, which require the \xintexprname package (it loads automatically +\xintfracname). And finally some examples using \xintseriesname, \xintgcdname +which are among the extra packages included in the \xintname distribution. + +The printing of the outputs will either use a custom |\printnumber| macro as +described in the previous section, or sometimes the |\np| command from the +\href{http://www.ctan.org/pkg/numprint}{numprint} package (see +\autoref{fn:np}). \begin{itemize} \item {$123456^{99}$: }\\ @@ -3487,6 +3549,11 @@ run.% \section{The \xintname bundle} +% \section{User interface} + +% {\etocdefaultlines\etocsettocstyle{}{}\localtableofcontents} + + \subsection{Characteristics} \begin{framed} @@ -3621,151 +3688,370 @@ the complete expandability.% \footnote{The Lua\TeX{} project possibly makes endeavours such as \xintname appear even more insane that they are, in truth.} -% \section{Missing things} +\subsection{Floating point evaluations} +\label{ssec:floatingpoint} -% `Arbitrary-precision' floating-point -% operations are currently limited to the basic four operations, the power -% function with integer exponent, and the extraction of square-roots. +\emph{This documentation is currently undergoing revision and is provided here + in some transient intermediate state.} -\subsection{Origins of the package} -Package |bigintcalc| by \textsc{Heiko Oberdiek} already -provides expandable arithmetic operations on ``big integers'', -exceeding the \TeX{} limits (of $2^{31}-1$), so why another% -% -\footnote{this section was written before the \xintfracname package; the - author is not aware of another package allowing expandable - computations with arbitrarily big fractions.} -% -one? +Floating point macros are provided by package \xintfracname to work with a +given arbitrary precision |P|. The default value is $P=16$ meaning that the +significands for non-zero numbers have $16$ decimal digits, the first one non +zero. The syntax to set the +precision to |P| is \centeredline{|\xintDigits:=P;|} To query the current +value use \csbxint{theDigits}. +\begin{everbatim*} +The current precision for floating point evaluations is \xinttheDigits. +{\xintDigits:=32;% +The current precision for floating point evaluations is \xinttheDigits.} +The current precision for floating point evaluations is \xinttheDigits. +\end{everbatim*} + +It is also possible to pass |P| as an optional argument within brackets to the +floating point macros such as \csbxint{FloatAdd}, \csbxint{FloatMul}, ... + +\csbxint{thefloatexpr}|...\relax| also admits an optional argument |Q| within +brackets, but it has no influence on the precision |P| for the computations, +its use is only to specify a rounding precision on output, typically to clean +up the computation result from cumulated errors resulting from iterated +operations, which unavoidably make possibly invalid the last digits (compared +to an exact theoretical evaluation; I say \emph{theoretical} because no +computer has ever nor ever will compute exactly $\sqrt 2$ in base $10$.) + +The maximal allowed value for |P| in a |\xintDigits:=P;| assignment is +\dtt{32767}. It was possible earlier to use even bigger |P|'s as optional +argument to \csbxint{Float} for a one-short conversion\MyMarginNote{Changed + with 1.2} to a gigantic float. However since release |1.2| this can't work +in complete generality: a fractional input will trigger the division macro +which can't handle inputs with more than about \dtt{19900} digits. For example +(tested 2015/11/07 with |v1.2b|) |\message{\xintFloat [19942]{1/7}}| works but +not |\message{\xintFloat [19943]{1/7}}|. On the other hand |\xintFloat +[50000]{1}| does work (slowly..), but there isn't much one can do afterwards +with it... + +More reasonably, working with significands of $24$, $32$, $48$, $64$, or even +$80$ digits is well within the reach of the package. + +%\begin{framed} +Currently, the only non-elementary operation is the square root +(\csbxint{FloatSqrt}). The elementary transcendantal functions are not yet +implemented. The power function (\csbxint{FloatPow}, \csbxint{FloatPower}) +accept only (positive or negative) integer exponents. +%\end{framed} -I got started on this in early March 2013, via a thread on the -|c.t.tex| usenet group, where \textsc{Ulrich D\,i\,e\,z} used the -previously cited package together with a macro (|\ReverseOrder|) -which I had contributed to another thread.% -% -\footnote{the \csa{ReverseOrder} could be avoided in that circumstance, - but it does play a crucial r\^ole here.} -% -What I had learned in this -other thread thanks to interaction with \textsc{Ulrich D\,i\,e\,z} and -\textsc{GL} on expandable manipulations of tokens motivated me to -try my hands at addition and multiplication. -I wrote macros \csa{bigMul} and \csa{bigAdd} which I posted to the -newsgroup; they appeared to work comparatively fast. These first -versions did not use the \eTeX{} \csa{numexpr} primitive, they worked -one digit at a time, having previously stored carry-arithmetic in -1200 macros. +\begin{framed} + Future releases of \xintname will have more extensive coverage of floating + point operations, and document better what exactly is the achieved + precision. The four basic operations always have and will achieve + \emph{correct rounding}. +\end{framed} -I noticed that the |bigintcalc| package used \csa{numexpr} -if available, but (as far as I could tell) not -to do computations many digits at a time. Using \csa{numexpr} for -one digit at a time for \csa{bigAdd} and \csa{bigMul} slowed them -a tiny bit but avoided cluttering \TeX{} memory with the 1200 -macros storing pre-computed digit arithmetic. I wondered if some speed -could be gained by using \csa{numexpr} to do four digits at a time -for elementary multiplications (as the maximal admissible number -for \csa{numexpr} has ten digits). +The maximal theoretically allowed exponent is currently set at +\dtt{\number"7FFFFFFF} (the minimal exponent is its opposite) which is the +maximal number handled by \TeX. + +% We refer here to the exponent |e| in a +% representation +% \leftedline{$x=\pm \underbrace{ddd\dots ddd}_{P\ \mathrm{digits}}\times 10^e$} +% where the \dtt{P} digits are the significand. This means that the maximal +% theoretical exactly representable number should be: +% \dtt{$9.9\dots 9\times 10^{\number"7FFFFFFF+(P-1)}$}. However, with for +% example the default \dtt{P=16} value for the precision, +% \begin{everbatim} +% \xintFloat {9.999999999999999e2147483662} +% \end{everbatim} +% raises an error, because the \eTeX{} primitive |\numexpr| suffers an +% arithmetic overflow if used for example as |\numexpr -1+2147483648\relax|, +% hence it understandably can't handle the |2147483662|. Sadly, already +% \begin{everbatim} +% \xintFloat {9.999999999999999e2147483647} +% \end{everbatim}% +% also raises an error, due to some arithmetic overflow originating in +% \csbxint{Float} parsing. There is no error with: +% \begin{everbatim*} +% \xintRaw {9.999999999999999e2147483647} +% \end{everbatim*}% +% but some extra manipulations done by |\xintFloat| (to go +% again from the |\xintRaw| format to the float format) create the +% problem. The maximal exactly represented and acceptable input to |\xintFloat| +% is observed to be: +% \begin{everbatim*} +% \xintFloat {9.999999999999999e2147483632} +% \end{everbatim*} +% With more |9|'s the number is still parsed but the output +% and the minimal one is \dtt{$10^{\number"7FFFFFFF}$} + +Perhaps in the future this will be +reduced, for example to \dtt{2147400000}. It could even be envisioned that the +maximal |e|${}_{\mathrm{max}}$ and minimal |e|${}_{\mathrm{min}}$ exponents +would be user-specified. + +% Suppose that the precision \dtt{P} has its default value \dtt{16}. Currently, attempting to subtract \dtt{1.0e-\the\numexpr\number"7FFFFFFF-15} from +% \dtt{1.1e-\the\numexpr\number"7FFFFFFF-15} by necessity leads to a low-level \eTeX{} error, +% because the result \dtt{1e-\xintiiPow2{31}} has a too big exponent in absolute +% value, thus necessarily somewhere an arithmetic overflow will occur. Actually, +% this overflow happens immediately during the parsing of +% \dtt{1.1e-\number"7FFFFFFF} because the very first parsing by \xintfracname +% will initially attempt to store the number as \dtt{11[-\xintiiPow2{31}]} and the +% arithmetic overflow will happen already at this stage. + +% reasonable value), and also would make easier the implementation of denormal + +Currently \xintfracname has no notion of |NaN|s or signed infinities or signed +zeroes. These notions are part of the +\href{https://en.wikipedia.org/wiki/IEEE_floating_point}{\texttt{IEEE + 754-2008}} standard for Floating-Point arithmetic (which initially regards +hardware floating point processing units but also has implications on +software)\footnote{The |IEEE 754-1985| was a binary standard with a specific + value for the precision ($24$ for single precision, $53$ for double + precision). The newer + \href{https://en.wikipedia.org/wiki/IEEE_floating_point}{\texttt{IEEE + 754-2008}} normalizes five basic formats, three binaries and two + decimals ($16$ and $34$ decimal digits) and discusses extended formats with + higher precision.} and, together with signed infinities, signed zeroes, +exception handling are not implemented currently by the \xintfracname macros +dealing with ``floating-point numbers''. -The present package is the result of this initial questioning. +\begin{framed} + % Floating point multiplication of two numbers with |P| digits of precision + % evaluates \emph{exactly} the exact product with |2P| or |2P-1| digits, + % before rounding to |P| digits: obviously this is very wasteful when |P| is + % large. But \xintname is initially an exact algebraic operator, not a + % floating point one with a fixed maximal size for operands, and the author + % hasn't yet had the opportunity to re-examine that point. + But the |IEEE 754| requirement of \emph{correct rounding} for addition, + subtraction, multiplication and division is achieved by \xintfracname and + the \csbxint{thefloatexpr}|...\relax| parser: this means that for two + operands of |P| digits the output coincides exactly with the rounding of an + exact evaluation. + + The rounding mode is ``round to nearest, ties away from zero'', which is + based on the rounding to integers which maps $(-0.5,0.5)$ to $0$, + $[0.5, 1.5)$ to $1$, etc... and $(-1.5,-0.5]$ to $-1$ etc... It is not + customizable. +\end{framed} + +\medskip -For the record, \xintname 1.2 also got its impulse from a fast ``reversing'' -macro, which I wrote after my interest got awakened again as a result of -correspondance with Bruno \textsc{Le Floch}: this new reverse uses a \TeX nique -which \emph{requires} the tokens to be digits. I wrote a routine which works -(expandably) in quasi-linear time, but a less fancy |O(N^2)| variant which I -developed concurrently proved to be faster all the way up to perhaps $7000$ -digits, thus I dropped the quasi-linear one. The less fancy variant has the -advantage that \xintname can handle numbers with more than $19900$ digits (but -not much more than $19950$). This is with the current common values of the input -save stack and maximal expansion depth: $5000$ and $10000$ respectively. +\emph{Also the square root will provide correct rounding.} + +% http://www.cse.msu.edu/~cse320/Documents/FloatingPoint.pdf +% https://en.wikipedia.org/wiki/IEEE_floating_point +% je n'ai pas cherché beaucoup mais je n'ai pas vu de lien gratuit +% pour récupérer IEEE 754-2008. Mais je l'avais peut-être déjà récupéré il y a +% quelques mois. + + +The other float operations produce a value from which the exact result differs +by at most \dtt{0.6} ``units in the last place'' (of the significand of the +returned value). Thus the last digit may be wrong by at most one unit +(compared to the exact rounding of the exact theoretical value), but if it is +$0$ or $9$ also with it the next to last digit, etc... some macros may achieve +higher precision, check their documentations. Notice in particular that the +routines will return a zero value only if the theoretical exact evaluation +would have produced also zero (but as mentioned above a computation leading to +a floating point underflow or floating point overflow will at some point +inevitably raise a low-level \eTeX{} arithmetic overflow error). + +What happens for inputs having more than \dtt{P} digits ? it is not the same +to correctly round a theoretical exact value obtained from the exact inputs or +correctly round the theoretical exact result obtained from rounded inputs. Up +to release |v1.2b| (\emph{|1.2c| hasn't changed anything yet.}), the four +basic operations first rounded the inputs to \dtt{P+2} digits of precision. +The power operation |A^B| first rounded |A| to a number of digits equal to the +precision \dtt{P} plus a certain quantity depending on the exponent |B|, for +example for squaring this gave a first rounding to \dtt{P+3} digits of +precision. But this meant that in some rare cases |x*x| or |x^2| could produce +slightly different values. + +For example consider \leftedline{\dtt{x=1.772453850905516665}} which has 19 +digits. We want its square correctly rounded to 16 digits. The exact value is +\leftedline{1.772453850905516665\string^2=3.141592653589795499056780930592722225} +whose rounding to 16 +digits is \dtt{3.141592653589795}. But if we first round |x| to 18 digits, and +square, this gives +\leftedline{1.77245385090551667\string^2=3.1415926535897955167813194396478889} whose +rounding to 16 digits is \dtt{3.141592653589796}. + +Another example of a similar type (such examples are the exception rather than +the rule, but are not especially hard to find, if one understands where to +look): with \leftedline{\dtt{x=18587988557251906450}} which has 20 digits, we +compute |1/x| correctly rounded to 16 digits of precision, but after rounding +first |x| to either 20 (no alteration), 18, or 16 digits (and trailing +zeroes). We obtain three distinct values: +\leftedline{1/x=5.379818246175220e-20, 5.379818246175219e-20, + 5.379818246175218e-20} + +A further topic is how the macros should handle fractional inputs |A/B|. If we +were to first round |A| and |B| to some precision \dtt{Q}, and then correctly +round the fraction to precision \dtt{P}, the process could give different +results for inputs |A/B| and |A'/B'| representing the same rational +number. As \xintfracname treats exactly fractions, this would be a very +disquieting situation. Consider for example the fraction: +\leftedline{1/1858798855725191=5379818246175218/\xintiiMul{1858798855725191}{5379818246175218}} +We mentioned already that the exact rounding to 16 digits is +\dtt{5.379818246175218e-16}. If however we treat the right hand side by first +rounding numerator and denominator to 16 digits, we are evaluating +\leftedline{5379818246175218/9999999999999999e15=\xintTrunc{24}{5379818246175218/9999999999999999}\dots +e-15} +and the result rounded to 16 digits is \dtt{5.379818246175219e-16}. + +Thus, the float macros of \xintfracname have always treated fractional inputs +|A/B| \emph{exactly}, not doing any a priori rounding of numerator and +denominator, but rounding the \emph{exact} fraction before further +treatment (as stated above the basic operations did this initial rounding of +the inputs with \dtt{P+2} digits of kept precision). The possible alternative +could have been to systematically first reduce |A/B| to smallest terms, then +round numerator and denominator, but this was not the choice made, as it +raises issues of efficiency and accuracy. + +In an \emph{expression} however \dtt{/} is an operator and if the parser sees +|A/B|, the arguments |A| and |B| will be treated as separate inputs and be +rounded separately first, before division; to avoid that one may +code |\xintexpr A/B\relax| inside the \csbxint{thefloatexpr}|...\relax|, or, +since |v1.2|, use the |qfloat(A/B)| syntax. \subsection{Expansion matters} -\label{sec:expansions} -By convention in this manual \fexpan sion (``full expansion'' or ``full first -expansion'') is the process of expanding repeatedly the first token seen until -hitting against something not further expandable like an unexpandable -\TeX-primitive or an opening brace |{| or a character (inactive). For - those familiar with \LaTeX3 (which is not used by \xintname) this is what is - called in its documentation full expansion. Technically, macro arguments in - \xintname which are submitted to such a \fexpan sion are so via prefixing them - with |\romannumeral-`0|. An explicit or implicit space token stops such an - expansion and is gobbled. +\subsubsection{Generalities about expandability in \TeX} + +\TeX{} is a macro language, and ``expansion'' is thus a crucial aspect, which +will be quite unfamiliar to most everyone with standard knowledge of the usual +programming languages. The whole of \xintname is about \emph{expandably} +implementing arithmetic computations. What does that mean ? + +\LaTeX{} users are familiar with counters, and its command |\setcounter|. The +first argument is the name of the counter, the second argument is a number, or +more generally something which will expand to a number. For example: +\begin{everbatim} +\newcounter{Foo} +\newcommand{\Bar}{17} +\setcounter{Foo}{\Bar} +\addtocounter{Foo}{\Bar} +\arabic{Foo} +\end{everbatim} +works and produces |34|. But imagine we have some macro |\Double| which +accepts a numerical argument, multiply it by two, and produces the result. Can +we do this: +\begin{everbatim} +\setcounter{Foo}{\Double{\Bar}} ? +\end{everbatim} +The answer depends on the \emph{expandability} of |\Double|. Perhaps |\Double| +will do a |\newcommand| internally? then it is \emph{not} expandable in this +context where \TeX{} is seeking to do a number assignment (which is +to what the \LaTeX{} |\setcounter| boils down in the end). This does not mean +that expansion does not apply, but something completely different: expansion +produces ``tokens'' which \TeX{} does not accept in such a context. + +Some users of \LaTeX{} know about the \TeX{} primitive |\edef|. Another way to +test expandability of |\Double| is to try |\edef\test{\Double{\Bar}}|: the +criterion is that |\Double| will expand, do its stuff, and clean up everything +and only leave the result of its action on |\Bar|. Thus typically if |\Double| +does a |\newcommand| (or rather a |\def|), then this will not be the case. The +|\newcommand| or |\def| is simply \emph{not} executed inside an |\edef|! This +is not completely equivalent to the earlier context, because when \TeX{} seeks +to build a number it has special constructs, like |"| to prefix hexadecimal +inputs, and thus the behavior is not exactly the same in an |\edef|, but I am +just trying to give a gist here of what happens. + +The little paradox is that \TeX{} from the start always required expandability +when doing assignments to count registers, or dimen registers, ..., but basic +arithmetic was provided via |\advance|, |\multiply|, and |\divide| primitives +which are \emph{not} expandable.% +% +\footnote{This is not to say that expandable arithmetic was not possible, it + is possible and has been done via the recording of the carries of digit + arithmetic in many macros and usage of some tools provided by the \TeX{} + language, but this is very cumbersome and slow (even in the \TeX{} + context).} +% +For example, something like +\begin{everbatim} +\setcounter{Foo}{\count0=\Bar\relax \multiply\count0 by 2 + \advance\count0 by 15 \the\count0 } +\end{everbatim} +although not creating errors produces only non-sense. + +Since 1999, \eTeX{} has extended \TeX{} with expandable arithmetic. Thus +nowadays% % -Most of the package macros, and all those dealing with computations, are -expandable in the strong sense that they expand to their final result via this -\fexpan sion. Again copied from \LaTeX3 documentation conventions, this will be -signaled in the description of the macro by a \etype{}star in the margin. -All% +\footnote{I do not discuss here the \href{http://www.ctan.org/pkg/calc}{calc} + package. It does surgery inside |\setcounter| to make + |\setcounter{Foo}{2*\Bar+15}| possible, but its parser is not expandable and + is functional only inside macros |calc| knows about.} one would simply do +\begin{everbatim} +\setcounter{Foo}{\numexpr 2*\Bar+15\relax} +\end{everbatim} +But we can not do, for example, |98765*67890| inside |\numexpr|, because the +result \xintiiMul{98765}{67890} exceeds the \TeX{} bound of \number"7FFFFFFF. + +\subsubsection{Full expansion of the first token} +\label{ssec:expansions} + +The whole business of \xintname is to build upon |\numexpr| and handle +arbitrarily large numbers. Each basic operation is thus done via a macro: +\csbxint{iiAdd}, \csbxint{iiSub}, \csbxint{iiMul}, \csbxint{iiDivision}. In +order to handle more complex operations, it must be possible to nest these +macros.% +% +\footnote{Actually this would not be really needed if the goal was only +to implement the parsing of expressions: as the expression is scanned from +left to right, there is only at any given time one operation to be done, hence +it is not really absolutely mandatory for the macros implementing the basic +operations to be nestable. This is however the path followed initially by +\xintname.} +% +But we saw already that an expandable macro can not do a |\newcommand| or +|\def|, and it can't do either an |\edef|. But the macro must expand its +arguments to find the digits it is supposed to manipulate. \TeX{} provides a +tool to do the job of (expandable !) repeated expansion of the first token +found until hitting something non expandable, such as a digit, a |\def| token, +a brace, a |\count| token, etc... is found. A space token also will stop the +expansion (and be swallowed, contrarily to the non-expandable tokens). + +By convention in this manual \fexpan sion (``full expansion'' or ``full first +expansion'') will be this \TeX{} process of expanding repeatedly the first +token seen. For those familiar with \LaTeX3 (which is not used by \xintname) +this is what is called in its documentation full expansion (whereas expansion +inside |\edef| would be described I think as ``exhaustive'' expansion). + +Most of the package macros, and all those dealing with computations% % -\footnote{except \csbxint{loop}, \csbxint{iloop} and \csbxint{XTrunc}.} +\footnote{except \csbxint{XTrunc}.}, % -expandable macros of the \xintname packages completely expand in two steps. +are expandable in the strong sense that they expand to their final result via +this \fexpan sion. This will be signaled in their descriptions via a +\etype{}star in the margin. -Furthermore the macros dealing with computations, as well as many utilities from -\xinttoolsname, apply this process of \fexpan sion to their arguments. Again -from \LaTeX3's conventions this will be signaled by a% +These macros not only have this property of \fexpan dability, they all begin +by first applying \fexpan sion to their arguments. Again from \LaTeX3's +conventions this will be signaled by a% % \ntype{{\setbox0 \hbox{\Ff}\hbox to \wd0 {\hss f\hss}}} % -margin annotation. Some additional parsing -which is done by most macros of \xintname is indicated with a -variant\ntype{\Numf{\kern.5cm}}; and the extended fraction parsing done by most -macros of \xintfracname has its own symbol\ntype{\Ff}. When the argument has a -priori to obey the \TeX{} bound of \dtt{\number"7FFFFFFF} it is -systematically fed to a |\numexpr..\relax| hence the expansion is then a -\emph{complete} one, signaled with an \ntype{\numx}\emph{x} in the margin. This -means not only complete expansion, but that infix -algebra is allowed, also with count registers, etc\dots - -The \csbxint{ApplyInline} and \csbxint{For*} macros from \xinttoolsname -apply a special iterated \fexpan sion, which gobbles spaces, to all -those items which are found \emph{unbraced} from left to right in the -list argument; this is denoted specially as here\ntype{{\lowast f}} in -the margin. Some other macros such as \csbxint{Sum} from \xintfracname -first do an \fexpan sion, then treat each found (braced or not) item -(skipping spaces between such items) via the general fraction input -parsing, this is signaled as here\ntype{f{$\to$}{\lowast\Ff}} in the -margin where the signification of the \lowast{} is thus a bit different -from the previous case. - -A few macros from \xinttoolsname do not expand, or expand only once their -argument\ntype{n{{\color{black}\upshape, resp.}} o}. This is also -signaled in the margin with notations \`a la \LaTeX3. +margin annotation next to the description of the arguments. -As the computations are done by \fexpan dable macros which \fexpan d their -argument they may be chained up to arbitrary depths and still produce expandable -macros. +\subsubsection{Summary of important expandability aspects} -Conversely, wherever the package expects on input a ``big'' integers, or a -``fraction'', \fexpan sion of the argument \emph{must result in a complete - expansion} for this argument to be acceptable.% -% -\footnote{this is not quite as - stringent as claimed here, see \autoref{sec:useofcount} for more details.} -The -main exception is inside \csbxint{expr}|...\relax| where everything will be -expanded from left to right, completely. - -Summary of important expansion aspects: \begin{enumerate} \item the macros \fexpan d their arguments, this means that they expand the first token seen (for each argument), then expand, etc..., until something un-expandable such as a\strut{} digit or a brace is hit against. This example % - \leftedline{|\def\x{98765}\def\y{43210}| |\xintAdd {\x}{\x\y}|} + \leftedline{|\def\x{98765}\def\y{43210}| |\xintiiAdd {\x}{\x\y}|} % is \emph{not} a legal construct, as the |\y| will remain untouched by expansion and not get converted into the digits which are expected by the - sub-routines of |\xintAdd|. It is a |\numexpr| which will expand it and an + sub-routines of |\xintiiAdd|. It is a |\numexpr| which will expand it and an arithmetic overflow will arise as |9876543210| exceeds the \TeX{} bounds. + The same would hold for |\xintAdd|. \begingroup\slshape - With \csbxint{theexpr} one could write |\xinttheexpr \x+\x\y\relax|, or - |\xintAdd\x{\xinttheexpr\x\y\relax}|.\hfill + To the contrary \csbxint{theiiexpr} and others have no issues with + things such as |\xinttheiiexpr \x+\x\y\relax|.\hfill \endgroup \item\label{fn:expansions} using |\if...\fi| constructs \emph{inside} the @@ -3842,8 +4128,7 @@ or use the \emph{lowercase} form of \csa{xintAdd}: and then \csa{AplusBC} will share the same properties as do the other \xintname `primitive' macros. -\end{enumerate} - +\item The |\romannumeral0| and |\romannumeral-`0| things above look like an invitation to hacker's territory; if it is not important that the macro expands in two steps only, there is no reason to follow these guidelines. Just chain @@ -3858,45 +4143,23 @@ such expandable macros: creates the |\AplusBC| macro doing the above and expanding in two expansion steps. -\subsection{User interface} -\label{ssec:userinterface} +\item In the expression parsers of \xintexprname such as + \csbxint{expr}|..\relax|, \csbxint{floatexpr}|..\relax| the contents are + expanded completely from left to right until the ending |\relax| is found + and swallowed, and spaces and even (to some extent) catcodes do not matter. -The user interface for executing operations on numbers is via macros such as -\csbxint{Add} or \csbxint{Mul} which have two arguments, or via expressions -\csbxint{expr}|..\relax| which use infix notations such as |+|, |-|, |*|, |/| -and |^| (or |**|) for the basic operations, and recognize functions of one or -more comma separated arguments (such as |max|, or |round|, or |sqrt|), -parentheses, logic operators of conjunction |&&|, disjunction \verb+||+, as -well as two-way |?| and three-way |??| conditionals and more. A few examples: -% -\begin{everbatim*} -\begin{enumerate}[nosep] - \item \xintiiAdd {2719873981798137981381789317981279}{13819093809180120910390190} - \item \xintiiMul {2719873981798137981381789317981279}{13819093809180120910390190} - \item \xintthefloatexpr (19317/21913+2198/9291)^3\relax - \item \xintDigits:=64;\xintthefloatexpr (19317/21913+2198/9291)^3\relax -% Let's compute the inner sum exactly, not as a float, before raising to third power: - \item \xintDigits:=16;\xintthefloatexpr \xintexpr 19317/21913+2198/9291\relax^3\relax -\end{enumerate} -\end{everbatim*} -In \csbxint{expr}|..\relax| the contents are expanded completely from left to -right until the ending |\relax| is found and swallowed, and spaces and even -(to some extent) catcodes do not matter. Algebraic operations are done -\emph{exactly}. +\item For all variants, prefixing with \csbxint{the} allows to print the + result or use it in other contexts. Shortcuts \csbxint{theexpr}, + \csbxint{thefloatexpr}, \csbxint{theiiexpr}, \dots\ are available. -The \csbxint{floatexpr} variant is for operations which are done using the -precision set via the |\xintDigits:=N;| assignment (default is with -significands of \dtt{16} digits). - -For all |\xintexpr| variants, prefixing with |\xintthe| allows to print -the result or use it in other contexts. Shortcuts \csbxint{theexpr}, -\csbxint{thefloatexpr}, \csbxint{theiiexpr}, \dots\ are available. +\end{enumerate} -The \csbxint{iiexpr} variant is only for big integers, it does not know -fractions. +\subsection{Analogies and differences of \csbh{xintiiexpr} with \csbh{numexpr}} -There are some important differences of syntax between |\numexpr| and -|\xintiiexpr| and variants: +\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| @@ -3908,258 +4171,30 @@ There are some important differences of syntax between |\numexpr| and |\xintthe\xintiiexpr 7 + 3 5\relax| expands (in two steps) to \dtt{\detokenize\expandafter\expandafter\expandafter {\xintthe\xintiiexpr 7 + 3 5\relax}}. - \item Also worth mentioning is the fact that |\numexpr -(1)\relax| is - illegal. But this is perfectly legal and with the expected result in - |\xintiiexpr...\relax|. \item Inside an |\edef|, expressions |\xintiiexpr...\relax| get fully - evaluated, but need the prefix |\xintthe| to get printed or used as - arguments to some macros, whereas expansion of |\numexpr| in an |\edef| - occurs only if prefixed with |\the| or |\number| (or |\romannumeral|, or - the expression is included in a bigger - |\numexpr| which will be the one to have to be prefixed\dots .) + evaluated, but to a private format which needs the prefix \csbxint{the} to + get printed or used as arguments to some macros; on the other hand + expansion of |\numexpr| in an |\edef| occurs only if prefixed with |\the| + or |\number| (or |\romannumeral|, or the expression is included in a + bigger |\numexpr| which will be the one to have to be prefixed\dots .) + \item |\the\numexpr| or |\number\numexpr| expands in one step, but + |\xintthe\xintiiexpr| needs two steps. +\item The \csbxint{the} prefix should not be applied to a sub + |\xintiiexpr|ession, as this forces the parsers to gather again one by one + the corresponding digits. +\item Also worth mentioning is the fact that |\numexpr -(1)\relax| is illegal. + But |\xintiiexpr -(1)\relax| is perfectly legal and gives the expected + result (what else ?). \end{itemize} -For macros such as \csbxint{Add} or -\csbxint{Mul} the arguments are each subjected to the process of \fexpan sion: -repeated expansion of the first token until finding something unexpandable (or -being stopped by a space token). - -Conversely this process of \fexpan sion always provokes the complete expansion -of the package macros and |\xintexpr..\relax| also will expand completely -under \fexpan sion, but to a private format; the \csbxint{the} prefix allows the -computation result either to be passed as argument to one of the package -macros,\footnote{the \csa{xintthe} prefix \fexpan ds the \csa{xintexpr}-ession - then unlocks it from its private format; it should not be used for - sub-expressions inside a bigger one as it is more efficient for the - expression parser to keep the result in the private format.} or also end up on -the printed page (or in an auxiliary file). -To recapitulate, all macros dealing with computations -\begin{enumerate} -\item \emph{expand completely under the sole process of repeated expansion of - the first token, (and two expansions suffice)},\footnote{see in - \autoref{sec:expansions} for more details.} - -\item \emph{apply this \fexpan sion to each one of their arguments.} -\end{enumerate} -Hence they can be nested one within the other up to arbitrary -depths. Conditional evaluations either within the macro arguments themselves, or -with branches defined in terms of these macros are made possible via macros such -as as \csbxint{ifSgn} or \csbxint{ifCmp}. - -\begin{framed} - There is no notion of \emph{declaration of a variable} to \xintname, - \xintfracname, or \xintexprname. - The user employs the |\def|, |\edef|, or - |\newcommand| (in \LaTeX) as usual, for example: \IMPORTANT -% -\begin{everbatim*} -\def\x{1729728} \def\y{352827927} \edef\z{\xintMul {\x}{\y}} -\meaning\z -\end{everbatim*}\ (see below for the |A/B[N]| output format; with |\xintiiMul| -in place of |\xintMul| there would not be the strange looking |/1[0]|.) - -The package provides |\oodef| which only expands twice its argument. This -provokes full expansion of the \xintname macros (nested to possibly many -levels), inclusive of |\xintexpr| and variants. However, it is typically slower -then |\edef| (and quite slower for small things) when the expansion ends up -consisting of less than about one thousand digits. The second utility next to -|\oodef| is |\fdef| which applies full expansion upfront and appears to be -competitive with and even faster than |\edef| already in the case of expansion -leading to a few dozen digits. -\end{framed} - -\begingroup % pour \z, \zz -The \xintexprname package has a private internal -representation for the evaluated computation result. With -% -\begin{everbatim*} -\edef\z {\xintexpr 3.141^18\relax} -\end{everbatim*} -% -the macro |\z| is already fully evaluated (two expansions were applied, and this -is enough), and can be reused in other |\xintexpr|-essions, such as for example -% -\begin{everbatim*} -\edef\zz {\xintexpr \z+1/\z\relax} - % (using short macro names such as \z and \zz is not too recommended in real - % life, some may have already definitions; I did it all in a group). -\end{everbatim*} -% -But to print it, or to use it as argument to one of the package macros, -it must be prefixed by |\xintthe| (a synonym for |\xintthe\xintexpr| is -\csbxint{theexpr}). Application of this |\xintthe| prefix outputs the -value in the \xintfracname semi-private internal format -|A/B[N]|,\footnote{there is also the notion of \csbxint{floatexpr}, for - which the output format after the action of \csa{xintthe} is a number in - floating point scientific notation.} representing the fraction -$(A/B)\times 10^N$. The |\zz| above produces a somewhat large output: -\begin{everbatim*} -\printnumber{\xintthe\zz }${}\approx{}$\xintFloat{\xintthe\zz} -\end{everbatim*} -\endgroup % pour \z, \zz - - \begin{framed} - By default, computations done by the macros of \xintfracname or within - |\xintexpr..\relax| are exact. Inputs containing decimal points or - scientific parts do not make the package switch to a `floating-point' mode. - The inputs, however long, are converted into exact internal representations. -% - % Floating point evaluations are done via special macros containing - % `Float' in their names, or inside |\xintfloatexpr|-essions. - - Manipulating exactly big fractions quickly leads to \dots bigger fractions. - There is a command \csbxint{Irr} (or the function |reduce| in an expression) - to reduce to smallest terms, but it has to be explicitely requested. Prior - to release |1.1| addition and subtraction blindly multiplied denominators; - they now check if one is a multiple of the other.\IMPORTANT\ But systematic - reduction of the result to its smallest terms would be too - costly.\def\everbatimindent{0pt } -\begin{everbatim*} -\xinttheexpr 27/25+46/50\relax\ is a bit simpler than \xinttheexpr (27*50+25*46)/(25*50)\relax, -but less so than \xinttheexpr reduce(27/25+46/50)\relax. And \xinttheexpr 3/75+4/50+2/100\relax\ -looks weird, but systematically reducing fractions would be too costly. -\end{everbatim*} - \end{framed} - -% -The |A/B[N]| shape is the output format of most \xintfracname macros, it -benefits from accelerated parsing when used on input, compared to the normal -user syntax which has no |[N]| part. An example of valid user input for a -fraction is -% -\leftedline{|-123.45602e78/+765.987e-123|} -% -where both the decimal parts, the scientific exponent parts, and the whole -denominator are optional components. The corresponding semi-private form in this -case would be -% -\leftedline{\xintRaw{-123.45602e78/+765.987e-123}} -% -The forward slash |/| is simply a delimiter to separate numerator and -denominator, in order to allow inputs having such denominators. - -Reduction to the irreducible form of the output must be asked for explicitely -via the \csbxint{Irr} macro or the |reduce| function within -|\xintexpr..\relax|. Elementary operations on fractions do very little of the -simplifications which could be obvious to (some) human beings. - - -\subsection{Floating point macros} - -Floating -point macros are provided to work with a given arbitrary precision. The default -size for significands is $16$ digits. Working with significands of $24$, $32$, -$48$, $64$, or even $80$ digits is well within the reach of the package. But -routine multiplications and divisions will become too slow if the precision goes -into the hundreds, although the syntax to set it (|\xintDigits:=P;|) allows -values up to $32767$.\footnote{for a one-shot conversion of a fraction to float - format, or one addition, a precision exceeding \dtt{32767} may be passed - as optional argument to the used macro.} The exponents may be as big as -\dtt{$\pm$\number"7FFFFFFF}.\footnote{almost\dots{} as inner manipulations - may either add or subtract the precision value to the exponent, arithmetic - overflow may occur if the exponents are a bit too close to the \TeX{} bound - \dtt{$\pm$\number"7FFFFFFF}.} - -\begin{framed} - Currently, the only transcendental operation is the square root - (\csbxint{FloatSqrt}). The elementary functions are not yet implemented. The - power function (\csbxint{FloatPow}, \csbxint{FloatPower}) accept only - (positive or negative) integer exponents. -\end{framed} - -\begin{framed} - Floating point multiplication of two numbers with |P| digits of precision - evaluates \emph{exactly} the exact product with |2P| or |2P-1| digits, - before rounding to |P| digits: obviously this is very wasteful when |P| is - large. But \xintname is initially an exact algebraic operator, not a - floating point one with a fixed maximal size for operands, and the author - hasn't yet had the opportunity to re-examine that point. -\end{framed} - -Here is such a floating point computation: -% -\leftedline{|\xintFloatPower [48] {1.1547}{\xintiiPow {2}{35}}|} -% -which thus computes $(1.1547)^{2^{35}}=(1.1547)^{\xintiiPow {2}{35}}$ to be -approximately -% -\leftedline{\dtt{\np{\xintFloatPower [48] {1.1547}{\xintiiPow {2}{35}}}}} -% -Notice that $2^{35}$ exceeds \TeX's bound, but \csa{xintFloatPower} allows it, -what counts is the exponent of the result which, while dangerously close to -$2^{31}$ is not quite there yet. The printing of the result was done via the -|\numprint| command from the \href{http://ctan.org/pkg/numprint}{numprint} -package\footnote{\url{http://ctan.org/pkg/numprint}}. - -The same computation can be done via the non-expandable assignment -|\xintDigits:=48;| and then -% -\leftedline{|\xintthefloatexpr 1.1547^(2^35)\relax|} -% -Notice though that |2^35| will be evaluated as a -floating point number, and if the floating point precision had been too -low, this computation would have given an inexact value. It is safer, -and also more efficient to code this as: -% -\leftedline{|\xintthefloatexpr 1.1547^\xintiiexpr 2^35\relax\relax|} -% -The \csbxint{iiexpr} is a cousin of \csbxint{expr} which is big integer-only -and skips the overhead of fraction management. Notice on this example that -being embedded inside the |floatexpr|-ession has nil influence on the -|iiexpr|-ession: expansion proceeds in exactly the same way as if it had been -at the `top' level. - -\xintexprname provides \emph{no} implementation of the |IEEE| standard: -no |NaN|s, signed infinities, signed zeroes, error traps, \dots; what is -achieved though is exact rounding for the basic operations. The only -non-algebraic operation currently implemented is square root extraction. -The power functions (there are three of them: \csbxint{Pow} to which |^| -is mapped in |\xintexpr..\relax|, \csbxint{FloatPower} for |^| in -|\xintfloatexpr..\relax|, and \csbxint{FloatPow} which is slighty faster -but limits the exponent to the \TeX{} bound) allow only integral -exponents. - - -\section{User interface} - -{\etocdefaultlines\etocsettocstyle{}{}\localtableofcontents} +\subsection{User interface} +\label{ssec:userinterface} +%{\etocdefaultlines\etocsettocstyle{}{}\localtableofcontents} -% Je ne sais pas ce que faisait ce paragraphe ici: -% -% Maintaining complete expandability is not for the faint of heart as it excludes -% doing macro definitions in the midst of the computation; in many cases, one does -% not need complete expandability, and definitions are allowed. In such contexts, -% there is no declaration for the user to be made to the package of a ``typed -% variable'' such as a long integer, or a (long) fraction, or possibly an -% |\xintexpr|-ession. Rather, the user has at its disposal the general tools of -% the \TeX{} language: |\def| and |\edef|. In \LaTeX\ there is |\newcommand| as -% wrapper to |\def|, -% but \LaTeX\ chose not to provide an analogous wrapper for |\edef|. It can still -% be used directly of course.\footnote{I don't know if \LaTeX3 will still allow -% direct use of |\def| and |\edef|\dots} - -%%%%%%%%%%%%% pas le bon endroit pour cette discussion -% The \xinttoolsname package provides |\oodef|, resp. |\fdef|, which expands -% twice, resp. fully (\fexpan sion), the replacement text\footnote{only for -% parameter less undelimited macros.}, hence forces complete expansion when -% this replacement text is a call to one of the \xintname bundle macros, its -% arguments being either explicit digits or further such macro calls. They are -% useful as sometimes one does not want |\edef| expansion, \emph{e.g.} with a -% macro such as \csbxint{Trim} which acts on lists of braced tokens which one -% might not want to see expanded. Furthermore |\fdef| appears to be faster than -% |\edef| in (non-trivial) situations already with only a few dozens of digits: I -% tested it to be a bit faster than |\edef| for expanding |\xintiiPow {2}{100}| -% (which has $31$ digits). However |\oodef| needs thousands of digits to become -% competitive.% -% % -% \footnote{earlier releases of this manual sort of suggested \csa{oodef} was -% competitive starting with a ``few hundred'' digits but that was perhaps a bit -% optimistic. The better choice is \csa{fdef}.} - -This section will explain the various inputs which are recognized by the package -macros and the format for their outputs. Inputs have mainly five possible -shapes: +The next sections will explain the various inputs which are recognized by the +package macros and the format for their outputs. Inputs have mainly five +possible shapes: \begin{enumerate} \item expressions which will end up inside a |\numexpr..\relax|, @@ -4190,6 +4225,112 @@ Outputs are mostly of the following types: or be used as argument to the package macros. \end{enumerate} +\subsection{No declaration of variables} + +\begin{framed} + There is no notion of a \emph{declaration of a variable}, which would be + needed to use the arithmetic macros.\footnotemark{} + To do a computation and assign its result to some macro |\z|, the user will employ the |\def|, |\edef|, or |\newcommand| (in \LaTeX) + as usual, keeping in mind that two expansion steps are needed, thus |\edef| + is initially the main tool: \IMPORTANT +% +\begin{everbatim*} +\def\x{1729728} \def\y{352827927} \edef\z{\xintiiMul {\x}{\y}} +\meaning\z +\end{everbatim*} + +As an alternative to |\edef| the package provides |\oodef| which expands +exactly twice the replacement text, and |\fdef| which applies \fexpan sion to +the replacement text during the definition. +\begin{everbatim*} +\def\x{1729728} \def\y{352827927} \oodef\w {\xintiiMul\x\y} \fdef\z{\xintiiMul {\x}{\y}} +\meaning\w, \meaning\z +\end{everbatim*} + +In practice |\oodef| is slower than |\edef|, except for computations ending in +very big final replacement texts (thousands of digits). On the other hand +|\fdef| appears to be slightly faster than |\edef| already in the case of +expansions leading to only a few dozen digits. +\end{framed} +\footnotetext{\xintexprname does provide an interface to + declare and assign values to identifiers which can be used in expressions. + See \hyperlink{item:defvar}{\string\xintdefvar}.} + +% \begingroup % pour \z, \zz +% The \xintexprname package has a private internal +% representation for the evaluated computation result. With +% % +% \begin{everbatim*} +% \edef\z {\xintexpr 3.141^18\relax} +% \end{everbatim*} +% % +% the macro |\z| is already fully evaluated (two expansions were applied, and this +% is enough), and can be reused in other |\xintexpr|-essions, such as for example +% % +% \begin{everbatim*} +% \edef\zz {\xintexpr \z+1/\z\relax} +% % (using short macro names such as \z and \zz is not too recommended in real +% % life, some may have already definitions; I did it all in a group). +% \end{everbatim*} +% % +% But to print it, or to use it as argument to one of the package macros, +% it must be prefixed by |\xintthe| (a synonym for |\xintthe\xintexpr| is +% \csbxint{theexpr}). Application of this |\xintthe| prefix outputs the +% value in the \xintfracname semi-private internal format +% |A/B[N]|,\footnote{there is also the notion of \csbxint{floatexpr}, for +% which the output format after the action of \csa{xintthe} is a number in +% floating point scientific notation.} representing the fraction +% $(A/B)\times 10^N$. The |\zz| above produces a somewhat large output: +% \begin{everbatim*} +% \printnumber{\xintthe\zz }${}\approx{}$\xintFloat{\xintthe\zz} +% \end{everbatim*} +% \endgroup % pour \z, \zz + +% \begin{framed} +% By default, computations done by the macros of \xintfracname or within +% |\xintexpr..\relax| are exact. Inputs containing decimal points or +% scientific parts do not make the package switch to a `floating-point' mode. +% The inputs, however long, are converted into exact internal representations. +% % +% % Floating point evaluations are done via special macros containing +% % `Float' in their names, or inside |\xintfloatexpr|-essions. + +% Manipulating exactly big fractions quickly leads to \dots bigger fractions. +% There is a command \csbxint{Irr} (or the function |reduce| in an expression) +% to reduce to smallest terms, but it has to be explicitely requested. Prior +% to release |1.1| addition and subtraction blindly multiplied denominators; +% they now check if one is a multiple of the other.\IMPORTANT\ But systematic +% reduction of the result to its smallest terms would be too +% costly.\def\everbatimindent{0pt } +% \begin{everbatim*} +% \xinttheexpr 27/25+46/50\relax\ is a bit simpler than \xinttheexpr (27*50+25*46)/(25*50)\relax, +% but less so than \xinttheexpr reduce(27/25+46/50)\relax. And \xinttheexpr 3/75+4/50+2/100\relax\ +% looks weird, but systematically reducing fractions would be too costly. +% \end{everbatim*} +% \end{framed} + +% % +% The |A/B[N]| shape is the output format of most \xintfracname macros, it +% benefits from accelerated parsing when used on input, compared to the normal +% user syntax which has no |[N]| part. An example of valid user input for a +% fraction is +% % +% \leftedline{|-123.45602e78/+765.987e-123|} +% % +% where both the decimal parts, the scientific exponent parts, and the whole +% denominator are optional components. The corresponding semi-private form in this +% case would be +% % +% \leftedline{\xintRaw{-123.45602e78/+765.987e-123}} +% % +% The forward slash |/| is simply a delimiter to separate numerator and +% denominator, in order to allow inputs having such denominators. + +% Reduction to the irreducible form of the output must be asked for explicitely +% via the \csbxint{Irr} macro or the |reduce| function within +% |\xintexpr..\relax|. Elementary operations on fractions do very little of the +% simplifications which could be obvious to (some) human beings. + \subsection {Input formats}\label{sec:inputs} Some macro arguments are by nature `short' integers,\ntype{\numx} \emph{i.e.} @@ -4270,29 +4411,14 @@ the allowed input formats for `long numbers' and `fractions' are: overhead than the general one, thus allowing more efficient nesting of macros as it is the one used on output (except for the floating macros). Any deviation from the rules above will result in errors.\footnote{With - earlier releases the |N| could not be empty and had to be given as - explicit digits, not some macro or expression expanded in |\numexpr|.} + releases earlier than |1.2| the |N| could not be empty and had to be + given as explicit digits, not some macro or expression expanded in + |\numexpr|.} \end{description} - Examples of inputs and outputs: -\begin{everbatim*} - \xintAdd{+--0367.8920280/-++278.289287}{-109.2882/+270.12898}\newline - \xintAdd{10.1e1}{101.010e3}\newline - \xintFloatAdd{10.1e1}{101.010e3}\newline - \xintiiPow {2}{100}\newline - \xintPow {2}{100}\newline - \xintFloatPow {2}{100}\par -\end{everbatim*} - % - Produced fractions having a denominator equal to one are, as a general - rule, nevertheless printed as fractions. In math mode \csbxint{Frac} - will remove such dummy denominators, and in inline text mode one has - \csbxint{PRaw} with the similar effect. - % - \begin{quote} - |\xintPRaw{\xintAdd{10.1e1}{101.010e3}}|\dtt{=\xintPRaw{\xintAdd{10.1e1}{101.010e3}}}\\ - % - |\xintRaw{1.234e5/6.789e3}|\dtt{=\xintRaw{1.234e5/6.789e3}}% - \end{quote} + Notice that |*|, |+| and |-| contrarily to the |/| (which is treated simply + as a kind of delimiter) are not acceptable within arguments of this + type\ntype{\Ff} + (see however \autoref{sec:useofcount} for some exceptions). \item the \hyperref[xintexpr]{expression format} is for inclusion in an \csbxint{expr}|...\relax|, it uses infix notations, function names, complete @@ -4303,14 +4429,6 @@ the allowed input formats for `long numbers' and `fractions' are: release |1.2|: there must be digits either before or after.} \end{enumerate} -Even with \xintfracname loaded, some macros by their nature cannot accept -fractions on input. Those parsing their inputs through \csbxint{Num} will now -accept fractions, truncating them first to integers. - -% The scientific notation is necessarily (except in |\xintexpr..\relax|) with a -% lowercase |e|. It may appear both at the numerator and at the denominator of a -% fraction. - Generally speaking, there should be no spaces among the digits in the inputs (in arguments to the package macros). Although most would be harmless in most macros, there are some cases where spaces could break havoc.% @@ -4356,6 +4474,38 @@ contain to some extent infix algebra with count registers, see the section accepted if it is a whole number in disguise; and for macros accepting the full fraction format with no restriction there is the corresponding symbol in the margin\ntype{\Ff}. +% + +There are also some slighly more obscure expansion types: in particular, the +\csbxint{ApplyInline} and \csbxint{For*} macros from \xinttoolsname apply a +special iterated \fexpan sion, which gobbles spaces, to the non-braced items +(braced items are submitted to no expansion because the opening brace stops +it) coming from their list argument; this is denoted by a special +symbol\ntype{{\lowast f}} in the margin. Some other macros such as +\csbxint{Sum} from \xintfracname first do an \fexpan sion, then treat each +found (braced or not) item (skipping spaces between such items) via the +general fraction input parsing, this is signaled as +here\ntype{f{$\to$}{\lowast\Ff}} in the margin where the signification of the +\lowast{} is thus a bit different from the previous case. + +A few macros from \xinttoolsname do not expand, or expand only once their +argument\ntype{n{{\color{black}\upshape, resp.}} o}. This is also +signaled in the margin with notations \`a la \LaTeX3. + +As the computations are done by \fexpan dable macros which \fexpan d their +argument they may be chained up to arbitrary depths and still produce expandable +macros. + +Conversely, wherever the package expects on input a ``big'' integers, or a +``fraction'', \fexpan sion of the argument \emph{must result in a complete + expansion} for this argument to be acceptable.% +% +\footnote{this is not quite as + stringent as claimed here, see \autoref{sec:useofcount} for more details.} +The +main exception is inside \csbxint{expr}|...\relax| where everything will be +expanded from left to right, completely. + \subsection{Output formats} @@ -5024,7 +5174,7 @@ is equivalent to setting |\A| to \dtt{\tmpA}, |\B| to \dtt{\tmpB}, |\U| to \xintiSub{\xintiMul\tmpU\tmpA}{\xintiMul\tmpV\tmpB}} is a Bezout Identity. Thus, what |\xintAssign| does is to first apply an -\hyperref[sec:expansions]{\fexpan sion} to what comes next; it then defines one +\hyperref[ssec:expansions]{\fexpan sion} to what comes next; it then defines one after the other (using |\def|; an optional argument allows to modify the expansion type, see \autoref{xintAssign} for details), the macros found after |\to| to correspond to the successive braced contents (or single tokens) located @@ -5416,7 +5566,7 @@ and then an ``item'' is what is delimited by commas. So \csa{xintCSVtoList} takes on input a `comma separated list of items' and converts it into a `\TeX{} list of braced items'. The argument to |\xintCSVtoList| may be a macro: it will first be -\hyperref[sec:expansions]{\fexpan ded}. Hence the item before the first comma, +\hyperref[ssec:expansions]{\fexpan ded}. Hence the item before the first comma, if it is itself a macro, will be expanded which may or may not be a good thing. A space inserted at the start of the first item serves to stop that expansion (and disappears). The macro \csbxint{CSVtoListNoExpand}\etype{n} does the same @@ -6509,7 +6659,7 @@ macro definition, to prepare material for later execution, contrarily to what The first argument |\macro| does not have to be an expandable macro. \csa{xintApplyInline} submits its second, token list parameter to an -\hyperref[sec:expansions]{\fexpan +\hyperref[ssec:expansions]{\fexpan sion}. Then, each \emph{unbraced} item will also be \fexpan ded. This provides an easy way to insert one list inside another. \emph{Braced} items are not expanded. Spaces in-between items are gobbled (as well as those at the start @@ -6653,7 +6803,7 @@ which encapsulate the item in a macro expanding to that item. \begin{framed} The starred variant \csbxint{For*} deals with token lists (\emph{spaces between braced items or single tokens are not significant}) and - \hyperref[sec:expansions]{\fexpan ds} each \emph{unbraced} list item. This + \hyperref[ssec:expansions]{\fexpan ds} each \emph{unbraced} list item. This makes it easy to simulate concatenation of various list macros |\x|, |\y|, ... If |\x| expands to |{1}{2}{3}| and |\y| expands to |{4}{5}{6}| then |{\x\y}| as argument to |\xintFor*| has the same effect as |{{1}{2}{3}{4}{5}{6}}|% @@ -7746,7 +7896,7 @@ operands is the same as truncated division), or truncated (\csbxint{iiDivTrunc}) In the description of the macros the \texttt{\n} and \texttt{\m} symbols stand for explicit (big) integers within braces or more generally any control -sequence (possibly within braces) \hyperref[sec:expansions]{\fexpan ding} to +sequence (possibly within braces) \hyperref[ssec:expansions]{\fexpan ding} to such a big integer. The macros with a single |i| in their names parse their arguments @@ -7812,7 +7962,7 @@ expression, in the arguments to the package macros, see the 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{sec:expansions}. +in \autoref{ssec:expansions}. \subsection{\csbh{xintNum}, \csbh{xintiNum}}\label{xintiNum} @@ -7940,7 +8090,9 @@ with things such as |2^999999999| without any problem. \begin{everbatim*} $\xintFloatPow[32]{2}{50000}<\xintFloatPow[32]{2}{999999999}$ \end{everbatim*}% -and both are computed swiftly!\footnote{see however \autoref{fn:floatpow}.} +and both are computed swiftly! +% je ne sais plus ce qu'était cette note de bas de page +%\footnote{see however \autoref{fn:floatpow}.} Within an \csbxint{iiexpr}|..\relax| the infix operator |^| is mapped to \csa{xintiiPow}; within an \csbxint{expr}-ession it is mapped to \csbxint{Pow} @@ -8035,7 +8187,7 @@ Version |1.0| was released |2013/03/28|. This is \texttt{\xintbndlversion} of moved to separate package \xintcorename, which is automatically loaded by \xintname. -See the documentation of \xintcorename or \autoref{sec:expansions} for the +See the documentation of \xintcorename or \autoref{ssec:expansions} for the significance of the \textcolor[named]{PineGreen}{\Numf}, \textcolor[named]{PineGreen}{\emph{f}}, \textcolor[named]{PineGreen}{\numx} and \textcolor[named]{PineGreen}{$\star$} margin annotations and some @@ -8703,7 +8855,7 @@ of \csa{xintDecSplit}. \xintiiE {123}{89} \end{everbatim*} -\pagebreak +%\pagebreak \section{Commands of the \xintfracname package} \label{sec:frac} @@ -8757,6 +8909,8 @@ hence there is a partial dependency of \xintfracname on \xinttoolsname,\IMPORTANT{} and the latter must be required explicitely by the user intending to use \csbxint{XTrunc}. +Refer to \autoref{ssec:floatingpoint} for general background information on +how floating point numbers and evaluations are implemented. \subsection{\csbh{xintNum}}\label{xintNum} @@ -9299,18 +9453,200 @@ works to get the \emph{exact} result. There is \emph{no problem} using them for \leftedline{|\xintFloatAdd {1e1234567890}{1}|\dtt{=\xintFloatAdd {1e1234567890}{1}}} -\subsection{\csbh{xintFloatE}}\label{xintFloatE} -%{\small New with |1.097|.} +\subsection{\csbh{xintAdd}}\label{xintAdd} -|\xintFloatE [P]{f}{x}|\etype{{\upshape[\numx]}\Ff\numx} multiplies the input -|f| by $10^x$, and -converts it to float format according to the optional first argument or current -value of |\xintDigits|. -% -\leftedline{|\xintFloatE {1.23e37}{53}|\dtt{=\xintFloatE {1.23e37}{53}}} +Computes the addition\etype{\Ff\Ff} of two fractions. To keep for integers the +integer format on output use \csbxint{iAdd}. + +Checks if one denominator is a multiple of the other. Else multiplies the +denominators. + +\subsection{\csbh{xintSub}}\label{xintSub} + +Computes the difference\etype{\Ff\Ff} of two fractions (|\xintSub{F}{G}| +computes |F-G|). To keep for integers the integer format on output use +\csbxint{iSub}. + +Checks if one denominator is a multiple of the other. Else multiplies the +denominators. + +\subsection{\csbh{xintMul}}\label{xintMul} + +Computes the product\etype{\Ff\Ff} of two fractions. To keep for integers the +integer format on output use \csbxint{iMul}. + +No reduction attempted. + +\subsection{\csbh{xintSqr}}\label{xintSqr} + +Computes the square\etype{\Ff} of one fraction. To maintain for integer input +an integer format on output use \csbxint{iSqr}. + +\subsection{\csbh{xintDiv}}\label{xintDiv} + +Computes the algebraic quotient \etype{\Ff\Ff} of two fractions. +(|\xintDiv{F}{G}| computes |F/G|). To keep for integers the integer format on +output use \csbxint{iMul}. + +No reduction attempted. + +\subsection{\csbh{xintFac}}\label{xintFac} +%{\small Modified in |1.08b| (to allow fractions on input).\par} + +The original\etype{\Numf} is extended to allow a fraction |f| which will be +truncated first to an integer |n|. See \csbxint{iFac} for a discussion of the +maximal allowed input. + +Output format is an integer without trailing |/1[0]|. + +The original macro\etype{\numx} (which parses its input via |\numexpr|) is +still available as \csbxint{iFac}. + +\subsection{\csbh{xintPow}}\label{xintPow} + +\csa{xintPow}{|{f}{g}|}:\etype{\Ff\Numf} computes |f^g| with |f| a fraction +and |g| possibly also, but |g| will first get truncated to an integer. + +The output will now always be in the form |A/B[n]| (even when the exponent +vanishes: |\xintPow {2/3}{0}|\dtt{=\xintPow{2/3}{0}}). + +The original +is available as \csbxint{iPow}. + +%%%%% OBSOLETE +% The exponent (after truncation to an integer) will be checked to not exceed +% |100000|. Indeed |2^50000| already has \dtt{\xintLen {\xintFloatPow +% [1]{2}{50000}}} digits, and squaring such a number would take hours (I +% think) with the expandable routine of \xintname. + +\subsection{\csbh{xintSum}}\label{xintSum}\label{xintSumExpr} + +% The original commands are extended to accept fractions on input and produce +% fractions on output. Their outputs will now always be in the form |A/B[n]|. The +% originals are available as \csa{xintiiSum} and \csa{xintiiSumExpr}. + +This\etype{f{$\to$}{\lowast\Ff}} computes the sum of fractions. The output +will now always be in the form |A/B[n]|. The original, for big integers only +(in strict format), is available as \csa{xintiiSum}. + +\begin{everbatim*} +\xintSum {{1282/2196921}{-281710/291927}{4028/28612}} +\end{everbatim*} + +No simplification attempted. + +% \subsection{\csbh{xintPrd}, \csbh{xintPrdExpr}}\label{xintPrd}\label{xintPrdExpr} + +\subsection{\csbh{xintPrd}}\label{xintPrd}\label{xintPrdExpr} + +TThis\etype{f{$\to$}{\lowast\Ff}} computes the product of fractions. The output +will now always be in the form |A/B[n]|. The original, for big integers only +(in strict format), is available as \csa{xintiiPrd}. + +\begin{everbatim*} +\xintPrd {{1282/2196921}{-281710/291927}{4028/28612}} +\end{everbatim*} + +No simplification attempted. + +\subsection{\csbh{xintCmp}}\label{xintCmp} +%{\small Rewritten in |1.08a|.\par} + +This\etype{\Ff\Ff} compares two fractions |F| and |G| and produces +|-1|, |0|, or |1| according to |F<G|, |F=G|, |F>G|. + +For choosing branches according to the result of comparing |f| and |g|, the +following syntax is recommended: |\xintSgnFork{\xintCmp{f}{g}}{code for + f<g}{code for f=g}{code for f>g}|. + +% Note that since release |1.08a| using this macro on inputs with large powers of +% tens does not take a quasi-infinite time, contrarily to the earlier, somewhat +% dumb version (the earlier version indirectly led to the creation of giant chains +% of zeroes in certain circumstances, causing a serious efficiency impact). + +\subsection{\csbh{xintIsOne}} + +This\etype{\Ff} returns |1| if the fraction is |1| and |0| if not. + +\begin{everbatim*} +\xintIsOne {21921379213/21921379213} but \xintIsOne {1.00000000000000000000000000000001} +\end{everbatim*} + +\subsection{\csbh{xintGeq}}\label{xintGeq} +%{\small Rewritten in |1.08a|.\par} + +This\etype{\Ff\Ff} compares the \emph{absolute values} of two +fractions.|\xintGeq{f}{g}| returns |1| if {\catcode`| 12 $|f|\geqslant|g|$} and |0| +if not. + +May be used for expandably branching as: +\verb+\xintSgnFork{\xintGeq{f}{g}}{}{code for |f|<|g|}{code for + |f|+$\geqslant$\verb+|g|}+ + +\subsection{\csbh{xintMax}}\label{xintMax} +%{\small Rewritten in |1.08a|.\par} + +The maximum of two fractions.\etype{\Ff\Ff} But now |\xintMax {2}{3}| +returns \dtt{\xintMax {2}{3}}. The original, for use with (possibly big) +integers only with no need of normalization, is available as \csbxint{iiMax}: +|\xintiiMax {2}{3}=|\dtt{\xintiMax {2}{3}}.\etype{ff} + +There is also \csbxint{iMax}\etype{\Numf\Numf} which works with fractions but +first truncates them to integers. + +\begin{everbatim*} +\xintMax {2.5}{7.2} but \xintiMax {2.5}{7.2} +\end{everbatim*} + +\subsection{\csbh{xintMin}}\label{xintMin} +%{\small Rewritten in |1.08a|.\par} + +The maximum of two fractions.\etype{\Ff\Ff} The original, for use with (possibly big) +integers only with no need of normalization, is available as \csbxint{iiMin}: +|\xintiiMin {2}{3}=|\dtt{\xintiMin {2}{3}}.\etype{ff} + +There is also \csbxint{iMin}\etype{\Numf\Numf} which works with fractions but first +truncates them to integers. + +\begin{everbatim*} +\xintMin {2.5}{7.2} but \xintiMin {2.5}{7.2} +\end{everbatim*} + +\subsection{\csbh{xintMaxof}}\label{xintMaxof} + +The maximum of any number of fractions, each within braces, and the whole +thing within braces. \etype{f{$\to$}{\lowast\Ff}} + +\begin{everbatim*} +\xintMaxof {{1.23}{1.2299}{1.2301}} and \xintMaxof {{-1.23}{-1.2299}{-1.2301}} +\end{everbatim*} + +\subsection{\csbh{xintMinof}}\label{xintMinof} + +The minimum of any number of fractions, each within braces, and the whole +thing within braces. \etype{f{$\to$}{\lowast\Ff}} + +\begin{everbatim*} +\xintMinof {{1.23}{1.2299}{1.2301}} and \xintMinof {{-1.23}{-1.2299}{-1.2301}} +\end{everbatim*} + +\subsection{\csbh{xintAbs}}\label{xintAbs} + +The absolute value\etype{\Ff}. Note that |\xintAbs {-2}|\dtt{=\xintAbs {-2}} +whereas |\xintiAbs {-2}|\dtt{=\xintiAbs {-2}}. + +\subsection{\csbh{xintSgn}}\label{xintSgn} + +The sign of a fraction.\etype{\Ff} -\subsection{\csbh{xintDigits}, \csbh{xinttheDigits}}\label{xintDigits} +\subsection{\csbh{xintOpp}}\label{xintOpp} + +The opposite of a fraction. Note that |\xintOpp {3}| now outputs \dtt{\xintOpp + {3}} whereas |\xintiOpp {3}| returns \dtt{\xintiOpp {3}}. +\subsection{\csbh{xintDigits}, \csbh{xinttheDigits}} +\label{xintDigits} +\label{xinttheDigits} %{\small New with release |1.07|.\par} The syntax |\xintDigits := D;| (where spaces do not matter) assigns the @@ -9380,13 +9716,15 @@ scientific notation if possible. Here are the rules: \end{itemize} \end{everbatim*} -\subsection{\csbh{xintAdd}}\label{xintAdd} - -Computes the addition\etype{\Ff\Ff} of two fractions. To keep for integers the -integer format on output use \csbxint{iAdd}. +\subsection{\csbh{xintFloatE}}\label{xintFloatE} +%{\small New with |1.097|.} -Checks if one denominator is a multiple of the other. Else multiplies the -denominators. +|\xintFloatE [P]{f}{x}|\etype{{\upshape[\numx]}\Ff\numx} multiplies the input +|f| by $10^x$, and +converts it to float format according to the optional first argument or current +value of |\xintDigits|. +% +\leftedline{|\xintFloatE {1.23e37}{53}|\dtt{=\xintFloatE {1.23e37}{53}}} \subsection{\csbh{xintFloatAdd}}\label{xintFloatAdd} @@ -9397,15 +9735,6 @@ denominators. and outputs in float format with precision |P| (which is optional) or |\xintDigits| if |P| was absent, the result of this computation. -\subsection{\csbh{xintSub}}\label{xintSub} - -Computes the difference\etype{\Ff\Ff} of two fractions (|\xintSub{F}{G}| -computes |F-G|). To keep for integers the integer format on output use -\csbxint{iSub}. - -Checks if one denominator is a multiple of the other. Else multiplies the -denominators. - \subsection{\csbh{xintFloatSub}}\label{xintFloatSub} %{\small New with release |1.07|.\par} @@ -9415,18 +9744,6 @@ denominators. exactly and outputs in float format with precision |P| (which is optional), or |\xintDigits| if |P| was absent, the result of this computation. -\subsection{\csbh{xintMul}}\label{xintMul} - -Computes the product\etype{\Ff\Ff} of two fractions. To keep for integers the -integer format on output use \csbxint{iMul}. - -No reduction attempted. - -\subsection{\csbh{xintSqr}}\label{xintSqr} - -Computes the square\etype{\Ff} of one fraction. To maintain for integer input -an integer format on output use \csbxint{iSqr}. - \subsection{\csbh{xintFloatMul}}\label{xintFloatMul} %{\small New with release |1.07|.\par} @@ -9447,14 +9764,6 @@ exactly and outputs in float format with precision |P| (which is optional), or time to come back to it. \end{framed} -\subsection{\csbh{xintDiv}}\label{xintDiv} - -Computes the algebraic quotient \etype{\Ff\Ff} of two fractions. -(|\xintDiv{F}{G}| computes |F/G|). To keep for integers the integer format on -output use \csbxint{iMul}. - -No reduction attempted. - \subsection{\csbh{xintFloatDiv}}\label{xintFloatDiv} %{\small New with release |1.07|.\par} @@ -9464,18 +9773,6 @@ No reduction attempted. exactly and outputs in float format with precision |P| (which is optional), or |\xintDigits| if |P| was absent, the result of this computation. -\subsection{\csbh{xintFac}}\label{xintFac} -%{\small Modified in |1.08b| (to allow fractions on input).\par} - -The original\etype{\Numf} is extended to allow a fraction |f| which will be -truncated first to an integer |n|. See \csbxint{iFac} for a discussion of the -maximal allowed input. - -Output format is an integer without trailing |/1[0]|. - -The original macro\etype{\numx} (which parses its input via |\numexpr|) is -still available as \csbxint{iFac}. - \subsection{\csbh{xintFloatFac}}\label{xintFloatFac} \csa{xintFloatFac}|[P]{f}|\etype{{\upshape[\numx]}\Ff} returns the @@ -9496,23 +9793,6 @@ The macro |\xintFloatFac| chooses dynamically an appropriate number of digits for the intermediate computations, large enough to achieve the desired accuracy (hopefully). -\subsection{\csbh{xintPow}}\label{xintPow} - -\csa{xintPow}{|{f}{g}|}:\etype{\Ff\Numf} computes |f^g| with |f| a fraction -and |g| possibly also, but |g| will first get truncated to an integer. - -The output will now always be in the form |A/B[n]| (even when the exponent -vanishes: |\xintPow {2/3}{0}|\dtt{=\xintPow{2/3}{0}}). - -The original -is available as \csbxint{iPow}. - -%%%%% OBSOLETE -% The exponent (after truncation to an integer) will be checked to not exceed -% |100000|. Indeed |2^50000| already has \dtt{\xintLen {\xintFloatPow -% [1]{2}{50000}}} digits, and squaring such a number would take hours (I -% think) with the expandable routine of \xintname. - \subsection{\csbh{xintFloatPow}}\label{xintFloatPow} %{\small New with |1.07|.\par} @@ -9541,41 +9821,73 @@ accuracy (hopefully). \csa{xintFloatPower}|[P]{f}{g}|\etype{{\upshape[\numx]}\Ff\Numf} computes a floating point value |f^g| where the exponent |g| is not constrained to be at most the \TeX{} bound \texttt{\number "7FFFFFFF}. It may even be a fraction -|A/B| but must simplify to a (possibly big) integer. +|A/B| but must simplify to a (possibly big) integer. The exponent of the +\emph{output} however \emph{must} at any rate obey the \TeX{} +\dtt{\number"7FFFFFFF} bound. % \leftedline{|\xintFloatPower [8]{1.000000000001}{1e12}|% \dtt{=\xintFloatPower [8]{1.000000000001}{1e12}}} % \leftedline{|\xintFloatPower [8]{3.1415}{3e9}|% - \dtt{=\xintFloatPower [8]{3.1415}{3e9}}} Note that |3e9>2^31|. But the -number following |e| in the output must at any rate obey the \TeX{} -\dtt{\number"7FFFFFFF} bound. + \dtt{=\xintFloatPower [8]{3.1415}{3e9}}} Notice that |3e9>2^31|. + +Here is another example: +% +\leftedline{|\xintFloatPower [48] {1.1547}{\xintiiPow {2}{35}}|} +% +computes $(1.1547)^{2^{35}}=(1.1547)^{\xintiiPow {2}{35}}$ to be +approximately +% +\leftedline{\dtt{\np{\xintFloatPower [48] {1.1547}{\xintiiPow {2}{35}}}}} +% +Again, $2^{35}$ exceeds \TeX's bound, but \csa{xintFloatPower} allows it, what +counts is the exponent of the result which, while dangerously close to +$2^{31}$ is not quite there yet.\footnote{The printing of the result was done + via the |\numprint| command from the \url{http://ctan.org/pkg/numprint} + package.} -Inside an |\xintfloatexpr|-ession, \csa{xintFloatPower} is the function to which -|^| is mapped. The exponent may then be something like |(144/3/(1.3-.5)-37)| -which is, in disguise, an integer. - -The intermediate multiplications are done with a higher precision than -|\xintDigits| or the optional |P| argument, in order for the -final result to hopefully have the desired accuracy.% -% -\footnote{\label{fn:floatpow}% - Release |1.2| did not change a single line of code to these macros because - they don't access low-level entry points. There is some sure important - efficiency gains to be obtained in maintaining internally the best inner - format for the successive squarings and multiplications, but I decided to - postpone that, as the more urgent issue is to improve \csbxint{FloatMul} to - not compute exactly with all digits the product before keeping only the - required digits.} - -There is an important difference between (for example) |\xintFloatPower -[48]{X}{Y}| and |\xintthefloatexpr [48] X^Y \relax|: in the former case the -computation is done with |48| digits or precision (but if |X| and |Y| are -themselves floating point macros of \xintfracname, their respective -evaluations obey only the precision set optionally in the macros), whereas -with \csbxint{thefloatexpr} the evaluation of the expression proceeds with -|\xintDigits| digits of precision, but is rounded to |48| digits (thus this -example makes sense only if |48<\xintDigits|.) +Inside an |\xintfloatexpr|-ession, \csa{xintFloatPower} is the function to +which |^| is mapped. Thus the same computation as above can be done via the +non-expandable assignment |\xintDigits:=48;| and +% +\leftedline{|\xintthefloatexpr 1.1547^(2^35)\relax|} +% +There is a subtlety here that the |2^35| will be evaluated as a floating point +number but fortunately it only has \dtt{\xintLen{\xintiiPow{2}{35}}} digits, +hence the final evaluation is done with a correct exponent. It is safer, and +also more efficient to code the above rather as: +% +\leftedline{|\xintthefloatexpr 1.1547^\xintiiexpr 2^35\relax\relax|} +% +to guarantee no loss of digits in the exponent. + +There is an important difference between |\xintFloatPower [Q]{X}{Y}| and +|\xintthefloatexpr [Q] X^Y \relax|: in the former case the computation is done +with |Q| digits or precision (but if |X| and |Y| themselves stand for some +floating point macros with arguments, their respective evaluations obey the +precision |\xinttheDigits| or as set optionally in the macro calls +themselves), whereas with \csbxint{thefloatexpr} the evaluation of the +expression proceeds with |\xinttheDigits| digits of precision, and the final +output is rounded to |Q| digits: thus this makes real sense only if used with +|Q<\xinttheDigits|. + +The intermediate multiplications executed by |\xintFloatPower| are done with a +higher precision than |\xinttheDigits| or the optional |P| argument, in order +for the final result to have the desired accuracy. +% % +% \footnote{\label{fn:floatpow}% +% Release |1.2| did not change a single line of code to these macros because +% they don't access low-level entry points. There is some sure important +% efficiency gains to be obtained in maintaining internally the best inner +% format for the successive squarings and multiplications, but I decided to +% postpone that, as the more urgent issue is to improve \csbxint{FloatMul} to +% not compute exactly with all digits the product before keeping only the +% required digits.} +\emph{This means that the error, compared to rounding an exact evaluation, is + guaranteed to be strictly less than |0.6| floating point unit. The last + digit may thus be wrong, and if it is |0| or |9| with it the next to last, + etc... } +% ATTENTION A VERIFIER QUE JE FAIS BIEN CELA. \subsection{\csbh{xintFloatSqrt}}\label{xintFloatSqrt} %{\small New with |1.08|.\par} @@ -9606,131 +9918,6 @@ the value of |\xintDigits|. The computation is done for a precision of at least % \subsection{\csbh{xintSum}, \csbh{xintSumExpr}}\label{xintSum} % \label{xintSumExpr} -\subsection{\csbh{xintSum}}\label{xintSum}\label{xintSumExpr} - -% The original commands are extended to accept fractions on input and produce -% fractions on output. Their outputs will now always be in the form |A/B[n]|. The -% originals are available as \csa{xintiiSum} and \csa{xintiiSumExpr}. - -This\etype{f{$\to$}{\lowast\Ff}} computes the sum of fractions. The output -will now always be in the form |A/B[n]|. The original, for big integers only -(in strict format), is available as \csa{xintiiSum}. - -\begin{everbatim*} -\xintSum {{1282/2196921}{-281710/291927}{4028/28612}} -\end{everbatim*} - -No simplification attempted. - -% \subsection{\csbh{xintPrd}, \csbh{xintPrdExpr}}\label{xintPrd}\label{xintPrdExpr} - -\subsection{\csbh{xintPrd}}\label{xintPrd}\label{xintPrdExpr} - -TThis\etype{f{$\to$}{\lowast\Ff}} computes the product of fractions. The output -will now always be in the form |A/B[n]|. The original, for big integers only -(in strict format), is available as \csa{xintiiPrd}. - -\begin{everbatim*} -\xintPrd {{1282/2196921}{-281710/291927}{4028/28612}} -\end{everbatim*} - -No simplification attempted. - -\subsection{\csbh{xintCmp}}\label{xintCmp} -%{\small Rewritten in |1.08a|.\par} - -This\etype{\Ff\Ff} compares two fractions |F| and |G| and produces -|-1|, |0|, or |1| according to |F<G|, |F=G|, |F>G|. - -For choosing branches according to the result of comparing |f| and |g|, the -following syntax is recommended: |\xintSgnFork{\xintCmp{f}{g}}{code for - f<g}{code for f=g}{code for f>g}|. - -% Note that since release |1.08a| using this macro on inputs with large powers of -% tens does not take a quasi-infinite time, contrarily to the earlier, somewhat -% dumb version (the earlier version indirectly led to the creation of giant chains -% of zeroes in certain circumstances, causing a serious efficiency impact). - -\subsection{\csbh{xintIsOne}} - -This\etype{\Ff} returns |1| if the fraction is |1| and |0| if not. - -\begin{everbatim*} -\xintIsOne {21921379213/21921379213} but \xintIsOne {1.00000000000000000000000000000001} -\end{everbatim*} - -\subsection{\csbh{xintGeq}}\label{xintGeq} -%{\small Rewritten in |1.08a|.\par} - -This\etype{\Ff\Ff} compares the \emph{absolute values} of two -fractions.|\xintGeq{f}{g}| returns |1| if {\catcode`| 12 $|f|\geqslant|g|$} and |0| -if not. - -May be used for expandably branching as: -\verb+\xintSgnFork{\xintGeq{f}{g}}{}{code for |f|<|g|}{code for - |f|+$\geqslant$\verb+|g|}+ - -\subsection{\csbh{xintMax}}\label{xintMax} -%{\small Rewritten in |1.08a|.\par} - -The maximum of two fractions.\etype{\Ff\Ff} But now |\xintMax {2}{3}| -returns \dtt{\xintMax {2}{3}}. The original, for use with (possibly big) -integers only with no need of normalization, is available as \csbxint{iiMax}: -|\xintiiMax {2}{3}=|\dtt{\xintiMax {2}{3}}.\etype{ff} - -There is also \csbxint{iMax}\etype{\Numf\Numf} which works with fractions but -first truncates them to integers. - -\begin{everbatim*} -\xintMax {2.5}{7.2} but \xintiMax {2.5}{7.2} -\end{everbatim*} - -\subsection{\csbh{xintMin}}\label{xintMin} -%{\small Rewritten in |1.08a|.\par} - -The maximum of two fractions.\etype{\Ff\Ff} The original, for use with (possibly big) -integers only with no need of normalization, is available as \csbxint{iiMin}: -|\xintiiMin {2}{3}=|\dtt{\xintiMin {2}{3}}.\etype{ff} - -There is also \csbxint{iMin}\etype{\Numf\Numf} which works with fractions but first -truncates them to integers. - -\begin{everbatim*} -\xintMin {2.5}{7.2} but \xintiMin {2.5}{7.2} -\end{everbatim*} - -\subsection{\csbh{xintMaxof}}\label{xintMaxof} - -The maximum of any number of fractions, each within braces, and the whole -thing within braces. \etype{f{$\to$}{\lowast\Ff}} - -\begin{everbatim*} -\xintMaxof {{1.23}{1.2299}{1.2301}} and \xintMaxof {{-1.23}{-1.2299}{-1.2301}} -\end{everbatim*} - -\subsection{\csbh{xintMinof}}\label{xintMinof} - -The minimum of any number of fractions, each within braces, and the whole -thing within braces. \etype{f{$\to$}{\lowast\Ff}} - -\begin{everbatim*} -\xintMinof {{1.23}{1.2299}{1.2301}} and \xintMinof {{-1.23}{-1.2299}{-1.2301}} -\end{everbatim*} - -\subsection{\csbh{xintAbs}}\label{xintAbs} - -The absolute value\etype{\Ff}. Note that |\xintAbs {-2}|\dtt{=\xintAbs {-2}} -whereas |\xintiAbs {-2}|\dtt{=\xintiAbs {-2}}. - -\subsection{\csbh{xintSgn}}\label{xintSgn} - -The sign of a fraction.\etype{\Ff} - -\subsection{\csbh{xintOpp}}\label{xintOpp} - -The opposite of a fraction. Note that |\xintOpp {3}| now outputs \dtt{\xintOpp - {3}} whereas |\xintiOpp {3}| returns \dtt{\xintiOpp {3}}. - \subsection{\csbh{xintiDivision}, \csbh{xintiQuo}, \csbh{xintiRem}, \csbh{xintFDg}, \csbh{xintLDg}, \csbh{xintMON}, \csbh{xintMMON}, \csbh{xintOdd}} @@ -9873,436 +10060,105 @@ it allows also to be prefixed with |\xintthe|. Furthemore, if |\a| and |\b| are already defined |\edef\x {\xintexpr \a+\b\relax}| will do the computation on the spot.% Rather than |\edef| one can use |\oodef|. +\subsection{\csh{xintdefvar}, \csh{xintdeffunc}} +\label{xintdefvar} +\label{xintdefiivar} +\label{xintdeffloatvar} +\label{xintdeffunc} +\label{xintdefiifunc} +\label{xintdeffloatfunc} -\subsection{Some features of the 1.1 release of \xintexprname} -\label{sec:expr11} - -Release |1.1| brought many changes to \xintexprname. This chapter is for -people already familiar with earlier versions. A more systematic item per item -syntax description is provided in the next \autoref{sec:expr}. Both this -section and the next are in need of being improved. - -First, there were some breaking changes: -\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, - itemindent=0pt, listparindent=\leftmarginiii, leftmargin=\leftmarginii] - \item in |\xintiiexpr|, |/| does \emph{rounded} division, rather than as - in earlier releases the - Euclidean division (for positive arguments, this is truncated division). - The new |//| operator does truncated division, - \item the |:| operator for three-way branching is gone, replaced with |??|, - \item |1e(3+5)| is now illegal. The number parser identifies |e| and |E| - in the same way it does for the decimal mark, earlier versions treated - |e| as |E| rather as postfix operators, - \item the |add| and |mul| have a new syntax, old syntax is with |`+`| and - |`*`| (quotes mandatory), |sum| and |prd| are gone, - \item no more special treatment for encountered brace pairs |{..}| by the - number scanner, |a/b[N]| notation can be used without use of braces (the - |N| will end up space-stripped in a |\numexpr|, it is not parsed by the - |\xintexpr|-ession scanner). - \item although |&| and \verb+|+ are still available as Boolean operators the - use of |&&| and \verb+||+ is strongly recommended. The single - letter operators might be assigned some other meaning in later releases - (bitwise operations, perhaps). Do not use them. - \item place holders for |\xintNewExpr| - could be denoted |#1|, |#2|, ... or also, for special purposes |$1|, |$2|, - ... Only the first form is now accepted and the special cases previously - treated via the second form are now managed via a |protect(...)| function. -\end{itemize} - -Let's now describle some of the numerous additional functionalities. - -\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, - itemindent=\leftmarginii, listparindent=\leftmarginii, leftmargin=0em] - \item |\xintiexpr|, |\xinttheiexpr| admit an optional argument within - brackets |[d]|, it then presents the computation result (or results, if - comma separated) after rounding to |d| digits after decimal mark, (the - whole computation is done exactly, as in |xintexpr|), +It is possible to assign a variable name to let it known to the parsers of \xintexprname. \begin{everbatim*} -\xinttheiexpr [32] 1.23^50, 1.231^50\relax +\xintdefvar Pi:=3.1415926535 8979323846 2643; +\xintthefloatexpr Pi^100\relax \end{everbatim*} - \item |\xintfloatexpr|, |\xintthefloatexpr| similarly admit an optional - argument which serves to keep only |d| digits of precision, getting rid - of cumulated uncertainties in the last digits (the whole computation is - done according to the precision set via |\xintDigits|), -\begin{everbatim*} -\xintDigits:=32;\xintthefloatexpr 1.010101^10-1.0101^10\relax -\xintDigits:=16;\xintthefloatexpr 1.010101^10-1.0101^10\relax +The definition of the variable is done either with \csa{xintdefvar}, +\csa{xintdefiivar}, or \csa{xintdeffloatvar}, the variable will be computed +using respectively \csbxint{theexpr}, \csbxint{theiiexpr} or +\csbxint{thefloatexpr}. The variable once defined can be used in the other +parsers, except naturally that in \csa{xintiiexpr} only integers are accepted. -\xintthefloatexpr [12] 1.010101^10-1.0101^10\relax -\end{everbatim*} - - \item |\xinttheexpr| and |\xintthefloatexpr| ``pretty-print'' if possible, - the former removing unit denominator or |[0]| brackets, the latter - avoiding scientific notation if decimal notation is practical, - \item the |//| does truncated division and |/:| is the associated modulo, - \item multi-character operators |&&|, \verb+||+, |==|, |<=|, |>=|, |!=|, - |**|, - \item multi-letter infix binary words |'and'|, |'or'|, |'xor'|, |'mod'| - (quotes mandatory), - \item functions |even|, |odd|, |first|, |last|, - \item |\xintdefvar A3:=3.1415;| for variable definitions (non expandable, - naturally), usable in subsequent expressions; variable names may contain - letters, digits, underscores. They should not start with a digit, the - |@| is reserved, and single lowercase and uppercase Latin letters are - predefined to work as dummy variables (see next), - \item generation of comma separated lists |a..b|, |a..[d]..b|, - \item Python syntax-like list extractors |[list][n:]|, |[list][:n]|, |[list][a:b]| - and |[list][n]| (|n=0| for the number of list items), the step is always - |+1|, - \item function |reversed|, to reverse the order of list items, - \item itemwise sequence operations |a*[list]|, etc.., on both sides |a*[list]^b|, - \item dummy variables in |add| and |mul|: |add(x(x+1)(x-1), x=-10..10)|, - \item variable substitutions with |subs|: |subs(subs(add(x^2+y^2,x=1..y),y=t),t=20)|, - \item sequence generation using |seq| with a dummy variable: |seq(x^3, x=-10..10)|, - \item simple recursive sequences with |rseq|, with |@| given the last value, - |rseq(1;2@+1,i=1..10)|, - \item higher recursion with |rrseq|, |@1|, |@2|, |@3|, |@4|, and |@@(n)| - for earlier values, up to |n=K| where |K| is the number of terms of the - initial stretch |rrseq(0,1;@1+@2,i=2..100)|, - \item iteration with |iter| which is like |rrseq| but outputs only the - last |K| terms, where |K| was the number of initial terms, - \item inside |seq|, |rseq|, |rrseq|, |iter|, possibility to use |omit|, - |abort| and |break| to control termination, - \item |n++| potentially infinite index generation for |seq|, |rseq|, - |rrseq|, and |iter|, it is advised to use |abort| or |break(..)| at - some point, - \item the |add|, |mul|, |seq|, ... are nestable,% -\footnote{but |add(seq(x,x=1..t),t=1..2)| fails for the reason that |add| will - receive not a list of numbers but a list of lists.} - \item |\xintthecoords| converts a comma separated list of an even number - of items to the format as expected by the |TikZ| |coordinates| syntax, - \item completely rewritten |\xintNewExpr|, new |protect| function to handle - external macros. However not all constructs are compatible with - |\xintNewExpr|. -\end{itemize} - -% \subsection{Examples with the \texorpdfstring{\unexpanded{\unexpanded{|v1.1|}}}{v1.1} \csh{xintexpr}} - -And now some examples: - -\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, - itemindent=\leftmarginii, listparindent=\leftmarginii, leftmargin=0em] -\item One can define variables (the definition itself is a non expandable - step). The allowed names are composed of letters, digits, and underscores. - The variable should not start with a digit and single letters |a..z|, |A..Z| - are predefined for use as dummy variables --- see below. The |@| is - reserved. +Since release |1.2c| it is possible also to declare functions: \begin{everbatim*} -\begingroup - \xintdefvar a_1 := 3.14159;\xintdefvar a2 := 2.71828;\xinttheiexpr [5] a_1+a2\relax -\endgroup -\end{everbatim*} -\item |add| and |mul| have a new syntax requiring a dummy variable: -\begin{everbatim*} -\xinttheexpr add(x, x=1,3,19), mul(x^2, x=1,3,19), add(x(x+1), x= 1,3,19)\relax -\end{everbatim*} - -Use |`+`| and |`*`| (left ticks mandatory) for syntax without dummy variables: -\begin{everbatim*} -\xinttheexpr `+`(1,3,19), `*`(1^2,3^2,19^2), `+`(1*2,3*4,19*20)\relax -\end{everbatim*} -\item The |seq| function generates sequences according to a given formula: -\begin{everbatim*} -\xinttheexpr seq(x(x+1)(x+2), x=1,3,19), `+`(seq(x(x+1)(x+2), x=1,3,19)), - add(x(x+1)(x+2), x=1,3,19)\relax -\end{everbatim*} -\begin{everbatim*} -And this is nestable! -\xinttheexpr seq(seq(x^y, y=1..5),x=1..5), add(mul(x^y,y=1..5), x=1..5), - add(x^15, x=1..5)\relax % 15 = 1+2+3+4+5 -\end{everbatim*} - -One should use parentheses appropriately. The \csbxint{expr} parser in normal -operation is not bad at identifying missing or extra opening or closing -parentheses, but when it handles |seq|, |add|, |mul| or similar constructs it -switches to another mode of operation (it starts using delimited macros, -something which is almost non-existent in all its other operations) and ill-formed -expressions are much more likely to let the parser fetch tokens from beyond the -mandatory ending |\relax|. Thus, in case of a missing parenthesis in such -circumstances the error message from \TeX{} might be very cryptic, even for -the seasoned \xintname user. - -\item As seen in the last example |a..b| constructs the integers from |a| to - |b|. This is (small) integer only. A more general |a..[d]..b| works with big - integers, or fractions, from |a| to |b| with step |d|. -\begin{everbatim*} -\xinttheexpr seq(2x+1, x=1..10, 100..110, 3/5..[1/5]..7/5)\relax -\end{everbatim*} -\item itemwise operations on lists are possible, as well as item extractions: -\begin{everbatim*} -\xinttheiiexpr 2*[1,10,100]^3, 5+[2*[1,10,100]^3]*100 \relax -\end{everbatim*} -\begin{everbatim*} -\xinttheiiexpr 1+[seq(3^j, j=1..10, 21..30)][17], 1+3^27\relax -\end{everbatim*} - -We used the |[list][n]| construct which gives the nth item from the list. In -this context there are also the functions |last| and |first|. There is no real -concept of a list object, nor list operations, although itemwise manipulation -are made possible as shown above via the |[..]| constructor. The list -manipulation utilities are so far a bit limited. There is no notion of an -``nuple'' object. The variable |nil| is reserved, it represents an empty list. - -\item |subs| is similar to |seq| in syntax but is for variable substitution: -\begin{everbatim*} -\xinttheexpr subs(100*subs(10*subs(3*x+5,x=y+50)+2,y=z^2),z=10)\relax % 100(10(3*150+5)+2) -\end{everbatim*} -\begin{everbatim*} -\xinttheexpr subs(subs(add(x^2+y^2,x=1..y),y=t),t=20)\relax -\end{everbatim*} - -The substituted variable may be a comma separated list (this is impossible -with |seq| which will always pick one item after the other of a list). -\begin{everbatim*} -\xinttheexpr subs([x]^2,x=-123,17,32)\relax -\end{everbatim*} - -\item last but not least, |seq| has variants |rseq| and |rrseq| which allow - recursive definitions. They start with at least one initial value, then a - semi-colon, then the formula, then the list of indices to iterate over. |@| - (or |@1|) evaluates to the last computed item, and |rrseq| keeps the memory - of the |K| last results, where |K| was the number of initial terms. One - accesses them via |@1, @2, @3, @4| and |@@(N)| for |N>4|. It is even - possible to nest them and use |@@@| to access the values of the master - recursion... -\begin{everbatim*} -\xinttheiiexpr rseq(1; 2*@, i=1..10), `+`(rseq(1; 2*@, i=1..10))\relax -\end{everbatim*} -\begin{everbatim*} -\xinttheiiexpr rseq(2; @(@+1)/2, i=1..5)\relax -\end{everbatim*} -\begin{everbatim*} -\xinttheiiexpr rseq(0,1; (@1,add(x,x=@1)), y=2..10)\relax -\end{everbatim*} - -Some Fibonacci fun -\begin{everbatim*} -\xinttheiiexpr rrseq(0,1; @1+@2, x=2..10), last(rrseq(0,1; @1+@2, x=2..100))\relax -\end{everbatim*} -\begin{everbatim*} -Sum of previous last three: \xinttheiiexpr rrseq(0,0,1; @1+@2+@3, i=1..20)\relax -\end{everbatim*} -\begin{everbatim*} -Big numbers: \printnumber{\xinttheexpr rseq(1; @(@+1), j=1..10)\relax } -\end{everbatim*} - -Nested recursion often quickly leads to gigantic outputs. This is an -experimental feature, susceptible to be removed or altered in the future. -\begin{everbatim*} -\xinttheexpr rrseq(1; `+`(rrseq(0,1; @@@(1)+@1+@2, i=1..10)), j=1..5)\relax -\end{everbatim*} - -\item The special keywords |omit|, |abort| and |break(..)| are available - inside |seq|, |rseq|, |rrseq|, as well as the |n++| for a potentially - infinite iteration. The |n++| construct in conjunction with an |abort| or - |break| is often more efficient, because in other cases the list to iterate - over is first completely constructed. -\begin{everbatim*} -First Fibonacci number at least |2^31| and its index -\xinttheiiexpr iter(0,1; (@1>=2^31)?{break(i)}{@2+@1}, i=1++)\relax -\end{everbatim*} - -\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 +\xintdeffunc + rump(x,y):=1335*y^6/4+x^2*(11*x^2*y^2-y^6-121*y^4-2)+11*y^8/2+x/2/y; +\xinttheexpr rump(77617,33096)\relax \end{everbatim*} -The syntax in this last example may look a bit involved. First |x/:m| computes -|x modulo m| (this is the modulo with respect to truncated division, which -here for positive arguments is like Euclidean division; in -|\xintexpr...\relax|, |a/:b| is such that |a = b*(a//b)+a/:b|, with |a//b| the -algebraic quotient |a/b| truncated to an integer.). 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. - -% 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 - -\item The |iter| function is like |rrseq| but does not leave a trace of earlier items, - it starts with |K| initial values, then it iterates: either a fixed number of times, - or until aborting or breaking. And ultimately it prints |K| final values. -\begin{everbatim*} -The first Fibonacci number beyond the \TeX{} bound is -\xinttheiiexpr subs(iter(0,1;(@1>N)?{break(i)}{@1+@2},i=1++),N=2^31)\relax{} -and the previous number was its index. -\end{everbatim*}But this was a bit too easy, what is the smallest Fibonacci number not representable on 64 bits? -\begin{everbatim*} -The first Fibonacci number beyond |2^64| bound is -\xinttheiiexpr subs(iter(0,1;(@1>N)?{break(i)}{@1+@2},i=1++),N=2^64)\relax{} -and the previous number was its index. -\end{everbatim*} - -One more recursion: +\begin{framed} + The names of the macros \csa{xintdeffunc}, \csa{xintdefiifunc}, + \csa{xintdeffloatfunc} (and those for variables) as well as their syntax + (with |:=| and an ending |;|) will be set definitely only in next release. + \footnotemark +\end{framed} +\footnotetext{with the current syntax, the |;| as used for |iter|, |rseq|, + |rrseq| must be hidden as |{;}| to not be confused with the |;| ending the + declaration.} + +A function may be declared either via \csa{xintdeffunc}, \csa{xintdefiifunc}, +\csa{xintdeffloatfunc}. It will then be known \emph{only} to the parser which +was used for its definition. Thus to test the \textsc{Rump} polynomial with +floats, we must declare |rump| as a function to be used there (I use +coefficients |333.75| and |5.5| rather than fractions only because this is how +I saw the polynomial defined in one computer class reference found on +internet): \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 +\xintdeffloatfunc + rump(x,y):=333.75*y^6+x^2*(11*x^2*y^2-y^6-121*y^4-2)+5.5*y^8+x/2/y; \end{everbatim*} -Ok, a final one: +The numbers are scanned with the current precision, here it is \dtt{16}, hence +they are scanned exactly. We can then vary the precision for the evaluation. \begin{everbatim*} -\def\syrMax #1{\xinttheiiexpr iter(#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 +\def\CR{\cr} +\halign +{\tabskip1ex +\hfil\bfseries#&\xintDigits:=\xintiloopindex;\xintthefloatexpr rump(77617,33096)#\cr +\xintiloop [8+1] +\xintiloopindex &\relax\CR +\ifnum\xintiloopindex<40 \repeat +} \end{everbatim*} -Well, one more: - +It is licit to overload a variable name (all Latin letters are predefined as +dummy variables) with a function name and vice versa. The context decides if +the function or variable interpretation must be used (dropping various cases +of tacit multiplication as normally applied to variables). \begin{everbatim*} -\newcommand\GCD [2]{\xinttheiiexpr rrseq(#1,#2; (@1=0)?{abort}{@2/:@1}, i=1++)\relax } -\GCD {13^10*17^5*29^5}{2^5*3^6*17^2} +\xintdefiifunc f(x):=x^3; +\xinttheiiexpr add(f(f),f=100..120)\relax\newline +\xintdeffunc f(x,y):=x^2+y^2; +\xinttheexpr mul(f(f(f,f),f(f,f)),f=1..10)\relax \end{everbatim*} -and the ultimate: - -\begin{everbatim*} -\newcommand\Factors [1]{\xinttheiiexpr - subs(seq((i/:3=2)?{omit}{[L][i]},i=1..([L][0])), - L=rseq(#1;(p^2>[@][1])?{([@][1]>1)?{break(1,[@][1],1)}{abort}} - {(([@][1])/:p)?{omit} - {iter(([@][1])//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. \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(([@][1])//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 |([@][1])/: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} - -For comparison, here is an \fexpan dable macro expanding to the same result, -but coded directly with the \xintname macros. Here |#1| can not be itself an -expression, naturally. But at least we let |\Factorize| \fexpan d its -argument. -\begin{everbatim} -\makeatletter -\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}}}% -\makeatother -\end{everbatim} - -The macro |\Factorize| puts a little stress on the input save stack in order -not be bothered with previously gathered things. I timed it to be about eight -times faster than |\Factors| in test cases such as -|16246355912554185673266068721806243461403654781833| and others. Among the -various things explaining the speed-up, there is fact that we step by -increments of two, not one, and also that we divide only once, obtaining -quotient and remainder in one go. These two things already make for a speed-up -factor of about four. Thus, our earlier |\Factors| was not completely -inefficient, and was quite easier to come up with than |\Factorize|. - -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 -\end{itemize} - -%\phantomsection -\phantomsection\label{sec:expr11coords} +Once a Latin letter has been redeclared as a user variable it is impossible to +``unassign'' it, one can only redeclare it with a new value. These +declarations are local. -To conclude with this overview of the new features in \xintexprname |1.1|, I -will mention {\bfseries |\xintthecoords|} which converts a comma separated -list as produced by |\xintfloatexpr| or |\xintiexpr [d]| to the format -expected by the |TikZ| |coordinates| syntax. +There are restrictions in the definition of functions: dummy variables may be +used only with explicit value lists, for example |\xintdeffunc +f(x):=add(i^2,i=1..x);| is currently impossible or rather the definition of +|f| goes through, but the function generates low-level \TeX{} errors on use. +On the other hand |\xintdeffunc f(x):= add(x^i, i=1..10);| is perfectly legal +and does work. \begin{everbatim*} -{\centering\begin{tikzpicture}[scale=10]\xintDigits:=8; - \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 into (x1, y1) (x2, y2)... format - \xintfloatexpr seq((x^2-1,mul(x-t,t=-1+[0..4]/2)),x=-1.2..[0.1]..+1.2) \relax }; -\end{tikzpicture}\par } +\xintdefiifunc f(x):=add(x^i, i=0..10); +\xinttheiiexpr seq(f(n), n=0..10)\relax \end{everbatim*} -% Notice: if x goes no take exactly value 1 or -1, the origin appears slightly -% off the curve, not MY fault!!! +Sorry about the brevity of the documentation, it will be completed at a later +date. The mechanism for functions is closely related to the \csbxint{NewExpr} +command and uses the exact same underlying mechanism.\footnote{In particular, + contrarily to variables, function declarations have global scope. + \emph{might change in the future}} A function once declared +is a first class citizen, the expression is entirely parsed and converted into +nested \fexpan dable macros during its definition. When used its action is via +this defined macro. With |\xintverbosetrue| the values of the variables and +the meaning of the functions (or rather their associated macros) will be written +to the log. -\csbxint{thecoords} should be followed immediately by \csbxint{floatexpr} or -\csbxint{iexpr} or \csbxint{iiexpr}, but not |\xintthefloatexpr|, etc\dots - -Besides, as |TikZ| will not understand the |A/B[N]| format which is used on -output by |\xintexpr|, |\xintexpr| is not really usable with |\xintthecoords| -for a |TikZ| picture, but one may use it on its own, and the reason for the -spaces in and between coordinate pairs is to allow if necessary to print on -the page for examination with about correct line-breaks. - -\begin{everbatim*} -\edef\x{\xintthecoords \xintexpr rrseq(1/2,1/3; @1+@2, x=1..20)\relax } -\meaning\x +++ -\end{everbatim*} \subsection{The syntax}\label{ssec:syntax} @@ -11080,6 +10936,436 @@ one obtains as output \xinttheexpr 2^3,3^4,5^6\relax{}. % See \autoref{ssec:countinexpr} for count and dimen registers and variables. +\subsection{Some features of the 1.1 release of \xintexprname} +\label{sec:expr11} + +Release |1.1| brought many changes to \xintexprname. This chapter is for +people already familiar with earlier versions. A more systematic item per item +syntax description is provided in the next \autoref{sec:expr}. Both this +section and the next are in need of being improved. + +First, there were some breaking changes: +\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, + itemindent=0pt, listparindent=\leftmarginiii, leftmargin=\leftmarginii] + \item in |\xintiiexpr|, |/| does \emph{rounded} division, rather than as + in earlier releases the + Euclidean division (for positive arguments, this is truncated division). + The new |//| operator does truncated division, + \item the |:| operator for three-way branching is gone, replaced with |??|, + \item |1e(3+5)| is now illegal. The number parser identifies |e| and |E| + in the same way it does for the decimal mark, earlier versions treated + |e| as |E| rather as postfix operators, + \item the |add| and |mul| have a new syntax, old syntax is with |`+`| and + |`*`| (quotes mandatory), |sum| and |prd| are gone, + \item no more special treatment for encountered brace pairs |{..}| by the + number scanner, |a/b[N]| notation can be used without use of braces (the + |N| will end up space-stripped in a |\numexpr|, it is not parsed by the + |\xintexpr|-ession scanner). + \item although |&| and \verb+|+ are still available as Boolean operators the + use of |&&| and \verb+||+ is strongly recommended. The single + letter operators might be assigned some other meaning in later releases + (bitwise operations, perhaps). Do not use them. + \item place holders for |\xintNewExpr| + could be denoted |#1|, |#2|, ... or also, for special purposes |$1|, |$2|, + ... Only the first form is now accepted and the special cases previously + treated via the second form are now managed via a |protect(...)| function. +\end{itemize} + +Let's now describle some of the numerous additional functionalities. + +\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, + itemindent=\leftmarginii, listparindent=\leftmarginii, leftmargin=0em] + \item |\xintiexpr|, |\xinttheiexpr| admit an optional argument within + brackets |[d]|, it then presents the computation result (or results, if + comma separated) after rounding to |d| digits after decimal mark, (the + whole computation is done exactly, as in |xintexpr|), +\begin{everbatim*} +\xinttheiexpr [32] 1.23^50, 1.231^50\relax +\end{everbatim*} + \item |\xintfloatexpr|, |\xintthefloatexpr| similarly admit an optional + argument which serves to keep only |d| digits of precision, getting rid + of cumulated uncertainties in the last digits (the whole computation is + done according to the precision set via |\xintDigits|), +\begin{everbatim*} +\xintDigits:=32;\xintthefloatexpr 1.010101^10-1.0101^10\relax + +\xintDigits:=16;\xintthefloatexpr 1.010101^10-1.0101^10\relax + +\xintthefloatexpr [12] 1.010101^10-1.0101^10\relax +\end{everbatim*} + + \item |\xinttheexpr| and |\xintthefloatexpr| ``pretty-print'' if possible, + the former removing unit denominator or |[0]| brackets, the latter + avoiding scientific notation if decimal notation is practical, + \item the |//| does truncated division and |/:| is the associated modulo, + \item multi-character operators |&&|, \verb+||+, |==|, |<=|, |>=|, |!=|, + |**|, + \item multi-letter infix binary words |'and'|, |'or'|, |'xor'|, |'mod'| + (quotes mandatory), + \item functions |even|, |odd|, |first|, |last|, + \item\hypertarget{item:defvar}{}|\xintdefvar A3:=3.1415;| for variable definitions (non expandable, + naturally), usable in subsequent expressions; variable names may contain + letters, digits, underscores. They should not start with a digit, the + |@| is reserved, and single lowercase and uppercase Latin letters are + predefined to work as dummy variables (see next), + \item generation of comma separated lists |a..b|, |a..[d]..b|, + \item Python syntax-like list extractors |[list][n:]|, |[list][:n]|, |[list][a:b]| + and |[list][n]| (|n=0| for the number of list items), the step is always + |+1|, + \item function |reversed|, to reverse the order of list items, + \item itemwise sequence operations |a*[list]|, etc.., on both sides |a*[list]^b|, + \item dummy variables in |add| and |mul|: |add(x(x+1)(x-1), x=-10..10)|, + \item variable substitutions with |subs|: |subs(subs(add(x^2+y^2,x=1..y),y=t),t=20)|, + \item sequence generation using |seq| with a dummy variable: |seq(x^3, x=-10..10)|, + \item simple recursive sequences with |rseq|, with |@| given the last value, + |rseq(1;2@+1,i=1..10)|, + \item higher recursion with |rrseq|, |@1|, |@2|, |@3|, |@4|, and |@@(n)| + for earlier values, up to |n=K| where |K| is the number of terms of the + initial stretch |rrseq(0,1;@1+@2,i=2..100)|, + \item iteration with |iter| which is like |rrseq| but outputs only the + last |K| terms, where |K| was the number of initial terms, + \item inside |seq|, |rseq|, |rrseq|, |iter|, possibility to use |omit|, + |abort| and |break| to control termination, + \item |n++| potentially infinite index generation for |seq|, |rseq|, + |rrseq|, and |iter|, it is advised to use |abort| or |break(..)| at + some point, + \item the |add|, |mul|, |seq|, ... are nestable,% +\footnote{but |add(seq(x,x=1..t),t=1..2)| fails for the reason that |add| will + receive not a list of numbers but a list of lists.} + \item |\xintthecoords| converts a comma separated list of an even number + of items to the format as expected by the |TikZ| |coordinates| syntax, + \item completely rewritten |\xintNewExpr|, new |protect| function to handle + external macros. However not all constructs are compatible with + |\xintNewExpr|. +\end{itemize} + +% \subsection{Examples with the \texorpdfstring{\unexpanded{\unexpanded{|v1.1|}}}{v1.1} \csh{xintexpr}} + +And now some examples: + +\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, + itemindent=\leftmarginii, listparindent=\leftmarginii, leftmargin=0em] +\item One can define variables (the definition itself is a non expandable + step). The allowed names are composed of letters, digits, and underscores. + The variable should not start with a digit and single letters |a..z|, |A..Z| + are predefined for use as dummy variables --- see below. The |@| is + reserved. +\begin{everbatim*} +\begingroup + \xintdefvar a_1 := 3.14159;\xintdefvar a2 := 2.71828;\xinttheiexpr [5] a_1+a2\relax +\endgroup +\end{everbatim*} +\item |add| and |mul| have a new syntax requiring a dummy variable: +\begin{everbatim*} +\xinttheexpr add(x, x=1,3,19), mul(x^2, x=1,3,19), add(x(x+1), x= 1,3,19)\relax +\end{everbatim*} + +Use |`+`| and |`*`| (left ticks mandatory) for syntax without dummy variables: +\begin{everbatim*} +\xinttheexpr `+`(1,3,19), `*`(1^2,3^2,19^2), `+`(1*2,3*4,19*20)\relax +\end{everbatim*} +\item The |seq| function generates sequences according to a given formula: +\begin{everbatim*} +\xinttheexpr seq(x(x+1)(x+2), x=1,3,19), `+`(seq(x(x+1)(x+2), x=1,3,19)), + add(x(x+1)(x+2), x=1,3,19)\relax +\end{everbatim*} +\begin{everbatim*} +And this is nestable! +\xinttheexpr seq(seq(x^y, y=1..5),x=1..5), add(mul(x^y,y=1..5), x=1..5), + add(x^15, x=1..5)\relax % 15 = 1+2+3+4+5 +\end{everbatim*} + +One should use parentheses appropriately. The \csbxint{expr} parser in normal +operation is not bad at identifying missing or extra opening or closing +parentheses, but when it handles |seq|, |add|, |mul| or similar constructs it +switches to another mode of operation (it starts using delimited macros, +something which is almost non-existent in all its other operations) and ill-formed +expressions are much more likely to let the parser fetch tokens from beyond the +mandatory ending |\relax|. Thus, in case of a missing parenthesis in such +circumstances the error message from \TeX{} might be very cryptic, even for +the seasoned \xintname user. + +\item As seen in the last example |a..b| constructs the integers from |a| to + |b|. This is (small) integer only. A more general |a..[d]..b| works with big + integers, or fractions, from |a| to |b| with step |d|. +\begin{everbatim*} +\xinttheexpr seq(2x+1, x=1..10, 100..110, 3/5..[1/5]..7/5)\relax +\end{everbatim*} +\item itemwise operations on lists are possible, as well as item extractions: +\begin{everbatim*} +\xinttheiiexpr 2*[1,10,100]^3, 5+[2*[1,10,100]^3]*100 \relax +\end{everbatim*} +\begin{everbatim*} +\xinttheiiexpr 1+[seq(3^j, j=1..10, 21..30)][17], 1+3^27\relax +\end{everbatim*} + +We used the |[list][n]| construct which gives the nth item from the list. In +this context there are also the functions |last| and |first|. There is no real +concept of a list object, nor list operations, although itemwise manipulation +are made possible as shown above via the |[..]| constructor. The list +manipulation utilities are so far a bit limited. There is no notion of an +``nuple'' object. The variable |nil| is reserved, it represents an empty list. + +\item |subs| is similar to |seq| in syntax but is for variable substitution: +\begin{everbatim*} +\xinttheexpr subs(100*subs(10*subs(3*x+5,x=y+50)+2,y=z^2),z=10)\relax % 100(10(3*150+5)+2) +\end{everbatim*} +\begin{everbatim*} +\xinttheexpr subs(subs(add(x^2+y^2,x=1..y),y=t),t=20)\relax +\end{everbatim*} + +The substituted variable may be a comma separated list (this is impossible +with |seq| which will always pick one item after the other of a list). +\begin{everbatim*} +\xinttheexpr subs([x]^2,x=-123,17,32)\relax +\end{everbatim*} + +\item last but not least, |seq| has variants |rseq| and |rrseq| which allow + recursive definitions. They start with at least one initial value, then a + semi-colon, then the formula, then the list of indices to iterate over. |@| + (or |@1|) evaluates to the last computed item, and |rrseq| keeps the memory + of the |K| last results, where |K| was the number of initial terms. One + accesses them via |@1, @2, @3, @4| and |@@(N)| for |N>4|. It is even + possible to nest them and use |@@@| to access the values of the master + recursion... +\begin{everbatim*} +\xinttheiiexpr rseq(1; 2*@, i=1..10), `+`(rseq(1; 2*@, i=1..10))\relax +\end{everbatim*} +\begin{everbatim*} +\xinttheiiexpr rseq(2; @(@+1)/2, i=1..5)\relax +\end{everbatim*} +\begin{everbatim*} +\xinttheiiexpr rseq(0,1; (@1,add(x,x=@1)), y=2..10)\relax +\end{everbatim*} + +Some Fibonacci fun +\begin{everbatim*} +\xinttheiiexpr rrseq(0,1; @1+@2, x=2..10), last(rrseq(0,1; @1+@2, x=2..100))\relax +\end{everbatim*} +\begin{everbatim*} +Sum of previous last three: \xinttheiiexpr rrseq(0,0,1; @1+@2+@3, i=1..20)\relax +\end{everbatim*} +\begin{everbatim*} +Big numbers: \printnumber{\xinttheexpr rseq(1; @(@+1), j=1..10)\relax } +\end{everbatim*} + +Nested recursion often quickly leads to gigantic outputs. This is an +experimental feature, susceptible to be removed or altered in the future. +\begin{everbatim*} +\xinttheexpr rrseq(1; `+`(rrseq(0,1; @@@(1)+@1+@2, i=1..10)), j=1..5)\relax +\end{everbatim*} + +\item The special keywords |omit|, |abort| and |break(..)| are available + inside |seq|, |rseq|, |rrseq|, as well as the |n++| for a potentially + infinite iteration. The |n++| construct in conjunction with an |abort| or + |break| is often more efficient, because in other cases the list to iterate + over is first completely constructed. +\begin{everbatim*} +First Fibonacci number at least |2^31| and its index +\xinttheiiexpr iter(0,1; (@1>=2^31)?{break(i)}{@2+@1}, i=1++)\relax +\end{everbatim*} + +\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. First |x/:m| computes +|x modulo m| (this is the modulo with respect to truncated division, which +here for positive arguments is like Euclidean division; in +|\xintexpr...\relax|, |a/:b| is such that |a = b*(a//b)+a/:b|, with |a//b| the +algebraic quotient |a/b| truncated to an integer.). 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. + +% 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 + +\item The |iter| function is like |rrseq| but does not leave a trace of earlier items, + it starts with |K| initial values, then it iterates: either a fixed number of times, + or until aborting or breaking. And ultimately it prints |K| final values. +\begin{everbatim*} +The first Fibonacci number beyond the \TeX{} bound is +\xinttheiiexpr subs(iter(0,1;(@1>N)?{break(i)}{@1+@2},i=1++),N=2^31)\relax{} +and the previous number was its index. +\end{everbatim*}But this was a bit too easy, what is the smallest Fibonacci number not representable on 64 bits? +\begin{everbatim*} +The first Fibonacci number beyond |2^64| bound is +\xinttheiiexpr subs(iter(0,1;(@1>N)?{break(i)}{@1+@2},i=1++),N=2^64)\relax{} +and the previous number was its index. +\end{everbatim*} + +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 iter(#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*} + +Well, one more: + +\begin{everbatim*} +\newcommand\GCD [2]{\xinttheiiexpr rrseq(#1,#2; (@1=0)?{abort}{@2/:@1}, i=1++)\relax } +\GCD {13^10*17^5*29^5}{2^5*3^6*17^2} +\end{everbatim*} + +and the ultimate: + +\begin{everbatim*} +\newcommand\Factors [1]{\xinttheiiexpr + subs(seq((i/:3=2)?{omit}{[L][i]},i=1..([L][0])), + L=rseq(#1;(p^2>[@][1])?{([@][1]>1)?{break(1,[@][1],1)}{abort}} + {(([@][1])/:p)?{omit} + {iter(([@][1])//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. \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(([@][1])//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 |([@][1])/: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} + +For comparison, here is an \fexpan dable macro expanding to the same result, +but coded directly with the \xintname macros. Here |#1| can not be itself an +expression, naturally. But at least we let |\Factorize| \fexpan d its +argument. +\begin{everbatim} +\makeatletter +\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}}}% +\makeatother +\end{everbatim} + +The macro |\Factorize| puts a little stress on the input save stack in order +not be bothered with previously gathered things. I timed it to be about eight +times faster than |\Factors| in test cases such as +|16246355912554185673266068721806243461403654781833| and others. Among the +various things explaining the speed-up, there is fact that we step by +increments of two, not one, and also that we divide only once, obtaining +quotient and remainder in one go. These two things already make for a speed-up +factor of about four. Thus, our earlier |\Factors| was not completely +inefficient, and was quite easier to come up with than |\Factorize|. + +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 +\end{itemize} + +%\phantomsection +\phantomsection\label{sec:expr11coords} + +To conclude with this overview of the new features in \xintexprname |1.1|, I +will mention {\bfseries |\xintthecoords|} which converts a comma separated +list as produced by |\xintfloatexpr| or |\xintiexpr [d]| to the format +expected by the |TikZ| |coordinates| syntax. +\begin{everbatim*} +{\centering\begin{tikzpicture}[scale=10]\xintDigits:=8; + \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 into (x1, y1) (x2, y2)... format + \xintfloatexpr seq((x^2-1,mul(x-t,t=-1+[0..4]/2)),x=-1.2..[0.1]..+1.2) \relax }; +\end{tikzpicture}\par } +\end{everbatim*} + +% Notice: if x goes no take exactly value 1 or -1, the origin appears slightly +% off the curve, not MY fault!!! + +\csbxint{thecoords} should be followed immediately by \csbxint{floatexpr} or +\csbxint{iexpr} or \csbxint{iiexpr}, but not |\xintthefloatexpr|, etc\dots + +Besides, as |TikZ| will not understand the |A/B[N]| format which is used on +output by |\xintexpr|, |\xintexpr| is not really usable with |\xintthecoords| +for a |TikZ| picture, but one may use it on its own, and the reason for the +spaces in and between coordinate pairs is to allow if necessary to print on +the page for examination with about correct line-breaks. + +\begin{everbatim*} +\edef\x{\xintthecoords \xintexpr rrseq(1/2,1/3; @1+@2, x=1..20)\relax } +\meaning\x +++ +\end{everbatim*} + \subsection{\texorpdfstring{\texttt{\protect\string\numexpr}}{\textbackslash numexpr} or \texorpdfstring{\texttt{\protect\string\dimexpr}}{\textbackslash dimexpr} expressions, count and dimension registers and variables} @@ -13861,6 +14147,13 @@ $1$ or $-1$. % This is \expandafter|\xintbndlversion| of \expandafter|\xintbndldate|. % % \begin{itemize} +% \item |1.2c| of |2015/11/16| fixes another bad bug from |1.2|, this time in +% the subtraction of |xintcore.sty| (it showed in certain cases with a +% |00000001| string.) New macros \csa{xintdeffunc}, \csa{xintdefiifunc}, +% \csa{xintdeffloatfunc} and boolean \csa{ifxintverbose}. Some on-going code +% improvements and documentation enhancements, stopped in order to issue +% this bugfix release. +% % \item |1.2b| of |2015/10/29| corrects a bug introduced in recent release % |1.2| in the division macro of |xintcore.sty| (a sub-routine expecting % only eight digit numbers was called with |1+99999999|; happened with @@ -14092,7 +14385,7 @@ $1$ or $-1$. \fi \XINT_providespackage \ProvidesPackage {xintkernel}% - [2015/10/29 v1.2b Paraphernalia for the xint packages (jfB)]% + [2015/11/16 v1.2c Paraphernalia for the xint packages (jfB)]% % \end{macrocode} % \subsection{Constants} % |v1.2| decides to move them to \xintkernelnameimp from \xintcorenameimp and @@ -14312,6 +14605,15 @@ $1$ or $-1$. }% \edef\XINT_length_finish_c #1#2\Z #3% {\noexpand\expandafter\space\noexpand\the\numexpr #3+#1\relax}% +% \end{macrocode} +% \subsection{\csh{xintMessage}, \csh{ifxintverbose}} +% \lverb|1.2c added for use by \xintdefvar and \xintdeffunct of xintexpr.| +% \begin{macrocode} +\def\xintMessage #1#2#3{% + \immediate\write16{Package #1 (#2) on line \the\inputlineno :}% + \immediate\write16{\space\space\space\space#3}% +}% +\newif\ifxintverbose \XINT_restorecatcodes_endinput% % \end{macrocode} %\catcode`\<=0 \catcode`\>=11 \catcode`\*=11 \catcode`\/=11 @@ -14388,7 +14690,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xinttools}% - [2015/10/29 v1.2b Expandable and non-expandable utilities (jfB)]% + [2015/11/16 v1.2c 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.| @@ -15876,7 +16178,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintcore}% - [2015/10/29 v1.2b Expandable arithmetic on big integers (jfB)]% + [2015/11/16 v1.2c Expandable arithmetic on big integers (jfB)]% % \end{macrocode} % \subsection{Counts for holding needed constants} % \begin{macrocode} @@ -16029,6 +16331,29 @@ $1$ or $-1$. \edef\XINT_sepandrev_andcount_done #1.#21#3!% {\noexpand\expandafter\space\noexpand\the\numexpr #1-#3.}% % \end{macrocode} +% \lverb|Needed ending pattern: 1\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W. The +% \romannumeral in unrevbyviii_a is for special effects. I must document when +% needed and used.| +% \begin{macrocode} +\def\XINT_unrevbyviii #11#2!1#3!1#4!1#5!1#6!1#7!1#8!1#9!% +{% + \xint_gob_til_R #9\XINT_unrevbyviii_a\R + \XINT_unrevbyviii {#9#8#7#6#5#4#3#2#1}% +}% +\edef\XINT_unrevbyviii_a\R\XINT_unrevbyviii #1#2\W + {\noexpand\expandafter\space + \noexpand\romannumeral`&&@\noexpand\xint_gob_til_Z #1}% +% \end{macrocode} +% \lverb|Can work with ending pattern: 1\Z!1\R!1\R!1\R!1\R!1\R!1\R!\W but the +% longer one of unrevbyviii is ok here too. Used currently (1.2) only by +% addition, now (1.2c) with long ending pattern. Does the final clean up of +% leading zeroes contrarily to general \XINT_unrevbyviii.| +% \begin{macrocode} +\def\XINT_smallunrevbyviii 1#1!1#2!1#3!1#4!1#5!1#6!1#7!1#8!#9\W% +{% + \expandafter\XINT_cuz_small\xint_gob_til_Z #8#7#6#5#4#3#2#1% +}% +% \end{macrocode} % \subsection{Blocks of eight, for needs of v1.2 \csh{xintiiDivision}.} % \begin{macrocode} \def\XINT_sepbyviii_andcount @@ -16100,19 +16425,6 @@ $1$ or $-1$. }% \def\XINT_div_unsepR_end\R\XINT_div_unsepR #1{\XINT_div_unsepR_done #1}% \def\XINT_div_unsepR_done #1\R #2\W {\XINT_cuz #1\R}% -%%%%%%%%%%%% -\def\XINT_unrevbyviii #11#2!1#3!1#4!1#5!1#6!1#7!1#8!1#9!% -{% - \xint_gob_til_R #9\XINT_unrevbyviii_a\R - \XINT_unrevbyviii {#9#8#7#6#5#4#3#2#1}% -}% -\edef\XINT_unrevbyviii_a\R\XINT_unrevbyviii #1#2\W - {\noexpand\expandafter\space - \noexpand\romannumeral`&&@\noexpand\xint_gob_til_Z #1}% -\def\XINT_smallunrevbyviii 1#1!1#2!1#3!1#4!1#5!1#6!1#7!1#8!#9\W% -{% - \expandafter\XINT_cuz_small\xint_gob_til_Z #8#7#6#5#4#3#2#1% -}% % \end{macrocode} % \subsection{\csh{xintReverseDigits}} % \lverb|v1.2. Needed now by \xintLDg.| @@ -16399,9 +16711,9 @@ $1$ or $-1$. #1\XINT_rsepbyviii_end_A 2345678% \XINT_rsepbyviii_end_B 2345678\relax XX% \R.\R.\R.\R.\R.\R.\R.\R.\W - \Z!\Z!\Z!\Z!\Z!\W + \Z!\Z!\Z!\Z!\W }% -\def\XINT_dec_pos_aa {\XINT_sub_aa 100000001!\Z!\Z!\Z!\Z!\Z!\W }% +\def\XINT_dec_pos_aa {\XINT_sub_aa 100000001!\Z!\Z!\Z!\Z!\W }% % \end{macrocode} % \subsection{\csh{xintInc}} % \lverb!v1.08. Rewritten for v1.2.! @@ -16421,6 +16733,9 @@ $1$ or $-1$. }% \def\XINT_inc_zero #1\Z { 1}% \def\XINT_inc_neg {\expandafter\XINT_opp\romannumeral0\XINT_dec_pos }% +% \end{macrocode} +% \lverb|1.2c interface to addition has changed.| +% \begin{macrocode} \def\XINT_inc_pos #1\Z {% \expandafter\XINT_inc_pos_aa @@ -16429,9 +16744,10 @@ $1$ or $-1$. #1\XINT_rsepbyviii_end_A 2345678% \XINT_rsepbyviii_end_B 2345678\relax XX% \R.\R.\R.\R.\R.\R.\R.\R.\W - \Z!\Z!\Z!\Z!\Z!\W + 1\Z!1\Z!1\Z!1\Z!1\Z!\W + 1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% -\def\XINT_inc_pos_aa {\XINT_add_aa 100000001!\Z!\Z!\Z!\Z!\Z!\W }% +\def\XINT_inc_pos_aa {\XINT_add_aa 100000001!1\Z!1\Z!1\Z!1\Z!\W }% % \end{macrocode} % \subsection{Core arithmetic} % \lverb|The four operations have been rewritten entirely for release v1.2. @@ -16497,6 +16813,35 @@ $1$ or $-1$. \X #1% }% \let\XINT_add_plusplus \XINT_add_pp_a +% \end{macrocode} +% \lverb|I have been annoyed since the preparation of 1.2 release that +% addition sometimes had the (pre-reverse) output with a final 1! (now 1\Z!) +% sometimes not. It didn' matter for addition itself if it executes the final +% reverse as the 1! was then be swallowed. But if one wants to call addition +% repeatedly or from another routine such as \XINT_mul_loop, keeping reverse +% format, this is annoying. Finally for 1.2c I decide (2015/11/14) to impose +% always the ending 1! (or rather 1\Z!, which thus does not need to be put in +% the pattern for _unrevbyviii). I take this opportunity to move the ending +% pattern needed by \XINT_add_out to \XINT_add_pp_b, thus replacing a final +% fetch of the complete output to clean up the \Z's and \W at the end of the +% input. This was also needed to make \XINT_mul_loop callable directly +% independently of whether the first argument is only one 10^8 digit long. +% +% Impacted callers: \XINT_mul_loop (and through it square and pow) and +% \XINT_inc_pos_ the latter must insert the pattern previously found in +% \XINT_add_out as it calls \XINT_add_aa directly. +% +% I also modify addition to use 1\Z!1\Z!1\Z!1\Z!\W as input delimiter (earlier +% version had \Z!\Z!\Z!\Z!\Z!\W but four are enough and we now have 1's). The +% rationale is that multiplication and now addition always set the output +% (before reversal) to be followed by 1\Z!, thus it makes sense for 1\Z! to +% also serve as (part of) delimiting inputs. Earlier, addition had \Z! for +% input, but this can not be put on output by a \numexpr, hence it used 1! on +% output, but this is not a good delimiter as the 1! may and will arise in +% number part, thus one had to use !1! or 1!\W etc... to use it. With 1\Z ! +% things are more unified and facilitate doing repeated additions and +% multiplications maintaining things reversed.| +% \begin{macrocode} \def\XINT_add_pp_b #1.#2\X #3\Z {% \expandafter\XINT_add_checklengths @@ -16507,8 +16852,13 @@ $1$ or $-1$. \XINT_rsepbyviii_end_B 2345678\relax\xint_c_ii\xint_c_iii \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W - \Z!\Z!\Z!\Z!\Z!\W #2\Z!\Z!\Z!\Z!\Z!\W + 1\Z!1\Z!1\Z!1\Z!\W #21\Z!1\Z!1\Z!1\Z!\W + 1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% +% \end{macrocode} +% \lverb|I keep #1.#2. to check if at most 6 + 6 base 10^8 digits which can be +% treated faster for final reverse. But is this overhead at all useful ? | +% \begin{macrocode} \def\XINT_add_checklengths #1.#2.% {% \ifnum #2>#1 @@ -16518,43 +16868,37 @@ $1$ or $-1$. \fi #1.#2.% }% -\def\XINT_add_exchange #1.#2.#3\Z!\Z!\Z!\Z!\Z!\W #4\Z +\def\XINT_add_exchange #1.#2.#3\W #4\W {% - \XINT_add_A #2.#1.#4\Z!\Z!\Z!\Z!\Z!\W #3\Z + \XINT_add_A #2.#1.#4\W #3\W }% \def\XINT_add_A #1.#2.% {% - \ifnum #1>\xint_c_vi % + \ifnum #1>\xint_c_vi \expandafter\XINT_add_aa \else \expandafter\XINT_add_aa_small \fi }% -%%%%%%%%%%%% -\def\XINT_add_out #1\Z #2\W% -{% - \expandafter\XINT_cuz_small\romannumeral0\XINT_unrevbyviii {}% - #11\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W -}% -\def\XINT_add_out_small #1\Z #2\W% -{% - \XINT_smallunrevbyviii #11\Z!1\R!1\R!1\R!1\R!1\R!1\R!\W -}% -%%%%%%%%%%%% \def\XINT_add_aa {\expandafter\XINT_add_out\the\numexpr\XINT_add_a \xint_c_ii}% +\def\XINT_add_out{\expandafter\XINT_cuz_small\romannumeral0\XINT_unrevbyviii {}}% \def\XINT_add_aa_small - {\expandafter\XINT_add_out_small\the\numexpr\XINT_add_a \xint_c_ii}% + {\expandafter\XINT_smallunrevbyviii\the\numexpr\XINT_add_a \xint_c_ii}% +% \end{macrocode} +% \lverb|2 as first token of #1 stands for "no carry", 3 will mean a carry (we are adding +% 1<8digits> to 1<8digits>.) Version 1.2c has terminators of the shape 1\Z!, +% replacing the \Z! used in 1.2.| +% \begin{macrocode} \def\XINT_add_a #1!#2!#3!#4!#5\W #6!#7!#8!#9!% {% \XINT_add_b #1!#6!#2!#7!#3!#8!#4!#9!#5\W }% -\def\XINT_add_b #1#2!#3!% +\def\XINT_add_b #11#2#3!#4!% {% \xint_gob_til_Z #2\XINT_add_bi \Z - \expandafter\XINT_add_c\the\numexpr#1+#2+#3-\xint_c_ii.% + \expandafter\XINT_add_c\the\numexpr#1+1#2#3+#4-\xint_c_ii.% }% -\def\XINT_add_bi\Z - \expandafter\XINT_add_c - \the\numexpr#1+#2+#3-\xint_c_ii.#4!#5!#6!#7!#8!#9!\Z !\W +\def\XINT_add_bi\Z\expandafter\XINT_add_c + \the\numexpr#1+#2+#3-\xint_c_ii.#4!#5!#6!#7!#8!#9!\W {% \XINT_add_k #1#3!#5!#7!#9!% }% @@ -16562,10 +16906,10 @@ $1$ or $-1$. {% 1#2\expandafter!\the\numexpr\XINT_add_d #1% }% -\def\XINT_add_d #1#2!#3!% +\def\XINT_add_d #11#2#3!#4!% {% \xint_gob_til_Z #2\XINT_add_di \Z - \expandafter\XINT_add_e\the\numexpr#1+#2+#3-\xint_c_ii.% + \expandafter\XINT_add_e\the\numexpr#1+1#2#3+#4-\xint_c_ii.% }% \def\XINT_add_di\Z\expandafter\XINT_add_e \the\numexpr#1+#2+#3-\xint_c_ii.#4!#5!#6!#7!#8\W @@ -16576,10 +16920,10 @@ $1$ or $-1$. {% 1#2\expandafter!\the\numexpr\XINT_add_f #1% }% -\def\XINT_add_f #1#2!#3!% +\def\XINT_add_f #11#2#3!#4!% {% \xint_gob_til_Z #2\XINT_add_fi \Z - \expandafter\XINT_add_g\the\numexpr#1+#2+#3-\xint_c_ii.% + \expandafter\XINT_add_g\the\numexpr#1+1#2#3+#4-\xint_c_ii.% }% \def\XINT_add_fi\Z\expandafter\XINT_add_g \the\numexpr#1+#2+#3-\xint_c_ii.#4!#5!#6\W @@ -16590,10 +16934,10 @@ $1$ or $-1$. {% 1#2\expandafter!\the\numexpr\XINT_add_h #1% }% -\def\XINT_add_h #1#2!#3!% +\def\XINT_add_h #11#2#3!#4!% {% \xint_gob_til_Z #2\XINT_add_hi \Z - \expandafter\XINT_add_i\the\numexpr#1+#2+#3-\xint_c_ii.% + \expandafter\XINT_add_i\the\numexpr#1+1#2#3+#4-\xint_c_ii.% }% \def\XINT_add_hi\Z \expandafter\XINT_add_i\the\numexpr#1+#2+#3-\xint_c_ii.#4\W @@ -16604,29 +16948,29 @@ $1$ or $-1$. {% 1#2\expandafter!\the\numexpr\XINT_add_a #1% }% -%%%%%%%%%%%% -\def\XINT_add_k #1% - {\if #12\expandafter\XINT_add_ke\else\expandafter\XINT_add_l \fi}% -\def\XINT_add_ke #1% -{% - \xint_gob_til_Z #1\XINT_add_kf\Z 1% -}% -\def\XINT_add_kf\Z 1{1}% -\def\XINT_add_l #1% -{% - \xint_gob_til_Z #1\XINT_add_lf\Z \XINT_add_m 1% -}% -\def\XINT_add_lf\Z\XINT_add_m 1{100000001}% -\def\XINT_add_m #1!% -{% - \expandafter\XINT_add_n\the\numexpr\xint_c_i+#1.% -}% -\def\XINT_add_n #1#2.% -{% - 1#2\expandafter!\the\numexpr\XINT_add_o #1% -}% -\def\XINT_add_o #1% - {\if #12\expandafter\XINT_add_l\else\expandafter\XINT_add_ke \fi}% +% \end{macrocode} +% \lverb|These ending routines modified in 1.2c in order to clean up here (and +% not via \XINT_add_out) the tokens up to the final \W, and to always have a +% final 1\Z! (1.2 version had a final 1! not 1\Z!, and only under certain +% circumstances): when the two operands have the same length and the addition +% creates no carry or more generally when we had a carry propagating to the +% last block but the final addition created no carry, we end up in +% \XINT_add_ke with an empty #1 and a \numexpr to stop. This is why we put +% 1\Z! (1.2 had 1!, but 1\Z! is also used by multiplication on output) +% in that case, and now with 1.2c for all other cases as well.| +% \begin{macrocode} +\def\XINT_add_k #1{\if #12\expandafter\XINT_add_ke\else\expandafter\XINT_add_l \fi}% +\def\XINT_add_ke #11\Z #2\W {\XINT_add_kf #11\Z!}% +\def\XINT_add_kf 1{1\relax }% +\def\XINT_add_l 1#1#2{\xint_gob_til_Z #1\XINT_add_lf \Z \XINT_add_m 1#1#2}% +\def\XINT_add_lf #1\W {1\relax 00000001!1\Z!}% +\def\XINT_add_m #1!{\expandafter\XINT_add_n\the\numexpr\xint_c_i+#1.}% +\def\XINT_add_n #1#2.{1#2\expandafter!\the\numexpr\XINT_add_o #1}% +% \end{macrocode} +% \lverb|Here 2 stands for "carry", and 1 for "no carry" (we have been adding +% 1 to 1<8digits>.)| +% \begin{macrocode} +\def\XINT_add_o #1{\if #12\expandafter\XINT_add_l\else\expandafter\XINT_add_ke \fi}% % \end{macrocode} % \subsection{\csh{xintiSub}, \csh{xintiiSub}} % \lverb|Entirely rewritten for v1.2.| @@ -16686,7 +17030,7 @@ $1$ or $-1$. \XINT_rsepbyviii_end_B 2345678\relax \xint_c_ii\xint_c_iii \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W - \Z!\Z!\Z!\Z!\Z!\W #2\Z!\Z!\Z!\Z!\Z!\W + \Z!\Z!\Z!\Z!\W #2\Z!\Z!\Z!\Z!\W }% \def\XINT_sub_checklengths #1.#2.% {% @@ -16696,15 +17040,10 @@ $1$ or $-1$. \expandafter\XINT_sub_aa \fi }% -\def\XINT_sub_exchange #1\Z!\Z!\Z!\Z!\Z!\W #2\Z +\def\XINT_sub_exchange #1\W #2\W {% - \expandafter\XINT_opp\romannumeral0\XINT_sub_aa - #2\Z!\Z!\Z!\Z!\Z!\W #1\Z + \expandafter\XINT_opp\romannumeral0\XINT_sub_aa #2\W #1\W }% -%%%%%%%%%%%% -\def\XINT_sub_prepare_rescue #1\W {\relax\Z-\W}% -\def\XINT_sub_prepare_cuz #1\W {\relax\XINT_cuz_byviii!\Z 0\W\R}% -%%%%%%%%%%%% \def\XINT_sub_aa {\expandafter\XINT_sub_out\the\numexpr\XINT_sub_a \xint_c_i }% \def\XINT_sub_out #1\Z #2#3\W {% @@ -16712,31 +17051,10 @@ $1$ or $-1$. \expandafter\XINT_cuz_small \romannumeral0\XINT_unrevbyviii {}#11\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% -\def\XINT_sub_startrescue\expandafter\XINT_cuz_small - \romannumeral0\XINT_unrevbyviii #1#2\Z!#3\W -{% - \expandafter\XINT_sub_rescue_finish - \the\numexpr\XINT_sub_rescue_a #2!% - 1\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W \R -}% -\def\XINT_sub_rescue_finish - {\expandafter-\romannumeral0\expandafter\XINT_cuz - \romannumeral0\XINT_unrevbyviii {}}% -\def\XINT_sub_rescue_a #1!% -{% - \expandafter\XINT_sub_rescue_c\the\numexpr \xint_c_xii_e_viii-#1.% -}% -\def\XINT_sub_rescue_c 1#1#2.% -{% - 1#2\expandafter!\the\numexpr\XINT_sub_rescue_d #1% -}% -\def\XINT_sub_rescue_d #1#2#3!% -{% - \xint_gob_til_minus #2\XINT_sub_rescue_z -% - \expandafter\XINT_sub_rescue_c\the\numexpr \xint_c_xii_e_viii_mone-#2#3+#1.% -}% -\def\XINT_sub_rescue_z #1.{1!}% -%%%%%%%%%%%% +% \end{macrocode} +% \lverb|The routine starting with \XINT_sub_a requires the first argument to +% be at most as long as second argument.| +% \begin{macrocode} \def\XINT_sub_a #1!#2!#3!#4!#5\W #6!#7!#8!#9!% {% \XINT_sub_b #1!#6!#2!#7!#3!#8!#4!#9!#5\W @@ -16778,7 +17096,7 @@ $1$ or $-1$. 1#2\expandafter!\the\numexpr\XINT_sub_a #1% }% \def\XINT_sub_bi\Z - \expandafter\XINT_sub_c\the\numexpr#1+1#2-#3.#4!#5!#6!#7!#8!#9!\Z !\W + \expandafter\XINT_sub_c\the\numexpr#1+1#2-#3.#4!#5!#6!#7!#8!#9!\W {% \XINT_sub_k #1#2!#5!#7!#9!% }% @@ -16797,43 +17115,84 @@ $1$ or $-1$. {% \XINT_sub_k #1#2!% }% -%%%%%%%%%%%% +% \end{macrocode} +% \lverb|First input terminated. Have we reached the end of second +% (necessarily at least as long) input? If not, then we are certain that even +% if there is carry it will not propagate beyond the end of second input. But +% it may propagate along chains of 00000000. And if its goes to the final +% block which is just 1<00000001>!, we will have at least those eight zeros to +% clean up. But not more than those eight followed by the leading zeroes of +% next to last block (which will be leading block of final output). On the +% other hand if we have also reached the end of the second input, then if +% first input was smaller there might be arbitrarily many zeroes to clean up, +% if it was larger, we will have to rescue the whole thing.| +% \begin{macrocode} \def\XINT_sub_k #1#2% {% \xint_gob_til_Z #2\XINT_sub_p\Z \XINT_sub_l #1#2% }% -\def\XINT_sub_l #1% -{% - \xint_UDzerofork - #1\XINT_sub_m - 0{}% - \krof -}% -\def\XINT_sub_m #1!% +% \end{macrocode} +% \lverb|Here second input was longer. The carry if there is one will be +% extinguished before the end. 1.2c wants subtraction to output before final +% reversal the blocks with the same 1\Z! terminator as addition and +% multiplication. CANCELED FOR THE TIME BEING. +% +% 2015/11/15. I discover with shame that Release 1.2 of 10/10 had a bad bad +% bad bad bug in case of long stretches of zeroes, for example with +% \xintiiSub {10000000112345678}{12345679} which returned 99999999 .... sorry. +% +% I was rewriting inner entry to subtraction to look a bit more for +% input/output as addition and multiplication but I will now rather quickly +% leave everything standing and issue a bugfix release asap.| +% \begin{macrocode} +\def\XINT_sub_l #1{\xint_UDzerofork #1\XINT_sub_l_carry 0\XINT_sub_l_nocarry\krof}% +\def\XINT_sub_l_nocarry 1{1\relax }% +\def\XINT_sub_l_carry #1!{\expandafter\XINT_sub_m\the\numexpr 1#1-\xint_c_i!}% +\def\XINT_sub_m 1#1{\xint_UDzerofork #1\XINT_sub_n_carry 0\XINT_sub_n_nocarry\krof}% +\def\XINT_sub_n_carry #1!{1#1\expandafter!\the\numexpr\XINT_sub_l_carry }% +\def\XINT_sub_n_nocarry #1!#2#3!% {% - \expandafter\XINT_sub_n\the\numexpr 1#1-\xint_c_i!% + \xint_gob_til_Z #2\xint_gob_til_eightzeroes #1\XINT_sub_n_zero + 00000000\xint_gob_til_Z\Z 1\relax #1!#2#3!% }% -\def\XINT_sub_n 1#1% +\def\XINT_sub_n_zero 00000000\xint_gob_til_Z\Z 1\relax 00000000!{1!}% +% \end{macrocode} +% \lverb|Here we are in the situation were the two inputs had the same length +% in base 10^8. If #1=0 we bitterly discover that first input was greater than +% second input despite having same length (in base 10^8). The \numexpr will +% expand beyond the -1 or 1. If #1=1 we had no carry but perhaps the result +% will have plenty of zeroes to clean-up. The result might even be simply zero.| +% \begin{macrocode} +\def\XINT_sub_p\Z\XINT_sub_l #1#2\W {% \xint_UDzerofork - #1{\XINT_sub_o}% - 0{\XINT_sub_n_checkzero}% + #1{-1\relax\Z -\W}% + 0{1\relax \XINT_cuz_byviii!\Z 0\W\R }% \krof }% -\def\XINT_sub_o #1!{1#1\expandafter!\the\numexpr\XINT_sub_m }% -\def\XINT_sub_n_checkzero #1!% +\def\XINT_sub_startrescue\expandafter\XINT_cuz_small + \romannumeral0\XINT_unrevbyviii #1#2\Z!#3\W {% - \xint_gob_til_eightzeroes #1\XINT_sub_n_prepare_cuz 00000000% - 1#1!% + \expandafter\XINT_sub_rescue_finish + \the\numexpr\XINT_sub_rescue_a #2!% + 1\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W \R }% -\def\XINT_sub_n_prepare_cuz 00000000100000000{1\XINT_sub_prepare_cuz}% -\def\XINT_sub_p\Z\XINT_sub_l #1\Z!% +\def\XINT_sub_rescue_finish + {\expandafter-\romannumeral0\expandafter\XINT_cuz\romannumeral0\XINT_unrevbyviii {}}% +\def\XINT_sub_rescue_a #1!% {% - \xint_UDzerofork - #1{-1\XINT_sub_prepare_rescue}% - 0{1\XINT_sub_prepare_cuz }% - \krof + \expandafter\XINT_sub_rescue_c\the\numexpr \xint_c_xii_e_viii-#1.% +}% +\def\XINT_sub_rescue_c 1#1#2.% +{% + 1#2\expandafter!\the\numexpr\XINT_sub_rescue_d #1% +}% +\def\XINT_sub_rescue_d #1#2#3!% +{% + \xint_gob_til_minus #2\XINT_sub_rescue_z -% + \expandafter\XINT_sub_rescue_c\the\numexpr \xint_c_xii_e_viii_mone-#2#3+#1.% }% +\def\XINT_sub_rescue_z #1.{1!}% % \end{macrocode} % \subsection{\csh{xintiMul}, \csh{xintiiMul}} % \lverb|Completely rewritten for v1.2.| @@ -16905,7 +17264,7 @@ $1$ or $-1$. 1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% % \end{macrocode} -% \lverb|Cooking recipee, 2015/10/05.| +% \lverb|Cooking recipe, 2015/10/05.| % \begin{macrocode} \def\XINT_mul_checklengths #1.#2.% {% @@ -16940,31 +17299,60 @@ $1$ or $-1$. {\expandafter\XINT_mul_out\the\numexpr\XINT_verysmallmul 0.#1!}% \def\XINT_mul_exchange #1\XINT_mul_start #2\W #31\Z!% {\fi\fi\XINT_mul_start #31\Z!\W #2}% +% \end{macrocode} +% \lverb|1.2c: earlier version of addition had sometimes a final 1!, but not +% in all cases. Version 1.2c of \XINT_add_a always has an ending 1\Z!, which +% is thus expected by \XINT_mul_loop.| +% \begin{macrocode} \def\XINT_mul_start - {\expandafter\XINT_mul_out\the\numexpr\XINT_mul_loop 100000000!\Z\W}% + {\expandafter\XINT_mul_out\the\numexpr\XINT_mul_loop 100000000!1\Z!\W}% \def\XINT_mul_out {\expandafter\XINT_cuz_small\romannumeral0\XINT_unrevbyviii {}}% -\def\XINT_mul_loop #1\Z #2\W #3\W 1#4!% +% \end{macrocode} +% \lverb|The 1.2 \XINT_mul_loop could *not* be called directly with a small +% multiplicand, due to problems caused in case the addition done in +% \XINT_mul_a produced only 1 block the second one being either empty or a 1! +% which had to be handled by \XINT_mul_loop and \XINT_mul_e. But +% \XINT_mul_loop was only called via \xintiiMul for arguments with at least 2 +% digits in base 10^8, thus no problem. But this made it annoying for +% \xintiiPow and \xintiiSqr which had to check if the intended multiplier had +% only 1 digit in base 10^8. It also made it annoying to create recursive +% algorithms which did multiplications maintaining the result reverses, for +% iterative use of output as input. +% +% Finally on 2015/11/14 during 1.2c preparation I modified the addition to +% *always* have the ending 1\Z!.\numexpr expands even through spaces to find +% operators and even something like 1<space>\Z will try to expand the \Z. Thus +% we have to not forget that #2 in \XINT_mul_e might be \Z! (a #2=1\Z! in +% \XINT_mul_a hence \XINT_add_a is no problem). Again this can only happen if +% we use \XINT_mul_loop directly with a small first argument (in place of +% smallmul). Anyway, now the routine \XINT_mul_loop can handle a small #2, +% with no black magic with delimiters and checking if #1 empty, although it +% never happens when called via \xintiiMul. +% +% The delimiting patterns for addition was changed to use 1\Z! to fit what is +% used on output (by necessity).| +% \begin{macrocode} +\def\XINT_mul_loop #1\W #2\W 1#3!% {% - \xint_gob_til_Z #4\XINT_mul_e \Z - \expandafter\XINT_mul_a\the\numexpr \XINT_smallmul 1#4!#3\W - #11!\W #3\W + \xint_gob_til_Z #3\XINT_mul_e \Z + \expandafter\XINT_mul_a\the\numexpr \XINT_smallmul 1#3!#2\W + #1\W #2\W }% -\def\XINT_mul_a #11\Z!\W #2!1!#3\W +% \end{macrocode} +% \lverb|Each of #1 and #2 brings its 1\Z! for \XINT_add_a.| +% \begin{macrocode} +\def\XINT_mul_a #1\W #2\W {% \expandafter\XINT_mul_b\the\numexpr - \XINT_add_a \xint_c_ii #2!\Z!\Z!\Z!\Z!\Z!\W #1\Z!\Z!\Z!\Z!\Z!\W + \XINT_add_a \xint_c_ii #21\Z!1\Z!1\Z!\W #11\Z!1\Z!1\Z!\W\W }% \def\XINT_mul_b 1#1!{1#1\expandafter!\the\numexpr\XINT_mul_loop }% -\def\XINT_mul_e\Z #1\W #2!1!#3\W #4\W {#2!1\Z!}% -% \end{macrocode} -% \lverb|1.2 small and mini multiplication in base 10^8 with carry. On output -% the small multiplication suppresses ending zeroes. The situation is -% different with addition which may end up inserting a final 1!, thus -% multiplication is « cleaner » in that aspect. Used by the main -% multiplication routines. But division, float factorial, etc.. have their -% own variants as they need output with specific constraints. -% | +\def\XINT_mul_e\Z #1\W 1#2\W #3\W {1\relax #2}% +% \end{macrocode} +% \lverb|1.2 small and mini multiplication in base 10^8 with carry. Used by +% the main multiplication routines. But division, float factorial, etc.. have +% their own variants as they need output with specific constraints.| % \begin{macrocode} \def\XINT_minimulwc_a 1#1.#2.#3!#4#5#6#7#8.% {% @@ -17018,7 +17406,8 @@ $1$ or $-1$. \def\XINT_verysmallmul_bi\the\numexpr\xint_c_x^ix+#1#2#3.% {1#3\expandafter!\the\numexpr\XINT_verysmallmul #1#2.}% % \end{macrocode} -% \lverb|Used by division and by squaring, not by multiplication itself.| +% \lverb|Used by division and by squaring, not by multiplication itself. +% Attention, returns least significant 1<8digits> first.| % \begin{macrocode} \def\XINT_minimul_a #1.#2!#3#4#5#6#7!% {% @@ -17059,6 +17448,11 @@ $1$ or $-1$. \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W \Z }% +% \end{macrocode} +% \lverb|1.2c \XINT_mul_loop can be called directly even with small arguments, +% thus the following is not anymore a necessity. The 1!\R in \XINT_sqr_start +% is to obey the new calling pattern of \XINT_mul_loop.| +% \begin{macrocode} \def\XINT_sqr_a #1.% {% \ifnum #1=\xint_c_i \expandafter\XINT_sqr_small @@ -17080,7 +17474,7 @@ $1$ or $-1$. \def\XINT_sqr_start #1\Z {% \expandafter\XINT_mul_out - \the\numexpr\XINT_mul_loop 100000000!\Z\W #11\Z!\W #11\Z!% + \the\numexpr\XINT_mul_loop 100000000!1\Z!\W #11\Z!\W #11\Z!% 1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% % \end{macrocode} @@ -17172,19 +17566,9 @@ $1$ or $-1$. {\noexpand\xintError:FractionRoundedToZero\space 0}% \def\XINT_pow_BisZero #1#2{ 1}% % \end{macrocode} -% \lverb|B = #1 > 0, A = #2 > 1.| -% \begin{macrocode} -% \def\XINT_pow_checkBsize #1% -% {% -% \ifnum #1>131000 -% \expandafter\XINT_pow_BtooBig -% \else -% \expandafter\XINT_pow_I_in -% \fi -% {#1}% -% }% -% \edef\XINT_pow_BtooBig #1#2{\noexpand\xintError:ExponentTooBig\space 0}% -%%%%%%%%%%%% +% \lverb|B = #1 > 0, A = #2 > 1. Earlier code checked if size of B did not +% exceed a given limit (for example 131000).| +% \begin{macrocode} \def\XINT_pow_I_in #1#2% {% \expandafter\XINT_pow_I_loop @@ -17206,23 +17590,28 @@ $1$ or $-1$. \fi #1.% }% \def\XINT_pow_I_exit \ifodd #1\fi #2.#3\W {\XINT_mul_out #3}% +% \end{macrocode} +% \lverb|The 1.2c \XINT_mul_loop can be called directly even with small +% arguments, hence the "butcheckifsmall" is not a necessity as it was earlier +% with 1.2. On 2^30, it does bring roughly a 40$char37 $space time gain +% though, and 30$char37 $space gain for 2^60. The overhead on big computations +% should be negligible.| +% \begin{macrocode} \def\XINT_pow_I_squareit #1.#2\W% {% \expandafter\XINT_pow_I_loop \the\numexpr #1/\xint_c_ii\expandafter.% \the\numexpr\XINT_pow_mulbutcheckifsmall #2\W #2\W }% -%%%%%%%%%%%% \def\XINT_pow_mulbutcheckifsmall #1!1#2% {% \xint_gob_til_Z #2\XINT_pow_mul_small\Z - \XINT_mul_loop 100000000!\Z\W #1!1#2% + \XINT_mul_loop 100000000!1\Z!\W #1!1#2% }% -\def\XINT_pow_mul_small\Z\XINT_mul_loop 100000000!\Z\W 1#1!1\Z!\W +\def\XINT_pow_mul_small\Z \XINT_mul_loop 100000000!1\Z!\W 1#1!1\Z!\W {% \XINT_smallmul 1#1!% }% -%%%%%%%%%%%% \def\XINT_pow_II_in #1.#2\W {% \expandafter\XINT_pow_II_loop @@ -17264,14 +17653,42 @@ $1$ or $-1$. % \end{macrocode} % \subsection{\csh{xintiFac}, \csh{xintiiFac}} % \lverb|Moved to xintcore.sty with release 1.2 (to be usable by \bnumexpr). -% The routine has been partially rewritten and there is an intrinsic limit at -% 9999. Anyhow with current default settings of the etex memory and the -% current 1.2 routine (last commit: eada1b1), the maximal possible computation -% is 5971! (which has 19956 digits). Also, I add \xintiiFac which does only -% \romannumeral-`0 and not \numexpr on its argument. This is for a silly -% slight optimization of the \xintiiexpr (and \bnumexpr) parsers. If the -% argument is >=2^31 an arithmetic overflow will occur in the \ifnum. This is -% not as good as in the \numexpr, but well.| +% +% The routine has been partially rewritten with release 1.2 to exploit the new +% inner structure of multiplication. I impose an intrinsic limit of the +% argument at maximal value 9999. Anyhow with current default settings of the +% etex memory and the current 1.2 routine (last commit: eada1b1), the maximal +% possible computation is 5971! (which has 19956 digits). Also, I add +% \xintiiFac which does only \romannumeral-`0 and not \numexpr on its +% argument. This is for a silly slight optimization of the \xintiiexpr (and +% \bnumexpr) parsers. If the argument is >=2^31 an arithmetic overflow will +% occur in the \ifnum. This is not as good as in the \numexpr, but well. +% +% 2015/11/14 added note on the implementation: we can roughly estimate for big +% n that we do n/2 "small" multiplications of numbers of size k log(k) with k +% along a step 2 arithmetic sequence up to n. Each small multiplication should +% have a linear cost O(k log(k)) (as we maintain the reversed representation) +% hence a total cost of O(n^2 log(n)); and this seems to be confirmed +% experimentally, or rather on computing n! for n=100, 200, ..., 2000 I +% obtained a good fit (only roughly 20$char37 $space variation) of the +% computation time with the square of the length of n! -- to the extent the +% big variability of \pdfelapsedtime allows to draw any conclusion -- I did +% not repeat the computations at least 100 times as I should have. With an +% approach based on binary splitting n!=AB and A=[n/2]! each of A and B will +% be of size n/2 log(n), but xint schoolbook multiplication in TeX is worse +% than quadratic due to penalty when TeX needs to fetch arguments and it +% didn't seem promising. I didn't even test. Binary splitting is good when a +% fast multiplication is available. +% +% No wait! incredibly a very naive five lines of code implementation of binary +% splitting approach with recursive uses of \xintiiMul is only about 1.6x--2x +% slower in the range N=200 to 2000 ! this seems to say that the reversing +% done by \xintiiMul both on input and for output is quite efficient. The best +% case seems to be around N=1000, hence multiplication of 500 digits numbers, +% after that the impact of over-quadratic computation time seems to show: for +% N=4000, the naive binary splitting approach is about 3.4x slower than the +% naive iterated small multiplications as here (naturally with sub-quadratic +% multiplication that would be otherwise).| % \begin{macrocode} \def\xintiFac {\romannumeral0\xintifac }% \def\xintifac #1% @@ -18242,28 +18659,32 @@ $1$ or $-1$. \romannumeral0\XINT_zeroes_forviii #1\R\R\R\R\R\R\R\R{10}0000001\W #1\XINT_rsepbyviii_end_A 2345678\XINT_rsepbyviii_end_B 2345678\relax XX% \R.\R.\R.\R.\R.\R.\R.\R.\W - \Z!\Z!\Z!\Z!\Z!\W + 1\Z!1\Z!1\Z!1\Z!\W\R }% -\def\XINT_iidivround_pos_b 1#1#2#3#4#5#6#7#8!#9% +\def\XINT_iidivround_pos_b 1#1#2#3#4#5#6#7#8!1#9% {% \xint_gob_til_Z #9\XINT_iidivround_small\Z \ifnum #8>\xint_c_iv \expandafter\XINT_iidivround_pos_up \else \expandafter\XINT_iidivround_pos_finish \fi - 1#1#2#3#4#5#6#70!#9% + 1#1#2#3#4#5#6#70!1#9% }% +% \end{macrocode} +% \lverb|1.2c interface to addition has changed. Will have to come back here +% for improvements.| +% \begin{macrocode} \def\XINT_iidivround_pos_up {% \expandafter\XINT_iidivround_pos_finish - \the\numexpr\XINT_add_a\xint_c_ii 100000010!\Z!\Z!\Z!\Z!\Z!\W + \the\numexpr\XINT_add_a\xint_c_ii 100000010!1\Z!1\Z!1\Z!1\Z!\W }% -\def\XINT_iidivround_pos_finish #10!#2\Z #3\W +\def\XINT_iidivround_pos_finish #10!#2\R {% \expandafter\XINT_cuz_small\romannumeral0\XINT_unrevbyviii {}% - #1!#21\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W + #1!#21\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% -\def\XINT_iidivround_small\Z\ifnum #1>#2\fi 1#30!#4\W +\def\XINT_iidivround_small\Z\ifnum #1>#2\fi 1#30!#4\W\R {% \ifnum #1>\xint_c_iv \expandafter\XINT_iidivround_small_up @@ -18419,7 +18840,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xint}% - [2015/10/29 v1.2b Expandable operations on big integers (jfB)]% + [2015/11/16 v1.2c Expandable operations on big integers (jfB)]% % \end{macrocode} % \subsection{More token management} % \begin{macrocode} @@ -20262,7 +20683,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintbinhex}% - [2015/10/29 v1.2b Expandable binary and hexadecimal conversions (jfB)]% + [2015/11/16 v1.2c Expandable binary and hexadecimal conversions (jfB)]% % \end{macrocode} % \subsection{Constants, etc...} % \lverb!v1.08! @@ -20963,7 +21384,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintgcd}% - [2015/10/29 v1.2b Euclide algorithm with xint package (jfB)]% + [2015/11/16 v1.2c Euclide algorithm with xint package (jfB)]% % \end{macrocode} % \subsection{\csh{xintGCD}, \csh{xintiiGCD}} % \lverb|The macros of 1.09a benefits from the \xintnum which has been inserted @@ -21665,7 +22086,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintfrac}% - [2015/10/29 v1.2b Expandable operations on fractions (jfB)]% + [2015/11/16 v1.2c 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 @@ -22833,7 +23254,7 @@ $1$ or $-1$. {% \expandafter\XINT_round_B \romannumeral0\expandafter\XINT_trunc_A - \romannumeral0\XINT_infrac {#2}{\the\numexpr #1+1\relax}{#1}% + \romannumeral0\XINT_infrac {#2}{#1+\xint_c_i}{#1}% }% \def\XINT_round_B #1\Z {% @@ -22847,7 +23268,7 @@ $1$ or $-1$. }% \def\XINT_round_C #1% {% - \ifnum #1<5 + \ifnum #1<\xint_c_v \expandafter\XINT_round_Daa \else \expandafter\XINT_round_Dba @@ -24594,7 +25015,12 @@ $1$ or $-1$. % \subsection{\csh{xintFloatFac}, \csh{XINTFloatFac}} % \lverb|1.2. Je dois documenter le raisonnement sur la précision à imposer % pour les calculs par blocs de huit faits en sous-main. Par ailleurs j'ai été -% amené à une routine smallmul spéciale.| +% amené à une routine smallmul spéciale. +% +% Comment 2015/11/13: at least I do have a file which privately document my +% choice of precision (I could reduce by one unit here). I hesitated with doing +% a divide and conquer approach, but last time I thought about it I did not see +% an obvious advantage in this context. But I should implement and compare.| % \begin{macrocode} \def\xintFloatFac {\romannumeral0\xintfloatfac}% \def\xintfloatfac #1{\XINT_flfac_chkopt \xintfloat #1\xint_relax }% @@ -24801,7 +25227,12 @@ $1$ or $-1$. }% % \end{macrocode} % \subsection{\csh{xintFloatSqrt}, \csh{XINTinFloatSqrt}} -% \lverb|1.08| +% \lverb|1.08. Note 2015/11/16: I absolutely must document what's happening +% here, I have a file with comments from June 2013 which however is not +% completely explicit (as I did the rounding integer square root \xintiiSqrtR +% more than one year later, I am not +% 100$char37 $space sure the one here does correct rounding, and I don't +% have time to check now.)| % \begin{macrocode} \def\xintFloatSqrt {\romannumeral0\xintfloatsqrt }% \def\xintfloatsqrt #1{\XINT_flsqrt_chkopt \xintfloat #1\xint_relax }% @@ -25054,7 +25485,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintseries}% - [2015/10/29 v1.2b Expandable partial sums with xint package (jfB)]% + [2015/11/16 v1.2c Expandable partial sums with xint package (jfB)]% % \end{macrocode} % \subsection{\csh{xintSeries}} % \lverb|& @@ -25559,7 +25990,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintcfrac}% - [2015/10/29 v1.2b Expandable continued fractions with xint package (jfB)]% + [2015/11/16 v1.2c Expandable continued fractions with xint package (jfB)]% % \end{macrocode} % \subsection{\csh{xintCFrac}} % \begin{macrocode} @@ -26670,7 +27101,11 @@ $1$ or $-1$. % % \etocstandarddisplaystyle % \etocstandardlines +% \etocsetnexttocdepth {subsection} +% % \localtableofcontents +% \etocsettocstyle{}{} +% % \etocmarkbothnouc {Package \xintexprnameimp implementation} % % The first version was released in June 2013. I was greatly helped in this task @@ -26984,7 +27419,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintexpr}% - [2015/10/29 v1.2b Expandable expression parser (jfB)]% + [2015/11/16 v1.2c Expandable expression parser (jfB)]% \catcode`! 11 % \end{macrocode} % \subsection{Locking and unlocking} @@ -27105,6 +27540,12 @@ $1$ or $-1$. \def\xintbareiieval {\expandafter\XINT_iiexpr_until_end_a\romannumeral`&&@\XINT_expr_getnext }% % \end{macrocode} +% \subsection{\csh{xintthebareeval}, \csh{xintthebarefloateval}, \csh{xintthebareiieval}} +% \begin{macrocode} +\def\xintthebareeval {\expandafter\XINT_expr_unlock\romannumeral0\xintbareeval}% +\def\xintthebarefloateval {\expandafter\XINT_expr_unlock\romannumeral0\xintbarefloateval}% +\def\xintthebareiieval {\expandafter\XINT_expr_unlock\romannumeral0\xintbareiieval}% +% \end{macrocode} % \subsection{\csh{xinteval}, \csh{xintiieval}} % \begin{macrocode} \def\xinteval {\expandafter\XINT_expr_wrap\romannumeral0\xintbareeval }% @@ -27180,6 +27621,7 @@ $1$ or $-1$. % \end{macrocode} % \subsection{Macros handling csv lists on output (for \csh{XINT_expr_print} et % al. routines)} +% \localtableofcontents % \lverb|Changed completely for 1.1, which adds the optional arguments to % \xintiexpr and \xintfloatexpr.| % \subsubsection{\csh{XINT_::_end}} @@ -27257,8 +27699,8 @@ $1$ or $-1$. % \lverb|Pour \xintfloatexpr. Attention, prépare sous la forme digits[N] pour % traitement par les macros. Pas utilisé en sortie. Utilise \XINT_:::_end. % -% 1.1a I believe this is not needed for \xintNewExpr, as it is removed by -% re-defined by \XINT_flexpr_wrap code, hence no need to add the extra +% 1.1a: I believe this is not needed for \xintNewExpr, as it is removed by +% re-defined \XINT_flexpr_wrap code, hence no need to add the extra % \romannumeral-`0. Sub-expressions in \xintNewExpr are not supported. % % I didn't start and don't want now to think about it at all. @@ -27341,7 +27783,8 @@ $1$ or $-1$. % \end{macrocode} % \subsection{The integer or decimal number or hexa-decimal number or % function name or variable name or special hacky things big parser} -% \lverb|1.2 release has replaced chains of \romannumeral-`0 by \csname +% \localtableofcontents +% \lverb@1.2 release has replaced chains of \romannumeral-`0 by \csname % governed expansion. Thus there is no more the limit at about 5000 digits for % parsed numbers. % @@ -27371,7 +27814,15 @@ $1$ or $-1$. % % With v1.2, \xinttheexpr . \relax does not work anymore (it did in earlier % releases). There must be digits either before or after the decimal mark. Thus -% both \xinttheexpr 1.\relax and \xinttheexpr .1\relax are legal.| +% both \xinttheexpr 1.\relax and \xinttheexpr .1\relax are legal. +% +% The ` syntax is here used for special constructs like `+`(..), `*`(..) where +% + or * will be treated as functions. Current implementation pick only one +% token (could have been braced stuff), thus here it will be + or *, and via +% \XINT_expr_op_` this into becomes a suitable +% \XINT_{expr|iiexpr|flexpr}_func_+ (or *). Documentation of 1.1 said to use +% `+`(...), but `+(...) is also valid. The opening parenthesis must be there, +% it is not allowed to come from expansion.@ % \begin{macrocode} \catcode96 11 % ` \def\XINT_expr_scan_nbr_or_func #1% this #1 has necessarily here catcode 12 @@ -27381,6 +27832,7 @@ $1$ or $-1$. \ifnum \xint_c_ix<1#1 \xint_dothis \XINT_expr_startint\fi \xint_orthat \XINT_expr_scanfunc #1% }% +\def\XINT_expr_onlitteral_` #1#2#3({\xint_c_xviii `{#2}}% \catcode96 12 % ` \def\XINT_expr_startint #1% {% @@ -27626,7 +28078,7 @@ $1$ or $-1$. #1\expandafter\XINT_expr_scanhexII_a\romannumeral`&&@#2% }% % \end{macrocode} -% \subsubsection{Function and variable names} +% \subsubsection{Parsing names of functions and variables} % \begin{macrocode} \def\XINT_expr_scanfunc {% @@ -27636,6 +28088,14 @@ $1$ or $-1$. {% \expandafter #1\romannumeral`&&@\expandafter\XINT_expr_scanfunc_b\romannumeral`&&@#2% }% +% \end{macrocode} +% \lverb|This handles: 1) tacit multiplication by a variable in front a of +% sub-expression, 2) tacit multiplication in front of a \count etc..., 3) +% functions are recognized via an encountered opening parenthesis (but later +% this must be disambiguated from variables with tacit multiplication) 4) +% _ is allowed as part of variable or function names 5) also @ (used +% privately), 6) also digits, 6) letters or category code letters.| +% \begin{macrocode} \def\XINT_expr_scanfunc_b #1% {% \ifx !#1\xint_dothis{\xint_firstoftwo{(_*!}}\fi @@ -27648,13 +28108,36 @@ $1$ or $-1$. \xint_orthat {(_}% #1% }% -\def\XINT_expr_func #1(#2% -{% #2=` pour une fonction, #2=_ pour une variable - \if #2`\ifcsname XINT_expr_var_#1\endcsname - \expandafter\expandafter\expandafter\xint_thirdofthree - \fi\fi - \xint_firstoftwo {\xint_c_xviii #2{#1}}{\xint_c_xviii _{#1}*(}% -}% +% \end{macrocode} +% \lverb@Comments written 2015/11/12: earlier there was an \ifcsname test for +% checking if we had a variable in front of a (, for tacit multiplication for +% example in x(y+z(x+w)) to work. But after I had implemented functions (that +% was yesterday...), I had the problem if was impossible to re-declare a +% variable name such as "f" as a function name. The problem is that here we +% can not test if the function is available because we don't know if we are in +% expr, iiexpr or floatexpr. The \xint_c_xviii causes all fetching operations +% to stop and control is handed over to the routines which will be expr, +% iiexpr ou floatexpr specific, i.e. the \XINT_{expr|iiexpr|flexpr}_op_{`|_} +% which are invoked by the until_<op>_b macros earlier in the stream. +% Functions may exist for one but not the two other parsers. Variables are +% declared via one parser and usable in the others, but naturally \xintiiexpr +% has its restrictions. +% +% Thinking about this again I decided to treat a priori cases such as x(...) +% as functions, after having assigned to each variable a low-weight macro +% which will convert this into _getop\.=<value of x>*(...). To activate that +% macro at the right time I could for this exploit the "onlitteral" intercept, +% which is parser independent (1.2c). +% +% This led to me necessarily to rewrite partially the seq, add, mul, subs, +% iter ... routines as now the variables fetch only one token. I think the +% thing is more efficient. +% +% In \XINT_expr_func the #2 is _ if #1 must be a variable name, or #2=` if #1 +% must be either a function name or possibly a variable name which will then +% have to be followed by tacit multiplication.@ +% \begin{macrocode} +\def\XINT_expr_func #1(#2{\xint_c_xviii #2{#1}}% % \end{macrocode} % \subsection{\csh{XINT_expr_getop}: finding the next operator or closing % parenthesis or end of expression} @@ -27728,8 +28211,10 @@ $1$ or $-1$. \def\XINT_expr_unknown_operator #1{\xintError:removed \xint_gobble_i {#1}}% \def\XINT_expr_foundop #1{\csname XINT_expr_precedence_#1\endcsname #1}% % \end{macrocode} -% \subsection{Opening and closing parentheses, square brackets for lists, the -% \textasciicircum C for omit and abort within seq or rseq} +% \subsection{Expansion spanning; opening and closing parentheses} +% \lverb|Version 1.1 had a hack inside the until macros for handling the omit +% and abort in iterations over dummy variables. This has been removed by +% 1.2c, see the subsection where omit and abort are discussed.| % \begin{macrocode} \catcode`) 11 \def\XINT_tmpa #1#2#3#4% (avant #4#5) @@ -27743,10 +28228,7 @@ $1$ or $-1$. }% \def#2##1##2% {% - \ifcase ##1\xint_afterfi - {\ifx\XINT_expr_itself_^C ##2\xint_dothis - {\expandafter#1\romannumeral`&&@\expandafter\XINT_expr_getnext\xint_gobble_i}\fi - \xint_orthat \XINT_expr_done }% + \ifcase ##1\expandafter\XINT_expr_done \or\xint_afterfi{\XINT_expr_extra_) \expandafter #1\romannumeral`&&@\XINT_expr_getop }% \else @@ -27770,9 +28252,7 @@ $1$ or $-1$. ##1{\expandafter #3\romannumeral`&&@#5}% -{#4##1}% \krof }% - \def #4##1##2{\ifcase ##1% - \xint_afterfi{\ifx\XINT_expr_itself_^C ##2\xint_dothis{\xint_c_ ##2}\fi - \xint_orthat\XINT_expr_missing_) }% + \def #4##1##2{\ifcase ##1\expandafter\XINT_expr_missing_) \or \csname XINT_#6_op_##2\expandafter\endcsname \else \xint_afterfi{\expandafter #3\romannumeral`&&@\csname XINT_#6_op_##2\endcsname }% @@ -27791,35 +28271,78 @@ $1$ or $-1$. {#1}% }% \expandafter\let\csname XINT_expr_precedence_)\endcsname\xint_c_i +% \end{macrocode} +% \subsection{\textbar, \textbar\textbar, \&, +% \&\&, <, >, =, ==, <=, >=, !=, +, \textendash, +% \texorpdfstring{\protect\lowast}{*}, /, \textasciicircum, +% \texorpdfstring{\protect\lowast\protect\lowast}{**}, //, /:, .., ..[, ].., +% ][, ][:, :], and ++ operators} +% \localtableofcontents +% \subsubsection{Square brackets for lists, the +% !? for omit and abort, and the ++ postfix construct} +% \lverb|This is all very clever and only need setting some suitable precedence +% levels, if only I could understand what I did in 2014... just joking. Notice +% that op_) macros are defined here in the \xintFor loop. +% +% There is some clever business going on here with the letter a for handling +% constructs such as [3..5]*2 (I think...). +% +% 1.2c has replaced 1.1's private dealings with "^C" (which was done before +% dummy variables got implemented) by use of "!?". See discussion of omit and abort.| +% \begin{macrocode} \expandafter\let\csname XINT_expr_precedence_]\endcsname\xint_c_i \expandafter\let\csname XINT_expr_precedence_;\endcsname\xint_c_i \let\XINT_expr_precedence_a \xint_c_xviii -\expandafter\let\csname XINT_expr_precedence_^C\endcsname \xint_c_ +\let\XINT_expr_precedence_!? \xint_c_ii \expandafter\let\csname XINT_expr_precedence_++)\endcsname \xint_c_i +% \end{macrocode} +% \lverb|Comments added 2015/11/13 Here we have in particular the mechanism +% for post action on lists via op_] The precedence_] is the one of a closing +% parenthesis. We need the closing parenthesis to do its job, hence we can not +% define a op_]+ operator for example, as we want to assign it the precedence +% of addition not the one of closing parenthesis. The trick I used in 1.1 was +% to let the op_] insert the letter a, this letter exceptionnally also being a +% legitimate operator, launch the _getop and let it find a a*, a+, a/, a-, a^, +% a** operator standing for ]*, ]+, ]/, ]^, ]** postfix item by item list +% operator. I thought I had in mind an example to show that having defined +% op_a and precedence_a for the letter a caused a reduction in syntax for this +% letter, but it seems I am lacking now an example.| +% \begin{macrocode} \catcode`. 11 \catcode`= 11 \catcode`+ 11 \xintFor #1 in {expr,flexpr,iiexpr} \do {% \expandafter\let\csname XINT_#1_op_)\endcsname \XINT_expr_getop \expandafter\let\csname XINT_#1_op_;\endcsname \space \expandafter\def\csname XINT_#1_op_]\endcsname ##1{\XINT_expr_getop ##1a}% \expandafter\let\csname XINT_#1_op_a\endcsname \XINT_expr_getop +% \end{macrocode} +% \lverb|1.1 2014/10/29 did \expandafter\.=+\xintiCeil which transformed it into +% \romannumeral0\xinticeil, which seems a bit weird. This exploited the fact +% that dummy variables macros could back then pick braced material (which in the +% case at hand here ended being {\romannumeral0\xinticeil...} and were submitted +% to two expansions. The result of this was to provide a not value which got +% expanded only in the first loop of the :_A and following macros of seq, +% iter, rseq, etc... +% +% Anyhow with 1.2c I have changed the implementation of dummy variables which +% now need to fetch a single locked token, which they do not expand. +% +% The \xintiCeil appears a bit dispendious, but I need the starting value in a +% \numexpr compatible form in the iteration loops.| +% \begin{macrocode} \expandafter\def\csname XINT_#1_op_++)\endcsname ##1##2\relax {\expandafter\XINT_expr_foundend \expandafter - {\expandafter\.=+\xintiCeil{\XINT_expr_unlock ##1}}}% + {\expandafter\.=+\csname .=\xintiCeil{\XINT_expr_unlock ##1}\endcsname }}% }% \catcode`. 12 \catcode`= 12 \catcode`+ 12 -% \end{macrocode} -% \subsection{\textbar, \textbar\textbar, \&, -% \&\&, <, >, =, ==, <=, >=, !=, +, \textendash, \texorpdfstring{\protect\lowast}{*}, /, \textasciicircum, \texorpdfstring{\protect\lowast\protect\lowast}{**}, //, /:, .., ..[, ].., ][, ][:, :], \textasciicircum C, and ++ operators} -% \begin{macrocode} \catcode`& 12 \xintFor* #1 in {{==}{<=}{>=}{!=}{&&}{||}{**}{//}{/:}{..}{..[}{].}{]..}% {+[}{-[}{*[}{/[}{**[}{^[}{a+}{a-}{a*}{a/}{a**}{a^}% - {][}{][:}{:]}{^C}{++}{++)}} + {][}{][:}{:]}{!?}{++}{++)}} \do {\expandafter\def\csname XINT_expr_itself_#1\endcsname {#1}}% \catcode`& 7 % \end{macrocode} -% \subsubsection{The \textbar, -% \&, xor, <, >, =, <=, >=, !=, //, /:, .., ..[, and ].. operators} +% \subsubsection{The \textbar, \&, xor, <, >, =, <=, >=, !=, //, /: and .. +% operators for expr and floatexpr} % \begin{macrocode} \def\XINT_tmpc #1#2#3#4#5#6#7#8% {% @@ -27871,6 +28394,10 @@ $1$ or $-1$. }% }% \catcode`& 7 +% \end{macrocode} +% \subsubsection{The +, \textendash, \texorpdfstring{\protect\lowast}{*}, /, +% \textasciicircum, ..[, and ].. operators for expr and floatexpr} +% \begin{macrocode} \def\XINT_tmpa #1{\XINT_tmpb {expr}{xint}#1}% \xintApplyInline {\XINT_tmpa }{% {+{vi}{vi}{Add}}% @@ -27891,6 +28418,9 @@ $1$ or $-1$. {{..[}{iii}{vi}{SeqA::csv}}% {{]..}{iii}{vi}{SeqB::csv}}% }% +% \end{macrocode} +% \subsubsection{The previous operators for iiexpr} +% \begin{macrocode} \def\XINT_tmpa #1{\XINT_tmpb {iiexpr}{xint}#1}% \catcode`& 12 \xintApplyInline {\XINT_tmpa }{% @@ -27919,6 +28449,8 @@ $1$ or $-1$. % \subsubsection{The ]+, ]\textendash, ]\texorpdfstring{\protect\lowast}{*}, ]/, ]\textasciicircum, +[, \textendash[, \texorpdfstring{\protect\lowast}{*}[, /[, and \textasciicircum[ list % operators} % \paragraph{\csh{XINT_expr_binop_inline_b}}\par +% \lverb|This handles acting on comma separated values (no need to bother +% about spaces in this context; expansion in a \csname...\endcsname.| % \begin{macrocode} \def\XINT_expr_binop_inline_a {\expandafter\xint_gobble_i\romannumeral`&&@\XINT_expr_binop_inline_b }% @@ -27965,6 +28497,9 @@ $1$ or $-1$. \csname #4\expandafter\endcsname \csname XINT_expr_precedence_#2\endcsname {#1}% }% +% \end{macrocode} +% \lverb|This is for [x..y]*z syntax etc...| +% \begin{macrocode} \xintApplyInline {\expandafter\XINT_tmpb \xint_firstofone}{% {{expr}{a+}{vi}{xintAdd}}% {{expr}{a-}{vi}{xintSub}}% @@ -28009,6 +28544,9 @@ $1$ or $-1$. \csname #4\expandafter\endcsname \csname XINT_expr_precedence_#2\endcsname {#1}% }% +% \end{macrocode} +% \lverb|This is for z*[x..y] syntax etc...| +% \begin{macrocode} \xintApplyInline {\expandafter\XINT_tmpb\xint_firstofone }{% {{expr}{+[}{vi}{xintAdd}}% {{expr}{-[}{vi}{xintSub}}% @@ -28081,14 +28619,17 @@ $1$ or $-1$. % \end{macrocode} % \subsubsection{List selectors: [list][N], [list][:b], [list][a:], [list][a:b]} % \lverb|1.1 (27 octobre 2014) I implement Python syntax, see -% http://stackoverflow.com/a/13005464/4184837. Do not implement third -% argument giving the step. Also, I gather that [5:2] selector returns empty +% http://stackoverflow.com/a/13005464/4184837. I do not implement third +% argument giving the step. Also, Python [5:2] selector returns empty % and not, as I could have been tempted to do, (list[5], list[4], list[3]). -% Anyway, it is simpler not to go that way. For reversing I could implement -% [::-1] but this would get confusing, better to do function "reversed". +% Anyway, it is simpler not to do that. For reversing I could allow +% [::-1] syntax but this would get confusing, better to do function "reversed". % % This gets the job done, but I would definitely need \xintTrim::csv, \xintKeep::csv, -% \xintNthElt::csv for better efficiency. Not for 1.1.| +% \xintNthElt::csv for better efficiency. Not for 1.1. +% +% The \xintListSel::csv was named \xintListSel:csv, but as it not only +% extracts one item but may produce csv, I renamed it.| % \begin{macrocode} \def\XINT_tmpa #1#2#3#4#5#6% {% @@ -28109,8 +28650,8 @@ $1$ or $-1$. \else \xint_afterfi {\expandafter ##2\expandafter ##3\csname - .=\expandafter\xintListSel:csv \romannumeral`&&@\XINT_expr_unlock ##4;% - \XINT_expr_unlock ##1;\endcsname % unlock for \xintNewExpr + .=\expandafter\xintListSel::csv \romannumeral`&&@\XINT_expr_unlock ##4;% + \XINT_expr_unlock ##1;\endcsname % unlock added for \xintNewExpr }% \fi }% @@ -28166,17 +28707,22 @@ $1$ or $-1$. \let\XINT_flexpr_op_:] \XINT_expr_op_:] \let\XINT_iiexpr_op_:] \XINT_expr_op_:] \let\XINT_expr_precedence_][: \xint_c_iii +% \end{macrocode} +% \lverb|At the end of the replacement text of \XINT_expr_op_][:, the : after +% index 0 must be catcode 12, else will be mistaken for the start of variable +% by expression parser (as <digits><variable> is allowed by the syntax and does +% tacit multiplication).| +% \begin{macrocode} \edef\XINT_expr_op_][: #1{\xint_c_ii \expandafter\noexpand \csname XINT_expr_itself_][\endcsname #10\string :}% % \end{macrocode} -% \lverb|: must be catcode 12, else will be mistaken for start of variable by -% expression parser. In \xintListSel:csv some complications are due to -% \xintNewExpr matters.| +% \subsubsection{\csh{xintListSel::csv}} +% \lverb|Some complications here are due to \xintNewExpr matters.| % \begin{macrocode} \let\XINT_flexpr_op_][: \XINT_expr_op_][: \let\XINT_iiexpr_op_][: \XINT_expr_op_][: \catcode`[ 12 \catcode`] 12 -\def\xintListSel:csv #1{% +\def\xintListSel::csv #1{% \if ]\noexpand#1\xint_dothis{\expandafter\XINT_listsel:_s\romannumeral`&&@}\fi \if :\noexpand#1\xint_dothis{\XINT_listsel:_:}\fi \xint_orthat {\XINT_listsel:_nth #1}% @@ -28192,19 +28738,11 @@ $1$ or $-1$. {\xintNthElt {\xintNum{#1}}{\xintCSVtoListNonStripped{#2}}}% \def\XINT_listsel:_PP #1;#2;#3;% {\xintListWithSep,% - {\xintTrim {\xintNum{#1}}% - {\xintKeep {\xintNum{#2}}% - {\xintCSVtoListNonStripped{#3}}% - }% - }% + {\xintTrim {\xintNum{#1}}{\xintKeep {\xintNum{#2}}{\xintCSVtoListNonStripped{#3}}}}% }% \def\XINT_listsel:_NN #1;#2;#3;% {\xintListWithSep,% - {\xintTrim {\xintNum{#2}}% - {\xintKeep {\xintNum{#1}}% - {\xintCSVtoListNonStripped{#3}}% - }% - }% + {\xintTrim {\xintNum{#2}}{\xintKeep {\xintNum{#1}}{\xintCSVtoListNonStripped{#3}}}}% }% \def\XINT_listsel:_NP #1;#2;#3;% {\expandafter\XINT_listsel:_NP_a \the\numexpr #1+% @@ -28220,6 +28758,7 @@ $1$ or $-1$. \def\XINT_listsel:_PO\XINT_listsel:_PP #1;#2;{\XINT_listsel:_PP #1;0;}% % \end{macrocode} %\subsection{Macros for a..b list generation} +% \localtableofcontents %\lverb|Attention, ne produit que des listes de petits entiers!| %\subsubsection{\csh{xintSeq::csv}} %\lverb|Commence par remplacer a par ceil(a) et b par floor(b) et renvoie @@ -28307,17 +28846,31 @@ $1$ or $-1$. \def\XINT_seq::csv_e #1,{ }% % \end{macrocode} %\subsection{Macros for a..[d]..b list generation} -%\lverb|Contrarily to a..b which is limited to small integers, this works with a, b, and d -%(big) fractions. It will produce a «nil» list, if a>b and d<0 or a<b and d>0.| +% \localtableofcontents +% +% \lverb|Contrarily to a..b which is limited to small integers, this works +% with a, b, and d (big) fractions. It will produce a «nil» list, if a>b and +% d<0 or a<b and d>0.| +% %\subsubsection{\csh{xintSeqA::csv}, \csh{xintiiSeqA::csv}, \csh{XINTinFloatSeqA::csv}} +% +% \lverb|2015/11/11 Naturally, I did not document anything in 2014, and today +% I was perplexed about what these macros do; and why something was wrong with +% \xintNewIIExpr and a..[b]..c things therein. In fact \xintiiSeqB:f:csv had a +% typo in its name, but this had escaped my 2014 tests; and if I had corrected +% it I would have seen another problem with a..[b]..C in \xintNewIIExpr, the +% \xintiiSeqB:f:csv macro calls \xintiiSeqA::csv with arguments which have no +% more a \XINT_expr_unlock. But \xintiiSeqA::csv tried to be clever and +% assumed the \XINT_expr_unlock were there. The other two expanded either in +% \xintraw or \XINTinfloat, hence no problem arose in +% \xintNewExpr/\xintNewFloatExpr. The fix has been to let \xintiiSeqA::csv act +% a bit more like the other two.| % \begin{macrocode} \def\xintSeqA::csv #1% {\expandafter\XINT_seqa::csv\expandafter{\romannumeral0\xintraw {#1}}}% \def\XINT_seqa::csv #1#2{\expandafter\XINT_seqa::csv_a \romannumeral0\xintraw {#2};#1;}% -\def\xintiiSeqA::csv #1#2{\XINT_iiseqa::csv #1#2}% -\def\XINT_iiseqa::csv #1#2#3#4{\expandafter\XINT_seqa::csv_a - \romannumeral`&&@\expandafter \XINT_expr_unlock\expandafter#4% - \expandafter;\romannumeral`&&@\XINT_expr_unlock #2;}% +\def\xintiiSeqA::csv #1{\expandafter\XINT_iiseqa::csv\expandafter{\romannumeral`&&@#1}}% +\def\XINT_iiseqa::csv #1#2{\expandafter\XINT_seqa::csv_a\romannumeral`&&@#2;#1;}% \def\XINTinFloatSeqA::csv #1{\expandafter\XINT_flseqa::csv\expandafter {\romannumeral0\XINTinfloat [\XINTdigits]{#1}}}% \def\XINT_flseqa::csv #1#2% @@ -28329,6 +28882,8 @@ $1$ or $-1$. \krof #1}% % \end{macrocode} %\subsubsection{\csh{xintSeqB::csv}} +% \lverb|With one year late documentation, let's just say, the #1 is +% \XINT_expr_unlock\.=Ua;b; with U=z or n or p, a=step, b=start.| % \begin{macrocode} \def\xintSeqB::csv #1#2% {\expandafter\XINT_seqb::csv \expandafter{\romannumeral0\xintraw{#2}}{#1}}% @@ -28398,7 +28953,7 @@ $1$ or $-1$. \def\XINT_flseqb::csv_z #1#2#3{,#1}% % \end{macrocode} % \subsection{The comma as binary operator} -% \lverb|New with 1.09a.| +% \lverb|New with 1.09a. Suffices to set its precedence level to two.| % \begin{macrocode} \def\XINT_tmpa #1#2#3#4#5#6% {% @@ -28434,6 +28989,8 @@ $1$ or $-1$. }% % \end{macrocode} % \subsection{The minus as prefix operator of variable precedence level} +% +% \lverb|Inherits the precedence level of the previous infix operator.| % \begin{macrocode} \def\XINT_tmpa #1#2#3% {% @@ -28472,7 +29029,9 @@ $1$ or $-1$. % \subsection{? as two-way and ?? as three-way conditionals with braced branches} % \lverb|In 1.1, I overload ? with ??, as : will be used for list extraction, % problem with (stuff)?{?(1)}{0} for example, one should put a space (stuff)?{ -% ?(1)}{0} will work. Small idiosyncrasy. ?{yes}{no} and ??{<0}{=0}{>0}| +% ?(1)}{0} will work. Small idiosyncrasy. +% +% syntax: ?{yes}{no} and ??{<0}{=0}{>0}| % \begin{macrocode} \let\XINT_expr_precedence_? \xint_c_x \def\XINT_expr_op_? #1#2{\if ?#2\expandafter \XINT_expr_op_??\fi @@ -28490,8 +29049,7 @@ $1$ or $-1$. }% % \end{macrocode} % \subsection{! as postfix factorial operator} -% \lverb|Float version was at last done 2015/10/06. As xint does not have yet -% exp/log, Stirling is no go.| +% \lverb|A float version \xintFloatFac was at last done 2015/10/06.| % \begin{macrocode} \let\XINT_expr_precedence_! \xint_c_x \def\XINT_expr_op_! #1{\expandafter\XINT_expr_getop @@ -28508,7 +29066,10 @@ $1$ or $-1$. % \xintE, \xintiiE, and \XINTinFloatE all put #2 in a \numexpr. But attention % to the fact that \numexpr stops at spaces separating digits: % \the\numexpr 3 + 7 9\relax gives 109\relax !! Hence we have to be -% careful.| +% careful. +% +% \numexpr will not handle catcode 11 digits, but adding a \detokenize will +% suddenly make illicit for N to rely on macro expansion.| % \begin{macrocode} \catcode`[ 11 \catcode`* 11 @@ -28525,7 +29086,9 @@ $1$ or $-1$. \catcode`[ 12 \catcode`* 12 % \end{macrocode} -% \subsection{For variables} +% \subsection{\csh{XINT_expr_op__} for recognizing variables} +% \lverb|The 1.1 mechanism for \XINT_expr_var_<varname> has been modified in 1.2c. +% The <varname> associated macro is now only expanded once, not twice.| % \begin{macrocode} \def\XINT_expr_op__ #1% op__ with two _'s {% @@ -28534,8 +29097,7 @@ $1$ or $-1$. \else \expandafter\xint_secondoftwo \fi - {\expandafter\expandafter\expandafter\expandafter - \expandafter\expandafter\expandafter + {\expandafter\expandafter\expandafter \XINT_expr_getop\csname XINT_expr_var_#1\endcsname}% {\XINT_expr_unknown_variable {#1}% \expandafter\XINT_expr_getop\csname .=0\endcsname}% @@ -28544,61 +29106,182 @@ $1$ or $-1$. \let\XINT_flexpr_op__ \XINT_expr_op__ \let\XINT_iiexpr_op__ \XINT_expr_op__ % \end{macrocode} -% \subsubsection{Defining variables} -% \lverb|1.1 An active : character will be a pain and I almot decided not to -% use := but rather = as affectation operator, but this is the same problem -% inside expressions with the modulo operator /:, or with babel+frenchb with -% all high punctuation ?, !, :, ;. +% \subsection{User defined variables: \csh{xintdefvar}, \csh{xintdefiivar}, \csh{xintdeffloatvar}} +% \lverb|1.1 An active : character will be a pain with our delimited macros and +% I almost decided not to use := but rather = as assignation operator, but this +% is the same problem inside expressions with the modulo operator /:, or with +% babel+frenchb with all high punctuation ?, !, :, ;. +% +% Variable names may contain letters, digits, underscores, and must not start +% with a digit. Names starting with @ or un underscore are reserved. +% +% Note (2015/11/11): although defined since october 2014 with 1.1, they were +% only very briefly mentioned in the user documentation, I should have +% expanded more. I am now adding functions to variables, and will rewrite +% entirely the documentation of xintexpr.sty. +% +% 1.2c adds the "onlitteral" macros as we changed our tricks to disambiguate +% variables from functions if followed by a parenthesis, in order to allow +% function names to have precedence on variable names. % -% It is not recommended to overwrite single Latin letters which are -% pre-defined to serve as dummy variables. Variable names may contain -% letters, digits, underscores, and must not start with a digit.| +% I don't issue warnings if a an attempt to define a variable name clashes +% with a pre-existing function name, as I would have to check expr, iiexpr and +% also floatexpr. And anyhow overloading a function name with a variable name +% is allowed, the only thing to know is that if an opening parenthesis follows +% it is the function meaning which prevails. +% +% 2015/11/13: I now first do an a priori complete expansion of #1, and then apply +% \detokenize to the result, and remove spaces. Should xintexpr log the values +% of the declared variables ? | % \begin{macrocode} \catcode`: 12 -\def\xintdefvar #1:=#2;{\expandafter\odef - \csname XINT_expr_var_\xint_zapspaces #1 \xint_gobble_i\endcsname - {\expandafter\empty\romannumeral0\xintbareeval #2\relax }}% -\def\xintdefiivar #1:=#2;{\expandafter\odef - \csname XINT_expr_var_\xint_zapspaces #1 \xint_gobble_i\endcsname - {\expandafter\empty\romannumeral0\xintbareiieval #2\relax }% -}% -\def\xintdeffloatvar #1:=#2;{\expandafter\odef - \csname XINT_expr_var_\xint_zapspaces #1 \xint_gobble_i\endcsname - {\expandafter\empty\romannumeral0\xintbarefloateval #2\relax }% +\def\xintdefvar #1:=#2;{% + \edef\XINT_expr_tmpa{#1}% + \edef\XINT_expr_tmpa + {\expandafter\xint_zapspaces\detokenize\expandafter{\XINT_expr_tmpa} \xint_gobble_i}% + \edef\XINT_expr_tmpb {\romannumeral0\xintbareeval #2\relax }% + \ifxintverbose\xintMessage {info}{xintexpr} + {Variable \XINT_expr_tmpa\space defined with value + \expandafter\XINT_expr_unlock\XINT_expr_tmpb.}% + \fi + \expandafter\edef\csname XINT_expr_var_\XINT_expr_tmpa\endcsname + {\expandafter\noexpand\XINT_expr_tmpb}% + \expandafter\edef\csname XINT_expr_onlitteral_\XINT_expr_tmpa\endcsname + {\noexpand\XINT_expr_getop\expandafter\noexpand\XINT_expr_tmpb *(}% +}% +\def\xintdefiivar #1:=#2;{% + \edef\XINT_expr_tmpa{#1}% + \edef\XINT_expr_tmpa + {\expandafter\xint_zapspaces\detokenize\expandafter{\XINT_expr_tmpa} \xint_gobble_i}% + \edef\XINT_expr_tmpb {\romannumeral0\xintbareiieval #2\relax }% + \ifxintverbose\xintMessage {info}{xintexpr} + {Variable \XINT_expr_tmpa\space defined with value + \expandafter\XINT_expr_unlock\XINT_expr_tmpb.}% + \fi + \expandafter\edef\csname XINT_expr_var_\XINT_expr_tmpa\endcsname + {\expandafter\noexpand\XINT_expr_tmpb}% + \expandafter\edef\csname XINT_expr_onlitteral_\XINT_expr_tmpa\endcsname + {\noexpand\XINT_expr_getop\expandafter\noexpand\XINT_expr_tmpb *(}% +}% +\def\xintdeffloatvar #1:=#2;{% + \edef\XINT_expr_tmpa{#1}% + \edef\XINT_expr_tmpa + {\expandafter\xint_zapspaces\detokenize\expandafter{\XINT_expr_tmpa} + \xint_gobble_i}% + \edef\XINT_expr_tmpb {\romannumeral0\xintbarefloateval #2\relax }% + \ifxintverbose\xintMessage {info}{xintexpr} + {Variable \XINT_expr_tmpa\space defined with value + \expandafter\XINT_expr_unlock\XINT_expr_tmpb.}% + \fi + \expandafter\edef\csname XINT_expr_var_\XINT_expr_tmpa\endcsname + {\expandafter\noexpand\XINT_expr_tmpb}% + \expandafter\edef\csname XINT_expr_onlitteral_\XINT_expr_tmpa\endcsname + {\noexpand\XINT_expr_getop\expandafter\noexpand\XINT_expr_tmpb *(}% }% \catcode`: 11 % \end{macrocode} -% \subsubsection{Letters as dummy variables; the nil list} +% \subsection{All letters usable as dummy variables} +% \lverb|The nil variable was introduced in 1.1 but I don't think it is used +% anywhere (comment 2015/11/11; well it is, for example in the macros handling +% a..[d]..b, or for seq with dummy variable where omit has omitted everyting). +% +% 1.2c has changed the way variables are disambiguated from functions and for +% this it has added here the definitions of \XINT_expr_onlitteral_<name>. +% +% In 1.1 a letter variable say X was acting as a delimited macro looking for !X{stuff} and +% then would expand the stuff inside a \csname.=...\endcsname. I don't think I used the +% possibilities this opened and the 1.2c version has stuff _already_ encapsulated thus a +% single token. Only one expansion, not two is then needed in \XINT_expr_op__. +% +% I had to accordingly modify seq, add, mul and subs, but fortunately realized that the @, +% @1, etc... variables for rseq, rrseq and iter already had been defined in +% the way now also followed by the Latin letters as dummy variables.| % \begin{macrocode} \def\XINT_tmpa #1% {% \expandafter\def\csname XINT_expr_var_#1\endcsname ##1\relax !#1##2% - {\romannumeral0\XINT_expr_lockscan ##2!##1\relax !#1{##2}}% + {##2##1\relax !#1##2}% + \expandafter\def\csname XINT_expr_onlitteral_#1\endcsname ##1\relax !#1##2% + {\XINT_expr_getop ##2*(##1\relax !#1##2}% }% \xintApplyUnbraced \XINT_tmpa {abcdefghijklmnopqrstuvwxyz}% \xintApplyUnbraced \XINT_tmpa {ABCDEFGHIJKLMNOPQRSTUVWXYZ}% -\expandafter\def\expandafter\XINT_expr_var_nil\expandafter - {\expandafter\empty\csname .= \endcsname}% +\edef\XINT_expr_var_nil {\expandafter\noexpand\csname .= \endcsname}% +\edef\XINT_expr_onlitteral_nil + {\noexpand\XINT_expr_getop\expandafter\noexpand\csname .= \endcsname *(}% % \end{macrocode} -% \subsubsection{The omit and abort constructs} -% \begin{macrocode} -\catcode`. 11 \catcode`= 11 -\def\XINT_expr_var_omit #1\relax !{1^C!{}{}{}\.=!\relax !}% 24 juin -\def\XINT_expr_var_abort #1\relax !{1^C!{}{}{}\.=^\relax !}% 25 juin -\catcode`. 12 \catcode`= 12 -% \end{macrocode} -% \subsubsection{The @, @1, @2, @3, @4, @@, @@(1), \dots, @@@, @@@(1), \dots -% for recursion} -% \lverb|I had completely forgotten what the @@@ etc... stuff were supposed to -% do: this is for nesting recursions! (I was mad back in June 2014). @@(N) -% gives the Nth back, @@@(N) gives the Nth back of the higher recursion!| +% \subsection{The omit and abort constructs} +% \lverb|& attention à ce & qui est de catcode 14 dans les \lverb +% June 24 and 25, 2014. +% +% Added comments 2015/11/13: +% +% Et la documentation ? on n'y comprend plus rien. Trop +% rusé.$newline +% \def\XINT_expr_var_omit #1\relax !{1^C!{}{}{}\.=!\relax !}$newline +% \def\XINT_expr_var_abort #1\relax !{1^C!{}{}{}\.=^\relax !}$newline +% C'était accompagné de \XINT_expr_precedence_^C=0 et d'un hack au sein même +% des macros until de plus bas niveau. +% +% Le mécanisme sioux était le suivant: ^C est déclaré comme un opérateur de +% précédence nulle. Lorsque le parseur trouve un "omit" dans un seq ou autre, +% il va insérer dans le stream \XINT_expr_getop suivi du texte de +% remplacement. Donc ici on avait un 1 comme place holder, puis l'opérateur +% ^C. Celui-ci étant de précédence zéro provoque la finalisation de tous les +% calculs antérieurs dans le sous-bareeval. Mais j'ai dû hacker le until_end_b +% (et le until_)_b) qui confronté à ^C, va se relancer à zéro, le getnext va +% trouver le !{}{}{}\.=! et ensuite il y aura \relax, et le résultat sera \.=! +% pour omit ou \.=^ pour abort. Les routines des boucles seq, iter, etc... +% peuvent alors repérer le ! ou ^ et agir en conséquence (un long paragraphe +% pour ne décrire que partiellement une ou deux lignes de codes...). +% +% Mais ^C a été fait alors que je n'avais pas encore les variables muettes. Je +% dois trouver autre chose, car seq(2^C, C=1..5) est alors impossible. De +% toute façon ce ^C était à usage interne uniquement. +% +% Il me faut un symbole d'opérateur qui ne rentre pas en conflit. Bon je vais +% prendre !?. Ensuite au lieu de hacker until_end, il vaut mieux lui donner +% précédence 2 (mais ça ne pourra pas marcher à l'intérieur de parenthèses il +% faut d'abord les fermer manuellement) et lui associer un simplement un op +% spécial. Je n'avais pas fait cela peut-être pour éviter d'avoir à définir +% plusieurs macros. Le #1 dans la définition de \XINT_expr_op_!? est le +% résultat de l'évaluation forcée précédente. +% +% Attention que les premier ! doiventt être de catcode 12 sinon ils +% signalent une sous-expression qui déclenche une multiplication tacite. +% +% 2015/11/13| +% \begin{macrocode} +\edef\XINT_expr_var_omit #1\relax !{1\string !?!\relax !}% +\edef\XINT_expr_var_abort #1\relax !{1\string !?^\relax !}% +\def\XINT_expr_op_!? #1#2\relax {\expandafter\XINT_expr_foundend\csname .=#2\endcsname}% +\let\XINT_iiexpr_op_!? \XINT_expr_op_!? +\let\XINT_flexpr_op_!? \XINT_expr_op_!? +% \end{macrocode} +% \subsection{The special variables @, @1, @2, @3, @4, @@, @@(1), \dots, @@@, +% @@@(1), \dots for recursion} +% \lverb|October 2014: I had completely forgotten what the @@@ etc... stuff +% were supposed to do: this is for nesting recursions! (I was mad back in +% June). @@(N) gives the Nth back, @@@(N) gives the Nth back of the higher +% recursion! +% +% 1.2c adds the needed "onlitteral" now that tacit multiplication between a +% variable and a ( has a new mechanism.| % \begin{macrocode} \catcode`? 3 -\def\XINT_expr_var_@ #1~#2{ #2#1~#2}% +\def\XINT_expr_var_@ #1~#2{#2#1~#2}% \expandafter\let\csname XINT_expr_var_@1\endcsname \XINT_expr_var_@ -\expandafter\def\csname XINT_expr_var_@2\endcsname #1~#2#3{ #3#1~#2#3}% -\expandafter\def\csname XINT_expr_var_@3\endcsname #1~#2#3#4{ #4#1~#2#3#4}% -\expandafter\def\csname XINT_expr_var_@4\endcsname #1~#2#3#4#5{ #5#1~#2#3#4#5}% +\expandafter\def\csname XINT_expr_var_@2\endcsname #1~#2#3{#3#1~#2#3}% +\expandafter\def\csname XINT_expr_var_@3\endcsname #1~#2#3#4{#4#1~#2#3#4}% +\expandafter\def\csname XINT_expr_var_@4\endcsname #1~#2#3#4#5{#5#1~#2#3#4#5}% +\def\XINT_expr_onlitteral_@ #1~#2{\XINT_expr_getop #2*(#1~#2}% +\expandafter\let\csname XINT_expr_onlitteral_@1\endcsname \XINT_expr_onlitteral_@ +\expandafter\def\csname XINT_expr_onlitteral_@2\endcsname #1~#2#3% + {\XINT_expr_getop #3*(#1~#2#3}% +\expandafter\def\csname XINT_expr_onlitteral_@3\endcsname #1~#2#3#4% + {\XINT_expr_getop #4*(#1~#2#3#4}% +\expandafter\def\csname XINT_expr_onlitteral_@4\endcsname #1~#2#3#4#5% + {\XINT_expr_getop #5*(#1~#2#3#4#5}% \def\XINT_expr_func_@@ #1#2#3#4~#5?% {% \expandafter#1\expandafter#2\romannumeral0\xintntheltnoexpand @@ -28634,16 +29317,30 @@ $1$ or $-1$. }% \catcode`? 11 % \end{macrocode} -% \subsection{For functions} +% \subsection{\csh{XINT_expr_op_`} for recognizing functions} +% \lverb|The "onlitteral" intercepts is for bool, togl, protect, ... but also +% for add, mul, seq, etc... Genuine functions have expr, iiexpr and +% flexpr versions (or only one or two of the three). +% +% With 1.2c "onlitteral" is also used to recognize variables. However as I use +% only a \ifcsname test, in order to be able to re-define a variable as +% function, I move the check for being a function first. Each variable name now +% has its onlitteral_<name> associated macro which is the new way tacit +% multiplication in front of a parenthesis is implemented. This used to be +% decided much earlier at the time of \XINT_expr_func. +% +% The advantage of our choices for 1.2c is that the same name can be used for +% a variable or a function, the parser will apply the correct interpretation +% which is decided by the presence or not of an opening parenthesis next.| % \begin{macrocode} -\def\XINT_tmpa #1#2#3{% - \def #1##1% \XINT_expr_op_`, #2=\XINT_expr_oparen +\def\XINT_tmpa #1#2#3{% + \def #1##1% {% - \ifcsname XINT_expr_onlitteral_##1\endcsname - \xint_dothis{\csname XINT_expr_onlitteral_##1\endcsname}\fi \ifcsname XINT_#3_func_##1\endcsname \xint_dothis{\expandafter\expandafter \csname XINT_#3_func_##1\endcsname\romannumeral`&&@#2}\fi + \ifcsname XINT_expr_onlitteral_##1\endcsname + \xint_dothis{\csname XINT_expr_onlitteral_##1\endcsname}\fi \xint_orthat{\XINT_expr_unknown_function {##1}% \expandafter\XINT_expr_func_unknown\romannumeral`&&@#2}% }% @@ -28655,12 +29352,12 @@ $1$ or $-1$. \csname XINT_#1_oparen\endcsname {#1}% }% -\expandafter\def\csname XINT_expr_onlitteral_`\endcsname #1#2#3({\xint_c_xviii `{#2}}% +\def\XINT_expr_func_unknown #1#2#3% + {\expandafter #1\expandafter #2\csname .=0\endcsname }% % \end{macrocode} -% \subsection{The bool, togl, protect, unknown, and break ``functions''} -% \lverb|bool, togl and protect use delimited macros. Only unknown and break -% are true functions with a more flexible parsing of the opening and closing -% parentheses, which may possibly arise from expansion itself.| +% \subsection{The bool, togl, protect pseudo ``functions''} +% \lverb|bool, togl and protect use delimited macros. They are not true +% functions, they turn off the parser to gather their "variable".| % \begin{macrocode} \def\XINT_expr_onlitteral_bool #1)% {\expandafter\XINT_expr_getop\csname .=\xintBool{#1}\endcsname }% @@ -28668,8 +29365,11 @@ $1$ or $-1$. {\expandafter\XINT_expr_getop\csname .=\xintToggle{#1}\endcsname }% \def\XINT_expr_onlitteral_protect #1)% {\expandafter\XINT_expr_getop\csname .=\detokenize{#1}\endcsname }% -\def\XINT_expr_func_unknown #1#2#3% - {\expandafter #1\expandafter #2\csname .=0\endcsname }% +% \end{macrocode} +% \subsection{The break function} +% \lverb|break is a true function, the parsing via expansion of the succeeding +% material proceeded via _oparen macros as with any other function.| +% \begin{macrocode} \def\XINT_expr_func_break #1#2#3% {\expandafter #1\expandafter #2\csname.=?\romannumeral`&&@\XINT_expr_unlock #3\endcsname }% \let\XINT_flexpr_func_break \XINT_expr_func_break @@ -28687,6 +29387,7 @@ $1$ or $-1$. {\expandafter\XINT_expr_getop\csname .=\XINTinFloatdigits{#1}\endcsname }% % \end{macrocode} % \subsection{seq and the implementation of dummy variables} +% \localtableofcontents % \lverb|All of seq, add, mul, rseq, etc... (actually all of the extensive % changes from xintexpr 1.09n to 1.1) was done around June 15-25th 2014, but the % problem is that I did not document the code enough, and I had a hard time @@ -28774,125 +29475,149 @@ $1$ or $-1$. % \begin{macrocode} \def\XINT_isbalanced_no\xint_bye #1\xint_bye\xint_bye {\xint_c_i }% % \end{macrocode} -% \subsubsection{\csh{XINT_allexpr_func_seqx}, \csh{XINT_allexpr_func_subx}} +% \subsubsection{\csh{XINT_allexpr_func_seqx}} +% \lverb|1.2c uses \xintthebareval, ... which strangely were not available at +% 1.1 time. This spares some tokens from \XINT_expr_seq:_d and cousins. Also now +% variables have changed their mode of operation they pick only one token which +% must be an already encapsulated value. +% +% In \XINT_allexp_seqx, #2 is the list, evaluated and encapsulated, #3 is the +% dummy variable, #4 is the expression to evaluate repeatedly. +% +% A special case is a list generated by <variable>++: then #2 is {\.=+\.=<start>}.| % \begin{macrocode} -\def\XINT_expr_func_seqx #1#2{\XINT_allexpr_seqx \xintbareeval }% -\def\XINT_flexpr_func_seqx #1#2{\XINT_allexpr_seqx \xintbarefloateval}% -\def\XINT_iiexpr_func_seqx #1#2{\XINT_allexpr_seqx \xintbareiieval }% -\def\XINT_allexpr_seqx #1#2#3#4% #2 is the index list, fully evaluated and encapsulated -{% #3 is the Latin letter serving as dummy variable, #4 is the expression to evaluate +\def\XINT_expr_func_seqx #1#2{\XINT_allexpr_seqx \xintthebareeval }% +\def\XINT_flexpr_func_seqx #1#2{\XINT_allexpr_seqx \xintthebarefloateval}% +\def\XINT_iiexpr_func_seqx #1#2{\XINT_allexpr_seqx \xintthebareiieval }% +\def\XINT_allexpr_seqx #1#2#3#4% +{% \expandafter \XINT_expr_getop \csname .=\expandafter\XINT_expr_seq:_aa - \romannumeral`&&@\XINT_expr_unlock #2!{#1#4\relax !#3},^,\endcsname + \romannumeral`&&@\XINT_expr_unlock #2!{#1#4\relax !#3}\endcsname }% \def\XINT_expr_seq:_aa #1{\if +#1\expandafter\XINT_expr_seq:_A\else \expandafter\XINT_expr_seq:_a\fi #1}% % \end{macrocode} -% \subsubsection{break, abort, omit within seq} -% \lverb|when evaluation is done in seq:_d, after the ! we find: the Latin -% letter, the braced evaluated value to which it will be assigned, a saved copy of the -% the \xintexpr stuff, the braced accumulated comma separated list of previous -% computations, and the rest of the list of comma separated values to assign to -% the dummy letter and at the very end there is ^ and the final comma.| +% \subsubsection{Evaluation over list, \csh{XINT_expr_seq:_a} with break, +% abort, omit} +% \lverb|The #2 here is \...bareeval <expression>\relax !<variable name>. The #1 +% is a comma separated list of values to assign to the dummy variable. The +% \XINT_expr_seq_empty? intervenes immediately after handling of firstvalue. +% +% 1.2c has rewritten to a large extent this and other similar loops because +% the dummy variables now fetch a single encapsulated token (apart from a good +% means to lose a few hours needlessly -- as I have had to rewrite and review +% most everything, this change could make the thing more efficient if the same +% variable is used many times in an expression, but we are talking +% micro-seconds here anyhow.)| % \begin{macrocode} \def\XINT_expr_seq:_a #1!#2{\expandafter\XINT_expr_seq_empty? - \romannumeral0\XINT_expr_seq:_b {#2}#1}% -\def\XINT_expr_seq:_b #1#2,{\XINT_expr_seq:_c #2,{#1}}% -\def\XINT_expr_seq:_c #1{\if ,#1\xint_dothis\XINT_expr_seq:_noop\fi - \if ^#1\xint_dothis\XINT_expr_seq:_end\fi - \xint_orthat\XINT_expr_seq:_d #1}% -\def\XINT_expr_seq:_d #1,#2{\expandafter\XINT_expr_seq:_e - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#2{#1}{#2}}% -\def\XINT_expr_seq:_e #1{\if #1^\xint_dothis\XINT_expr_seq:_abort\fi + \romannumeral0\XINT_expr_seq:_b {#2}#1,^,}% +\def\XINT_expr_seq:_b #1#2#3,{% + \if ,#2\xint_dothis\XINT_expr_seq:_noop\fi + \if ^#2\xint_dothis\XINT_expr_seq:_end\fi + \xint_orthat{\expandafter\XINT_expr_seq:_c}\csname.=#2#3\endcsname {#1}% +}% +\def\XINT_expr_seq:_noop\csname.=,#1\endcsname #2{\XINT_expr_seq:_b {#2}#1,}% +\def\XINT_expr_seq:_end \csname.=^\endcsname #1{}% +\def\XINT_expr_seq:_c #1#2{\expandafter\XINT_expr_seq:_d\romannumeral`&&@#2#1{#2}}% +\def\XINT_expr_seq:_d #1{\if #1^\xint_dothis\XINT_expr_seq:_abort\fi \if #1?\xint_dothis\XINT_expr_seq:_break\fi \if #1!\xint_dothis\XINT_expr_seq:_omit\fi \xint_orthat{\XINT_expr_seq:_goon #1}}% -\def\XINT_expr_seq:_goon #1!#2#3#4{,#1\XINT_expr_seq:_b {#4}}% -\def\XINT_expr_seq:_omit #1!#2#3#4{\XINT_expr_seq:_b {#4}}% \def\XINT_expr_seq:_abort #1!#2#3#4#5^,{}% \def\XINT_expr_seq:_break #1!#2#3#4#5^,{,#1}% -\def\XINT_expr_seq:_noop ,#1{\XINT_expr_seq:_b {#1}}% -\def\XINT_expr_seq:_end ^,#1{}% if all is omit, _empty? constructs "nil" +\def\XINT_expr_seq:_omit #1!#2#3#4{\XINT_expr_seq:_b {#4}}% +\def\XINT_expr_seq:_goon #1!#2#3#4{,#1\XINT_expr_seq:_b {#4}}% +% \end{macrocode} +% \lverb|If all is omitted or list is empty, _empty? will fetch with +% ##1 \endcsname and construct "nil" via <space>\endcsname, if not ##1 will be +% a comma and the gobble will swallow the space token and the extra \endcsname.| +% \begin{macrocode} \def\XINT_expr_seq_empty? #1{% \def\XINT_expr_seq_empty? ##1{\if ,##1\expandafter\xint_gobble_i\fi #1\endcsname }}% \XINT_expr_seq_empty? { }% % \end{macrocode} -% \subsubsection{\csh{XINT_expr_seq:_A}} -% \lverb|This is for index lists generated by ++. The starting point will have -% been replaced by its ceil. For efficiency I use \numexpr rather than -% \xintInc, hence the indexing is limited to small integers.| +% \subsubsection{Evaluation over ++ generated lists with \csh{XINT_expr_seq:_A}} +% \lverb|This is for index lists generated by n++. The starting point will have +% been replaced by its ceil (added: in fact with version 1.1. the ceil was not +% yet evaluated, but _var_<letter> did an expansion of what they fetch). We use +% \numexpr rather than \xintInc, hence the indexing is limited to small +% integers. +% +% The 1.2c version of n++ produces a #1 here which is already a single +% \.=<value> token.| % \begin{macrocode} -\def\XINT_expr_seq:_A +#1!#2,^,% - {\expandafter\XINT_expr_seq_empty?\romannumeral0\XINT_expr_seq:_D {#1}{#2}}% -\def\XINT_expr_seq:_D #1#2{\expandafter\XINT_expr_seq:_E - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#2{#1}{#2}}% +\def\XINT_expr_seq:_A +#1!% + {\expandafter\XINT_expr_seq_empty?\romannumeral0\XINT_expr_seq:_D #1}% +\def\XINT_expr_seq:_D #1#2{\expandafter\XINT_expr_seq:_E\romannumeral`&&@#2#1{#2}}% \def\XINT_expr_seq:_E #1{\if #1^\xint_dothis\XINT_expr_seq:_Abort\fi \if #1?\xint_dothis\XINT_expr_seq:_Break\fi \if #1!\xint_dothis\XINT_expr_seq:_Omit\fi \xint_orthat{\XINT_expr_seq:_Goon #1}}% -\def\XINT_expr_seq:_Goon #1!#2#3#4% - {,#1\expandafter\XINT_expr_seq:_D\expandafter{\the\numexpr #3+\xint_c_i}{#4}}% -\def\XINT_expr_seq:_Omit #1!#2#3#4% - {\expandafter\XINT_expr_seq:_D\expandafter{\the\numexpr #3+\xint_c_i}{#4}}% \def\XINT_expr_seq:_Abort #1!#2#3#4{}% \def\XINT_expr_seq:_Break #1!#2#3#4{,#1}% -% \end{macrocode} -% \subsubsection{add and mul, \csh{XINT_expr_onlitteral_add}, -% \csh{XINT_expr_onlitteral_mul}} +\def\XINT_expr_seq:_Omit #1!#2#3% + {\expandafter\XINT_expr_seq:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\endcsname}% +\def\XINT_expr_seq:_Goon #1!#2#3% + {,#1\expandafter\XINT_expr_seq:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\endcsname}% +% \end{macrocode} +% \subsection{add, mul} +% \lverb|1.2c uses more directly the \xintiiAdd etc... macros and has +% opxadd/opxmul rather than a single opx. This is less conceptual as I use +% explicitely the associated macro names for +, * but this makes other things +% more efficient, and the code more readable.| % \begin{macrocode} \def\XINT_expr_onlitteral_add {\expandafter\XINT_expr_onlitteral_add_f\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}}% -\def\XINT_expr_onlitteral_add_f #1#2{\xint_c_xviii `{opx}#2)\relax #1+}% +\def\XINT_expr_onlitteral_add_f #1#2{\xint_c_xviii `{opxadd}#2)\relax #1}% \def\XINT_expr_onlitteral_mul {\expandafter\XINT_expr_onlitteral_mul_f\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}}% -\def\XINT_expr_onlitteral_mul_f #1#2{\xint_c_xviii `{opx}#2)\relax #1*}% -% \end{macrocode} -% \subsubsection{\csh{XINT_expr_func_opx}, \csh{XINT_flexpr_func_opx}, -% \csh{XINT_iiexpr_func_opx}} -% \begin{macrocode} -\expandafter\edef\csname XINT_expr_op:_+\endcsname - {\noexpand\xint_gobble_v {}{}{}\expandafter\noexpand\csname .=0\endcsname}% -\expandafter\edef\csname XINT_expr_op:_*\endcsname - {\noexpand\xint_gobble_v {}{}{}\expandafter\noexpand\csname .=1\endcsname}% -\def\XINT_expr_func_opx #1#2{\XINT_allexpr_opx \xintexpr }% -\def\XINT_flexpr_func_opx #1#2{\XINT_allexpr_opx \xintfloatexpr }% -\def\XINT_iiexpr_func_opx #1#2{\XINT_allexpr_opx \xintiiexpr }% -\def\XINT_allexpr_opx #1#2#3#4#5% +\def\XINT_expr_onlitteral_mul_f #1#2{\xint_c_xviii `{opxmul}#2)\relax #1}% % \end{macrocode} -% \lverb|au d\'epart on avait op(#4,#3=#2 (\'evalu\'e ici)) #3=la variable, -% #4=expression, #5=+ ou*.| +% \subsubsection{\csh{XINT_expr_func_opxadd}, \csh{XINT_flexpr_func_opxadd}, +% \csh{XINT_iiexpr_func_opxadd} and same for mul} +% |modified 1.2c.| % \begin{macrocode} -{% - \expandafter\XINT_expr_getop\romannumeral0\expandafter\XINT_expr_op:_a - \csname XINT_expr_op:_#5\expandafter\endcsname - \romannumeral`&&@\XINT_expr_unlock #2!#5#1#3{#4}% -}% -% \end{macrocode} -% \subsubsection{\csh{XINT_expr_op:_a}, \dots} -% \begin{macrocode} -\def\XINT_expr_op:_a #1#2!#3#4#5#6{\XINT_expr_op:_b {#1#4#3{#6\relax\relax !#5}}#2,^,}% +\def\XINT_expr_func_opxadd #1#2{\XINT_allexpr_opx \xintbareeval {\xintAdd 0}}% +\def\XINT_flexpr_func_opxadd #1#2{\XINT_allexpr_opx \xintbarefloateval {\XINTinFloatAdd 0}}% +\def\XINT_iiexpr_func_opxadd #1#2{\XINT_allexpr_opx \xintbareiieval {\xintiiAdd 0}}% +\def\XINT_expr_func_opxmul #1#2{\XINT_allexpr_opx \xintbareeval {\xintMul 1}}% +\def\XINT_flexpr_func_opxmul #1#2{\XINT_allexpr_opx \xintbarefloateval {\XINTinFloatMul 1}}% +\def\XINT_iiexpr_func_opxmul #1#2{\XINT_allexpr_opx \xintbareiieval {\xintiiMul 1}}% % \end{macrocode} -% \lverb|#1=op_+ ou op_*, #2=liste, #3=+ou*,#4=\xintexpr, etc, #5=la -% var,#6=expression| +% \lverb|#1=bareval etc, #2={Add0} ou {Mul1}, #3=liste encapsulée, #4=la variable, #5=expression| % \begin{macrocode} -\def\XINT_expr_op:_b #1#2,{\XINT_expr_op:_c #2,#1}% -\def\XINT_expr_op:_c #1{\if ,#1\xint_dothis\XINT_expr_op:_noop\fi - \if ^#1\xint_dothis\XINT_expr_op:_end\fi - \xint_orthat\XINT_expr_op:_d #1}% -\def\XINT_expr_op:_noop #1,#2#3#4#5{\XINT_expr_op:_b {{#2}#3#4{#5}}}% -\def\XINT_expr_op:_d #1,#2#3#4#5% -% \end{macrocode} -% \lverb|#1=valeur, #2=partiel, #3=\xintexpr #4=+ ou *, #5 = expression| -% \begin{macrocode} - {\expandafter\expandafter\expandafter\XINT_expr_op:_e #3#2#4#3#5{#1}{#3#4{#5}}}% +\def\XINT_allexpr_opx #1#2#3#4#5% +{% + \expandafter\XINT_expr_getop + \csname.=\romannumeral`&&@\expandafter\XINT_expr_op:_a + \romannumeral`&&@\XINT_expr_unlock #3!{#1#5\relax !#4}{#2}\endcsname +}% +\def\XINT_expr_op:_a #1!#2#3{\XINT_expr_op:_b #3{#2}#1,^,}% % \end{macrocode} -% \lverb|#2=nom de la variable, #3=ancienne valeur variable| +% \lverb|#2 in \XINT_expr_op:_b is the partial result of computation so far, not +% locked. A noop with have #4=, and #5 the next item which we need to recover. +% No need to be very efficient for that in op:_noop. In op:_d, #4 is \xintAdd or +% similar.| % \begin{macrocode} -\def\XINT_expr_op:_e !#1!#2#3#4{\XINT_expr_op:_b {{!#1}#4}}% -\def\XINT_expr_op:_end ^,#1#2#3#4{\expandafter\expandafter\expandafter\space - \expandafter\xint_gobble_iv #1}% +\def\XINT_expr_op:_b #1#2#3#4#5,{% + \if ,#4\xint_dothis\XINT_expr_op:_noop\fi + \if ^#4\xint_dothis\XINT_expr_op:_end\fi + \xint_orthat{\expandafter\XINT_expr_op:_c}\csname.=#4#5\endcsname {#3}#1{#2}% +}% +\def\XINT_expr_op:_c #1#2#3#4{\expandafter\XINT_expr_op:_d\romannumeral0#2#1#3{#4}{#2}}% +\def\XINT_expr_op:_d #1!#2#3#4#5% + {\expandafter\XINT_expr_op:_b\expandafter #4\expandafter + {\romannumeral`&&@#4{\XINT_expr_unlock#1}{#5}}}% +\def\XINT_expr_op:_noop\csname.=,#1\endcsname #2#3#4{\XINT_expr_seq:_b #3{#4}{#2}#1,}% +\def\XINT_expr_op:_end \csname.=^\endcsname #1#2#3{#3}% % \end{macrocode} -% \subsubsection{subs, \csh{XINT_expr_onlitteral_subs}} +% \subsection{subs} +% \lverb|Got simpler with 1.2c as now the dummy variable fetches an already encapsulated +% value, which is anyhow the form in which we get it.| % \begin{macrocode} \def\XINT_expr_onlitteral_subs {\expandafter\XINT_expr_onlitteral_subs_f\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}}% @@ -28902,66 +29627,69 @@ $1$ or $-1$. \def\XINT_iiexpr_func_subx #1#2{\XINT_allexpr_subx \xintbareiieval }% \def\XINT_allexpr_subx #1#2#3#4% #2 is the value to assign to the dummy variable {% #3 is the dummy variable, #4 is the expression to evaluate - \expandafter \XINT_expr_getop - \csname .=\expandafter\XINT_expr_subx:_a - \romannumeral`&&@\XINT_expr_unlock #2!{#1#4\relax !#3}\endcsname + \expandafter\expandafter\expandafter\XINT_expr_getop + \expandafter\XINT_expr_subx:_end\romannumeral0#1#4\relax !#3#2% }% -\def\XINT_expr_subx:_a #1!#2% - {\expandafter\XINT_expr_subx:_end \romannumeral0#2{#1}}% -% \end{macrocode} -% \lverb|attention, if one day I add a space in unlock, will need -% \romannumeral-`0| -% \begin{macrocode} -\def\XINT_expr_subx:_end #1!#2#3{\XINT_expr_unlock #1}% +\def\XINT_expr_subx:_end #1!#2#3{#1}% % \end{macrocode} % \subsection{rseq} -% \lverb|When func_rseq has its turn, initial segment has been scanned by oparen, the ; -% mimicking the rôle of a closing parenthesis, and stopping further expansion.| +% \localtableofcontents +% +% \lverb|When func_rseq has its turn, initial segment has been scanned by +% oparen, the ; mimicking the rôle of a closing parenthesis, and stopping +% further expansion. Notice that the ; is discovered during standard parsing +% mode, it may be for example {;} or arise from expansion as rseq does not use +% a delimited macro to locate it. +% +% Here and in rrseq and iter, 1.2c adds also use of \xintthebareeval, etc...| % \begin{macrocode} -\def\XINT_expr_func_rseq {\XINT_allexpr_rseq \xintbareeval }% -\def\XINT_flexpr_func_rseq {\XINT_allexpr_rseq \xintbarefloateval }% -\def\XINT_iiexpr_func_rseq {\XINT_allexpr_rseq \xintbareiieval }% -\def\XINT_allexpr_rseq #1#2% +\def\XINT_expr_func_rseq {\XINT_allexpr_rseq \xintbareeval \xintthebareeval }% +\def\XINT_flexpr_func_rseq {\XINT_allexpr_rseq \xintbarefloateval \xintthebarefloateval }% +\def\XINT_iiexpr_func_rseq {\XINT_allexpr_rseq \xintbareiieval \xintthebareiieval }% +\def\XINT_allexpr_rseq #1#2#3% {% - \expandafter\XINT_expr_rseqx\expandafter #1\expandafter - #2\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% + \expandafter\XINT_expr_rseqx\expandafter #1\expandafter#2\expandafter + #3\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% }% % \end{macrocode} % \subsubsection{\csh{XINT_expr_rseqx}} -% \lverb|The (#4) is for ++ mechanism which must have its closing parenthesis.| +% \lverb|The (#5) is for ++ mechanism which must have its closing parenthesis.| % \begin{macrocode} -\def\XINT_expr_rseqx #1#2#3#4% +\def\XINT_expr_rseqx #1#2#3#4#5% {% - \expandafter\XINT_expr_rseqy\romannumeral0#1(#4)\relax - #2#3#1% + \expandafter\XINT_expr_rseqy\romannumeral0#1(#5)\relax #3#4#2% }% % \end{macrocode} % \subsubsection{\csh{XINT_expr_rseqy}} % \lverb|#1=valeurs pour variable (locked), % #2=toutes les valeurs initiales (csv,locked), % #3=variable, #4=expr, -% #5=\xintbareeval ou \xintbarefloateval ou \xintbareiieval| +% #5=\xintthebareeval ou \xintthebarefloateval ou \xintthebareiieval| % \begin{macrocode} \def\XINT_expr_rseqy #1#2#3#4#5% {% \expandafter \XINT_expr_getop \csname .=\XINT_expr_unlock #2% \expandafter\XINT_expr_rseq:_aa - \romannumeral`&&@\XINT_expr_unlock #1!{#5#4\relax !#3}#2,^,\endcsname + \romannumeral`&&@\XINT_expr_unlock #1!{#5#4\relax !#3}#2\endcsname }% \def\XINT_expr_rseq:_aa #1{\if +#1\expandafter\XINT_expr_rseq:_A\else \expandafter\XINT_expr_rseq:_a\fi #1}% % \end{macrocode} % \subsubsection{\csh{XINT_expr_rseq:_a} etc\dots} % \begin{macrocode} -\def\XINT_expr_rseq:_a #1!#2#3{\XINT_expr_rseq:_b #3{#2}#1}% -\def\XINT_expr_rseq:_b #1#2#3,{\XINT_expr_rseq:_c #3,~#1{#2}}% -\def\XINT_expr_rseq:_c #1{\if ,#1\xint_dothis\XINT_expr_rseq:_noop\fi - \if ^#1\xint_dothis\XINT_expr_rseq:_end\fi - \xint_orthat\XINT_expr_rseq:_d #1}% -\def\XINT_expr_rseq:_d #1,~#2#3{\expandafter\XINT_expr_rseq:_e - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#3{#1}~#2{#3}}% -\def\XINT_expr_rseq:_e #1{% +\def\XINT_expr_rseq:_a #1!#2#3{\XINT_expr_rseq:_b {#3}{#2}#1,^,}% +\def\XINT_expr_rseq:_b #1#2#3#4,{% + \if ,#3\xint_dothis\XINT_expr_rseq:_noop\fi + \if ^#3\xint_dothis\XINT_expr_rseq:_end\fi + \xint_orthat{\expandafter\XINT_expr_rseq:_c}\csname.=#3#4\endcsname + {#1}{#2}% +}% +\def\XINT_expr_rseq:_noop\csname.=,#1\endcsname #2#3{\XINT_expr_rseq:_b {#2}{#3}#1,}% +\def\XINT_expr_rseq:_end \csname.=^\endcsname #1#2{}% +\def\XINT_expr_rseq:_c #1#2#3% + {\expandafter\XINT_expr_rseq:_d\romannumeral`&&@#3#1~#2{#3}}% +\def\XINT_expr_rseq:_d #1{% \if ^#1\xint_dothis\XINT_expr_rseq:_abort\fi \if ?#1\xint_dothis\XINT_expr_rseq:_break\fi \if !#1\xint_dothis\XINT_expr_rseq:_omit\fi @@ -28971,49 +29699,50 @@ $1$ or $-1$. \def\XINT_expr_rseq:_omit #1!#2#3~{\XINT_expr_rseq:_b }% \def\XINT_expr_rseq:_abort #1!#2#3~#4#5#6^,{}% \def\XINT_expr_rseq:_break #1!#2#3~#4#5#6^,{,#1}% -\def\XINT_expr_rseq:_noop ,~#1#2{\XINT_expr_rseq:_b #1{#2}}% -\def\XINT_expr_rseq:_end ^,~#1#2{}% no nil for rseq % \end{macrocode} % \subsubsection{\csh{XINT_expr_rseq:_A} etc\dots} -% \lverb |n++ for rseq| +% \lverb |n++ for rseq. With 1.2c dummy variables pick a single token.| % \begin{macrocode} -\def\XINT_expr_rseq:_A +#1!#2#3,^,{\XINT_expr_rseq:_D {#1}#3{#2}}% -\def\XINT_expr_rseq:_D #1#2#3{\expandafter\XINT_expr_rseq:_E - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#3{#1}~#2{#3}}% +\def\XINT_expr_rseq:_A +#1!#2#3{\XINT_expr_rseq:_D #1#3{#2}}% +\def\XINT_expr_rseq:_D #1#2#3% + {\expandafter\XINT_expr_rseq:_E\romannumeral`&&@#3#1~#2{#3}}% \def\XINT_expr_rseq:_E #1{\if #1^\xint_dothis\XINT_expr_rseq:_Abort\fi \if #1?\xint_dothis\XINT_expr_rseq:_Break\fi \if #1!\xint_dothis\XINT_expr_rseq:_Omit\fi \xint_orthat{\XINT_expr_rseq:_Goon #1}}% \def\XINT_expr_rseq:_Goon #1!#2#3~#4#5% - {,#1\expandafter\XINT_expr_rseq:_D\expandafter{\the\numexpr #3+\xint_c_i\expandafter}% - \romannumeral0\XINT_expr_lockit{#1}{#5}}% + {,#1\expandafter\XINT_expr_rseq:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\expandafter\endcsname + \romannumeral0\XINT_expr_lockit{#1}{#5}}% \def\XINT_expr_rseq:_Omit #1!#2#3~%#4#5% - {\expandafter\XINT_expr_rseq:_D\expandafter{\the\numexpr #3+\xint_c_i}}% + {\expandafter\XINT_expr_rseq:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\endcsname }% \def\XINT_expr_rseq:_Abort #1!#2#3~#4#5{}% \def\XINT_expr_rseq:_Break #1!#2#3~#4#5{,#1}% % \end{macrocode} % \subsection{rrseq} +% \localtableofcontents % \lverb|When func_rrseq has its turn, initial segment has been scanned by oparen, the ; % mimicking the rôle of a closing parenthesis, and stopping further expansion.| % \begin{macrocode} -\def\XINT_expr_func_rrseq {\XINT_allexpr_rrseq \xintbareeval }% -\def\XINT_flexpr_func_rrseq {\XINT_allexpr_rrseq \xintbarefloateval }% -\def\XINT_iiexpr_func_rrseq {\XINT_allexpr_rrseq \xintbareiieval }% -\def\XINT_allexpr_rrseq #1#2% +\def\XINT_expr_func_rrseq {\XINT_allexpr_rrseq \xintbareeval \xintthebareeval }% +\def\XINT_flexpr_func_rrseq {\XINT_allexpr_rrseq \xintbarefloateval \xintthebarefloateval }% +\def\XINT_iiexpr_func_rrseq {\XINT_allexpr_rrseq \xintbareiieval \xintthebareiieval }% +\def\XINT_allexpr_rrseq #1#2#3% {% - \expandafter\XINT_expr_rrseqx\expandafter #1\expandafter - #2\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% + \expandafter\XINT_expr_rrseqx\expandafter #1\expandafter#2\expandafter + #3\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% }% % \end{macrocode} % \subsubsection{\csh{XINT_expr_rrseqx}} -% \lverb|The (#4) is for ++ mechanism which must have its closing parenthesis.| +% \lverb|The (#5) is for ++ mechanism which must have its closing parenthesis.| % \begin{macrocode} -\def\XINT_expr_rrseqx #1#2#3#4% +\def\XINT_expr_rrseqx #1#2#3#4#5% {% - \expandafter\XINT_expr_rrseqy\romannumeral0#1(#4)\expandafter\relax + \expandafter\XINT_expr_rrseqy\romannumeral0#1(#5)\expandafter\relax \expandafter{\romannumeral0\xintapply \XINT_expr_lockit - {\xintRevWithBraces{\xintCSVtoListNonStripped{\XINT_expr_unlock #2}}}}% - #2#3#1% + {\xintRevWithBraces{\xintCSVtoListNonStripped{\XINT_expr_unlock #3}}}}% + #3#4#2% }% % \end{macrocode} % \subsubsection{\csh{XINT_expr_rrseqy}} @@ -29021,83 +29750,86 @@ $1$ or $-1$. % #2=initial values (reversed, one (braced) token each) % #3=toutes les valeurs initiales (csv,locked), % #4=variable, #5=expr, -% #6=\xintbareeval ou \xintbarefloateval ou \xintbareiieval| +% #6=\xintthebareeval ou \xintthebarefloateval ou \xintthebareiieval| % \begin{macrocode} \def\XINT_expr_rrseqy #1#2#3#4#5#6% {% \expandafter \XINT_expr_getop \csname .=\XINT_expr_unlock #3% \expandafter\XINT_expr_rrseq:_aa - \romannumeral`&&@\XINT_expr_unlock #1!{#6#5\relax !#4}{#2},^,\endcsname + \romannumeral`&&@\XINT_expr_unlock #1!{#6#5\relax !#4}{#2}\endcsname }% \def\XINT_expr_rrseq:_aa #1{\if +#1\expandafter\XINT_expr_rrseq:_A\else \expandafter\XINT_expr_rrseq:_a\fi #1}% % \end{macrocode} % \subsubsection{\csh{XINT_expr_rrseq:_a} etc\dots} +% \lverb|Attention que ? a catcode 3 ici et dans iter.| % \begin{macrocode} \catcode`? 3 -\def\XINT_expr_rrseq:_a #1!#2#3{\XINT_expr_rrseq:_b {#3}{#2}#1}% -\def\XINT_expr_rrseq:_b #1#2#3,{\XINT_expr_rrseq:_c #3,~#1?{#2}}% -\def\XINT_expr_rrseq:_c #1{\if ,#1\xint_dothis\XINT_expr_rrseq:_noop\fi - \if ^#1\xint_dothis\XINT_expr_rrseq:_end\fi - \xint_orthat\XINT_expr_rrseq:_d #1}% -\def\XINT_expr_rrseq:_d #1,~#2?#3{\expandafter\XINT_expr_rrseq:_e - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#3{#1}~#2?{#3}}% -\def\XINT_expr_rrseq:_goon #1!#2#3~#4?#5{,#1\expandafter\XINT_expr_rrseq:_b\expandafter - {\romannumeral0\xinttrim{-1}{\XINT_expr_lockit{#1}#4}}{#5}}% -\def\XINT_expr_rrseq:_omit #1!#2#3~{\XINT_expr_rrseq:_b }% -\def\XINT_expr_rrseq:_abort #1!#2#3~#4?#5#6^,{}% -\def\XINT_expr_rrseq:_break #1!#2#3~#4?#5#6^,{,#1}% -\def\XINT_expr_rrseq:_noop ,~#1?#2{\XINT_expr_rrseq:_b {#1}{#2}}% -\def\XINT_expr_rrseq:_end ^,~#1?#2{}% No nil for rrseq. -\catcode`? 11 -\def\XINT_expr_rrseq:_e #1{% +\def\XINT_expr_rrseq:_a #1!#2#3{\XINT_expr_rrseq:_b {#3}{#2}#1,^,}% +\def\XINT_expr_rrseq:_b #1#2#3#4,{% + \if ,#3\xint_dothis\XINT_expr_rrseq:_noop\fi + \if ^#3\xint_dothis\XINT_expr_rrseq:_end\fi + \xint_orthat{\expandafter\XINT_expr_rrseq:_c}\csname.=#3#4\endcsname + {#1}{#2}% +}% +\def\XINT_expr_rrseq:_noop\csname.=,#1\endcsname #2#3{\XINT_expr_rrseq:_b {#2}{#3}#1,}% +\def\XINT_expr_rrseq:_end \csname.=^\endcsname #1#2{}% +\def\XINT_expr_rrseq:_c #1#2#3% + {\expandafter\XINT_expr_rrseq:_d\romannumeral`&&@#3#1~#2?{#3}}% +\def\XINT_expr_rrseq:_d #1{% \if ^#1\xint_dothis\XINT_expr_rrseq:_abort\fi \if ?#1\xint_dothis\XINT_expr_rrseq:_break\fi \if !#1\xint_dothis\XINT_expr_rrseq:_omit\fi \xint_orthat{\XINT_expr_rrseq:_goon #1}% }% +\def\XINT_expr_rrseq:_goon #1!#2#3~#4?#5{,#1\expandafter\XINT_expr_rrseq:_b\expandafter + {\romannumeral0\xinttrim{-1}{\XINT_expr_lockit{#1}#4}}{#5}}% +\def\XINT_expr_rrseq:_omit #1!#2#3~{\XINT_expr_rrseq:_b }% +\def\XINT_expr_rrseq:_abort #1!#2#3~#4?#5#6^,{}% +\def\XINT_expr_rrseq:_break #1!#2#3~#4?#5#6^,{,#1}% % \end{macrocode} % \subsubsection{\csh{XINT_expr_rrseq:_A} etc\dots} -% \lverb |n++ for rrseq| +% \lverb |n++ for rrseq. With 1.2C, the #1 in \XINT_expr_rrseq:_A is a single token.| % \begin{macrocode} -\catcode`? 3 -\def\XINT_expr_rrseq:_A +#1!#2#3,^,{\XINT_expr_rrseq:_D {#1}{#3}{#2}}% -\def\XINT_expr_rrseq:_D #1#2#3{\expandafter\XINT_expr_rrseq:_E - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#3{#1}~#2?{#3}}% +\def\XINT_expr_rrseq:_A +#1!#2#3{\XINT_expr_rrseq:_D #1{#3}{#2}}% +\def\XINT_expr_rrseq:_D #1#2#3% + {\expandafter\XINT_expr_rrseq:_E\romannumeral`&&@#3#1~#2?{#3}}% \def\XINT_expr_rrseq:_Goon #1!#2#3~#4?#5% - {,#1\expandafter\XINT_expr_rrseq:_D\expandafter{\the\numexpr #3+\xint_c_i\expandafter}% + {,#1\expandafter\XINT_expr_rrseq:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\expandafter\endcsname \expandafter{\romannumeral0\xinttrim{-1}{\XINT_expr_lockit{#1}#4}}{#5}}% \def\XINT_expr_rrseq:_Omit #1!#2#3~%#4?#5% - {\expandafter\XINT_expr_rrseq:_D\expandafter{\the\numexpr #3+\xint_c_i}}% + {\expandafter\XINT_expr_rrseq:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\endcsname}% \def\XINT_expr_rrseq:_Abort #1!#2#3~#4?#5{}% \def\XINT_expr_rrseq:_Break #1!#2#3~#4?#5{,#1}% -\catcode`? 11 \def\XINT_expr_rrseq:_E #1{\if #1^\xint_dothis\XINT_expr_rrseq:_Abort\fi \if #1?\xint_dothis\XINT_expr_rrseq:_Break\fi \if #1!\xint_dothis\XINT_expr_rrseq:_Omit\fi \xint_orthat{\XINT_expr_rrseq:_Goon #1}}% % \end{macrocode} % \subsection{iter} +% \localtableofcontents % \begin{macrocode} -\def\XINT_expr_func_iter {\XINT_allexpr_iter \xintbareeval }% -\def\XINT_flexpr_func_iter {\XINT_allexpr_iter \xintbarefloateval }% -\def\XINT_iiexpr_func_iter {\XINT_allexpr_iter \xintbareiieval }% -\def\XINT_allexpr_iter #1#2% +\def\XINT_expr_func_iter {\XINT_allexpr_iter \xintbareeval \xintthebareeval }% +\def\XINT_flexpr_func_iter {\XINT_allexpr_iter \xintbarefloateval \xintthebarefloateval }% +\def\XINT_iiexpr_func_iter {\XINT_allexpr_iter \xintbareiieval \xintthebareiieval }% +\def\XINT_allexpr_iter #1#2#3% {% - \expandafter\XINT_expr_iterx\expandafter #1\expandafter - #2\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% + \expandafter\XINT_expr_iterx\expandafter #1\expandafter #2\expandafter + #3\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% }% % \end{macrocode} % \subsubsection{\csh{XINT_expr_iterx}} -% \lverb|The (#4) is for ++ mechanism which must have its closing parenthesis.| +% \lverb|The (#5) is for ++ mechanism which must have its closing parenthesis.| % \begin{macrocode} -\def\XINT_expr_iterx #1#2#3#4% +\def\XINT_expr_iterx #1#2#3#4#5% {% - \expandafter\XINT_expr_itery\romannumeral0#1(#4)\expandafter\relax + \expandafter\XINT_expr_itery\romannumeral0#1(#5)\expandafter\relax \expandafter{\romannumeral0\xintapply \XINT_expr_lockit - {\xintRevWithBraces{\xintCSVtoListNonStripped{\XINT_expr_unlock #2}}}}% - #2#3#1% + {\xintRevWithBraces{\xintCSVtoListNonStripped{\XINT_expr_unlock #3}}}}% + #3#4#2% }% % \end{macrocode} % \subsubsection{\csh{XINT_expr_itery}} @@ -29112,21 +29844,32 @@ $1$ or $-1$. \expandafter \XINT_expr_getop \csname .=% \expandafter\XINT_expr_iter:_aa - \romannumeral`&&@\XINT_expr_unlock #1!{#6#5\relax !#4}{#2},^,\endcsname + \romannumeral`&&@\XINT_expr_unlock #1!{#6#5\relax !#4}{#2}\endcsname }% \def\XINT_expr_iter:_aa #1{\if +#1\expandafter\XINT_expr_iter:_A\else \expandafter\XINT_expr_iter:_a\fi #1}% % \end{macrocode} % \subsubsection{\csh{XINT_expr_iter:_a} etc\dots} % \begin{macrocode} -\catcode`? 3 -\def\XINT_expr_iter:_a #1!#2#3{\XINT_expr_iter:_b {#3}{#2}#1}% -\def\XINT_expr_iter:_b #1#2#3,{\XINT_expr_iter:_c #3,~#1?{#2}}% -\def\XINT_expr_iter:_c #1{\if ,#1\xint_dothis\XINT_expr_iter:_noop\fi - \if ^#1\xint_dothis\XINT_expr_iter:_end\fi - \xint_orthat\XINT_expr_iter:_d #1}% -\def\XINT_expr_iter:_d #1,~#2?#3{\expandafter\XINT_expr_iter:_e - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#3{#1}~#2?{#3}}% +\def\XINT_expr_iter:_a #1!#2#3{\XINT_expr_iter:_b {#3}{#2}#1,^,}% +\def\XINT_expr_iter:_b #1#2#3#4,{% + \if ,#3\xint_dothis\XINT_expr_iter:_noop\fi + \if ^#3\xint_dothis\XINT_expr_iter:_end\fi + \xint_orthat{\expandafter\XINT_expr_iter:_c}\csname.=#3#4\endcsname + {#1}{#2}% +}% +\def\XINT_expr_iter:_noop\csname.=,#1\endcsname #2#3{\XINT_expr_iter:_b {#2}{#3}#1,}% +\def\XINT_expr_iter:_end \csname.=^\endcsname #1#2% + {\expandafter\xint_gobble_i\romannumeral0\xintapplyunbraced + {,\XINT_expr:_unlock}{\xintReverseOrder{#1\space}}}% +\def\XINT_expr_iter:_c #1#2#3% + {\expandafter\XINT_expr_iter:_d\romannumeral`&&@#3#1~#2?{#3}}% +\def\XINT_expr_iter:_d #1{% + \if ^#1\xint_dothis\XINT_expr_iter:_abort\fi + \if ?#1\xint_dothis\XINT_expr_iter:_break\fi + \if !#1\xint_dothis\XINT_expr_iter:_omit\fi + \xint_orthat{\XINT_expr_iter:_goon #1}% +}% \def\XINT_expr_iter:_goon #1!#2#3~#4?#5{\expandafter\XINT_expr_iter:_b\expandafter {\romannumeral0\xinttrim{-1}{\XINT_expr_lockit{#1}#4}}{#5}}% \def\XINT_expr_iter:_omit #1!#2#3~{\XINT_expr_iter:_b }% @@ -29136,53 +29879,42 @@ $1$ or $-1$. \def\XINT_expr_iter:_break #1!#2#3~#4?#5#6^,% {\expandafter\xint_gobble_iv\romannumeral0\xintapplyunbraced {,\XINT_expr:_unlock}{\xintReverseOrder{#4\space}},#1}% -\def\XINT_expr_iter:_noop ,~#1?#2{\XINT_expr_iter:_b {#1}{#2}}% -\def\XINT_expr_iter:_end ^,~#1?#2% - {\expandafter\xint_gobble_i\romannumeral0\xintapplyunbraced - {,\XINT_expr:_unlock}{\xintReverseOrder{#1\space}}}% -\catcode`? 11 -\def\XINT_expr_iter:_e #1{% - \if ^#1\xint_dothis\XINT_expr_iter:_abort\fi - \if ?#1\xint_dothis\XINT_expr_iter:_break\fi - \if !#1\xint_dothis\XINT_expr_iter:_omit\fi - \xint_orthat{\XINT_expr_iter:_goon #1}% -}% \def\XINT_expr:_unlock #1{\XINT_expr_unlock #1}% % \end{macrocode} % \subsubsection{\csh{XINT_expr_iter:_A} etc\dots} -% \lverb |n++ for iter| +% \lverb |n++ for iter. ? is of catcode 3 here.| % \begin{macrocode} -\catcode`? 3 -\def\XINT_expr_iter:_A +#1!#2#3,^,{\XINT_expr_iter:_D {#1}{#3}{#2}}% -\def\XINT_expr_iter:_D #1#2#3{\expandafter\XINT_expr_iter:_E - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#3{#1}~#2?{#3}}% +\def\XINT_expr_iter:_A +#1!#2#3{\XINT_expr_iter:_D #1{#3}{#2}}% +\def\XINT_expr_iter:_D #1#2#3% + {\expandafter\XINT_expr_iter:_E\romannumeral`&&@#3#1~#2?{#3}}% \def\XINT_expr_iter:_Goon #1!#2#3~#4?#5% - {\expandafter\XINT_expr_iter:_D\expandafter{\the\numexpr #3+\xint_c_i\expandafter}% + {\expandafter\XINT_expr_iter:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\expandafter\endcsname \expandafter{\romannumeral0\xinttrim{-1}{\XINT_expr_lockit{#1}#4}}{#5}}% \def\XINT_expr_iter:_Omit #1!#2#3~%#4?#5% - {\expandafter\XINT_expr_iter:_D\expandafter{\the\numexpr #3+\xint_c_i}}% + {\expandafter\XINT_expr_iter:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\endcsname}% \def\XINT_expr_iter:_Abort #1!#2#3~#4?#5% {\expandafter\xint_gobble_i\romannumeral0\xintapplyunbraced {,\XINT_expr:_unlock}{\xintReverseOrder{#4\space}}}% \def\XINT_expr_iter:_Break #1!#2#3~#4?#5% {\expandafter\xint_gobble_iv\romannumeral0\xintapplyunbraced {,\XINT_expr:_unlock}{\xintReverseOrder{#4\space}},#1}% -\catcode`? 11 \def\XINT_expr_iter:_E #1{\if #1^\xint_dothis\XINT_expr_iter:_Abort\fi \if #1?\xint_dothis\XINT_expr_iter:_Break\fi \if #1!\xint_dothis\XINT_expr_iter:_Omit\fi \xint_orthat{\XINT_expr_iter:_Goon #1}}% +\catcode`? 11 % \end{macrocode} % \subsection{Macros handling csv lists for functions with multiple comma % separated arguments in expressions} +% \localtableofcontents % \lverb|These 17 macros are used inside \csname...\endcsname. These things % are not initiated by a \romannumeral in general, but in some cases they are, % especially when involved in an \xintNewExpr. They will then be protected % against expansion and expand only later in contexts governed by an % initial \romannumeral-`0. There each new item may need to be expanded, which % would not be the case in the use for the _func_ things.| -% \begin{macrocode} -% \end{macrocode} % \subsubsection{\csh{xintANDof:csv}} % \lverb|1.09a. For use by \xintexpr inside \csname. 1.1, je remplace % ifTrueAelseB par iiNotZero pour des raisons d'optimisations.| @@ -29315,6 +30047,7 @@ $1$ or $-1$. % +\textasciigrave, \textasciigrave % \texorpdfstring{\protect\lowast}{*}\textasciigrave, ?, !, not, all, any, % xor, if, ifsgn, first, last, even, odd, and reversed functions} +% \localtableofcontents % \begin{macrocode} \def\XINT_expr_twoargs #1,#2,{{#1}{#2}}% \def\XINT_expr_argandopt #1,#2,#3.#4#5% @@ -29358,18 +30091,25 @@ $1$ or $-1$. {\expandafter #1\expandafter #2\csname.=\xintTFrac {\XINT_expr_unlock #3}\endcsname }% \def\XINT_flexpr_func_frac #1#2#3{\expandafter #1\expandafter #2\csname .=\XINTinFloatFracdigits {\XINT_expr_unlock #3}\endcsname }% -% no \XINT_iiexpr_func_frac +% \end{macrocode} +% \lverb|no \XINT_iiexpr_func_frac| +% \begin{macrocode} \def\XINT_expr_func_floor #1#2#3% {\expandafter #1\expandafter #2\csname .=\xintFloor {\XINT_expr_unlock #3}\endcsname }% \let\XINT_flexpr_func_floor\XINT_expr_func_floor +% \end{macrocode} +% \lverb|The floor and ceil functions in \xintiiexpr require protect(a/b) or, +% better, \qfrac(a/b); else the / will be executed first and do an integer +% rounded division.| +% \begin{macrocode} \def\XINT_iiexpr_func_floor #1#2#3% -{% mais absurde si on ne peut pas avoir quotient comme input +{% \expandafter #1\expandafter #2\csname.=\xintiFloor {\XINT_expr_unlock #3}\endcsname }% \def\XINT_expr_func_ceil #1#2#3% {\expandafter #1\expandafter #2\csname .=\xintCeil {\XINT_expr_unlock #3}\endcsname }% \let\XINT_flexpr_func_ceil\XINT_expr_func_ceil \def\XINT_iiexpr_func_ceil #1#2#3% -{% mais absurde si on ne peut pas avoir quotient comme input +{% \expandafter #1\expandafter #2\csname.=\xintiCeil {\XINT_expr_unlock #3}\endcsname }% \def\XINT_expr_func_sqr #1#2#3% {\expandafter #1\expandafter #2\csname.=\xintSqr {\XINT_expr_unlock #3}\endcsname }% @@ -29599,18 +30339,22 @@ $1$ or $-1$. {\expandafter #1\expandafter #2\csname .=\XINT_expr_unlock #3\endcsname }% \let\XINT_flexpr_func_nuple\XINT_expr_func_nuple \let\XINT_iiexpr_func_nuple\XINT_expr_func_nuple +% \end{macrocode} +% \lverb|1.2c +% hesitated but left the function "reversed" from 1.1 with this name, not "reverse". +% But the inner not public macro got renamed into \xintReverse::csv.| +% \begin{macrocode} \def\XINT_expr_func_reversed #1#2#3% - {\expandafter #1\expandafter #2\csname .=\xintReversed::csv - {\XINT_expr_unlock #3}\endcsname }% + {\expandafter #1\expandafter #2\csname .=% + \xintReverse::csv {\XINT_expr_unlock #3}\endcsname }% \let\XINT_flexpr_func_reversed\XINT_expr_func_reversed \let\XINT_iiexpr_func_reversed\XINT_expr_func_reversed -\def\xintReversed::csv #1% should be done directly, of course +\def\xintReverse::csv #1% should be done directly, of course {\xintListWithSep,{\xintRevWithBraces {\xintCSVtoListNonStripped{#1}}}}% % \end{macrocode} -% -% \subsection{f-expandable versions of the SeqB::csv routines, for +% \subsection{f-expandable versions of the \csh{xintSeqB::csv} and alike routines, for % \csh{xintNewExpr}} -% +% \localtableofcontents % \subsubsection{\csh{xintSeqB:f:csv}} % \lverb|Produces in f-expandable way. If the step is zero, gives empty result % except if start and end coincide.| @@ -29648,9 +30392,13 @@ $1$ or $-1$. % \end{macrocode} %\subsubsection{\csh{xintiiSeqB:f:csv}} % \lverb|Produces in f-expandable way. If the step is zero, gives empty result -% except if start and end coincide.| +% except if start and end coincide. +% +% 2015/11/11. I correct a typo dating back to release 1.1 (2014/10/29): the +% macro name had a "b" rather than "B", hence was not functional (causing +% \xintNewIIExpr to fail on inputs such as #1..[1]..#2).| % \begin{macrocode} -\def\xintiiSeqb:f:csv #1#2% +\def\xintiiSeqB:f:csv #1#2% {\expandafter\XINT_iiseqb:f:csv \expandafter{\romannumeral`&&@#2}{#1}}% \def\XINT_iiseqb:f:csv #1#2{\expandafter\XINT_iiseqb:f:csv_a\romannumeral`&&@#2#1!}% \def\XINT_iiseqb:f:csv_a #1#2;#3;#4!{% @@ -29711,8 +30459,59 @@ $1$ or $-1$. \XINT_seqb:f:csv_nc\XINT_seqb:f:csv_nb\XINT_flseqb:f:csv_na {#1}{#2}% }% % \end{macrocode} +% \subsection{User defined functions: \csh{xintdeffunc}, \csh{xintdefiifunc}, +% \csh{xintdeffloatfunc}} +% \localtableofcontents \lverb|1.2c (November 11-12, 2015). It is possible to +% overload a variable name with a function name (and conversely). The function +% interpretation with be used only if followed by an opening parenthesis, +% disabling the tacit multiplication usually applied to variables. Crazy +% things such as add(f(f), f=1..10) are possible if there is a function "f". +% Or we can use "e" both for an exponential function and the Euler constant. +% +% November 13: function candidates names first completely expanded, then +% detokenized and cleaned of spaces. Should xintexpr log the meaning of the +% underlying macro implementing the functions ? | +% \begin{macrocode} +\catcode`: 12 +\def\XINT_tmpa #1#2#3#4% +{% + \def #1##1(##2):=##3;{% + \edef\XINT_expr_tmpa{##1}% + \edef\XINT_expr_tmpa + {\expandafter\xint_zapspaces\detokenize\expandafter{\XINT_expr_tmpa} \xint_gobble_i}% + \def\XINT_expr_tmpb {0}% + \def\XINT_expr_tmpc {##3}% + \xintFor ####1 in {##2} \do + {\edef\XINT_expr_tmpb {\the\numexpr\XINT_expr_tmpb+\xint_c_i}% + \edef\XINT_expr_tmpc {subs(\unexpanded\expandafter{\XINT_expr_tmpc},% + ####1=################\XINT_expr_tmpb)}% + }% + \expandafter#3\csname XINT_#2_userfunc_\XINT_expr_tmpa\endcsname + [\XINT_expr_tmpb]{\XINT_expr_tmpc}% + \expandafter\XINT_expr_defuserfunc + \csname XINT_#2_func_\XINT_expr_tmpa\expandafter\endcsname + \csname XINT_#2_userfunc_\XINT_expr_tmpa\endcsname + \ifxintverbose\xintMessage {info}{xintexpr} + {Function \XINT_expr_tmpa\space for \string\xint #4 parser + associated to \string\XINT_#2_userfunc_\XINT_expr_tmpa\space + with meaning \expandafter\meaning + \csname XINT_#2_userfunc_\XINT_expr_tmpa\endcsname}% + \fi + }% +}% +\catcode`: 11 +\XINT_tmpa\xintdeffunc {expr} \XINT_NewFunc {expr}% +\XINT_tmpa\xintdefiifunc {iiexpr}\XINT_NewIIFunc {iiexpr}% +\XINT_tmpa\xintdeffloatfunc{flexpr}\XINT_NewFloatFunc{floatexpr}% +\def\XINT_expr_defuserfunc #1#2{% + \def #1##1##2##3{\expandafter ##1\expandafter ##2% + \csname .=\expandafter #2\romannumeral-`0\XINT_expr_unlock ##3,\endcsname + }% +}% +% \end{macrocode} % \subsection{\csh{xintNewExpr}, \csh{xintNewIExpr}, \csh{xintNewFloatExpr}, % \csh{xintNewIIExpr}} +% \localtableofcontents % \subsubsection{\csh{xintApply::csv}} % \lverb|Don't ask me what this if for. I wrote it in June 2014, and we are now % late October 2014.| @@ -29745,8 +30544,12 @@ $1$ or $-1$. % \subsubsection{\csh{XINT_expr_RApply::csv}, \csh{XINT_expr_LApply::csv}, % \csh{XINT_expr_RLApply:::csv}} % \lverb|The #1 in _Rapply will start with a ~. No risk of glueing to previous -% ~expandafter during the \scantokens.| +% ~expandafter during the \scantokens. +% +% Attention ici et dans la suite ~ avec catcode 12 (et non pas 3 comme +% ailleurs dans xintexpr).| % \begin{macrocode} +\catcode`~ 12 \def\XINT_expr_RApply::csv #1#2#3#4% {~xintApply::csv{~expandafter#1~xint_exchangetwo_keepbraces{#4}}{#3}}% \def\XINT_expr_LApply::csv #1#2#3#4{~xintApply::csv{#1{#3}}{#4}}% @@ -29755,14 +30558,40 @@ $1$ or $-1$. % \subsubsection{Mysterious stuff} % \lverb|actually I dimly remember that the whole point is to allow maximal % evaluation as long as macro parameters not encountered. Else it would be -% easier. \xintNewIExpr \f [2]{[12] #1+#2+3*6*1} will correctly compute the 18. -% -% 1.1a re-establishes the trick with \toks0\expandafter{\the\toks0\expandafter -% etc...} with *no* space after 0. I don't know why it was removed at some -% point before releasing 1.1, but \XINT_expr_redefinemacros is even bigger -% without the trick.| +% easier. \xintNewIExpr \f [2]{[12] #1+#2+3*6*1} will correctly compute the +% 18. +% +% Comments finally added 2015/12/11: the whole point here is to either expand +% completely a macro such as \xintAdd if it is has numeric arguments (the +% original macro is stored by \xintNewExpr in \xintNEAdd, which is not a good +% name anyhow, as I was reading it as Not Expand, whereas it is exactly the +% opposite and NE stands for New Expr), or handle the case when one of the two +% parameters only is numerical (the other being either a macro parameter, or a +% previously found macro not be expanded -- this is recursive), or none of +% them. In that case though, the non-numerical parameter may well stand +% ultimately for a whole list. Hence the various \xintApply one finds above. +% +% Indeed the catcode 12 dollar sign is used to signal a "virtual list" +% argument, a catcode 3 ~ will signal a "non-expandable". This happens when +% something add a "virtual list" argument, we must now leave the macros with a +% ~ meaning that it will become a real macro during the final \scantokens. +% Such "~" macro names will be created when they have a macro parameter as +% argument, or another "~" macro name, or a dollar prefixed argument as +% created by the NewExpr version of the \xintSeq::csv type macros which create +% comma separated lists. +% +% This 1.1 (2014/10/29) code works amazingly well allowing frankly amazing +% things such as the parsing by \xintNewExpr of [#1..[#2]..#3][#4:#5]. But we +% need to have a translation into exclusively f-expandable macros (avoiding +% \csname...\endcsname, but if absolutely needed perhaps I will do it +% ultimately.) And for the iterating loops seq, iter, etc..., we have no +% equivalent if the list of indices is not explicit. We succeed in doing it +% with explicit list, but if start, step, or end contains a macro parameter we +% are stuck (how could test for omit, abort, break work ?). Or we would need +% macro versions. +% +% ~ and $ of catcode 12 in what follows.| % \begin{macrocode} -\catcode`~ 12 % by the way, catcode is set to 3 in \XINTsetupcatcodes \catcode`$ 12 % $ \def\XINT_xptwo_getab_b #1#2!#3% {\expandafter\XINT_xptwo_getab_c\romannumeral`&&@#3!#1{#1#2}}% @@ -29792,7 +30621,7 @@ $1$ or $-1$. Lt,Gt,Eq,LtorEq,GtorEq,Neq,AND,OR,XOR,iQuo,iRem,Add,Sub,Mul,Div,Pow,E,% iiAdd,iiSub,iiMul,iiPow,iiQuo,iiRem,iiE,SeqA::csv,iiSeqA::csv}\do {\toks0 - \expandafter{\the\toks0% no space! (makes shorter macro in the end) + \expandafter{\the\toks0% no space! \expandafter\let\csname xint#1NE\expandafter\endcsname\csname xint#1\expandafter \endcsname\expandafter\def\csname xint#1\endcsname ####1####2{% \expandafter\XINT_NEfork @@ -29873,78 +30702,124 @@ $1$ or $-1$. {\toks0 \expandafter{\the\toks0\expandafter\def\csname xint#1:csv\endcsname {~xint#1:csv}}% }% -\xintFor #1 in {XINTinFloatMaxof,XINTinFloatMinof,XINTinFloatSum,XINTinFloatPrd}\do +\xintFor #1 in + {XINTinFloatMaxof,XINTinFloatMinof,XINTinFloatSum,XINTinFloatPrd}\do {\toks0 \expandafter{\the\toks0\expandafter\def\csname #1:csv\endcsname {~#1:csv}}% }% -\expandafter\def\expandafter\XINT_expr_redefinemacros\expandafter - {\the\toks0 - \def\XINT_flexpr_noopt {\expandafter\XINT_flexpr_withopt_b\expandafter-% - \romannumeral0\xintbarefloateval }% +% \end{macrocode} +% \lverb|~xintListSel::csv must have space after it, the reason being in +% \XINT_expr_until_:_b which inserts a : as fist token of something which will +% reappear later following ~xintListSel::csv. +% +% Notice that 1.1 was chicken and did not even try to expand the Reverse and +% ListSel by fear of the complexities and overhead of checking whether it +% contained macro parameters (possibly embedded in sub-macros).| +% \begin{macrocode} +\toks0 \expandafter{\the\toks0 + \def\xintReverse::csv {~xintReverse::csv }% + \def\xintListSel::csv {~xintListSel::csv }% +}% +\odef\XINT_expr_redefinemacros {\the\toks0}% Not \edef ! (subtle) +\def\XINT_expr_redefineprints +{% + \def\XINT_flexpr_noopt + {\expandafter\XINT_flexpr_withopt_b\expandafter-\romannumeral0\xintbarefloateval }% \def\XINT_flexpr_withopt_b ##1##2% {\expandafter\XINT_flexpr_wrap\csname .;##1.=\XINT_expr_unlock ##2\endcsname }% - \def\XINT_expr_unlock_sp ##1.;##2##3.=##4!{\if -##2\expandafter\xint_firstoftwo - \else\expandafter\xint_secondoftwo\fi \XINTdigits{{##2##3}}{##4}}% + \def\XINT_expr_unlock_sp ##1.;##2##3.=##4!% + {\if -##2\expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo\fi + \XINTdigits{{##2##3}}{##4}}% \def\XINT_expr_print ##1{\expandafter\xintSPRaw::csv\expandafter {\romannumeral`&&@\XINT_expr_unlock ##1}}% \def\XINT_iiexpr_print ##1{\expandafter\xintCSV::csv\expandafter {\romannumeral`&&@\XINT_expr_unlock ##1}}% \def\XINT_boolexpr_print ##1{\expandafter\xintIsTrue::csv\expandafter {\romannumeral`&&@\XINT_expr_unlock ##1}}% - \def\xintCSV::csv {~xintCSV::csv }% spaces to separate from possible catcode 11 - \def\xintSPRaw::csv {~xintSPRaw::csv }% stuff after - \def\xintPFloat::csv {~xintPFloat::csv }% - \def\xintIsTrue::csv {~xintIsTrue::csv }% - \def\xintRound::csv {~xintRound::csv }% % \end{macrocode} -% \lverb|\def\XINTinFloat::csv {~XINTinFloat::csv }% should not be needed.| +% \lverb|$indent 1) spaces after ::csv needed to separate from possible later stuff. +% Well I currently don't recall what I meant by that. +% +% 2) due to redefinitions done above of \XINT_flexpr_noopt, etc..., no need to +% redefine \xintFloat::csv as it is not used (sub-expressions not supported), +% it is \xintPFloat::csv which is neutralized.| % \begin{macrocode} - \def\xintReversed::csv {~xintReversed::csv }% - \def\xintListSel:csv {~xintListSel:csv }% + \def\xintCSV::csv {~xintCSV::csv }% + \def\xintSPRaw::csv {~xintSPRaw::csv }% + \def\xintPFloat::csv {~xintPFloat::csv }% + \def\xintIsTrue::csv {~xintIsTrue::csv }% + \def\xintRound::csv {~xintRound::csv }% }% \toks0 {}% -\def\xintNewExpr {\xint_NewExpr\xinttheexpr }% -\def\xintNewFloatExpr {\xint_NewExpr\xintthefloatexpr }% -\def\xintNewIExpr {\xint_NewExpr\xinttheiexpr }% -\def\xintNewIIExpr {\xint_NewExpr\xinttheiiexpr }% -\def\xintNewBoolExpr {\xint_NewExpr\xinttheboolexpr }% % \end{macrocode} +% \subsubsection{\csh{xintNewExpr}, ..., at last.} +% \lverb|1.2c modifications to accomodate \XINT_expr_deffunc_newexpr etc..| +% \begin{macrocode} +\def\xintNewExpr {\XINT_NewExpr{}\XINT_expr_redefineprints\xinttheexpr }% +\def\xintNewFloatExpr {\XINT_NewExpr{}\XINT_expr_redefineprints\xintthefloatexpr }% +\def\xintNewIExpr {\XINT_NewExpr{}\XINT_expr_redefineprints\xinttheiexpr }% +\def\xintNewIIExpr {\XINT_NewExpr{}\XINT_expr_redefineprints\xinttheiiexpr }% +\def\xintNewBoolExpr {\XINT_NewExpr{}\XINT_expr_redefineprints\xinttheboolexpr }% +% \end{macrocode} +% \lverb|1.2c for \xintdeffunc, \xintdefiifunc, \xintdeffloatfunc.| % \begin{macrocode} +\def\XINT_NewFunc {\XINT_NewExpr,\xintverbosefalse\xintthebareeval }% +\def\XINT_NewFloatFunc {\XINT_NewExpr,\xintverbosefalse\xintthebarefloateval }% +\def\XINT_NewIIFunc {\XINT_NewExpr,\xintverbosefalse\xintthebareiieval }% \def\XINT_newexpr_finish #1>{\noexpand\romannumeral`&&@}% -\def\xint_NewExpr #1#2[#3]% +% \end{macrocode} +% \lverb|1.2c adds optional logging. For this needed to pass to _NewExpr_a the +% macro name as parameter. And _NewExpr itself receives two new parameters to +% treat both \xintNewExpr and \xintdeffunc.| +% \begin{macrocode} +\def\XINT_NewExpr #1#2#3#4[#5]% {% \begingroup - \ifcase #3\relax - \toks0 {\xdef #2}% - \or \toks0 {\xdef #2##1}% - \or \toks0 {\xdef #2##1##2}% - \or \toks0 {\xdef #2##1##2##3}% - \or \toks0 {\xdef #2##1##2##3##4}% - \or \toks0 {\xdef #2##1##2##3##4##5}% - \or \toks0 {\xdef #2##1##2##3##4##5##6}% - \or \toks0 {\xdef #2##1##2##3##4##5##6##7}% - \or \toks0 {\xdef #2##1##2##3##4##5##6##7##8}% - \or \toks0 {\xdef #2##1##2##3##4##5##6##7##8##9}% + \ifcase #5\relax + \toks0 {\xdef #4}% + \or \toks0 {\xdef #4##1#1}% + \or \toks0 {\xdef #4##1#1##2#1}% + \or \toks0 {\xdef #4##1#1##2#1##3#1}% + \or \toks0 {\xdef #4##1#1##2#1##3#1##4#1}% + \or \toks0 {\xdef #4##1#1##2#1##3#1##4#1##5#1}% + \or \toks0 {\xdef #4##1#1##2#1##3#1##4#1##5#1##6#1}% + \or \toks0 {\xdef #4##1#1##2#1##3#1##4#1##5#1##6#1##7#1}% + \or \toks0 {\xdef #4##1#1##2#1##3#1##4#1##5#1##6#1##7#1##8#1}% + \or \toks0 {\xdef #4##1#1##2#1##3#1##4#1##5#1##6#1##7#1##8#1##9#1}% \fi \xintexprSafeCatcodes - \XINT_NewExpr #1% + \XINT_expr_redefinemacros + #2% + \XINT_NewExpr_a #4#3% }% +% \end{macrocode} +% \lverb|& attention que & est de catcode 14 +% $catcode38 12 +% For the 1.2a release I replaced all \romannumeral-`0 by a fancier +% \romannumeral`&&@ (with & of catcode 7). I got lucky here that it worked, +% despite @ being of catcode comment (anyhow \input xintexpr.sty would not +% have compiled if not, and I would have realized immediately). But to be +% honest I wouldn't have been 100$% sure +% beforehand that &&@ worked also with @ comment character. I now know.| +% \begin{macrocode} \catcode`~ 13 \catcode`@ 14 \catcode`\% 6 \catcode`# 12 \catcode`$ 11 @ $ -\def\XINT_NewExpr %1%2@ +\def\XINT_NewExpr_a %1%2%3@ {@ - \def\XINT_tmpa %%1%%2%%3%%4%%5%%6%%7%%8%%9{%2}@ - \XINT_expr_redefinemacros + \def\XINT_tmpa %%1%%2%%3%%4%%5%%6%%7%%8%%9{%3}@ \def~{$noexpand$}@ \catcode`: 11 \catcode`_ 11 \catcode`# 12 \catcode`~ 13 \escapechar 126 \endlinechar -1 \everyeof {\noexpand }@ \edef\XINT_tmpb {\scantokens\expandafter - {\romannumeral`&&@\expandafter%1\XINT_tmpa {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}\relax}@ + {\romannumeral`&&@\expandafter%2\XINT_tmpa {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}\relax}@ }@ \escapechar 92 \catcode`# 6 \catcode`$ 0 @ $ \the\toks0 {\scantokens\expandafter{\expandafter\XINT_newexpr_finish\meaning\XINT_tmpb}}@ + \ifxintverbose\xintMessage{info}{xintexpr} + {\string%1\space now with meaning \meaning%1}@ + \fi \endgroup }@ \catcode`% 14 @@ -30069,7 +30944,7 @@ $1$ or $-1$. Right bracket \] Circumflex \^ Underscore \_ Grave accent \` Left brace \{ Vertical bar \| Right brace \} Tilde \~} -\CheckSum {27060}% +\CheckSum {27248}% \makeatletter\check@checksum\makeatother \Finale %% End of file xint.dtx diff --git a/Master/texmf-dist/source/generic/xint/xint.ins b/Master/texmf-dist/source/generic/xint/xint.ins index dc5726c9e42..7cdee8cb820 100644 --- a/Master/texmf-dist/source/generic/xint/xint.ins +++ b/Master/texmf-dist/source/generic/xint/xint.ins @@ -21,7 +21,7 @@ %% same distribution. (The sources need not necessarily be %% in the same archive or directory.) %% --------------------------------------------------------------- -%% The xint bundle v1.2b 2015/10/29 +%% The xint bundle v1.2c 2015/11/16 %% Copyright (C) 2013-2015 by Jean-Francois Burnol %% --------------------------------------------------------------- %% diff --git a/Master/texmf-dist/tex/generic/xint/xint.sty b/Master/texmf-dist/tex/generic/xint/xint.sty index 14671472592..c7b57397a2a 100644 --- a/Master/texmf-dist/tex/generic/xint/xint.sty +++ b/Master/texmf-dist/tex/generic/xint/xint.sty @@ -21,7 +21,7 @@ %% same distribution. (The sources need not necessarily be %% in the same archive or directory.) %% --------------------------------------------------------------- -%% The xint bundle v1.2b 2015/10/29 +%% The xint bundle v1.2c 2015/11/16 %% Copyright (C) 2013-2015 by Jean-Francois Burnol %% xint: Expandable operations on big integers %% --------------------------------------------------------------- @@ -70,7 +70,7 @@ \XINTsetupcatcodes% defined in xintkernel.sty (loaded by xintcore.sty) \XINT_providespackage \ProvidesPackage{xint}% - [2015/10/29 v1.2b Expandable operations on big integers (jfB)]% + [2015/11/16 v1.2c Expandable operations on big integers (jfB)]% \long\def\xint_firstofthree #1#2#3{#1}% \long\def\xint_secondofthree #1#2#3{#2}% \long\def\xint_thirdofthree #1#2#3{#3}% diff --git a/Master/texmf-dist/tex/generic/xint/xintbinhex.sty b/Master/texmf-dist/tex/generic/xint/xintbinhex.sty index 8ca075ad991..18ade28b6f0 100644 --- a/Master/texmf-dist/tex/generic/xint/xintbinhex.sty +++ b/Master/texmf-dist/tex/generic/xint/xintbinhex.sty @@ -21,7 +21,7 @@ %% same distribution. (The sources need not necessarily be %% in the same archive or directory.) %% --------------------------------------------------------------- -%% The xint bundle v1.2b 2015/10/29 +%% The xint bundle v1.2c 2015/11/16 %% Copyright (C) 2013-2015 by Jean-Francois Burnol %% xintbinhex: Expandable binary and hexadecimal conversions %% --------------------------------------------------------------- @@ -70,7 +70,7 @@ \XINTsetupcatcodes% defined in xintkernel.sty \XINT_providespackage \ProvidesPackage{xintbinhex}% - [2015/10/29 v1.2b Expandable binary and hexadecimal conversions (jfB)]% + [2015/11/16 v1.2c Expandable binary and hexadecimal conversions (jfB)]% \newcount\xint_c_ii^xv \xint_c_ii^xv 32768 \newcount\xint_c_ii^xvi \xint_c_ii^xvi 65536 \newcount\xint_c_x^v \xint_c_x^v 100000 diff --git a/Master/texmf-dist/tex/generic/xint/xintcfrac.sty b/Master/texmf-dist/tex/generic/xint/xintcfrac.sty index ae235d35433..8200fd55c32 100644 --- a/Master/texmf-dist/tex/generic/xint/xintcfrac.sty +++ b/Master/texmf-dist/tex/generic/xint/xintcfrac.sty @@ -21,7 +21,7 @@ %% same distribution. (The sources need not necessarily be %% in the same archive or directory.) %% --------------------------------------------------------------- -%% The xint bundle v1.2b 2015/10/29 +%% The xint bundle v1.2c 2015/11/16 %% Copyright (C) 2013-2015 by Jean-Francois Burnol %% xintcfrac: Expandable continued fractions with xint package %% --------------------------------------------------------------- @@ -70,7 +70,7 @@ \XINTsetupcatcodes% defined in xintkernel.sty \XINT_providespackage \ProvidesPackage{xintcfrac}% - [2015/10/29 v1.2b Expandable continued fractions with xint package (jfB)]% + [2015/11/16 v1.2c Expandable continued fractions with xint package (jfB)]% \def\xintCFrac {\romannumeral0\xintcfrac }% \def\xintcfrac #1% {% diff --git a/Master/texmf-dist/tex/generic/xint/xintcore.sty b/Master/texmf-dist/tex/generic/xint/xintcore.sty index c6a06b1a974..243794986a4 100644 --- a/Master/texmf-dist/tex/generic/xint/xintcore.sty +++ b/Master/texmf-dist/tex/generic/xint/xintcore.sty @@ -21,7 +21,7 @@ %% same distribution. (The sources need not necessarily be %% in the same archive or directory.) %% --------------------------------------------------------------- -%% The xint bundle v1.2b 2015/10/29 +%% The xint bundle v1.2c 2015/11/16 %% Copyright (C) 2013-2015 by Jean-Francois Burnol %% xintcore: Expandable arithmetic on big integers %% --------------------------------------------------------------- @@ -70,7 +70,7 @@ \XINTsetupcatcodes% defined in xintkernel.sty \XINT_providespackage \ProvidesPackage{xintcore}% - [2015/10/29 v1.2b Expandable arithmetic on big integers (jfB)]% + [2015/11/16 v1.2c Expandable arithmetic on big integers (jfB)]% \ifdefined\m@ne\let\xint_c_mone\m@ne \else\csname newcount\endcsname\xint_c_mone \xint_c_mone -1 \fi \newcount\xint_c_x^viii \xint_c_x^viii 100000000 @@ -194,6 +194,18 @@ {\expandafter\XINT_sepandrev_andcount_done\the\numexpr \xint_c_ii*#3+#1.#2}% \edef\XINT_sepandrev_andcount_done #1.#21#3!% {\noexpand\expandafter\space\noexpand\the\numexpr #1-#3.}% +\def\XINT_unrevbyviii #11#2!1#3!1#4!1#5!1#6!1#7!1#8!1#9!% +{% + \xint_gob_til_R #9\XINT_unrevbyviii_a\R + \XINT_unrevbyviii {#9#8#7#6#5#4#3#2#1}% +}% +\edef\XINT_unrevbyviii_a\R\XINT_unrevbyviii #1#2\W + {\noexpand\expandafter\space + \noexpand\romannumeral`&&@\noexpand\xint_gob_til_Z #1}% +\def\XINT_smallunrevbyviii 1#1!1#2!1#3!1#4!1#5!1#6!1#7!1#8!#9\W% +{% + \expandafter\XINT_cuz_small\xint_gob_til_Z #8#7#6#5#4#3#2#1% +}% \def\XINT_sepbyviii_andcount {% \expandafter\XINT_sepbyviii_andcount_a\the\numexpr\XINT_sepbyviii @@ -263,19 +275,6 @@ }% \def\XINT_div_unsepR_end\R\XINT_div_unsepR #1{\XINT_div_unsepR_done #1}% \def\XINT_div_unsepR_done #1\R #2\W {\XINT_cuz #1\R}% -%%%%%%%%%%%% -\def\XINT_unrevbyviii #11#2!1#3!1#4!1#5!1#6!1#7!1#8!1#9!% -{% - \xint_gob_til_R #9\XINT_unrevbyviii_a\R - \XINT_unrevbyviii {#9#8#7#6#5#4#3#2#1}% -}% -\edef\XINT_unrevbyviii_a\R\XINT_unrevbyviii #1#2\W - {\noexpand\expandafter\space - \noexpand\romannumeral`&&@\noexpand\xint_gob_til_Z #1}% -\def\XINT_smallunrevbyviii 1#1!1#2!1#3!1#4!1#5!1#6!1#7!1#8!#9\W% -{% - \expandafter\XINT_cuz_small\xint_gob_til_Z #8#7#6#5#4#3#2#1% -}% \def\XINT_microrevsep #1#2#3#4#5#6#7#8% {% 1#8#7#6#5#4#3#2#1\expandafter!\the\numexpr\XINT_microrevsep @@ -504,9 +503,9 @@ #1\XINT_rsepbyviii_end_A 2345678% \XINT_rsepbyviii_end_B 2345678\relax XX% \R.\R.\R.\R.\R.\R.\R.\R.\W - \Z!\Z!\Z!\Z!\Z!\W + \Z!\Z!\Z!\Z!\W }% -\def\XINT_dec_pos_aa {\XINT_sub_aa 100000001!\Z!\Z!\Z!\Z!\Z!\W }% +\def\XINT_dec_pos_aa {\XINT_sub_aa 100000001!\Z!\Z!\Z!\Z!\W }% \def\xintInc {\romannumeral0\xintinc }% \def\xintinc #1% {% @@ -530,9 +529,10 @@ #1\XINT_rsepbyviii_end_A 2345678% \XINT_rsepbyviii_end_B 2345678\relax XX% \R.\R.\R.\R.\R.\R.\R.\R.\W - \Z!\Z!\Z!\Z!\Z!\W + 1\Z!1\Z!1\Z!1\Z!1\Z!\W + 1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% -\def\XINT_inc_pos_aa {\XINT_add_aa 100000001!\Z!\Z!\Z!\Z!\Z!\W }% +\def\XINT_inc_pos_aa {\XINT_add_aa 100000001!1\Z!1\Z!1\Z!1\Z!\W }% \def\xintiAdd {\romannumeral0\xintiadd }% \def\xintiadd #1{\expandafter\XINT_iadd\romannumeral0\xintnum{#1}\Z }% \def\xintiiAdd {\romannumeral0\xintiiadd }% @@ -589,7 +589,8 @@ \XINT_rsepbyviii_end_B 2345678\relax\xint_c_ii\xint_c_iii \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W - \Z!\Z!\Z!\Z!\Z!\W #2\Z!\Z!\Z!\Z!\Z!\W + 1\Z!1\Z!1\Z!1\Z!\W #21\Z!1\Z!1\Z!1\Z!\W + 1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% \def\XINT_add_checklengths #1.#2.% {% @@ -600,43 +601,32 @@ \fi #1.#2.% }% -\def\XINT_add_exchange #1.#2.#3\Z!\Z!\Z!\Z!\Z!\W #4\Z +\def\XINT_add_exchange #1.#2.#3\W #4\W {% - \XINT_add_A #2.#1.#4\Z!\Z!\Z!\Z!\Z!\W #3\Z + \XINT_add_A #2.#1.#4\W #3\W }% \def\XINT_add_A #1.#2.% {% - \ifnum #1>\xint_c_vi % + \ifnum #1>\xint_c_vi \expandafter\XINT_add_aa \else \expandafter\XINT_add_aa_small \fi }% -%%%%%%%%%%%% -\def\XINT_add_out #1\Z #2\W% -{% - \expandafter\XINT_cuz_small\romannumeral0\XINT_unrevbyviii {}% - #11\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W -}% -\def\XINT_add_out_small #1\Z #2\W% -{% - \XINT_smallunrevbyviii #11\Z!1\R!1\R!1\R!1\R!1\R!1\R!\W -}% -%%%%%%%%%%%% \def\XINT_add_aa {\expandafter\XINT_add_out\the\numexpr\XINT_add_a \xint_c_ii}% +\def\XINT_add_out{\expandafter\XINT_cuz_small\romannumeral0\XINT_unrevbyviii {}}% \def\XINT_add_aa_small - {\expandafter\XINT_add_out_small\the\numexpr\XINT_add_a \xint_c_ii}% + {\expandafter\XINT_smallunrevbyviii\the\numexpr\XINT_add_a \xint_c_ii}% \def\XINT_add_a #1!#2!#3!#4!#5\W #6!#7!#8!#9!% {% \XINT_add_b #1!#6!#2!#7!#3!#8!#4!#9!#5\W }% -\def\XINT_add_b #1#2!#3!% +\def\XINT_add_b #11#2#3!#4!% {% \xint_gob_til_Z #2\XINT_add_bi \Z - \expandafter\XINT_add_c\the\numexpr#1+#2+#3-\xint_c_ii.% + \expandafter\XINT_add_c\the\numexpr#1+1#2#3+#4-\xint_c_ii.% }% -\def\XINT_add_bi\Z - \expandafter\XINT_add_c - \the\numexpr#1+#2+#3-\xint_c_ii.#4!#5!#6!#7!#8!#9!\Z !\W +\def\XINT_add_bi\Z\expandafter\XINT_add_c + \the\numexpr#1+#2+#3-\xint_c_ii.#4!#5!#6!#7!#8!#9!\W {% \XINT_add_k #1#3!#5!#7!#9!% }% @@ -644,10 +634,10 @@ {% 1#2\expandafter!\the\numexpr\XINT_add_d #1% }% -\def\XINT_add_d #1#2!#3!% +\def\XINT_add_d #11#2#3!#4!% {% \xint_gob_til_Z #2\XINT_add_di \Z - \expandafter\XINT_add_e\the\numexpr#1+#2+#3-\xint_c_ii.% + \expandafter\XINT_add_e\the\numexpr#1+1#2#3+#4-\xint_c_ii.% }% \def\XINT_add_di\Z\expandafter\XINT_add_e \the\numexpr#1+#2+#3-\xint_c_ii.#4!#5!#6!#7!#8\W @@ -658,10 +648,10 @@ {% 1#2\expandafter!\the\numexpr\XINT_add_f #1% }% -\def\XINT_add_f #1#2!#3!% +\def\XINT_add_f #11#2#3!#4!% {% \xint_gob_til_Z #2\XINT_add_fi \Z - \expandafter\XINT_add_g\the\numexpr#1+#2+#3-\xint_c_ii.% + \expandafter\XINT_add_g\the\numexpr#1+1#2#3+#4-\xint_c_ii.% }% \def\XINT_add_fi\Z\expandafter\XINT_add_g \the\numexpr#1+#2+#3-\xint_c_ii.#4!#5!#6\W @@ -672,10 +662,10 @@ {% 1#2\expandafter!\the\numexpr\XINT_add_h #1% }% -\def\XINT_add_h #1#2!#3!% +\def\XINT_add_h #11#2#3!#4!% {% \xint_gob_til_Z #2\XINT_add_hi \Z - \expandafter\XINT_add_i\the\numexpr#1+#2+#3-\xint_c_ii.% + \expandafter\XINT_add_i\the\numexpr#1+1#2#3+#4-\xint_c_ii.% }% \def\XINT_add_hi\Z \expandafter\XINT_add_i\the\numexpr#1+#2+#3-\xint_c_ii.#4\W @@ -686,29 +676,14 @@ {% 1#2\expandafter!\the\numexpr\XINT_add_a #1% }% -%%%%%%%%%%%% -\def\XINT_add_k #1% - {\if #12\expandafter\XINT_add_ke\else\expandafter\XINT_add_l \fi}% -\def\XINT_add_ke #1% -{% - \xint_gob_til_Z #1\XINT_add_kf\Z 1% -}% -\def\XINT_add_kf\Z 1{1}% -\def\XINT_add_l #1% -{% - \xint_gob_til_Z #1\XINT_add_lf\Z \XINT_add_m 1% -}% -\def\XINT_add_lf\Z\XINT_add_m 1{100000001}% -\def\XINT_add_m #1!% -{% - \expandafter\XINT_add_n\the\numexpr\xint_c_i+#1.% -}% -\def\XINT_add_n #1#2.% -{% - 1#2\expandafter!\the\numexpr\XINT_add_o #1% -}% -\def\XINT_add_o #1% - {\if #12\expandafter\XINT_add_l\else\expandafter\XINT_add_ke \fi}% +\def\XINT_add_k #1{\if #12\expandafter\XINT_add_ke\else\expandafter\XINT_add_l \fi}% +\def\XINT_add_ke #11\Z #2\W {\XINT_add_kf #11\Z!}% +\def\XINT_add_kf 1{1\relax }% +\def\XINT_add_l 1#1#2{\xint_gob_til_Z #1\XINT_add_lf \Z \XINT_add_m 1#1#2}% +\def\XINT_add_lf #1\W {1\relax 00000001!1\Z!}% +\def\XINT_add_m #1!{\expandafter\XINT_add_n\the\numexpr\xint_c_i+#1.}% +\def\XINT_add_n #1#2.{1#2\expandafter!\the\numexpr\XINT_add_o #1}% +\def\XINT_add_o #1{\if #12\expandafter\XINT_add_l\else\expandafter\XINT_add_ke \fi}% \def\xintiiSub {\romannumeral0\xintiisub }% \def\xintiisub #1{\expandafter\XINT_iisub\romannumeral`&&@#1\Z }% \def\XINT_iisub #1#2\Z #3% @@ -764,7 +739,7 @@ \XINT_rsepbyviii_end_B 2345678\relax \xint_c_ii\xint_c_iii \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W - \Z!\Z!\Z!\Z!\Z!\W #2\Z!\Z!\Z!\Z!\Z!\W + \Z!\Z!\Z!\Z!\W #2\Z!\Z!\Z!\Z!\W }% \def\XINT_sub_checklengths #1.#2.% {% @@ -774,15 +749,10 @@ \expandafter\XINT_sub_aa \fi }% -\def\XINT_sub_exchange #1\Z!\Z!\Z!\Z!\Z!\W #2\Z +\def\XINT_sub_exchange #1\W #2\W {% - \expandafter\XINT_opp\romannumeral0\XINT_sub_aa - #2\Z!\Z!\Z!\Z!\Z!\W #1\Z + \expandafter\XINT_opp\romannumeral0\XINT_sub_aa #2\W #1\W }% -%%%%%%%%%%%% -\def\XINT_sub_prepare_rescue #1\W {\relax\Z-\W}% -\def\XINT_sub_prepare_cuz #1\W {\relax\XINT_cuz_byviii!\Z 0\W\R}% -%%%%%%%%%%%% \def\XINT_sub_aa {\expandafter\XINT_sub_out\the\numexpr\XINT_sub_a \xint_c_i }% \def\XINT_sub_out #1\Z #2#3\W {% @@ -790,31 +760,6 @@ \expandafter\XINT_cuz_small \romannumeral0\XINT_unrevbyviii {}#11\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% -\def\XINT_sub_startrescue\expandafter\XINT_cuz_small - \romannumeral0\XINT_unrevbyviii #1#2\Z!#3\W -{% - \expandafter\XINT_sub_rescue_finish - \the\numexpr\XINT_sub_rescue_a #2!% - 1\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W \R -}% -\def\XINT_sub_rescue_finish - {\expandafter-\romannumeral0\expandafter\XINT_cuz - \romannumeral0\XINT_unrevbyviii {}}% -\def\XINT_sub_rescue_a #1!% -{% - \expandafter\XINT_sub_rescue_c\the\numexpr \xint_c_xii_e_viii-#1.% -}% -\def\XINT_sub_rescue_c 1#1#2.% -{% - 1#2\expandafter!\the\numexpr\XINT_sub_rescue_d #1% -}% -\def\XINT_sub_rescue_d #1#2#3!% -{% - \xint_gob_til_minus #2\XINT_sub_rescue_z -% - \expandafter\XINT_sub_rescue_c\the\numexpr \xint_c_xii_e_viii_mone-#2#3+#1.% -}% -\def\XINT_sub_rescue_z #1.{1!}% -%%%%%%%%%%%% \def\XINT_sub_a #1!#2!#3!#4!#5\W #6!#7!#8!#9!% {% \XINT_sub_b #1!#6!#2!#7!#3!#8!#4!#9!#5\W @@ -856,7 +801,7 @@ 1#2\expandafter!\the\numexpr\XINT_sub_a #1% }% \def\XINT_sub_bi\Z - \expandafter\XINT_sub_c\the\numexpr#1+1#2-#3.#4!#5!#6!#7!#8!#9!\Z !\W + \expandafter\XINT_sub_c\the\numexpr#1+1#2-#3.#4!#5!#6!#7!#8!#9!\W {% \XINT_sub_k #1#2!#5!#7!#9!% }% @@ -875,43 +820,51 @@ {% \XINT_sub_k #1#2!% }% -%%%%%%%%%%%% \def\XINT_sub_k #1#2% {% \xint_gob_til_Z #2\XINT_sub_p\Z \XINT_sub_l #1#2% }% -\def\XINT_sub_l #1% -{% - \xint_UDzerofork - #1\XINT_sub_m - 0{}% - \krof -}% -\def\XINT_sub_m #1!% +\def\XINT_sub_l #1{\xint_UDzerofork #1\XINT_sub_l_carry 0\XINT_sub_l_nocarry\krof}% +\def\XINT_sub_l_nocarry 1{1\relax }% +\def\XINT_sub_l_carry #1!{\expandafter\XINT_sub_m\the\numexpr 1#1-\xint_c_i!}% +\def\XINT_sub_m 1#1{\xint_UDzerofork #1\XINT_sub_n_carry 0\XINT_sub_n_nocarry\krof}% +\def\XINT_sub_n_carry #1!{1#1\expandafter!\the\numexpr\XINT_sub_l_carry }% +\def\XINT_sub_n_nocarry #1!#2#3!% {% - \expandafter\XINT_sub_n\the\numexpr 1#1-\xint_c_i!% + \xint_gob_til_Z #2\xint_gob_til_eightzeroes #1\XINT_sub_n_zero + 00000000\xint_gob_til_Z\Z 1\relax #1!#2#3!% }% -\def\XINT_sub_n 1#1% +\def\XINT_sub_n_zero 00000000\xint_gob_til_Z\Z 1\relax 00000000!{1!}% +\def\XINT_sub_p\Z\XINT_sub_l #1#2\W {% \xint_UDzerofork - #1{\XINT_sub_o}% - 0{\XINT_sub_n_checkzero}% + #1{-1\relax\Z -\W}% + 0{1\relax \XINT_cuz_byviii!\Z 0\W\R }% \krof }% -\def\XINT_sub_o #1!{1#1\expandafter!\the\numexpr\XINT_sub_m }% -\def\XINT_sub_n_checkzero #1!% +\def\XINT_sub_startrescue\expandafter\XINT_cuz_small + \romannumeral0\XINT_unrevbyviii #1#2\Z!#3\W {% - \xint_gob_til_eightzeroes #1\XINT_sub_n_prepare_cuz 00000000% - 1#1!% + \expandafter\XINT_sub_rescue_finish + \the\numexpr\XINT_sub_rescue_a #2!% + 1\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W \R }% -\def\XINT_sub_n_prepare_cuz 00000000100000000{1\XINT_sub_prepare_cuz}% -\def\XINT_sub_p\Z\XINT_sub_l #1\Z!% +\def\XINT_sub_rescue_finish + {\expandafter-\romannumeral0\expandafter\XINT_cuz\romannumeral0\XINT_unrevbyviii {}}% +\def\XINT_sub_rescue_a #1!% {% - \xint_UDzerofork - #1{-1\XINT_sub_prepare_rescue}% - 0{1\XINT_sub_prepare_cuz }% - \krof + \expandafter\XINT_sub_rescue_c\the\numexpr \xint_c_xii_e_viii-#1.% +}% +\def\XINT_sub_rescue_c 1#1#2.% +{% + 1#2\expandafter!\the\numexpr\XINT_sub_rescue_d #1% +}% +\def\XINT_sub_rescue_d #1#2#3!% +{% + \xint_gob_til_minus #2\XINT_sub_rescue_z -% + \expandafter\XINT_sub_rescue_c\the\numexpr \xint_c_xii_e_viii_mone-#2#3+#1.% }% +\def\XINT_sub_rescue_z #1.{1!}% \def\xintiMul {\romannumeral0\xintimul }% \def\xintimul #1% {% @@ -1009,22 +962,22 @@ \def\XINT_mul_exchange #1\XINT_mul_start #2\W #31\Z!% {\fi\fi\XINT_mul_start #31\Z!\W #2}% \def\XINT_mul_start - {\expandafter\XINT_mul_out\the\numexpr\XINT_mul_loop 100000000!\Z\W}% + {\expandafter\XINT_mul_out\the\numexpr\XINT_mul_loop 100000000!1\Z!\W}% \def\XINT_mul_out {\expandafter\XINT_cuz_small\romannumeral0\XINT_unrevbyviii {}}% -\def\XINT_mul_loop #1\Z #2\W #3\W 1#4!% +\def\XINT_mul_loop #1\W #2\W 1#3!% {% - \xint_gob_til_Z #4\XINT_mul_e \Z - \expandafter\XINT_mul_a\the\numexpr \XINT_smallmul 1#4!#3\W - #11!\W #3\W + \xint_gob_til_Z #3\XINT_mul_e \Z + \expandafter\XINT_mul_a\the\numexpr \XINT_smallmul 1#3!#2\W + #1\W #2\W }% -\def\XINT_mul_a #11\Z!\W #2!1!#3\W +\def\XINT_mul_a #1\W #2\W {% \expandafter\XINT_mul_b\the\numexpr - \XINT_add_a \xint_c_ii #2!\Z!\Z!\Z!\Z!\Z!\W #1\Z!\Z!\Z!\Z!\Z!\W + \XINT_add_a \xint_c_ii #21\Z!1\Z!1\Z!\W #11\Z!1\Z!1\Z!\W\W }% \def\XINT_mul_b 1#1!{1#1\expandafter!\the\numexpr\XINT_mul_loop }% -\def\XINT_mul_e\Z #1\W #2!1!#3\W #4\W {#2!1\Z!}% +\def\XINT_mul_e\Z #1\W 1#2\W #3\W {1\relax #2}% \def\XINT_minimulwc_a 1#1.#2.#3!#4#5#6#7#8.% {% \expandafter\XINT_minimulwc_b @@ -1128,7 +1081,7 @@ \def\XINT_sqr_start #1\Z {% \expandafter\XINT_mul_out - \the\numexpr\XINT_mul_loop 100000000!\Z\W #11\Z!\W #11\Z!% + \the\numexpr\XINT_mul_loop 100000000!1\Z!\W #11\Z!\W #11\Z!% 1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% \def\xintiiPow {\romannumeral0\xintiipow }% @@ -1202,7 +1155,6 @@ \edef\XINT_pow_BisNegative #1#2% {\noexpand\xintError:FractionRoundedToZero\space 0}% \def\XINT_pow_BisZero #1#2{ 1}% -%%%%%%%%%%%% \def\XINT_pow_I_in #1#2% {% \expandafter\XINT_pow_I_loop @@ -1230,17 +1182,15 @@ \the\numexpr #1/\xint_c_ii\expandafter.% \the\numexpr\XINT_pow_mulbutcheckifsmall #2\W #2\W }% -%%%%%%%%%%%% \def\XINT_pow_mulbutcheckifsmall #1!1#2% {% \xint_gob_til_Z #2\XINT_pow_mul_small\Z - \XINT_mul_loop 100000000!\Z\W #1!1#2% + \XINT_mul_loop 100000000!1\Z!\W #1!1#2% }% -\def\XINT_pow_mul_small\Z\XINT_mul_loop 100000000!\Z\W 1#1!1\Z!\W +\def\XINT_pow_mul_small\Z \XINT_mul_loop 100000000!1\Z!\W 1#1!1\Z!\W {% \XINT_smallmul 1#1!% }% -%%%%%%%%%%%% \def\XINT_pow_II_in #1.#2\W {% \expandafter\XINT_pow_II_loop @@ -2047,28 +1997,28 @@ \romannumeral0\XINT_zeroes_forviii #1\R\R\R\R\R\R\R\R{10}0000001\W #1\XINT_rsepbyviii_end_A 2345678\XINT_rsepbyviii_end_B 2345678\relax XX% \R.\R.\R.\R.\R.\R.\R.\R.\W - \Z!\Z!\Z!\Z!\Z!\W + 1\Z!1\Z!1\Z!1\Z!\W\R }% -\def\XINT_iidivround_pos_b 1#1#2#3#4#5#6#7#8!#9% +\def\XINT_iidivround_pos_b 1#1#2#3#4#5#6#7#8!1#9% {% \xint_gob_til_Z #9\XINT_iidivround_small\Z \ifnum #8>\xint_c_iv \expandafter\XINT_iidivround_pos_up \else \expandafter\XINT_iidivround_pos_finish \fi - 1#1#2#3#4#5#6#70!#9% + 1#1#2#3#4#5#6#70!1#9% }% \def\XINT_iidivround_pos_up {% \expandafter\XINT_iidivround_pos_finish - \the\numexpr\XINT_add_a\xint_c_ii 100000010!\Z!\Z!\Z!\Z!\Z!\W + \the\numexpr\XINT_add_a\xint_c_ii 100000010!1\Z!1\Z!1\Z!1\Z!\W }% -\def\XINT_iidivround_pos_finish #10!#2\Z #3\W +\def\XINT_iidivround_pos_finish #10!#2\R {% \expandafter\XINT_cuz_small\romannumeral0\XINT_unrevbyviii {}% - #1!#21\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W + #1!#21\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% -\def\XINT_iidivround_small\Z\ifnum #1>#2\fi 1#30!#4\W +\def\XINT_iidivround_small\Z\ifnum #1>#2\fi 1#30!#4\W\R {% \ifnum #1>\xint_c_iv \expandafter\XINT_iidivround_small_up diff --git a/Master/texmf-dist/tex/generic/xint/xintexpr.sty b/Master/texmf-dist/tex/generic/xint/xintexpr.sty index f9c5cef5e39..e8ce94fce56 100644 --- a/Master/texmf-dist/tex/generic/xint/xintexpr.sty +++ b/Master/texmf-dist/tex/generic/xint/xintexpr.sty @@ -21,7 +21,7 @@ %% same distribution. (The sources need not necessarily be %% in the same archive or directory.) %% --------------------------------------------------------------- -%% The xint bundle v1.2b 2015/10/29 +%% The xint bundle v1.2c 2015/11/16 %% Copyright (C) 2013-2015 by Jean-Francois Burnol %% xintexpr: Expandable expression parser %% --------------------------------------------------------------- @@ -81,7 +81,7 @@ \XINTsetupcatcodes% \XINT_providespackage \ProvidesPackage{xintexpr}% - [2015/10/29 v1.2b Expandable expression parser (jfB)]% + [2015/11/16 v1.2c Expandable expression parser (jfB)]% \catcode`! 11 \def\xint_gob_til_! #1!{}% catcode 11 ! default in xintexpr.sty code. \edef\XINT_expr_lockscan#1!% not used for decimal numbers in xintexpr 1.2 @@ -136,6 +136,9 @@ {\expandafter\XINT_flexpr_until_end_a\romannumeral`&&@\XINT_expr_getnext }% \def\xintbareiieval {\expandafter\XINT_iiexpr_until_end_a\romannumeral`&&@\XINT_expr_getnext }% +\def\xintthebareeval {\expandafter\XINT_expr_unlock\romannumeral0\xintbareeval}% +\def\xintthebarefloateval {\expandafter\XINT_expr_unlock\romannumeral0\xintbarefloateval}% +\def\xintthebareiieval {\expandafter\XINT_expr_unlock\romannumeral0\xintbareiieval}% \def\xinteval {\expandafter\XINT_expr_wrap\romannumeral0\xintbareeval }% \def\xintiieval {\expandafter\XINT_iiexpr_wrap\romannumeral0\xintbareiieval }% \def\xintieval #1% @@ -297,6 +300,7 @@ \ifnum \xint_c_ix<1#1 \xint_dothis \XINT_expr_startint\fi \xint_orthat \XINT_expr_scanfunc #1% }% +\def\XINT_expr_onlitteral_` #1#2#3({\xint_c_xviii `{#2}}% \catcode96 12 % ` \def\XINT_expr_startint #1% {% @@ -524,13 +528,7 @@ \xint_orthat {(_}% #1% }% -\def\XINT_expr_func #1(#2% -{% #2=` pour une fonction, #2=_ pour une variable - \if #2`\ifcsname XINT_expr_var_#1\endcsname - \expandafter\expandafter\expandafter\xint_thirdofthree - \fi\fi - \xint_firstoftwo {\xint_c_xviii #2{#1}}{\xint_c_xviii _{#1}*(}% -}% +\def\XINT_expr_func #1(#2{\xint_c_xviii #2{#1}}% \def\XINT_expr_getop #1#2% this #1 is the current locked computed value {% \expandafter\XINT_expr_getop_a\expandafter #1\romannumeral`&&@#2% @@ -604,10 +602,7 @@ }% \def#2##1##2% {% - \ifcase ##1\xint_afterfi - {\ifx\XINT_expr_itself_^C ##2\xint_dothis - {\expandafter#1\romannumeral`&&@\expandafter\XINT_expr_getnext\xint_gobble_i}\fi - \xint_orthat \XINT_expr_done }% + \ifcase ##1\expandafter\XINT_expr_done \or\xint_afterfi{\XINT_expr_extra_) \expandafter #1\romannumeral`&&@\XINT_expr_getop }% \else @@ -631,9 +626,7 @@ ##1{\expandafter #3\romannumeral`&&@#5}% -{#4##1}% \krof }% - \def #4##1##2{\ifcase ##1% - \xint_afterfi{\ifx\XINT_expr_itself_^C ##2\xint_dothis{\xint_c_ ##2}\fi - \xint_orthat\XINT_expr_missing_) }% + \def #4##1##2{\ifcase ##1\expandafter\XINT_expr_missing_) \or \csname XINT_#6_op_##2\expandafter\endcsname \else \xint_afterfi{\expandafter #3\romannumeral`&&@\csname XINT_#6_op_##2\endcsname }% @@ -655,7 +648,7 @@ \expandafter\let\csname XINT_expr_precedence_]\endcsname\xint_c_i \expandafter\let\csname XINT_expr_precedence_;\endcsname\xint_c_i \let\XINT_expr_precedence_a \xint_c_xviii -\expandafter\let\csname XINT_expr_precedence_^C\endcsname \xint_c_ +\let\XINT_expr_precedence_!? \xint_c_ii \expandafter\let\csname XINT_expr_precedence_++)\endcsname \xint_c_i \catcode`. 11 \catcode`= 11 \catcode`+ 11 \xintFor #1 in {expr,flexpr,iiexpr} \do {% @@ -665,13 +658,13 @@ \expandafter\let\csname XINT_#1_op_a\endcsname \XINT_expr_getop \expandafter\def\csname XINT_#1_op_++)\endcsname ##1##2\relax {\expandafter\XINT_expr_foundend \expandafter - {\expandafter\.=+\xintiCeil{\XINT_expr_unlock ##1}}}% + {\expandafter\.=+\csname .=\xintiCeil{\XINT_expr_unlock ##1}\endcsname }}% }% \catcode`. 12 \catcode`= 12 \catcode`+ 12 \catcode`& 12 \xintFor* #1 in {{==}{<=}{>=}{!=}{&&}{||}{**}{//}{/:}{..}{..[}{].}{]..}% {+[}{-[}{*[}{/[}{**[}{^[}{a+}{a-}{a*}{a/}{a**}{a^}% - {][}{][:}{:]}{^C}{++}{++)}} + {][}{][:}{:]}{!?}{++}{++)}} \do {\expandafter\def\csname XINT_expr_itself_#1\endcsname {#1}}% \catcode`& 7 \def\XINT_tmpc #1#2#3#4#5#6#7#8% @@ -935,8 +928,8 @@ \else \xint_afterfi {\expandafter ##2\expandafter ##3\csname - .=\expandafter\xintListSel:csv \romannumeral`&&@\XINT_expr_unlock ##4;% - \XINT_expr_unlock ##1;\endcsname % unlock for \xintNewExpr + .=\expandafter\xintListSel::csv \romannumeral`&&@\XINT_expr_unlock ##4;% + \XINT_expr_unlock ##1;\endcsname % unlock added for \xintNewExpr }% \fi }% @@ -997,7 +990,7 @@ \let\XINT_flexpr_op_][: \XINT_expr_op_][: \let\XINT_iiexpr_op_][: \XINT_expr_op_][: \catcode`[ 12 \catcode`] 12 -\def\xintListSel:csv #1{% +\def\xintListSel::csv #1{% \if ]\noexpand#1\xint_dothis{\expandafter\XINT_listsel:_s\romannumeral`&&@}\fi \if :\noexpand#1\xint_dothis{\XINT_listsel:_:}\fi \xint_orthat {\XINT_listsel:_nth #1}% @@ -1013,19 +1006,11 @@ {\xintNthElt {\xintNum{#1}}{\xintCSVtoListNonStripped{#2}}}% \def\XINT_listsel:_PP #1;#2;#3;% {\xintListWithSep,% - {\xintTrim {\xintNum{#1}}% - {\xintKeep {\xintNum{#2}}% - {\xintCSVtoListNonStripped{#3}}% - }% - }% + {\xintTrim {\xintNum{#1}}{\xintKeep {\xintNum{#2}}{\xintCSVtoListNonStripped{#3}}}}% }% \def\XINT_listsel:_NN #1;#2;#3;% {\xintListWithSep,% - {\xintTrim {\xintNum{#2}}% - {\xintKeep {\xintNum{#1}}% - {\xintCSVtoListNonStripped{#3}}% - }% - }% + {\xintTrim {\xintNum{#2}}{\xintKeep {\xintNum{#1}}{\xintCSVtoListNonStripped{#3}}}}% }% \def\XINT_listsel:_NP #1;#2;#3;% {\expandafter\XINT_listsel:_NP_a \the\numexpr #1+% @@ -1117,10 +1102,8 @@ \def\xintSeqA::csv #1% {\expandafter\XINT_seqa::csv\expandafter{\romannumeral0\xintraw {#1}}}% \def\XINT_seqa::csv #1#2{\expandafter\XINT_seqa::csv_a \romannumeral0\xintraw {#2};#1;}% -\def\xintiiSeqA::csv #1#2{\XINT_iiseqa::csv #1#2}% -\def\XINT_iiseqa::csv #1#2#3#4{\expandafter\XINT_seqa::csv_a - \romannumeral`&&@\expandafter \XINT_expr_unlock\expandafter#4% - \expandafter;\romannumeral`&&@\XINT_expr_unlock #2;}% +\def\xintiiSeqA::csv #1{\expandafter\XINT_iiseqa::csv\expandafter{\romannumeral`&&@#1}}% +\def\XINT_iiseqa::csv #1#2{\expandafter\XINT_seqa::csv_a\romannumeral`&&@#2;#1;}% \def\XINTinFloatSeqA::csv #1{\expandafter\XINT_flseqa::csv\expandafter {\romannumeral0\XINTinfloat [\XINTdigits]{#1}}}% \def\XINT_flseqa::csv #1#2% @@ -1293,8 +1276,7 @@ \else \expandafter\xint_secondoftwo \fi - {\expandafter\expandafter\expandafter\expandafter - \expandafter\expandafter\expandafter + {\expandafter\expandafter\expandafter \XINT_expr_getop\csname XINT_expr_var_#1\endcsname}% {\XINT_expr_unknown_variable {#1}% \expandafter\XINT_expr_getop\csname .=0\endcsname}% @@ -1303,37 +1285,81 @@ \let\XINT_flexpr_op__ \XINT_expr_op__ \let\XINT_iiexpr_op__ \XINT_expr_op__ \catcode`: 12 -\def\xintdefvar #1:=#2;{\expandafter\odef - \csname XINT_expr_var_\xint_zapspaces #1 \xint_gobble_i\endcsname - {\expandafter\empty\romannumeral0\xintbareeval #2\relax }}% -\def\xintdefiivar #1:=#2;{\expandafter\odef - \csname XINT_expr_var_\xint_zapspaces #1 \xint_gobble_i\endcsname - {\expandafter\empty\romannumeral0\xintbareiieval #2\relax }% -}% -\def\xintdeffloatvar #1:=#2;{\expandafter\odef - \csname XINT_expr_var_\xint_zapspaces #1 \xint_gobble_i\endcsname - {\expandafter\empty\romannumeral0\xintbarefloateval #2\relax }% +\def\xintdefvar #1:=#2;{% + \edef\XINT_expr_tmpa{#1}% + \edef\XINT_expr_tmpa + {\expandafter\xint_zapspaces\detokenize\expandafter{\XINT_expr_tmpa} \xint_gobble_i}% + \edef\XINT_expr_tmpb {\romannumeral0\xintbareeval #2\relax }% + \ifxintverbose\xintMessage {info}{xintexpr} + {Variable \XINT_expr_tmpa\space defined with value + \expandafter\XINT_expr_unlock\XINT_expr_tmpb.}% + \fi + \expandafter\edef\csname XINT_expr_var_\XINT_expr_tmpa\endcsname + {\expandafter\noexpand\XINT_expr_tmpb}% + \expandafter\edef\csname XINT_expr_onlitteral_\XINT_expr_tmpa\endcsname + {\noexpand\XINT_expr_getop\expandafter\noexpand\XINT_expr_tmpb *(}% +}% +\def\xintdefiivar #1:=#2;{% + \edef\XINT_expr_tmpa{#1}% + \edef\XINT_expr_tmpa + {\expandafter\xint_zapspaces\detokenize\expandafter{\XINT_expr_tmpa} \xint_gobble_i}% + \edef\XINT_expr_tmpb {\romannumeral0\xintbareiieval #2\relax }% + \ifxintverbose\xintMessage {info}{xintexpr} + {Variable \XINT_expr_tmpa\space defined with value + \expandafter\XINT_expr_unlock\XINT_expr_tmpb.}% + \fi + \expandafter\edef\csname XINT_expr_var_\XINT_expr_tmpa\endcsname + {\expandafter\noexpand\XINT_expr_tmpb}% + \expandafter\edef\csname XINT_expr_onlitteral_\XINT_expr_tmpa\endcsname + {\noexpand\XINT_expr_getop\expandafter\noexpand\XINT_expr_tmpb *(}% +}% +\def\xintdeffloatvar #1:=#2;{% + \edef\XINT_expr_tmpa{#1}% + \edef\XINT_expr_tmpa + {\expandafter\xint_zapspaces\detokenize\expandafter{\XINT_expr_tmpa} + \xint_gobble_i}% + \edef\XINT_expr_tmpb {\romannumeral0\xintbarefloateval #2\relax }% + \ifxintverbose\xintMessage {info}{xintexpr} + {Variable \XINT_expr_tmpa\space defined with value + \expandafter\XINT_expr_unlock\XINT_expr_tmpb.}% + \fi + \expandafter\edef\csname XINT_expr_var_\XINT_expr_tmpa\endcsname + {\expandafter\noexpand\XINT_expr_tmpb}% + \expandafter\edef\csname XINT_expr_onlitteral_\XINT_expr_tmpa\endcsname + {\noexpand\XINT_expr_getop\expandafter\noexpand\XINT_expr_tmpb *(}% }% \catcode`: 11 \def\XINT_tmpa #1% {% \expandafter\def\csname XINT_expr_var_#1\endcsname ##1\relax !#1##2% - {\romannumeral0\XINT_expr_lockscan ##2!##1\relax !#1{##2}}% + {##2##1\relax !#1##2}% + \expandafter\def\csname XINT_expr_onlitteral_#1\endcsname ##1\relax !#1##2% + {\XINT_expr_getop ##2*(##1\relax !#1##2}% }% \xintApplyUnbraced \XINT_tmpa {abcdefghijklmnopqrstuvwxyz}% \xintApplyUnbraced \XINT_tmpa {ABCDEFGHIJKLMNOPQRSTUVWXYZ}% -\expandafter\def\expandafter\XINT_expr_var_nil\expandafter - {\expandafter\empty\csname .= \endcsname}% -\catcode`. 11 \catcode`= 11 -\def\XINT_expr_var_omit #1\relax !{1^C!{}{}{}\.=!\relax !}% 24 juin -\def\XINT_expr_var_abort #1\relax !{1^C!{}{}{}\.=^\relax !}% 25 juin -\catcode`. 12 \catcode`= 12 +\edef\XINT_expr_var_nil {\expandafter\noexpand\csname .= \endcsname}% +\edef\XINT_expr_onlitteral_nil + {\noexpand\XINT_expr_getop\expandafter\noexpand\csname .= \endcsname *(}% +\edef\XINT_expr_var_omit #1\relax !{1\string !?!\relax !}% +\edef\XINT_expr_var_abort #1\relax !{1\string !?^\relax !}% +\def\XINT_expr_op_!? #1#2\relax {\expandafter\XINT_expr_foundend\csname .=#2\endcsname}% +\let\XINT_iiexpr_op_!? \XINT_expr_op_!? +\let\XINT_flexpr_op_!? \XINT_expr_op_!? \catcode`? 3 -\def\XINT_expr_var_@ #1~#2{ #2#1~#2}% +\def\XINT_expr_var_@ #1~#2{#2#1~#2}% \expandafter\let\csname XINT_expr_var_@1\endcsname \XINT_expr_var_@ -\expandafter\def\csname XINT_expr_var_@2\endcsname #1~#2#3{ #3#1~#2#3}% -\expandafter\def\csname XINT_expr_var_@3\endcsname #1~#2#3#4{ #4#1~#2#3#4}% -\expandafter\def\csname XINT_expr_var_@4\endcsname #1~#2#3#4#5{ #5#1~#2#3#4#5}% +\expandafter\def\csname XINT_expr_var_@2\endcsname #1~#2#3{#3#1~#2#3}% +\expandafter\def\csname XINT_expr_var_@3\endcsname #1~#2#3#4{#4#1~#2#3#4}% +\expandafter\def\csname XINT_expr_var_@4\endcsname #1~#2#3#4#5{#5#1~#2#3#4#5}% +\def\XINT_expr_onlitteral_@ #1~#2{\XINT_expr_getop #2*(#1~#2}% +\expandafter\let\csname XINT_expr_onlitteral_@1\endcsname \XINT_expr_onlitteral_@ +\expandafter\def\csname XINT_expr_onlitteral_@2\endcsname #1~#2#3% + {\XINT_expr_getop #3*(#1~#2#3}% +\expandafter\def\csname XINT_expr_onlitteral_@3\endcsname #1~#2#3#4% + {\XINT_expr_getop #4*(#1~#2#3#4}% +\expandafter\def\csname XINT_expr_onlitteral_@4\endcsname #1~#2#3#4#5% + {\XINT_expr_getop #5*(#1~#2#3#4#5}% \def\XINT_expr_func_@@ #1#2#3#4~#5?% {% \expandafter#1\expandafter#2\romannumeral0\xintntheltnoexpand @@ -1369,13 +1395,13 @@ }% \catcode`? 11 \def\XINT_tmpa #1#2#3{% - \def #1##1% \XINT_expr_op_`, #2=\XINT_expr_oparen + \def #1##1% {% - \ifcsname XINT_expr_onlitteral_##1\endcsname - \xint_dothis{\csname XINT_expr_onlitteral_##1\endcsname}\fi \ifcsname XINT_#3_func_##1\endcsname \xint_dothis{\expandafter\expandafter \csname XINT_#3_func_##1\endcsname\romannumeral`&&@#2}\fi + \ifcsname XINT_expr_onlitteral_##1\endcsname + \xint_dothis{\csname XINT_expr_onlitteral_##1\endcsname}\fi \xint_orthat{\XINT_expr_unknown_function {##1}% \expandafter\XINT_expr_func_unknown\romannumeral`&&@#2}% }% @@ -1387,15 +1413,14 @@ \csname XINT_#1_oparen\endcsname {#1}% }% -\expandafter\def\csname XINT_expr_onlitteral_`\endcsname #1#2#3({\xint_c_xviii `{#2}}% +\def\XINT_expr_func_unknown #1#2#3% + {\expandafter #1\expandafter #2\csname .=0\endcsname }% \def\XINT_expr_onlitteral_bool #1)% {\expandafter\XINT_expr_getop\csname .=\xintBool{#1}\endcsname }% \def\XINT_expr_onlitteral_togl #1)% {\expandafter\XINT_expr_getop\csname .=\xintToggle{#1}\endcsname }% \def\XINT_expr_onlitteral_protect #1)% {\expandafter\XINT_expr_getop\csname .=\detokenize{#1}\endcsname }% -\def\XINT_expr_func_unknown #1#2#3% - {\expandafter #1\expandafter #2\csname .=0\endcsname }% \def\XINT_expr_func_break #1#2#3% {\expandafter #1\expandafter #2\csname.=?\romannumeral`&&@\XINT_expr_unlock #3\endcsname }% \let\XINT_flexpr_func_break \XINT_expr_func_break @@ -1441,82 +1466,83 @@ \def\XINT_isbalanced_d #1)#2% {\xint_bye #2\XINT_isbalanced_no\xint_bye\XINT_isbalanced_a #1#2}% \def\XINT_isbalanced_no\xint_bye #1\xint_bye\xint_bye {\xint_c_i }% -\def\XINT_expr_func_seqx #1#2{\XINT_allexpr_seqx \xintbareeval }% -\def\XINT_flexpr_func_seqx #1#2{\XINT_allexpr_seqx \xintbarefloateval}% -\def\XINT_iiexpr_func_seqx #1#2{\XINT_allexpr_seqx \xintbareiieval }% -\def\XINT_allexpr_seqx #1#2#3#4% #2 is the index list, fully evaluated and encapsulated -{% #3 is the Latin letter serving as dummy variable, #4 is the expression to evaluate +\def\XINT_expr_func_seqx #1#2{\XINT_allexpr_seqx \xintthebareeval }% +\def\XINT_flexpr_func_seqx #1#2{\XINT_allexpr_seqx \xintthebarefloateval}% +\def\XINT_iiexpr_func_seqx #1#2{\XINT_allexpr_seqx \xintthebareiieval }% +\def\XINT_allexpr_seqx #1#2#3#4% +{% \expandafter \XINT_expr_getop \csname .=\expandafter\XINT_expr_seq:_aa - \romannumeral`&&@\XINT_expr_unlock #2!{#1#4\relax !#3},^,\endcsname + \romannumeral`&&@\XINT_expr_unlock #2!{#1#4\relax !#3}\endcsname }% \def\XINT_expr_seq:_aa #1{\if +#1\expandafter\XINT_expr_seq:_A\else \expandafter\XINT_expr_seq:_a\fi #1}% \def\XINT_expr_seq:_a #1!#2{\expandafter\XINT_expr_seq_empty? - \romannumeral0\XINT_expr_seq:_b {#2}#1}% -\def\XINT_expr_seq:_b #1#2,{\XINT_expr_seq:_c #2,{#1}}% -\def\XINT_expr_seq:_c #1{\if ,#1\xint_dothis\XINT_expr_seq:_noop\fi - \if ^#1\xint_dothis\XINT_expr_seq:_end\fi - \xint_orthat\XINT_expr_seq:_d #1}% -\def\XINT_expr_seq:_d #1,#2{\expandafter\XINT_expr_seq:_e - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#2{#1}{#2}}% -\def\XINT_expr_seq:_e #1{\if #1^\xint_dothis\XINT_expr_seq:_abort\fi + \romannumeral0\XINT_expr_seq:_b {#2}#1,^,}% +\def\XINT_expr_seq:_b #1#2#3,{% + \if ,#2\xint_dothis\XINT_expr_seq:_noop\fi + \if ^#2\xint_dothis\XINT_expr_seq:_end\fi + \xint_orthat{\expandafter\XINT_expr_seq:_c}\csname.=#2#3\endcsname {#1}% +}% +\def\XINT_expr_seq:_noop\csname.=,#1\endcsname #2{\XINT_expr_seq:_b {#2}#1,}% +\def\XINT_expr_seq:_end \csname.=^\endcsname #1{}% +\def\XINT_expr_seq:_c #1#2{\expandafter\XINT_expr_seq:_d\romannumeral`&&@#2#1{#2}}% +\def\XINT_expr_seq:_d #1{\if #1^\xint_dothis\XINT_expr_seq:_abort\fi \if #1?\xint_dothis\XINT_expr_seq:_break\fi \if #1!\xint_dothis\XINT_expr_seq:_omit\fi \xint_orthat{\XINT_expr_seq:_goon #1}}% -\def\XINT_expr_seq:_goon #1!#2#3#4{,#1\XINT_expr_seq:_b {#4}}% -\def\XINT_expr_seq:_omit #1!#2#3#4{\XINT_expr_seq:_b {#4}}% \def\XINT_expr_seq:_abort #1!#2#3#4#5^,{}% \def\XINT_expr_seq:_break #1!#2#3#4#5^,{,#1}% -\def\XINT_expr_seq:_noop ,#1{\XINT_expr_seq:_b {#1}}% -\def\XINT_expr_seq:_end ^,#1{}% if all is omit, _empty? constructs "nil" +\def\XINT_expr_seq:_omit #1!#2#3#4{\XINT_expr_seq:_b {#4}}% +\def\XINT_expr_seq:_goon #1!#2#3#4{,#1\XINT_expr_seq:_b {#4}}% \def\XINT_expr_seq_empty? #1{% \def\XINT_expr_seq_empty? ##1{\if ,##1\expandafter\xint_gobble_i\fi #1\endcsname }}% \XINT_expr_seq_empty? { }% -\def\XINT_expr_seq:_A +#1!#2,^,% - {\expandafter\XINT_expr_seq_empty?\romannumeral0\XINT_expr_seq:_D {#1}{#2}}% -\def\XINT_expr_seq:_D #1#2{\expandafter\XINT_expr_seq:_E - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#2{#1}{#2}}% +\def\XINT_expr_seq:_A +#1!% + {\expandafter\XINT_expr_seq_empty?\romannumeral0\XINT_expr_seq:_D #1}% +\def\XINT_expr_seq:_D #1#2{\expandafter\XINT_expr_seq:_E\romannumeral`&&@#2#1{#2}}% \def\XINT_expr_seq:_E #1{\if #1^\xint_dothis\XINT_expr_seq:_Abort\fi \if #1?\xint_dothis\XINT_expr_seq:_Break\fi \if #1!\xint_dothis\XINT_expr_seq:_Omit\fi \xint_orthat{\XINT_expr_seq:_Goon #1}}% -\def\XINT_expr_seq:_Goon #1!#2#3#4% - {,#1\expandafter\XINT_expr_seq:_D\expandafter{\the\numexpr #3+\xint_c_i}{#4}}% -\def\XINT_expr_seq:_Omit #1!#2#3#4% - {\expandafter\XINT_expr_seq:_D\expandafter{\the\numexpr #3+\xint_c_i}{#4}}% \def\XINT_expr_seq:_Abort #1!#2#3#4{}% \def\XINT_expr_seq:_Break #1!#2#3#4{,#1}% +\def\XINT_expr_seq:_Omit #1!#2#3% + {\expandafter\XINT_expr_seq:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\endcsname}% +\def\XINT_expr_seq:_Goon #1!#2#3% + {,#1\expandafter\XINT_expr_seq:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\endcsname}% \def\XINT_expr_onlitteral_add {\expandafter\XINT_expr_onlitteral_add_f\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}}% -\def\XINT_expr_onlitteral_add_f #1#2{\xint_c_xviii `{opx}#2)\relax #1+}% +\def\XINT_expr_onlitteral_add_f #1#2{\xint_c_xviii `{opxadd}#2)\relax #1}% \def\XINT_expr_onlitteral_mul {\expandafter\XINT_expr_onlitteral_mul_f\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}}% -\def\XINT_expr_onlitteral_mul_f #1#2{\xint_c_xviii `{opx}#2)\relax #1*}% -\expandafter\edef\csname XINT_expr_op:_+\endcsname - {\noexpand\xint_gobble_v {}{}{}\expandafter\noexpand\csname .=0\endcsname}% -\expandafter\edef\csname XINT_expr_op:_*\endcsname - {\noexpand\xint_gobble_v {}{}{}\expandafter\noexpand\csname .=1\endcsname}% -\def\XINT_expr_func_opx #1#2{\XINT_allexpr_opx \xintexpr }% -\def\XINT_flexpr_func_opx #1#2{\XINT_allexpr_opx \xintfloatexpr }% -\def\XINT_iiexpr_func_opx #1#2{\XINT_allexpr_opx \xintiiexpr }% +\def\XINT_expr_onlitteral_mul_f #1#2{\xint_c_xviii `{opxmul}#2)\relax #1}% +\def\XINT_expr_func_opxadd #1#2{\XINT_allexpr_opx \xintbareeval {\xintAdd 0}}% +\def\XINT_flexpr_func_opxadd #1#2{\XINT_allexpr_opx \xintbarefloateval {\XINTinFloatAdd 0}}% +\def\XINT_iiexpr_func_opxadd #1#2{\XINT_allexpr_opx \xintbareiieval {\xintiiAdd 0}}% +\def\XINT_expr_func_opxmul #1#2{\XINT_allexpr_opx \xintbareeval {\xintMul 1}}% +\def\XINT_flexpr_func_opxmul #1#2{\XINT_allexpr_opx \xintbarefloateval {\XINTinFloatMul 1}}% +\def\XINT_iiexpr_func_opxmul #1#2{\XINT_allexpr_opx \xintbareiieval {\xintiiMul 1}}% \def\XINT_allexpr_opx #1#2#3#4#5% {% - \expandafter\XINT_expr_getop\romannumeral0\expandafter\XINT_expr_op:_a - \csname XINT_expr_op:_#5\expandafter\endcsname - \romannumeral`&&@\XINT_expr_unlock #2!#5#1#3{#4}% -}% -\def\XINT_expr_op:_a #1#2!#3#4#5#6{\XINT_expr_op:_b {#1#4#3{#6\relax\relax !#5}}#2,^,}% -\def\XINT_expr_op:_b #1#2,{\XINT_expr_op:_c #2,#1}% -\def\XINT_expr_op:_c #1{\if ,#1\xint_dothis\XINT_expr_op:_noop\fi - \if ^#1\xint_dothis\XINT_expr_op:_end\fi - \xint_orthat\XINT_expr_op:_d #1}% -\def\XINT_expr_op:_noop #1,#2#3#4#5{\XINT_expr_op:_b {{#2}#3#4{#5}}}% -\def\XINT_expr_op:_d #1,#2#3#4#5% - {\expandafter\expandafter\expandafter\XINT_expr_op:_e #3#2#4#3#5{#1}{#3#4{#5}}}% -\def\XINT_expr_op:_e !#1!#2#3#4{\XINT_expr_op:_b {{!#1}#4}}% -\def\XINT_expr_op:_end ^,#1#2#3#4{\expandafter\expandafter\expandafter\space - \expandafter\xint_gobble_iv #1}% + \expandafter\XINT_expr_getop + \csname.=\romannumeral`&&@\expandafter\XINT_expr_op:_a + \romannumeral`&&@\XINT_expr_unlock #3!{#1#5\relax !#4}{#2}\endcsname +}% +\def\XINT_expr_op:_a #1!#2#3{\XINT_expr_op:_b #3{#2}#1,^,}% +\def\XINT_expr_op:_b #1#2#3#4#5,{% + \if ,#4\xint_dothis\XINT_expr_op:_noop\fi + \if ^#4\xint_dothis\XINT_expr_op:_end\fi + \xint_orthat{\expandafter\XINT_expr_op:_c}\csname.=#4#5\endcsname {#3}#1{#2}% +}% +\def\XINT_expr_op:_c #1#2#3#4{\expandafter\XINT_expr_op:_d\romannumeral0#2#1#3{#4}{#2}}% +\def\XINT_expr_op:_d #1!#2#3#4#5% + {\expandafter\XINT_expr_op:_b\expandafter #4\expandafter + {\romannumeral`&&@#4{\XINT_expr_unlock#1}{#5}}}% +\def\XINT_expr_op:_noop\csname.=,#1\endcsname #2#3#4{\XINT_expr_seq:_b #3{#4}{#2}#1,}% +\def\XINT_expr_op:_end \csname.=^\endcsname #1#2#3{#3}% \def\XINT_expr_onlitteral_subs {\expandafter\XINT_expr_onlitteral_subs_f\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}}% \def\XINT_expr_onlitteral_subs_f #1#2{\xint_c_xviii `{subx}#2)\relax #1}% @@ -1525,43 +1551,43 @@ \def\XINT_iiexpr_func_subx #1#2{\XINT_allexpr_subx \xintbareiieval }% \def\XINT_allexpr_subx #1#2#3#4% #2 is the value to assign to the dummy variable {% #3 is the dummy variable, #4 is the expression to evaluate - \expandafter \XINT_expr_getop - \csname .=\expandafter\XINT_expr_subx:_a - \romannumeral`&&@\XINT_expr_unlock #2!{#1#4\relax !#3}\endcsname + \expandafter\expandafter\expandafter\XINT_expr_getop + \expandafter\XINT_expr_subx:_end\romannumeral0#1#4\relax !#3#2% }% -\def\XINT_expr_subx:_a #1!#2% - {\expandafter\XINT_expr_subx:_end \romannumeral0#2{#1}}% -\def\XINT_expr_subx:_end #1!#2#3{\XINT_expr_unlock #1}% -\def\XINT_expr_func_rseq {\XINT_allexpr_rseq \xintbareeval }% -\def\XINT_flexpr_func_rseq {\XINT_allexpr_rseq \xintbarefloateval }% -\def\XINT_iiexpr_func_rseq {\XINT_allexpr_rseq \xintbareiieval }% -\def\XINT_allexpr_rseq #1#2% +\def\XINT_expr_subx:_end #1!#2#3{#1}% +\def\XINT_expr_func_rseq {\XINT_allexpr_rseq \xintbareeval \xintthebareeval }% +\def\XINT_flexpr_func_rseq {\XINT_allexpr_rseq \xintbarefloateval \xintthebarefloateval }% +\def\XINT_iiexpr_func_rseq {\XINT_allexpr_rseq \xintbareiieval \xintthebareiieval }% +\def\XINT_allexpr_rseq #1#2#3% {% - \expandafter\XINT_expr_rseqx\expandafter #1\expandafter - #2\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% + \expandafter\XINT_expr_rseqx\expandafter #1\expandafter#2\expandafter + #3\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% }% -\def\XINT_expr_rseqx #1#2#3#4% +\def\XINT_expr_rseqx #1#2#3#4#5% {% - \expandafter\XINT_expr_rseqy\romannumeral0#1(#4)\relax - #2#3#1% + \expandafter\XINT_expr_rseqy\romannumeral0#1(#5)\relax #3#4#2% }% \def\XINT_expr_rseqy #1#2#3#4#5% {% \expandafter \XINT_expr_getop \csname .=\XINT_expr_unlock #2% \expandafter\XINT_expr_rseq:_aa - \romannumeral`&&@\XINT_expr_unlock #1!{#5#4\relax !#3}#2,^,\endcsname + \romannumeral`&&@\XINT_expr_unlock #1!{#5#4\relax !#3}#2\endcsname }% \def\XINT_expr_rseq:_aa #1{\if +#1\expandafter\XINT_expr_rseq:_A\else \expandafter\XINT_expr_rseq:_a\fi #1}% -\def\XINT_expr_rseq:_a #1!#2#3{\XINT_expr_rseq:_b #3{#2}#1}% -\def\XINT_expr_rseq:_b #1#2#3,{\XINT_expr_rseq:_c #3,~#1{#2}}% -\def\XINT_expr_rseq:_c #1{\if ,#1\xint_dothis\XINT_expr_rseq:_noop\fi - \if ^#1\xint_dothis\XINT_expr_rseq:_end\fi - \xint_orthat\XINT_expr_rseq:_d #1}% -\def\XINT_expr_rseq:_d #1,~#2#3{\expandafter\XINT_expr_rseq:_e - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#3{#1}~#2{#3}}% -\def\XINT_expr_rseq:_e #1{% +\def\XINT_expr_rseq:_a #1!#2#3{\XINT_expr_rseq:_b {#3}{#2}#1,^,}% +\def\XINT_expr_rseq:_b #1#2#3#4,{% + \if ,#3\xint_dothis\XINT_expr_rseq:_noop\fi + \if ^#3\xint_dothis\XINT_expr_rseq:_end\fi + \xint_orthat{\expandafter\XINT_expr_rseq:_c}\csname.=#3#4\endcsname + {#1}{#2}% +}% +\def\XINT_expr_rseq:_noop\csname.=,#1\endcsname #2#3{\XINT_expr_rseq:_b {#2}{#3}#1,}% +\def\XINT_expr_rseq:_end \csname.=^\endcsname #1#2{}% +\def\XINT_expr_rseq:_c #1#2#3% + {\expandafter\XINT_expr_rseq:_d\romannumeral`&&@#3#1~#2{#3}}% +\def\XINT_expr_rseq:_d #1{% \if ^#1\xint_dothis\XINT_expr_rseq:_abort\fi \if ?#1\xint_dothis\XINT_expr_rseq:_break\fi \if !#1\xint_dothis\XINT_expr_rseq:_omit\fi @@ -1571,116 +1597,128 @@ \def\XINT_expr_rseq:_omit #1!#2#3~{\XINT_expr_rseq:_b }% \def\XINT_expr_rseq:_abort #1!#2#3~#4#5#6^,{}% \def\XINT_expr_rseq:_break #1!#2#3~#4#5#6^,{,#1}% -\def\XINT_expr_rseq:_noop ,~#1#2{\XINT_expr_rseq:_b #1{#2}}% -\def\XINT_expr_rseq:_end ^,~#1#2{}% no nil for rseq -\def\XINT_expr_rseq:_A +#1!#2#3,^,{\XINT_expr_rseq:_D {#1}#3{#2}}% -\def\XINT_expr_rseq:_D #1#2#3{\expandafter\XINT_expr_rseq:_E - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#3{#1}~#2{#3}}% +\def\XINT_expr_rseq:_A +#1!#2#3{\XINT_expr_rseq:_D #1#3{#2}}% +\def\XINT_expr_rseq:_D #1#2#3% + {\expandafter\XINT_expr_rseq:_E\romannumeral`&&@#3#1~#2{#3}}% \def\XINT_expr_rseq:_E #1{\if #1^\xint_dothis\XINT_expr_rseq:_Abort\fi \if #1?\xint_dothis\XINT_expr_rseq:_Break\fi \if #1!\xint_dothis\XINT_expr_rseq:_Omit\fi \xint_orthat{\XINT_expr_rseq:_Goon #1}}% \def\XINT_expr_rseq:_Goon #1!#2#3~#4#5% - {,#1\expandafter\XINT_expr_rseq:_D\expandafter{\the\numexpr #3+\xint_c_i\expandafter}% - \romannumeral0\XINT_expr_lockit{#1}{#5}}% + {,#1\expandafter\XINT_expr_rseq:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\expandafter\endcsname + \romannumeral0\XINT_expr_lockit{#1}{#5}}% \def\XINT_expr_rseq:_Omit #1!#2#3~%#4#5% - {\expandafter\XINT_expr_rseq:_D\expandafter{\the\numexpr #3+\xint_c_i}}% + {\expandafter\XINT_expr_rseq:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\endcsname }% \def\XINT_expr_rseq:_Abort #1!#2#3~#4#5{}% \def\XINT_expr_rseq:_Break #1!#2#3~#4#5{,#1}% -\def\XINT_expr_func_rrseq {\XINT_allexpr_rrseq \xintbareeval }% -\def\XINT_flexpr_func_rrseq {\XINT_allexpr_rrseq \xintbarefloateval }% -\def\XINT_iiexpr_func_rrseq {\XINT_allexpr_rrseq \xintbareiieval }% -\def\XINT_allexpr_rrseq #1#2% +\def\XINT_expr_func_rrseq {\XINT_allexpr_rrseq \xintbareeval \xintthebareeval }% +\def\XINT_flexpr_func_rrseq {\XINT_allexpr_rrseq \xintbarefloateval \xintthebarefloateval }% +\def\XINT_iiexpr_func_rrseq {\XINT_allexpr_rrseq \xintbareiieval \xintthebareiieval }% +\def\XINT_allexpr_rrseq #1#2#3% {% - \expandafter\XINT_expr_rrseqx\expandafter #1\expandafter - #2\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% + \expandafter\XINT_expr_rrseqx\expandafter #1\expandafter#2\expandafter + #3\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% }% -\def\XINT_expr_rrseqx #1#2#3#4% +\def\XINT_expr_rrseqx #1#2#3#4#5% {% - \expandafter\XINT_expr_rrseqy\romannumeral0#1(#4)\expandafter\relax + \expandafter\XINT_expr_rrseqy\romannumeral0#1(#5)\expandafter\relax \expandafter{\romannumeral0\xintapply \XINT_expr_lockit - {\xintRevWithBraces{\xintCSVtoListNonStripped{\XINT_expr_unlock #2}}}}% - #2#3#1% + {\xintRevWithBraces{\xintCSVtoListNonStripped{\XINT_expr_unlock #3}}}}% + #3#4#2% }% \def\XINT_expr_rrseqy #1#2#3#4#5#6% {% \expandafter \XINT_expr_getop \csname .=\XINT_expr_unlock #3% \expandafter\XINT_expr_rrseq:_aa - \romannumeral`&&@\XINT_expr_unlock #1!{#6#5\relax !#4}{#2},^,\endcsname + \romannumeral`&&@\XINT_expr_unlock #1!{#6#5\relax !#4}{#2}\endcsname }% \def\XINT_expr_rrseq:_aa #1{\if +#1\expandafter\XINT_expr_rrseq:_A\else \expandafter\XINT_expr_rrseq:_a\fi #1}% \catcode`? 3 -\def\XINT_expr_rrseq:_a #1!#2#3{\XINT_expr_rrseq:_b {#3}{#2}#1}% -\def\XINT_expr_rrseq:_b #1#2#3,{\XINT_expr_rrseq:_c #3,~#1?{#2}}% -\def\XINT_expr_rrseq:_c #1{\if ,#1\xint_dothis\XINT_expr_rrseq:_noop\fi - \if ^#1\xint_dothis\XINT_expr_rrseq:_end\fi - \xint_orthat\XINT_expr_rrseq:_d #1}% -\def\XINT_expr_rrseq:_d #1,~#2?#3{\expandafter\XINT_expr_rrseq:_e - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#3{#1}~#2?{#3}}% -\def\XINT_expr_rrseq:_goon #1!#2#3~#4?#5{,#1\expandafter\XINT_expr_rrseq:_b\expandafter - {\romannumeral0\xinttrim{-1}{\XINT_expr_lockit{#1}#4}}{#5}}% -\def\XINT_expr_rrseq:_omit #1!#2#3~{\XINT_expr_rrseq:_b }% -\def\XINT_expr_rrseq:_abort #1!#2#3~#4?#5#6^,{}% -\def\XINT_expr_rrseq:_break #1!#2#3~#4?#5#6^,{,#1}% -\def\XINT_expr_rrseq:_noop ,~#1?#2{\XINT_expr_rrseq:_b {#1}{#2}}% -\def\XINT_expr_rrseq:_end ^,~#1?#2{}% No nil for rrseq. -\catcode`? 11 -\def\XINT_expr_rrseq:_e #1{% +\def\XINT_expr_rrseq:_a #1!#2#3{\XINT_expr_rrseq:_b {#3}{#2}#1,^,}% +\def\XINT_expr_rrseq:_b #1#2#3#4,{% + \if ,#3\xint_dothis\XINT_expr_rrseq:_noop\fi + \if ^#3\xint_dothis\XINT_expr_rrseq:_end\fi + \xint_orthat{\expandafter\XINT_expr_rrseq:_c}\csname.=#3#4\endcsname + {#1}{#2}% +}% +\def\XINT_expr_rrseq:_noop\csname.=,#1\endcsname #2#3{\XINT_expr_rrseq:_b {#2}{#3}#1,}% +\def\XINT_expr_rrseq:_end \csname.=^\endcsname #1#2{}% +\def\XINT_expr_rrseq:_c #1#2#3% + {\expandafter\XINT_expr_rrseq:_d\romannumeral`&&@#3#1~#2?{#3}}% +\def\XINT_expr_rrseq:_d #1{% \if ^#1\xint_dothis\XINT_expr_rrseq:_abort\fi \if ?#1\xint_dothis\XINT_expr_rrseq:_break\fi \if !#1\xint_dothis\XINT_expr_rrseq:_omit\fi \xint_orthat{\XINT_expr_rrseq:_goon #1}% }% -\catcode`? 3 -\def\XINT_expr_rrseq:_A +#1!#2#3,^,{\XINT_expr_rrseq:_D {#1}{#3}{#2}}% -\def\XINT_expr_rrseq:_D #1#2#3{\expandafter\XINT_expr_rrseq:_E - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#3{#1}~#2?{#3}}% +\def\XINT_expr_rrseq:_goon #1!#2#3~#4?#5{,#1\expandafter\XINT_expr_rrseq:_b\expandafter + {\romannumeral0\xinttrim{-1}{\XINT_expr_lockit{#1}#4}}{#5}}% +\def\XINT_expr_rrseq:_omit #1!#2#3~{\XINT_expr_rrseq:_b }% +\def\XINT_expr_rrseq:_abort #1!#2#3~#4?#5#6^,{}% +\def\XINT_expr_rrseq:_break #1!#2#3~#4?#5#6^,{,#1}% +\def\XINT_expr_rrseq:_A +#1!#2#3{\XINT_expr_rrseq:_D #1{#3}{#2}}% +\def\XINT_expr_rrseq:_D #1#2#3% + {\expandafter\XINT_expr_rrseq:_E\romannumeral`&&@#3#1~#2?{#3}}% \def\XINT_expr_rrseq:_Goon #1!#2#3~#4?#5% - {,#1\expandafter\XINT_expr_rrseq:_D\expandafter{\the\numexpr #3+\xint_c_i\expandafter}% + {,#1\expandafter\XINT_expr_rrseq:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\expandafter\endcsname \expandafter{\romannumeral0\xinttrim{-1}{\XINT_expr_lockit{#1}#4}}{#5}}% \def\XINT_expr_rrseq:_Omit #1!#2#3~%#4?#5% - {\expandafter\XINT_expr_rrseq:_D\expandafter{\the\numexpr #3+\xint_c_i}}% + {\expandafter\XINT_expr_rrseq:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\endcsname}% \def\XINT_expr_rrseq:_Abort #1!#2#3~#4?#5{}% \def\XINT_expr_rrseq:_Break #1!#2#3~#4?#5{,#1}% -\catcode`? 11 \def\XINT_expr_rrseq:_E #1{\if #1^\xint_dothis\XINT_expr_rrseq:_Abort\fi \if #1?\xint_dothis\XINT_expr_rrseq:_Break\fi \if #1!\xint_dothis\XINT_expr_rrseq:_Omit\fi \xint_orthat{\XINT_expr_rrseq:_Goon #1}}% -\def\XINT_expr_func_iter {\XINT_allexpr_iter \xintbareeval }% -\def\XINT_flexpr_func_iter {\XINT_allexpr_iter \xintbarefloateval }% -\def\XINT_iiexpr_func_iter {\XINT_allexpr_iter \xintbareiieval }% -\def\XINT_allexpr_iter #1#2% +\def\XINT_expr_func_iter {\XINT_allexpr_iter \xintbareeval \xintthebareeval }% +\def\XINT_flexpr_func_iter {\XINT_allexpr_iter \xintbarefloateval \xintthebarefloateval }% +\def\XINT_iiexpr_func_iter {\XINT_allexpr_iter \xintbareiieval \xintthebareiieval }% +\def\XINT_allexpr_iter #1#2#3% {% - \expandafter\XINT_expr_iterx\expandafter #1\expandafter - #2\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% + \expandafter\XINT_expr_iterx\expandafter #1\expandafter #2\expandafter + #3\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% }% -\def\XINT_expr_iterx #1#2#3#4% +\def\XINT_expr_iterx #1#2#3#4#5% {% - \expandafter\XINT_expr_itery\romannumeral0#1(#4)\expandafter\relax + \expandafter\XINT_expr_itery\romannumeral0#1(#5)\expandafter\relax \expandafter{\romannumeral0\xintapply \XINT_expr_lockit - {\xintRevWithBraces{\xintCSVtoListNonStripped{\XINT_expr_unlock #2}}}}% - #2#3#1% + {\xintRevWithBraces{\xintCSVtoListNonStripped{\XINT_expr_unlock #3}}}}% + #3#4#2% }% \def\XINT_expr_itery #1#2#3#4#5#6% {% \expandafter \XINT_expr_getop \csname .=% \expandafter\XINT_expr_iter:_aa - \romannumeral`&&@\XINT_expr_unlock #1!{#6#5\relax !#4}{#2},^,\endcsname + \romannumeral`&&@\XINT_expr_unlock #1!{#6#5\relax !#4}{#2}\endcsname }% \def\XINT_expr_iter:_aa #1{\if +#1\expandafter\XINT_expr_iter:_A\else \expandafter\XINT_expr_iter:_a\fi #1}% -\catcode`? 3 -\def\XINT_expr_iter:_a #1!#2#3{\XINT_expr_iter:_b {#3}{#2}#1}% -\def\XINT_expr_iter:_b #1#2#3,{\XINT_expr_iter:_c #3,~#1?{#2}}% -\def\XINT_expr_iter:_c #1{\if ,#1\xint_dothis\XINT_expr_iter:_noop\fi - \if ^#1\xint_dothis\XINT_expr_iter:_end\fi - \xint_orthat\XINT_expr_iter:_d #1}% -\def\XINT_expr_iter:_d #1,~#2?#3{\expandafter\XINT_expr_iter:_e - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#3{#1}~#2?{#3}}% +\def\XINT_expr_iter:_a #1!#2#3{\XINT_expr_iter:_b {#3}{#2}#1,^,}% +\def\XINT_expr_iter:_b #1#2#3#4,{% + \if ,#3\xint_dothis\XINT_expr_iter:_noop\fi + \if ^#3\xint_dothis\XINT_expr_iter:_end\fi + \xint_orthat{\expandafter\XINT_expr_iter:_c}\csname.=#3#4\endcsname + {#1}{#2}% +}% +\def\XINT_expr_iter:_noop\csname.=,#1\endcsname #2#3{\XINT_expr_iter:_b {#2}{#3}#1,}% +\def\XINT_expr_iter:_end \csname.=^\endcsname #1#2% + {\expandafter\xint_gobble_i\romannumeral0\xintapplyunbraced + {,\XINT_expr:_unlock}{\xintReverseOrder{#1\space}}}% +\def\XINT_expr_iter:_c #1#2#3% + {\expandafter\XINT_expr_iter:_d\romannumeral`&&@#3#1~#2?{#3}}% +\def\XINT_expr_iter:_d #1{% + \if ^#1\xint_dothis\XINT_expr_iter:_abort\fi + \if ?#1\xint_dothis\XINT_expr_iter:_break\fi + \if !#1\xint_dothis\XINT_expr_iter:_omit\fi + \xint_orthat{\XINT_expr_iter:_goon #1}% +}% \def\XINT_expr_iter:_goon #1!#2#3~#4?#5{\expandafter\XINT_expr_iter:_b\expandafter {\romannumeral0\xinttrim{-1}{\XINT_expr_lockit{#1}#4}}{#5}}% \def\XINT_expr_iter:_omit #1!#2#3~{\XINT_expr_iter:_b }% @@ -1690,38 +1728,28 @@ \def\XINT_expr_iter:_break #1!#2#3~#4?#5#6^,% {\expandafter\xint_gobble_iv\romannumeral0\xintapplyunbraced {,\XINT_expr:_unlock}{\xintReverseOrder{#4\space}},#1}% -\def\XINT_expr_iter:_noop ,~#1?#2{\XINT_expr_iter:_b {#1}{#2}}% -\def\XINT_expr_iter:_end ^,~#1?#2% - {\expandafter\xint_gobble_i\romannumeral0\xintapplyunbraced - {,\XINT_expr:_unlock}{\xintReverseOrder{#1\space}}}% -\catcode`? 11 -\def\XINT_expr_iter:_e #1{% - \if ^#1\xint_dothis\XINT_expr_iter:_abort\fi - \if ?#1\xint_dothis\XINT_expr_iter:_break\fi - \if !#1\xint_dothis\XINT_expr_iter:_omit\fi - \xint_orthat{\XINT_expr_iter:_goon #1}% -}% \def\XINT_expr:_unlock #1{\XINT_expr_unlock #1}% -\catcode`? 3 -\def\XINT_expr_iter:_A +#1!#2#3,^,{\XINT_expr_iter:_D {#1}{#3}{#2}}% -\def\XINT_expr_iter:_D #1#2#3{\expandafter\XINT_expr_iter:_E - \romannumeral`&&@\expandafter\XINT_expr_unlock\romannumeral0#3{#1}~#2?{#3}}% +\def\XINT_expr_iter:_A +#1!#2#3{\XINT_expr_iter:_D #1{#3}{#2}}% +\def\XINT_expr_iter:_D #1#2#3% + {\expandafter\XINT_expr_iter:_E\romannumeral`&&@#3#1~#2?{#3}}% \def\XINT_expr_iter:_Goon #1!#2#3~#4?#5% - {\expandafter\XINT_expr_iter:_D\expandafter{\the\numexpr #3+\xint_c_i\expandafter}% + {\expandafter\XINT_expr_iter:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\expandafter\endcsname \expandafter{\romannumeral0\xinttrim{-1}{\XINT_expr_lockit{#1}#4}}{#5}}% \def\XINT_expr_iter:_Omit #1!#2#3~%#4?#5% - {\expandafter\XINT_expr_iter:_D\expandafter{\the\numexpr #3+\xint_c_i}}% + {\expandafter\XINT_expr_iter:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\endcsname}% \def\XINT_expr_iter:_Abort #1!#2#3~#4?#5% {\expandafter\xint_gobble_i\romannumeral0\xintapplyunbraced {,\XINT_expr:_unlock}{\xintReverseOrder{#4\space}}}% \def\XINT_expr_iter:_Break #1!#2#3~#4?#5% {\expandafter\xint_gobble_iv\romannumeral0\xintapplyunbraced {,\XINT_expr:_unlock}{\xintReverseOrder{#4\space}},#1}% -\catcode`? 11 \def\XINT_expr_iter:_E #1{\if #1^\xint_dothis\XINT_expr_iter:_Abort\fi \if #1?\xint_dothis\XINT_expr_iter:_Break\fi \if #1!\xint_dothis\XINT_expr_iter:_Omit\fi \xint_orthat{\XINT_expr_iter:_Goon #1}}% +\catcode`? 11 \def\xintANDof:csv #1{\expandafter\XINT_andof:_a\romannumeral`&&@#1,,^}% \def\XINT_andof:_a #1{\if ,#1\expandafter\XINT_andof:_e \else\expandafter\XINT_andof:_c\fi #1}% @@ -1833,13 +1861,13 @@ {\expandafter #1\expandafter #2\csname .=\xintFloor {\XINT_expr_unlock #3}\endcsname }% \let\XINT_flexpr_func_floor\XINT_expr_func_floor \def\XINT_iiexpr_func_floor #1#2#3% -{% mais absurde si on ne peut pas avoir quotient comme input +{% \expandafter #1\expandafter #2\csname.=\xintiFloor {\XINT_expr_unlock #3}\endcsname }% \def\XINT_expr_func_ceil #1#2#3% {\expandafter #1\expandafter #2\csname .=\xintCeil {\XINT_expr_unlock #3}\endcsname }% \let\XINT_flexpr_func_ceil\XINT_expr_func_ceil \def\XINT_iiexpr_func_ceil #1#2#3% -{% mais absurde si on ne peut pas avoir quotient comme input +{% \expandafter #1\expandafter #2\csname.=\xintiCeil {\XINT_expr_unlock #3}\endcsname }% \def\XINT_expr_func_sqr #1#2#3% {\expandafter #1\expandafter #2\csname.=\xintSqr {\XINT_expr_unlock #3}\endcsname }% @@ -2069,11 +2097,11 @@ \let\XINT_flexpr_func_nuple\XINT_expr_func_nuple \let\XINT_iiexpr_func_nuple\XINT_expr_func_nuple \def\XINT_expr_func_reversed #1#2#3% - {\expandafter #1\expandafter #2\csname .=\xintReversed::csv - {\XINT_expr_unlock #3}\endcsname }% + {\expandafter #1\expandafter #2\csname .=% + \xintReverse::csv {\XINT_expr_unlock #3}\endcsname }% \let\XINT_flexpr_func_reversed\XINT_expr_func_reversed \let\XINT_iiexpr_func_reversed\XINT_expr_func_reversed -\def\xintReversed::csv #1% should be done directly, of course +\def\xintReverse::csv #1% should be done directly, of course {\xintListWithSep,{\xintRevWithBraces {\xintCSVtoListNonStripped{#1}}}}% \def\xintSeqB:f:csv #1#2% {\expandafter\XINT_seqb:f:csv \expandafter{\romannumeral0\xintraw{#2}}{#1}}% @@ -2105,7 +2133,7 @@ }% \def\XINT_seqb:f:csv_nb #1#2#3#4{#3,#1}% \def\XINT_seqb:f:csv_nc #1#2#3#4{#3}% -\def\xintiiSeqb:f:csv #1#2% +\def\xintiiSeqB:f:csv #1#2% {\expandafter\XINT_iiseqb:f:csv \expandafter{\romannumeral`&&@#2}{#1}}% \def\XINT_iiseqb:f:csv #1#2{\expandafter\XINT_iiseqb:f:csv_a\romannumeral`&&@#2#1!}% \def\XINT_iiseqb:f:csv_a #1#2;#3;#4!{% @@ -2160,6 +2188,42 @@ \xintifCmp {#1}{#2}% \XINT_seqb:f:csv_nc\XINT_seqb:f:csv_nb\XINT_flseqb:f:csv_na {#1}{#2}% }% +\catcode`: 12 +\def\XINT_tmpa #1#2#3#4% +{% + \def #1##1(##2):=##3;{% + \edef\XINT_expr_tmpa{##1}% + \edef\XINT_expr_tmpa + {\expandafter\xint_zapspaces\detokenize\expandafter{\XINT_expr_tmpa} \xint_gobble_i}% + \def\XINT_expr_tmpb {0}% + \def\XINT_expr_tmpc {##3}% + \xintFor ####1 in {##2} \do + {\edef\XINT_expr_tmpb {\the\numexpr\XINT_expr_tmpb+\xint_c_i}% + \edef\XINT_expr_tmpc {subs(\unexpanded\expandafter{\XINT_expr_tmpc},% + ####1=################\XINT_expr_tmpb)}% + }% + \expandafter#3\csname XINT_#2_userfunc_\XINT_expr_tmpa\endcsname + [\XINT_expr_tmpb]{\XINT_expr_tmpc}% + \expandafter\XINT_expr_defuserfunc + \csname XINT_#2_func_\XINT_expr_tmpa\expandafter\endcsname + \csname XINT_#2_userfunc_\XINT_expr_tmpa\endcsname + \ifxintverbose\xintMessage {info}{xintexpr} + {Function \XINT_expr_tmpa\space for \string\xint #4 parser + associated to \string\XINT_#2_userfunc_\XINT_expr_tmpa\space + with meaning \expandafter\meaning + \csname XINT_#2_userfunc_\XINT_expr_tmpa\endcsname}% + \fi + }% +}% +\catcode`: 11 +\XINT_tmpa\xintdeffunc {expr} \XINT_NewFunc {expr}% +\XINT_tmpa\xintdefiifunc {iiexpr}\XINT_NewIIFunc {iiexpr}% +\XINT_tmpa\xintdeffloatfunc{flexpr}\XINT_NewFloatFunc{floatexpr}% +\def\XINT_expr_defuserfunc #1#2{% + \def #1##1##2##3{\expandafter ##1\expandafter ##2% + \csname .=\expandafter #2\romannumeral-`0\XINT_expr_unlock ##3,\endcsname + }% +}% \def\xintApply::csv #1#2% {\expandafter\XINT_applyon::_a\expandafter {\romannumeral`&&@#2}{#1}}% \def\XINT_applyon::_a #1#2{\XINT_applyon::_b {#2}{}#1,,}% @@ -2181,11 +2245,11 @@ {\romannumeral`&&@\xintApply::csv {#2{#1}}{#3}},{#2}{#3}}% \def\XINT_applyon:::_e #1,#2#3#4{\XINT_applyon:::_b {#2}{#3}{#4, #1}}% \def\XINT_applyon:::_end #1,#2#3#4{\xint_secondoftwo #4}% +\catcode`~ 12 \def\XINT_expr_RApply::csv #1#2#3#4% {~xintApply::csv{~expandafter#1~xint_exchangetwo_keepbraces{#4}}{#3}}% \def\XINT_expr_LApply::csv #1#2#3#4{~xintApply::csv{#1{#3}}{#4}}% \def\XINT_expr_RLApply:::csv #1#2{~xintApply:::csv{#1}}% -\catcode`~ 12 % by the way, catcode is set to 3 in \XINTsetupcatcodes \catcode`$ 12 % $ \def\XINT_xptwo_getab_b #1#2!#3% {\expandafter\XINT_xptwo_getab_c\romannumeral`&&@#3!#1{#1#2}}% @@ -2215,7 +2279,7 @@ Lt,Gt,Eq,LtorEq,GtorEq,Neq,AND,OR,XOR,iQuo,iRem,Add,Sub,Mul,Div,Pow,E,% iiAdd,iiSub,iiMul,iiPow,iiQuo,iiRem,iiE,SeqA::csv,iiSeqA::csv}\do {\toks0 - \expandafter{\the\toks0% no space! (makes shorter macro in the end) + \expandafter{\the\toks0% no space! \expandafter\let\csname xint#1NE\expandafter\endcsname\csname xint#1\expandafter \endcsname\expandafter\def\csname xint#1\endcsname ####1####2{% \expandafter\XINT_NEfork @@ -2296,73 +2360,85 @@ {\toks0 \expandafter{\the\toks0\expandafter\def\csname xint#1:csv\endcsname {~xint#1:csv}}% }% -\xintFor #1 in {XINTinFloatMaxof,XINTinFloatMinof,XINTinFloatSum,XINTinFloatPrd}\do +\xintFor #1 in + {XINTinFloatMaxof,XINTinFloatMinof,XINTinFloatSum,XINTinFloatPrd}\do {\toks0 \expandafter{\the\toks0\expandafter\def\csname #1:csv\endcsname {~#1:csv}}% }% -\expandafter\def\expandafter\XINT_expr_redefinemacros\expandafter - {\the\toks0 - \def\XINT_flexpr_noopt {\expandafter\XINT_flexpr_withopt_b\expandafter-% - \romannumeral0\xintbarefloateval }% +\toks0 \expandafter{\the\toks0 + \def\xintReverse::csv {~xintReverse::csv }% + \def\xintListSel::csv {~xintListSel::csv }% +}% +\odef\XINT_expr_redefinemacros {\the\toks0}% Not \edef ! (subtle) +\def\XINT_expr_redefineprints +{% + \def\XINT_flexpr_noopt + {\expandafter\XINT_flexpr_withopt_b\expandafter-\romannumeral0\xintbarefloateval }% \def\XINT_flexpr_withopt_b ##1##2% {\expandafter\XINT_flexpr_wrap\csname .;##1.=\XINT_expr_unlock ##2\endcsname }% - \def\XINT_expr_unlock_sp ##1.;##2##3.=##4!{\if -##2\expandafter\xint_firstoftwo - \else\expandafter\xint_secondoftwo\fi \XINTdigits{{##2##3}}{##4}}% + \def\XINT_expr_unlock_sp ##1.;##2##3.=##4!% + {\if -##2\expandafter\xint_firstoftwo\else\expandafter\xint_secondoftwo\fi + \XINTdigits{{##2##3}}{##4}}% \def\XINT_expr_print ##1{\expandafter\xintSPRaw::csv\expandafter {\romannumeral`&&@\XINT_expr_unlock ##1}}% \def\XINT_iiexpr_print ##1{\expandafter\xintCSV::csv\expandafter {\romannumeral`&&@\XINT_expr_unlock ##1}}% \def\XINT_boolexpr_print ##1{\expandafter\xintIsTrue::csv\expandafter {\romannumeral`&&@\XINT_expr_unlock ##1}}% - \def\xintCSV::csv {~xintCSV::csv }% spaces to separate from possible catcode 11 - \def\xintSPRaw::csv {~xintSPRaw::csv }% stuff after + \def\xintCSV::csv {~xintCSV::csv }% + \def\xintSPRaw::csv {~xintSPRaw::csv }% \def\xintPFloat::csv {~xintPFloat::csv }% \def\xintIsTrue::csv {~xintIsTrue::csv }% - \def\xintRound::csv {~xintRound::csv }% - \def\xintReversed::csv {~xintReversed::csv }% - \def\xintListSel:csv {~xintListSel:csv }% + \def\xintRound::csv {~xintRound::csv }% }% \toks0 {}% -\def\xintNewExpr {\xint_NewExpr\xinttheexpr }% -\def\xintNewFloatExpr {\xint_NewExpr\xintthefloatexpr }% -\def\xintNewIExpr {\xint_NewExpr\xinttheiexpr }% -\def\xintNewIIExpr {\xint_NewExpr\xinttheiiexpr }% -\def\xintNewBoolExpr {\xint_NewExpr\xinttheboolexpr }% +\def\xintNewExpr {\XINT_NewExpr{}\XINT_expr_redefineprints\xinttheexpr }% +\def\xintNewFloatExpr {\XINT_NewExpr{}\XINT_expr_redefineprints\xintthefloatexpr }% +\def\xintNewIExpr {\XINT_NewExpr{}\XINT_expr_redefineprints\xinttheiexpr }% +\def\xintNewIIExpr {\XINT_NewExpr{}\XINT_expr_redefineprints\xinttheiiexpr }% +\def\xintNewBoolExpr {\XINT_NewExpr{}\XINT_expr_redefineprints\xinttheboolexpr }% +\def\XINT_NewFunc {\XINT_NewExpr,\xintverbosefalse\xintthebareeval }% +\def\XINT_NewFloatFunc {\XINT_NewExpr,\xintverbosefalse\xintthebarefloateval }% +\def\XINT_NewIIFunc {\XINT_NewExpr,\xintverbosefalse\xintthebareiieval }% \def\XINT_newexpr_finish #1>{\noexpand\romannumeral`&&@}% -\def\xint_NewExpr #1#2[#3]% +\def\XINT_NewExpr #1#2#3#4[#5]% {% \begingroup - \ifcase #3\relax - \toks0 {\xdef #2}% - \or \toks0 {\xdef #2##1}% - \or \toks0 {\xdef #2##1##2}% - \or \toks0 {\xdef #2##1##2##3}% - \or \toks0 {\xdef #2##1##2##3##4}% - \or \toks0 {\xdef #2##1##2##3##4##5}% - \or \toks0 {\xdef #2##1##2##3##4##5##6}% - \or \toks0 {\xdef #2##1##2##3##4##5##6##7}% - \or \toks0 {\xdef #2##1##2##3##4##5##6##7##8}% - \or \toks0 {\xdef #2##1##2##3##4##5##6##7##8##9}% + \ifcase #5\relax + \toks0 {\xdef #4}% + \or \toks0 {\xdef #4##1#1}% + \or \toks0 {\xdef #4##1#1##2#1}% + \or \toks0 {\xdef #4##1#1##2#1##3#1}% + \or \toks0 {\xdef #4##1#1##2#1##3#1##4#1}% + \or \toks0 {\xdef #4##1#1##2#1##3#1##4#1##5#1}% + \or \toks0 {\xdef #4##1#1##2#1##3#1##4#1##5#1##6#1}% + \or \toks0 {\xdef #4##1#1##2#1##3#1##4#1##5#1##6#1##7#1}% + \or \toks0 {\xdef #4##1#1##2#1##3#1##4#1##5#1##6#1##7#1##8#1}% + \or \toks0 {\xdef #4##1#1##2#1##3#1##4#1##5#1##6#1##7#1##8#1##9#1}% \fi \xintexprSafeCatcodes - \XINT_NewExpr #1% + \XINT_expr_redefinemacros + #2% + \XINT_NewExpr_a #4#3% }% \catcode`~ 13 \catcode`@ 14 \catcode`\% 6 \catcode`# 12 \catcode`$ 11 @ $ -\def\XINT_NewExpr %1%2@ +\def\XINT_NewExpr_a %1%2%3@ {@ - \def\XINT_tmpa %%1%%2%%3%%4%%5%%6%%7%%8%%9{%2}@ - \XINT_expr_redefinemacros + \def\XINT_tmpa %%1%%2%%3%%4%%5%%6%%7%%8%%9{%3}@ \def~{$noexpand$}@ \catcode`: 11 \catcode`_ 11 \catcode`# 12 \catcode`~ 13 \escapechar 126 \endlinechar -1 \everyeof {\noexpand }@ \edef\XINT_tmpb {\scantokens\expandafter - {\romannumeral`&&@\expandafter%1\XINT_tmpa {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}\relax}@ + {\romannumeral`&&@\expandafter%2\XINT_tmpa {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}\relax}@ }@ \escapechar 92 \catcode`# 6 \catcode`$ 0 @ $ \the\toks0 {\scantokens\expandafter{\expandafter\XINT_newexpr_finish\meaning\XINT_tmpb}}@ + \ifxintverbose\xintMessage{info}{xintexpr} + {\string%1\space now with meaning \meaning%1}@ + \fi \endgroup }@ \catcode`% 14 diff --git a/Master/texmf-dist/tex/generic/xint/xintfrac.sty b/Master/texmf-dist/tex/generic/xint/xintfrac.sty index d8280d3df97..018ce1554a5 100644 --- a/Master/texmf-dist/tex/generic/xint/xintfrac.sty +++ b/Master/texmf-dist/tex/generic/xint/xintfrac.sty @@ -21,7 +21,7 @@ %% same distribution. (The sources need not necessarily be %% in the same archive or directory.) %% --------------------------------------------------------------- -%% The xint bundle v1.2b 2015/10/29 +%% The xint bundle v1.2c 2015/11/16 %% Copyright (C) 2013-2015 by Jean-Francois Burnol %% xintfrac: Expandable operations on fractions %% --------------------------------------------------------------- @@ -70,7 +70,7 @@ \XINTsetupcatcodes% defined in xintkernel.sty \XINT_providespackage \ProvidesPackage{xintfrac}% - [2015/10/29 v1.2b Expandable operations on fractions (jfB)]% + [2015/11/16 v1.2c Expandable operations on fractions (jfB)]% \def\XINT_cntSgnFork #1% {% \ifcase #1\expandafter\xint_secondofthree @@ -999,7 +999,7 @@ {% \expandafter\XINT_round_B \romannumeral0\expandafter\XINT_trunc_A - \romannumeral0\XINT_infrac {#2}{\the\numexpr #1+1\relax}{#1}% + \romannumeral0\XINT_infrac {#2}{#1+\xint_c_i}{#1}% }% \def\XINT_round_B #1\Z {% @@ -1013,7 +1013,7 @@ }% \def\XINT_round_C #1% {% - \ifnum #1<5 + \ifnum #1<\xint_c_v \expandafter\XINT_round_Daa \else \expandafter\XINT_round_Dba diff --git a/Master/texmf-dist/tex/generic/xint/xintgcd.sty b/Master/texmf-dist/tex/generic/xint/xintgcd.sty index 8dac1d2e9a2..859588cd617 100644 --- a/Master/texmf-dist/tex/generic/xint/xintgcd.sty +++ b/Master/texmf-dist/tex/generic/xint/xintgcd.sty @@ -21,7 +21,7 @@ %% same distribution. (The sources need not necessarily be %% in the same archive or directory.) %% --------------------------------------------------------------- -%% The xint bundle v1.2b 2015/10/29 +%% The xint bundle v1.2c 2015/11/16 %% Copyright (C) 2013-2015 by Jean-Francois Burnol %% xintgcd: Euclidean algorithm with xint package %% --------------------------------------------------------------- @@ -70,7 +70,7 @@ \XINTsetupcatcodes% defined in xintkernel.sty \XINT_providespackage \ProvidesPackage{xintgcd}% - [2015/10/29 v1.2b Euclide algorithm with xint package (jfB)]% + [2015/11/16 v1.2c Euclide algorithm with xint package (jfB)]% \def\xintGCD {\romannumeral0\xintgcd }% \def\xintgcd #1% {% diff --git a/Master/texmf-dist/tex/generic/xint/xintkernel.sty b/Master/texmf-dist/tex/generic/xint/xintkernel.sty index c8cbf59f311..818d661ebc7 100644 --- a/Master/texmf-dist/tex/generic/xint/xintkernel.sty +++ b/Master/texmf-dist/tex/generic/xint/xintkernel.sty @@ -21,7 +21,7 @@ %% same distribution. (The sources need not necessarily be %% in the same archive or directory.) %% --------------------------------------------------------------- -%% The xint bundle v1.2b 2015/10/29 +%% The xint bundle v1.2c 2015/11/16 %% Copyright (C) 2013-2015 by Jean-Francois Burnol %% xintkernel: Paraphernalia for the xint packages %% --------------------------------------------------------------- @@ -156,7 +156,7 @@ \fi \XINT_providespackage \ProvidesPackage {xintkernel}% - [2015/10/29 v1.2b Paraphernalia for the xint packages (jfB)]% + [2015/11/16 v1.2c Paraphernalia for the xint packages (jfB)]% \chardef\xint_c_ 0 \chardef\xint_c_i 1 \chardef\xint_c_ii 2 @@ -303,6 +303,11 @@ }% \edef\XINT_length_finish_c #1#2\Z #3% {\noexpand\expandafter\space\noexpand\the\numexpr #3+#1\relax}% +\def\xintMessage #1#2#3{% + \immediate\write16{Package #1 (#2) on line \the\inputlineno :}% + \immediate\write16{\space\space\space\space#3}% +}% +\newif\ifxintverbose \XINT_restorecatcodes_endinput% \endinput %% diff --git a/Master/texmf-dist/tex/generic/xint/xintseries.sty b/Master/texmf-dist/tex/generic/xint/xintseries.sty index 1894a0ceecd..4c475f6b970 100644 --- a/Master/texmf-dist/tex/generic/xint/xintseries.sty +++ b/Master/texmf-dist/tex/generic/xint/xintseries.sty @@ -21,7 +21,7 @@ %% same distribution. (The sources need not necessarily be %% in the same archive or directory.) %% --------------------------------------------------------------- -%% The xint bundle v1.2b 2015/10/29 +%% The xint bundle v1.2c 2015/11/16 %% Copyright (C) 2013-2015 by Jean-Francois Burnol %% xintseries: Expandable partial sums with xint package %% --------------------------------------------------------------- @@ -70,7 +70,7 @@ \XINTsetupcatcodes% defined in xintkernel.sty \XINT_providespackage \ProvidesPackage{xintseries}% - [2015/10/29 v1.2b Expandable partial sums with xint package (jfB)]% + [2015/11/16 v1.2c Expandable partial sums with xint package (jfB)]% \def\xintSeries {\romannumeral0\xintseries }% \def\xintseries #1#2% {% diff --git a/Master/texmf-dist/tex/generic/xint/xinttools.sty b/Master/texmf-dist/tex/generic/xint/xinttools.sty index 8526c4ea5c1..3d865b3c645 100644 --- a/Master/texmf-dist/tex/generic/xint/xinttools.sty +++ b/Master/texmf-dist/tex/generic/xint/xinttools.sty @@ -21,7 +21,7 @@ %% same distribution. (The sources need not necessarily be %% in the same archive or directory.) %% --------------------------------------------------------------- -%% The xint bundle v1.2b 2015/10/29 +%% The xint bundle v1.2c 2015/11/16 %% Copyright (C) 2013-2015 by Jean-Francois Burnol %% xinttools: Expandable and non-expandable utilities %% --------------------------------------------------------------- @@ -70,7 +70,7 @@ \XINTsetupcatcodes% defined in xintkernel.sty \XINT_providespackage \ProvidesPackage{xinttools}% - [2015/10/29 v1.2b Expandable and non-expandable utilities (jfB)]% + [2015/11/16 v1.2c Expandable and non-expandable utilities (jfB)]% \newtoks\XINT_toks \xint_firstofone{\let\XINT_sptoken= } %<- space here! \def\xintgodef {\global\xintodef }% |