diff options
author | Karl Berry <karl@freefriends.org> | 2016-03-19 22:13:18 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2016-03-19 22:13:18 +0000 |
commit | ff3c0e83bcf8933daf4eebaf87613022ca946b6a (patch) | |
tree | c004090697462976dff59f90084c8012f970a0c6 /Master | |
parent | 4f476d8d94c0d15e98b145f8674621c8b309fe39 (diff) |
xint (19mar16)
git-svn-id: svn://tug.org/texlive/trunk@40077 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
19 files changed, 3325 insertions, 2412 deletions
diff --git a/Master/texmf-dist/doc/generic/xint/CHANGES.html b/Master/texmf-dist/doc/generic/xint/CHANGES.html index 0c940990e9b..6b3a243290e 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 1.2f" /> + <meta name="author" content="xint 1.2g" /> <title>CHANGE LOG</title> <style type="text/css">code{white-space: pre;}</style> <style type="text/css"> @@ -17,37 +17,41 @@ <body> <div id="header"> <h1 class="title">CHANGE LOG</h1> -<h2 class="author">xint 1.2f</h2> -<h3 class="date">2016/03/12</h3> +<h2 class="author">xint 1.2g</h2> +<h3 class="date">2016/03/19</h3> </div> <div id="TOC"> <ul> -<li><a href="#f-20160312"><code>1.2f (2016/03/12)</code></a><ul> +<li><a href="#g-20160319"><code>1.2g (2016/03/19)</code></a><ul> <li><a href="#incompatible-changes">Incompatible changes</a></li> -<li><a href="#bug-fixes">Bug fixes</a></li> <li><a href="#improvements-and-new-features">Improvements and new features</a></li> </ul></li> +<li><a href="#f-20160312"><code>1.2f (2016/03/12)</code></a><ul> +<li><a href="#incompatible-changes-1">Incompatible changes</a></li> +<li><a href="#bug-fixes">Bug fixes</a></li> +<li><a href="#improvements-and-new-features-1">Improvements and new features</a></li> +</ul></li> <li><a href="#e-20151122"><code>1.2e (2015/11/22)</code></a><ul> <li><a href="#bug-fixes-1">Bug fixes</a></li> -<li><a href="#improvements-and-new-features-1">Improvements and new features</a></li> +<li><a href="#improvements-and-new-features-2">Improvements and new features</a></li> </ul></li> <li><a href="#d-20151118"><code>1.2d (2015/11/18)</code></a><ul> <li><a href="#bug-fixes-2">Bug fixes</a></li> -<li><a href="#improvements-and-new-features-2">Improvements and new features</a></li> +<li><a href="#improvements-and-new-features-3">Improvements and new features</a></li> </ul></li> <li><a href="#c-20151116"><code>1.2c (2015/11/16)</code></a><ul> <li><a href="#bug-fixes-3">Bug fixes</a></li> -<li><a href="#improvements-and-new-features-3">Improvements and new features</a></li> +<li><a href="#improvements-and-new-features-4">Improvements and new features</a></li> </ul></li> <li><a href="#b-20151029"><code>1.2b (2015/10/29)</code></a><ul> <li><a href="#bug-fixes-4">Bug fixes</a></li> </ul></li> <li><a href="#a-20151019"><code>1.2a (2015/10/19)</code></a><ul> <li><a href="#bug-fixes-5">Bug fixes</a></li> -<li><a href="#improvements-and-new-features-4">Improvements and new features</a></li> +<li><a href="#improvements-and-new-features-5">Improvements and new features</a></li> </ul></li> <li><a href="#section"><code>1.2 (2015/10/10)</code></a><ul> -<li><a href="#improvements-and-new-features-5">Improvements and new features</a></li> +<li><a href="#improvements-and-new-features-6">Improvements and new features</a></li> </ul></li> <li><a href="#c-20150912"><code>1.1c (2015/09/12)</code></a></li> <li><a href="#b-20150831"><code>1.1b (2015/08/31)</code></a></li> @@ -79,13 +83,27 @@ <li><a href="#section-8"><code>1.0 (2013/03/28)</code></a></li> </ul> </div> -<pre><code>Source: xint.dtx 1.2f 2016/03/12 (doc 2016/03/12) +<pre><code>Source: xint.dtx 1.2g 2016/03/19 (doc 2016/03/19) Author: Jean-Francois Burnol Info: Expandable operations on big integers, decimals, fractions License: LPPL 1.3c</code></pre> -<h2 id="f-20160312"><code>1.2f (2016/03/12)</code></h2> +<h2 id="g-20160319"><code>1.2g (2016/03/19)</code></h2> <h3 id="incompatible-changes">Incompatible changes</h3> <ul> +<li><p>inside expressions, list item selector <code>[L][n]</code> counts starting at zero, not at one. This is more coherent with <code>[L][a:b]</code> which was already exactly like in Python since its introduction. A function len(L) replaces earlier <code>[L][0]</code>.</p></li> +<li><p>former <code>iter</code> keyword now called <code>iterr</code>. Indeed it matched with <code>rrseq</code>, the new <code>iter</code> (which was somehow missing from <code>1.1</code>) is the one matching <code>rseq</code>. Allows to iterate more easily with a "list" variable.</p></li> +</ul> +<h3 id="improvements-and-new-features">Improvements and new features</h3> +<ul> +<li><p>in <strong>xintexpr.sty</strong>: list selectors <code>[L][n]</code> and <code>[L][a:b]</code> are more efficient: the earlier <code>1.1</code> routines did back and forth conversions from comma separated values to braced tokens, the <code>1.2g</code> routines use macros from <strong>xinttools.sty</strong> handling directly the encountered lists of comma separated values.</p></li> +<li><p>in <strong>xinttools.sty</strong>: slight improvements in the efficiency of the <code>\xintNthElt</code>, <code>\xintKeep</code>, <code>\xintTrim</code> routines and new routines handling directly comma separated values. The latter are not included in the user manual (they are not <code>\long</code>, they don't make efforts to preserve some braces, do not worry about spaces, all those worries being irrelevant to the use in expressions for list selectors).</p></li> +<li><p>a slight speed improvement to <code>\xintFloatSqrt</code> in its quest of correct rounding.</p></li> +<li><p>float multiplication and division handle more swiftly operands (non-fractional) with few digits, when the float precision is large.</p></li> +<li><p>the syntax of expressions is described in a devoted chapter of the documentation; an example shows how to implement (expandably) the Brent-Salamin algorithm for computation of Pi using <code>iter</code> in a float expression.</p></li> +</ul> +<h2 id="f-20160312"><code>1.2f (2016/03/12)</code></h2> +<h3 id="incompatible-changes-1">Incompatible changes</h3> +<ul> <li>no more <code>\xintFac</code> macro but <code>\xintiFac/\xintiiFac/\xintFloatFac</code>.</li> </ul> <h3 id="bug-fixes">Bug fixes</h3> @@ -94,7 +112,7 @@ License: LPPL 1.3c</code></pre> <li><p><code>1.2c</code>'s fix to the subtraction bug from <code>1.2</code> introduced another bug, which in some cases could create leading zeroes in the output, or even worse. This could invalidate other routines using subtractions, like <code>\xintiiSquareRoot</code>.</p></li> <li><p>the comparison operators were not recognized by <code>\xintNewIIExpr</code> and <code>\xintdefiifunc</code> constructs.</p></li> </ul> -<h3 id="improvements-and-new-features">Improvements and new features</h3> +<h3 id="improvements-and-new-features-1">Improvements and new features</h3> <ul> <li><p>functions <code>binomial</code>, <code>pfactorial</code> and <code>factorial</code> in both integer and float versions.</p></li> <li><p>macros <code>\xintiiBinomial</code>, <code>\xintiiPFactorial</code> (<strong>xint.sty</strong>) and <code>\xintFloatBinomial</code>, <code>\xintFloatPFactorial</code> (<strong>xintfrac.sty</strong>). Improvements to <code>\xintFloatFac</code>.</p></li> @@ -104,7 +122,7 @@ License: LPPL 1.3c</code></pre> <li><p>modified behaviour for the <code>\xintPFloat</code> macro, used by <code>\xintthefloatexpr</code> to prettify its output. It now opts for decimal notation if and only if scientific notation would use an exponent between <code>-5</code> and <code>5</code> inclusive. The zero value is printed <code>0.</code> with a dot.</p></li> <li><p>the float macros for addition, subtraction, multiplication, division now first round their two operands to P, not P+2, significant places before doing the actual computation (P being the target precision). The same applies to the power macros and to the square root macro.</p></li> <li><p>the documentation offers a more precise (and accurate) discussion of floating point issues.</p></li> -<li><p>various under-the-hood code improvements; the floatexpr operations are chained in a faster way, from skipping some unneeded parsing on results of earlier computations. The absence of a real inner data structure for floats (incorporating their precisions, for one) is however still a bit hair rising: currently the lengths of the mantissas of the operands are computed again by each float macro or expression operation.</p></li> +<li><p>various under-the-hood code improvements; the floatexpr operations are chained in a faster way, from skipping some unneeded parsing on results of earlier computations. The absence of a real inner data structure for floats (incorporating their precisions, for one) is however still a bit hair raising: currently the lengths of the mantissas of the operands are computed again by each float macro or expression operation.</p></li> <li><p>(TeXperts only) the macros defined (internally) from <code>\xintdeffunc</code> et al. constructs do not incorporate an initial <code>\romannumeral</code> anymore.</p></li> <li><p>renewed desperate efforts at improving the documentation by random shuffling of sections and well thought additions; cuts were considered and even performed.</p></li> </ul> @@ -115,7 +133,7 @@ License: LPPL 1.3c</code></pre> <li><p>in <strong>xintexpr</strong>: release <code>1.2d</code> had broken the recognition of sub-expressions immediately after variable names (with tacit multiplication).</p></li> <li><p>in <strong>xintexpr</strong>: contrarily to what <code>1.2d</code> documentation said, tacit multiplication was not yet always done with enhanced precedence. Now yes.</p></li> </ul> -<h3 id="improvements-and-new-features-1">Improvements and new features</h3> +<h3 id="improvements-and-new-features-2">Improvements and new features</h3> <ul> <li><p>macro <code>\xintunassignvar</code>.</p></li> <li><p>slight modifications of the logged messages in case of <code>\xintverbosetrue</code>.</p></li> @@ -127,7 +145,7 @@ License: LPPL 1.3c</code></pre> <ul> <li>in <strong>xintcore</strong>: release <code>1.2c</code> had inadvertently broken the <code>\xintiiDivRound</code> macro.</li> </ul> -<h3 id="improvements-and-new-features-2">Improvements and new features</h3> +<h3 id="improvements-and-new-features-3">Improvements and new features</h3> <ul> <li><p>the function definitions done by <code>\xintdeffunc</code> et al., as well as the macro declarations by <code>\xintNewExpr</code> et al. now have only local scope.</p></li> <li><p>tacit multiplication applies to more cases, for example (x+y)z, and always ties more than standard * infix operator, e.g. x/2y is like x/(2*y).</p></li> @@ -138,7 +156,7 @@ License: LPPL 1.3c</code></pre> <ul> <li>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).</li> </ul> -<h3 id="improvements-and-new-features-3">Improvements and new features</h3> +<h3 id="improvements-and-new-features-4">Improvements and new features</h3> <ul> <li><p>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> @@ -151,16 +169,16 @@ License: LPPL 1.3c</code></pre> <h2 id="a-20151019"><code>1.2a (2015/10/19)</code></h2> <h3 id="bug-fixes-5">Bug fixes</h3> <ul> -<li>in <strong>xintexpr</strong>: recent release <code>1.2</code> introduced a bad bug in the parsing of decimal numbers and as a result <code>\xinttheexpr 0.01\relax</code> expanded to <code>0</code> ! (sigh...)</li> +<li>in <strong>xintexpr</strong>: recent release <code>1.2</code> introduced a bad bug in the parsing of decimal numbers and as a result <code>\xinttheexpr 0.01\relax</code> expanded to <code>0</code> ! (sigh...)</li> </ul> -<h3 id="improvements-and-new-features-4">Improvements and new features</h3> +<h3 id="improvements-and-new-features-5">Improvements and new features</h3> <ul> <li><p>added <code>\xintKeepUnbraced</code>, <code>\xintTrimUnbraced</code> (<strong>xinttools</strong>) and fixed documentation of <code>\xintKeep</code> and <code>\xintTrim</code> regarding brace stripping.</p></li> <li><p>added <code>\xintiiMaxof/\xintiiMinof</code> (<strong>xint</strong>).</p></li> <li><p>TeX hackers only: replaced all code uses of <code>\romannumeral-`0</code> by the quicker <code>\romannumeral`&&@</code> (<code>^</code> being used as letter, had to find another character usable with catcode 7).</p></li> </ul> <h2 id="section"><code>1.2 (2015/10/10)</code></h2> -<h3 id="improvements-and-new-features-5">Improvements and new features</h3> +<h3 id="improvements-and-new-features-6">Improvements and new features</h3> <ul> <li><p>the basic arithmetic implemented in <strong>xintcore</strong> has been entirely rewritten. The mathematics remains the elementary school one, but the <code>TeX</code> implementation achieves higher speed (except, regarding addition/subtraction, for numbers up to about thirty digits), the gains becoming quite significant for numbers with hundreds of digits.</p></li> <li><p>the inputs must have less than 19959 digits. But computations with thousands of digits take time.</p></li> @@ -168,7 +186,7 @@ License: LPPL 1.3c</code></pre> <li><p>a <em>qint</em> function is provided to help the parser gather huge integers in one-go, as an exception to its normal mode of operation which expands token by token.</p></li> <li><p><code>\xintFloatFac</code> macro for computing the factorials of integers as floating point numbers to a given precision. The <code>!</code> postfix operator inside <code>\xintfloatexpr</code> maps to this new macro rather than to the exact factorial as used by <code>\xintexpr</code> and <code>\xintiiexpr</code>.</p></li> <li><p>the macros <code>\xintAdd</code>, <code>\xintSub</code>, ..., now require package <strong>xintfrac</strong>. With only <strong>xintcore</strong> or <strong>xint</strong> loaded, one <em>must</em> use <code>\xintiiAdd</code>, <code>\xintiiSub</code>, ..., or <code>\xintiAdd</code>, <code>\xintiSub</code>, etc...</p></li> -<li><p>there is more flexibility in the parsing done by the macros from <strong>xintfrac</strong> on fractional input: the decimal parts of both the numerator and the denominator may arise from a separate expansion via <code>\romannumeral-`0</code>. Also the strict <code>A/B[N]</code> format is a bit relaxed: <code>N</code> may be empty or anything understood by <code>\numexpr</code>.</p></li> +<li><p>there is more flexibility in the parsing done by the macros from <strong>xintfrac</strong> on fractional input: the decimal parts of both the numerator and the denominator may arise from a separate expansion via <code>\romannumeral-`0</code>. Also the strict <code>A/B[N]</code> format is a bit relaxed: <code>N</code> may be anything understood by <code>\numexpr</code> (it could even be empty but that possibility has been removed by later <code>1.2f</code> release.)</p></li> <li><p>on the other hand an isolated dot <code>.</code> is not legal syntax anymore inside the expression parsers: there must be digits either before or after. It remains legal input for the macros of <strong>xintfrac</strong>.</p></li> <li><p>added <code>\ht</code>, <code>\dp</code>, <code>\wd</code>, <code>\fontcharht</code>, etc... to the tokens recognized by the parsers and expanded by <code>\number</code>.</p></li> <li><p>an obscure bug in package <strong>xintkernel</strong> has been fixed, regarding the sanitization of catcodes: under certain circumstances (which could not occur in a normal <code>LaTeX</code> context), unusual catcodes could end up being propagated to the external world.</p></li> diff --git a/Master/texmf-dist/doc/generic/xint/CHANGES.pdf b/Master/texmf-dist/doc/generic/xint/CHANGES.pdf Binary files differindex d4ad85a9f9a..f28290228f2 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 b3ad2a4b5e3..0f09abb700e 100644 --- a/Master/texmf-dist/doc/generic/xint/README +++ b/Master/texmf-dist/doc/generic/xint/README @@ -1,4 +1,4 @@ - Source: xint.dtx 1.2f 2016/03/12 (doc 2016/03/12) + Source: xint.dtx 1.2g 2016/03/19 (doc 2016/03/19) Author: Jean-Francois Burnol Info: Expandable operations on big integers, decimals, fractions License: LPPL 1.3c @@ -15,18 +15,24 @@ as sourcexint.pdf. AIM -The basic aim is provide _expandable_ computations on big integers, and -also big fractions. For example +The basic aim is provide _expandable_ computations on integers, +fractions, and floating point numbers. For example \xinttheexpr reduce(37189719/183618963+11390170/17310720)^17\relax will evaluate exactly the fraction (the result has 462 characters -including the fraction slash). One can also work with dummy variables. -For example +including the fraction slash). One can also work with dummy variables: \xinttheexpr mul(add(x(x+1)(x+2), x=y..y+15), y=171286,98762,9296)\relax -evaluates to 15979066346135829902328007959448563667099190784. +(evaluates to 15979066346135829902328007959448563667099190784.) + +Float computations are possible at an adjustable precision (default 16). + + \xintthefloatexpr 123456789^1000.5\relax + +Mathematical functions (apart from sqrt which achieves correct rounding +in arbitrary precision) are yet to be implemented. It is possible to use the package with Plain as well as with LaTeX. diff --git a/Master/texmf-dist/doc/generic/xint/README.html b/Master/texmf-dist/doc/generic/xint/README.html index 3cb30ba8d53..83b7a568fd8 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 1.2f" /> + <meta name="author" content="xint 1.2g" /> <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 1.2f</h2> -<h3 class="date">2016/03/12</h3> +<h2 class="author">xint 1.2g</h2> +<h3 class="date">2016/03/19</h3> </div> <div id="TOC"> <ul> @@ -36,7 +36,7 @@ <li><a href="#license">License</a></li> </ul> </div> -<pre><code>Source: xint.dtx 1.2f 2016/03/12 (doc 2016/03/12) +<pre><code>Source: xint.dtx 1.2g 2016/03/19 (doc 2016/03/19) Author: Jean-Francois Burnol Info: Expandable operations on big integers, decimals, fractions License: LPPL 1.3c</code></pre> @@ -44,11 +44,14 @@ License: LPPL 1.3c</code></pre> <p>Change log is to be found in <code>CHANGES.pdf</code> or <code>CHANGES.html</code>.</p> <p>The user manual is <code>xint.pdf</code>, and the commented source code is available as <code>sourcexint.pdf</code>.</p> <h1 id="aim">Aim</h1> -<p>The basic aim is provide <em>expandable</em> computations on big integers, and also big fractions. For example</p> +<p>The basic aim is provide <em>expandable</em> computations on integers, fractions, and floating point numbers. For example</p> <pre><code>\xinttheexpr reduce(37189719/183618963+11390170/17310720)^17\relax</code></pre> -<p>will evaluate exactly the fraction (the result has 462 characters including the fraction slash). One can also work with dummy variables. For example</p> +<p>will evaluate exactly the fraction (the result has 462 characters including the fraction slash). One can also work with dummy variables:</p> <pre><code>\xinttheexpr mul(add(x(x+1)(x+2), x=y..y+15), y=171286,98762,9296)\relax</code></pre> -<p>evaluates to <code>15979066346135829902328007959448563667099190784</code>.</p> +<p>(evaluates to <code>15979066346135829902328007959448563667099190784</code>.)</p> +<p>Float computations are possible at an adjustable precision (default 16).</p> +<pre><code>\xintthefloatexpr 123456789^1000.5\relax</code></pre> +<p>Mathematical functions (apart from <code>sqrt</code> which achieves correct rounding in arbitrary precision) are yet to be implemented.</p> <p>It is possible to use the package with Plain as well as with LaTeX.</p> <p>Sub-units <code>xintcore</code>, <code>xint</code> and <code>xintfrac</code> provide the underlying macros, and <code>xintexpr</code> loads all of them and provides expandable parsers allowing computations such as the above (and more). A more light-weight package <a href="http://www.ctan.org/pkg/bnumexpr">bnumexpr</a> (LaTeX only) loads only <code>xintcore</code> and provides a parser which handles only big integers, the four operations, the power operation and the factorial (1.2).</p> <h1 id="usage">Usage</h1> diff --git a/Master/texmf-dist/doc/generic/xint/README.pdf b/Master/texmf-dist/doc/generic/xint/README.pdf Binary files differindex f5d338fc252..82c9397f398 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 5552ceb954c..e511ceea138 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 b2ffd8533d6..236cf80017b 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 74bc80a0d62..47011e90fa7 100644 --- a/Master/texmf-dist/source/generic/xint/xint.dtx +++ b/Master/texmf-dist/source/generic/xint/xint.dtx @@ -3,27 +3,27 @@ % Extract all files via "etex xint.dtx" and do "make help" % or follow instructions from extracted README.md. %<*dtx> -\def\xintdtxtimestamp {Time-stamp: <12-03-2016 at 21:52:32 CET>} +\def\xintdtxtimestamp {Time-stamp: <19-03-2016 at 14:52:58 CET>} %</dtx> %<*drv> %% --------------------------------------------------------------- -\def\xintdocdate {2016/03/12} -\def\xintbndldate{2016/03/12} -\def\xintbndlversion {1.2f} +\def\xintdocdate {2016/03/19} +\def\xintbndldate{2016/03/19} +\def\xintbndlversion {1.2g} %</drv> %<readme>% README %<changes>% CHANGE LOG -%<readme|changes>% xint 1.2f -%<readme|changes>% 2016/03/12 +%<readme|changes>% xint 1.2g +%<readme|changes>% 2016/03/19 %<readme|changes> -%<readme|changes> Source: xint.dtx 1.2f 2016/03/12 (doc 2016/03/12) +%<readme|changes> Source: xint.dtx 1.2g 2016/03/19 (doc 2016/03/19) %<readme|changes> Author: Jean-Francois Burnol %<readme|changes> Info: Expandable operations on big integers, decimals, fractions %<readme|changes> License: LPPL 1.3c %<readme|changes> %<*!readme&!changes&!dohtmlsh&!dopdfsh&!makefile> %% --------------------------------------------------------------- -%% The xint bundle 1.2f 2016/03/12 +%% The xint bundle 1.2g 2016/03/19 %% Copyright (C) 2013-2016 by Jean-Francois Burnol %<xintkernel>%% xintkernel: Paraphernalia for the xint packages %<xinttools>%% xinttools: Expandable and non-expandable utilities @@ -51,18 +51,25 @@ available as `sourcexint.pdf`. Aim === -The basic aim is provide *expandable* computations on big integers, -and also big fractions. For example +The basic aim is provide *expandable* computations on integers, +fractions, and floating point numbers. For example \xinttheexpr reduce(37189719/183618963+11390170/17310720)^17\relax will evaluate exactly the fraction (the result has 462 characters including the fraction slash). One can also work with dummy -variables. For example +variables: \xinttheexpr mul(add(x(x+1)(x+2), x=y..y+15), y=171286,98762,9296)\relax -evaluates to `15979066346135829902328007959448563667099190784`. +(evaluates to `15979066346135829902328007959448563667099190784`.) + +Float computations are possible at an adjustable precision (default 16). + + \xintthefloatexpr 123456789^1000.5\relax + +Mathematical functions (apart from `sqrt` which achieves correct +rounding in arbitrary precision) are yet to be implemented. It is possible to use the package with Plain as well as with LaTeX. @@ -232,6 +239,49 @@ pandoctpl.latex, doHTMLs.sh, doPDFs.sh, xint.dvi, xint.pdf, Makefile.mk.</div> %</readme>-------------------------------------------------------- %<*changes>------------------------------------------------------- + +`1.2g (2016/03/19)` +---- + +### Incompatible changes + + - inside expressions, list item selector `[L][n]` counts starting at + zero, not at one. This is more coherent with `[L][a:b]` which was + already exactly like in Python since its introduction. A function + len(L) replaces earlier `[L][0]`. + + - former `iter` keyword now called `iterr`. Indeed it matched with + `rrseq`, the new `iter` (which was somehow missing from `1.1`) is the + one matching `rseq`. Allows to iterate more easily with a "list" + variable. + +### Improvements and new features + + - in **xintexpr.sty**: list selectors `[L][n]` and `[L][a:b]` are more + efficient: the earlier `1.1` routines did back and forth conversions + from comma separated values to braced tokens, the `1.2g` routines use + macros from **xinttools.sty** handling directly the encountered lists + of comma separated values. + + - in **xinttools.sty**: slight improvements in the efficiency of the + `\xintNthElt`, `\xintKeep`, `\xintTrim` routines and new routines + handling directly comma separated values. The latter are not included + in the user manual (they are not `\long`, they don't make efforts to + preserve some braces, do not worry about spaces, all those worries + being irrelevant to the use in expressions for list selectors). + + - a slight speed improvement to `\xintFloatSqrt` in its quest of + correct rounding. + + - float multiplication and division handle more swiftly operands + (non-fractional) with few digits, when the float precision is large. + + - the syntax of expressions is described in a devoted chapter of the + documentation; an example shows how to implement (expandably) the + Brent-Salamin algorithm for computation of Pi using `iter` in a float + expression. + + `1.2f (2016/03/12)` ---- @@ -287,7 +337,7 @@ Makefile.mk.</div> chained in a faster way, from skipping some unneeded parsing on results of earlier computations. The absence of a real inner data structure for floats (incorporating their precisions, for one) is however still a bit hair - rising: currently the lengths of the mantissas of the operands are computed + raising: currently the lengths of the mantissas of the operands are computed again by each float macro or expression operation. - (TeXperts only) the macros defined (internally) from `\xintdeffunc` et al. @@ -380,8 +430,8 @@ Makefile.mk.</div> ### Bug fixes - in **xintexpr**: recent release `1.2` introduced a bad bug in the - parsing of decimal numbers and as a result `\xinttheexpr - 0.01\relax` expanded to `0` ! (sigh...) + parsing of decimal numbers and as a result `\xinttheexpr 0.01\relax` + expanded to `0` ! (sigh...) ### Improvements and new features @@ -430,7 +480,9 @@ Makefile.mk.</div> **xintfrac** on fractional input: the decimal parts of both the numerator and the denominator may arise from a separate expansion via ``\romannumeral-`0``. Also the strict `A/B[N]` format is a bit - relaxed: `N` may be empty or anything understood by `\numexpr`. + relaxed: `N` may be anything understood by `\numexpr` (it could even + be empty but that possibility has been removed by later `1.2f` + release.) - on the other hand an isolated dot `.` is not legal syntax anymore inside the expression parsers: there must be digits either before or @@ -1803,9 +1855,9 @@ dvipdfmx CHANGES.dvi \def\gobbletodot #1.{} -\newif\ifindescription % 1 avril 2014 +\newif\ifinmanualmaintoc % 1 avril 2014 \ifnum\dosourcexint=0 - \indescriptiontrue + \inmanualmaintoctrue \fi \def\sectioncouleur{{cyan}} @@ -1843,7 +1895,7 @@ dvipdfmx CHANGES.dvi \addvspace{\smallskipamount}% \begin{multicols}{2} \leftskip \margegauchetoc % 12 octobre 2014 - \ifindescription + \ifinmanualmaintoc \rightskip \MARGEPAGENO \else \rightskip \MARGEPAGENO plus 2em minus 1em @@ -1853,11 +1905,11 @@ dvipdfmx CHANGES.dvi {} {\noindent \llap{\makebox[\margegauchetoc][l]{\ttzfamily\bfseries\etoclink - {\ifindescription\expandafter\textcolor\sectioncouleur + {\ifinmanualmaintoc\expandafter\textcolor\sectioncouleur {\normalfont\bfseries\ETOCsectionnumber}\fi .\expandafter\gobbletodot\etocthenumber}}}% \strut\etocname\nobreak - \unless\ifindescription\leaders\etoctoclineleaders\fi + \unless\ifinmanualmaintoc\leaders\etoctoclineleaders\fi \hfill\nobreak \strut\makebox[\MARGEPAGENO][r]{\small\etocpage}\endgraf } {\end{multicols}\endgroup\addvspace{\smallskipamount}}% @@ -2665,6 +2717,7 @@ pdfpagemode=UseOutlines} \etoctoccontentsline*{toctobookmark}{Contents}{2}% } +\inmanualmaintocfalse \clearpage @@ -3067,11 +3120,12 @@ Here is a (partial) list of the recognized symbols: max, min, |`+`|, |`*`|, not, all, any, xor, if, ifsgn, even, odd, first, last, reversed, bool, togl, factorial, binomial, pfactorial}\do {\dtt{#1}, } \item functions with dummy variables \xintFor #1 in {add, mul, seq, subs, - rseq, rrseq, iter}\do {\dtt{#1}\xintifForLast{.}{, }} + rseq, iter, rrseq, iterr}\do {\dtt{#1}\xintifForLast{.}{, }} \end{itemize} -See \autoref{ssec:syntax} for the complete syntax, as well as -\autoref{ssec:dummy} which contains examples illustrating further some -features which were added at the time of release |1.1 2014/10/28|. +See \autoref{sec:xintexprsyntax} (and \autoref{ssec:syntax}) for the complete +syntax, as well as \autoref{ssec:moredummies} which contains examples +illustrating further some features which were added at the time of release +|1.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 @@ -3131,8 +3185,8 @@ not have been obtained in reduced terms: |B| divides |D| or |D| divides |B|. \end{framed} -Make sure to read \autoref{ssec:userinterface}, \autoref{ssec:syntax} and the -rest of \autoref{sec:expr}. +Make sure to read \autoref{ssec:userinterface}, \autoref{sec:xintexprsyntax} +and also \autoref{sec:expr}. \subsection{Printing big numbers on the page}\label{ssec:printnumber} When producing very long numbers there is the question of printing them on @@ -3403,12 +3457,17 @@ digits. This is not so many, let us print them here: \hyperref[ssec:e-convergents]{convergents of $e$} with the further help of the \xintcfracname package are among further examples. +\item Also included, during the explanation of the \csbxint{floatexpr} syntax, + an \hyperlink{BrentSalamin}{expandable implementation} of the Brent-Salamin + algorithm for evaluating $\pi$. + \item There is also an example of an \hyperref[xintXTrunc]{interactive session}, where results are output to the log or to a file. \item The functionalities of \xintexprname are illustrated with various - examples, in places such as in \autoref{xintdeffunc} and \autoref{ssec:dummy}. + examples, and in locations such as in \autoref{xintdeffunc} and + \autoref{ssec:dummies}. \end{itemize} Almost all of the computational results interspersed throughout the documentation are not hard-coded in the source file of this document but are @@ -3467,9 +3526,16 @@ modify the \TeX{} bound on acceptable integers, and did not add floating point support. The \href{http://www.ctan.org/pkg/bigintcalc}{bigintcalc} package by -\textsc{Heiko Oberdiek} provided expandable operations (using some of |\numexpr| +\textsc{Heiko Oberdiek} provided expandable macros (using some of |\numexpr| possibilities, when available) on arbitrarily big integers, beyond the \TeX{} -bound. The present package does this again, using more of |\numexpr| (\xintname +bound.% +% +\footnote{This package does not provide a parser of expressions on big + integers like \csbxint{iiexpr}|...\relax|. One can use package + \href{http://ctan.org/pkg/bnumexpr}{bnumexpr} to associate the |bigintcalc| + macros with an expression parser.} +% +The present package does this again, using more of |\numexpr| (\xintname requires the \eTeX{} extensions) for higher speed, and also on fractions, not only integers. Arbitrary precision floating points operations are a derivative, and not the initial design goal.% @@ -3543,7 +3609,8 @@ routinely such computations in a document. I have long been thinking that without the expandability constraint much higher speeds could be achieved, but perhaps I have not given enough thought to sustain that optimistic stance.\footnote{The \href{http://www.ctan.org/pkg/apnum}{apnum} package - implements non-expandably arbitrary precision arithmetic operations.} + implements (non-expandably) arbitrary precision fixed point algebra and (v1.6) + functions exp, log, sqrt, the trigonometrical direct and inverse functions.} I remain of the opinion that if one really wants to do computations with \emph{thousands} of digits, one should drop the expandability requirement. @@ -3716,13 +3783,13 @@ The two values rounded to 16 significant places differ.\par Here is a summary of the situation regarding floats which was prevailing from release |1.08a| to release |1.2e|. Next, we will explain the new situation -with |1.2f|. +since |1.2f|. \begin{itemize} \item As explained above the |\xintFloat| macro which converts an input to a P-float does the following in case of fraction $A/B[N]$: it truncates both $A$ and $B$ to P+2 digits say $A'$ and $B'$ then computed the correct - rounding of $A'/B'$ to P digits. (not changed in |1.2f|) + rounding of $A'/B'$ to P digits. (not changed in |1.2f| and |1.2g|) \item The |\xintFloatAdd|, |\xintFloatSub|, |\xintFloatMul|, |\xintFloatDiv| routines each first rounded their inputs to P+2 digits (thus applying the previous item, but with P replaced by P+2). @@ -3742,7 +3809,7 @@ with |1.2f|. P+4$, then $B$ was dropped altogether, if $N-M\geqslant P+4$ then $A$ was dropped, else the operation was done exactly then rounded to P digits. But in those cases where one of the summands was dropped, correct rounding was not - guaranteed, because say $A$ having P+2 digits could be close or at a + guaranteed, because say $A$ having P+2 digits could be at a mid-point between two P-floats, thus neglecting $B$ (however small it may be) could viciate the final rounding. Also, when adding $B=0$ to $A$, as $A$ is already the P+2 rounded original input, the final P-digit value could @@ -3761,12 +3828,11 @@ Besides, when used in \cs{xintfloatexpr}, most of the time the inputs will already be results of earlier computations hence have P digits. It appears wasteful to extend them by two zeros prior to each operation. -Thus, |1.2f| adopts (provisorily perhaps) the policy that the inputs will -always be rounded first to P-floats, not (P+2)-floats.\CHANGED{1.2f} This does -not change the behaviour for inputs being already P-floats. All four -operations then and now produce the correctly rounded value. For coherence -also the square root and the power macros now first round their argument -to a P-float.% +Thus, |1.2f| adopts the policy that the inputs will always be rounded first to +P-floats, not (P+2)-floats.\CHANGED{1.2f} This does not change the behaviour +for inputs being already P-floats. All four operations then and now produce +the correctly rounded value. For coherence also the square root and the power +macros now first round their argument to a P-float.% % \footnote{The power macros do not aim at correct rounding, currently. But the change fixes the issue that there was a possible difference between the @@ -3777,10 +3843,11 @@ to a P-float.% Also,\NewWith {1.2f} |1.2f| has implemented \emph{correct rounding} (in arbitrary precision) for the square root extraction. -What is yet lacking from |1.2f| is the improved handling via \csbxint{Float} -of fractions to achieve independence from the chosen representatives (which -currently only applies if numerators and denominators are of lengths at most -the target precision plus two -- the exponent is arbitrary). +What is yet lacking from |1.2f| (now |1.2g|) is the improved handling via +\csbxint{Float} of fractions to achieve independence from the chosen +representatives (which currently only applies if numerators and denominators +are of lengths at most the target precision plus two -- the exponent is +arbitrary). Next major release will decide if this initial rounding of the inputs is kept; the more ambitious model would be for the basic operations to compute the @@ -4224,9 +4291,10 @@ 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 - releases earlier than |1.2| the |N| could not be empty and had to be + releases earlier than |1.2| the |N| had to be necessarily given as explicit digits, not some macro or expression expanded in - |\numexpr|.} + |\numexpr|. From |1.2| to |1.2e| an empty |N| was allowed, but |1.2f| + removed that.} \end{description} Notice that |*|, |+| and |-| contrarily to the |/| (which is treated simply as a kind of delimiter) are not acceptable within arguments of this @@ -4236,7 +4304,7 @@ the allowed input formats for `long numbers' and `fractions' are: \item the \hyperref[xintexpr]{expression format} is for inclusion in an \csbxint{expr}|...\relax|, it uses infix notations, function names, complete expansion, recognizes decimal and scientific numbers, and is described in - \autoref{ssec:syntax}.% + \autoref{sec:xintexprsyntax} and \autoref{ssec:syntax}.% % \footnote{Starting with release |1.2|, the isolated dot |"."| is not legal anymore in expressions: there must be digits either before or after.} @@ -5019,10 +5087,12 @@ The detailed cumulative change log since the initial release is in files \href{http://mirrors.ctan.org/macros/generic/xint/CHANGES.html}{this link}) and |CHANGES.pdf|. -In a command line console, issue |texdoc --list xint| to access them. Or, run -|etex xint.dtx| in a working repertory which will extract a |CHANGES.md| file -with Markdown syntax. On a unix-like system you can then run |make -f -Makefile.mk CHANGES.html| to get the |html| version (requires |pandoc|). +In a command line console, issue |texdoc --list xint| to access them. + +It is also possible to extract them from the source |xint.dtx|: |etex +xint.dtx| in a working repertory which will extract a |CHANGES.md| file with +Markdown syntax. On a unix-like system you can then run |make -f Makefile.mk +CHANGES.html| to get the |html| version (requires |pandoc|). The last major release is |1.2 (2015/10/10)|. It came with a complete rewrite of the core arithmetic routines. The efficiency for numbers with less than @@ -5032,7 +5102,7 @@ there for almost all sizes, and became quite noticeable for numbers with hundreds of digits. The allowable inputs are constrained to have less than about $19950$ digits ($19968$ for addition, $19959$ for multiplication). -|1.2a (2015/10/19)| to |1.2f (2016/03/12)|: unfortunately, release |1.2| had +|1.2a (2015/10/19)| to |1.2g (2016/03/19)|: unfortunately, release |1.2| had at least four bad bugs. Subsequent releases were supposed to fix them but sometimes they themselves introduced new bugs which had to get fixed in a later one. For example |1.2f| fixes a bug in subtraction which was introduced @@ -5041,6 +5111,7 @@ by |1.2c|'s fix of |1.2|'s subtraction. We managed to add some new features: \begin{enumerate}[noitemsep] + \item list selectors |[L][a:b]| or |[L][n]| in expressions are faster. \item faster \csbxint{iiSquareRoot} (and allied square root macros) and \csbxint{FloatSqrt}. The latter achieves \emph{correct rounding} in arbitrary precision.\CHANGED{1.2f} @@ -5069,6 +5140,8 @@ We managed to add some new features: (not P+2 as earlier) before doing the actual computation (P is the asked for precision or \csbxint{theDigits}). The same applies to the float power and square root operations. + \item some float operations are faster a handling small operands in the + context of a large float precision. \item extensive update to ``Commands of the \xintexprname package'' (\autoref{sec:expr}.) \item complete re-write of the \hyperref[ssec:quicksort]{Quick Sort @@ -5078,6 +5151,11 @@ We managed to add some new features: section of |sourcexint.pdf|. Trimming of irrelevant old comments. \end{enumerate} + Notice that |1.2f| and |1.2g| had a few backwards incompatible changes: no + |\xintFac| but |\xintiFac|, list item numbering in expressions starts from + zero not from one, |iter| keyword has a new meaning and the former one is + now associated with |iterr|. + \section{Some utilities from the \xinttoolsname package} This is a first overview. Many examples combining these utilities with the @@ -5218,8 +5296,1163 @@ expandability. Check it out (\autoref{xintiloop}). + +\section{The syntax of \xintexprname expressions} +\label{sec:xintexprsyntax} + +\localtableofcontents + +\subsection{Infix and other operators and their precedence levels} +% \ctexttt is a remnant of 1.09n manual, don't have time to get rid of it now. +\newcommand\ctexttt [1]{\begingroup\color[named]{DarkOrchid}%\bfseries + #1\endgroup} + + +We go through the various syntax elements from highest to lowest precedence. + +\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, + itemindent=0pt, listparindent=\leftmarginiii, + leftmargin=\leftmarginii] +\item Functions share the highest precedence. + + +\item \def\MicroFont{\color[named]{DarkOrchid}\ttfamily}The + |.| as decimal mark; the number scanner treats it as an inherent, + optional and unique component of a being formed number. One can do + things such as + % + \leftedline{\restoreMicroFont|\xinttheexpr 0.^2+2^.0\relax|} + % + which is |0^2+2^0| and produces \dtt{\xinttheexpr 0.^2+2^.0\relax}. + + However a single dot |"."| as in |\xinttheexpr .^2\relax| is now illegal + input.\IMPORTANT + +\item The |e| and |E| for scientific notation. They are parsed + like the decimal mark is. +\begingroup +\restoreMicroFont |1e3^2| is \dtt{\xinttheexpr 1e3^2\relax} +\endgroup + +\item The |"| for hexadecimal numbers: it is treated with highest + priority, allowed only at locations where the parser expects to start + forming a numeric operand, once encountered it triggers the + hexadecimal scanner which looks for successive hexadecimal digits (as + usual skipping spaces and expanding forward everything; letters |A|, ..., |F|, + but not |a|, ..., |f|) possibly a + unique optional dot (allowed directly in front) and then an optional + (possibly empty) fractional part. The dot and fractional part are not + allowed in {\restoreMicroFont|\xintiiexpr..\relax|}. The |"| + functionality \fbox{requires package \xintbinhexname} (there is + no warning, but an ``undefined control sequence'' error will + naturally results if the package has not been loaded). +\begingroup + \restoreMicroFont |"A*"A^"A| is \dtt{\xinttheexpr "A*"A^"A\relax}. +\endgroup + +\item The postfix operators \ctexttt{!} and the branching conditionals \ctexttt{?, ??}. + \begin{description} + \item[{\color[named]{DarkOrchid}!}] computes the factorial of an integer. + + \item[{\color[named]{DarkOrchid}?}] is used as |(cond)?{yes}{no}|. It + evaluates the (numerical) condition (any non-zero value counts as + |true|, zero counts as |false|). It then acts as a macro with two + mandatory arguments within braces (hence this escapes from the + parser scope, the braces can not be hidden in a macro), chooses the + correct branch \emph{without evaluating the wrong one}. Once the + braces are removed, the parser scans and expands the uncovered + material so for example + % + \leftedline{|\xinttheiexpr (3>2)?{5+6}{7-1}2^3\relax|} + % + is legal and computes + |5+62^3=|\dtt{\xinttheiexpr(3>2)?{5+(6}{7-(1}2^3)\relax}. Note + though that it would be better practice to include here the |2^3| + inside the branches. The contents of the branches may be arbitrary + as long as once glued to what is next the syntax is respected: + {|\xintexpr (3>2)?{5+(6}{7-(1}2^3)\relax| also works.} Differs thus + from the |if| conditional in two ways: the false branch is not at + all computed, and the number scanner is still active on exit, more + digits may follow. + + \item[{\color[named]{DarkOrchid}??}] is used as |(cond)??{<0}{=0}{>0}|. + |cond| is anything, its sign is evaluated and depending on the sign the + correct branch is un-braced, the two others are swallowed. The un-braced + branch will then be parsed as usual. Differs from the |ifsgn| conditional + as the two false branches are not evaluated and furthermore the number + scanner is still active on exit. + % + \leftedline{|\def\x{0.33}\def\y{1/3}|} + % + \leftedline{|\xinttheexpr (\x-\y)??{sqrt}{0}{1/}(\y-\x)\relax|% + \dtt{=\def\x{0.33}\def\y{1/3}% + \xinttheexpr (\x-\y)??{sqrt}{0}{1/}(\y-\x)\relax }} + % + \end{description} + +\item The minus sign |-| as prefix unary operator inherits the precedence of + the infix operator it follows. With things such as |5+------2*3|, the + \xintexprname parsers don't try to be efficient: once |2*3| is evaluated the + opposite function will be applied the necessary number of times. On the other + hand the plus sign |+| as prefix unary operator as in, for example + |5-++++++2*3|, is immediately gobbled. + +\item The power operator |^|, or |**|. It is left associative: + {\restoreMicroFont|\xinttheiexpr 2^2^3\relax|} evaluates to \xinttheiexpr + 2^2^3\relax, not \xinttheiexpr 2^(2^3)\relax. Note that if the float + precision is too low, iterated powers within |\xintfloatexpr..\relax| may + fail: for example with the default setting |(1+1e-8)^(12^16)| will be + computed with |12^16| approximated from its $16$ most significant digits + but it has $18$ digits (\dtt{={\xintiiPow{12}{16}}}), hence the result is + wrong: + \begingroup + % + \leftedline{$\np{\xintthefloatexpr (1+1e-8)^(12^16)\relax }$} + % + One should code + % + \leftedline{\restoreMicroFont|\xintthe\xintfloatexpr (1+1e-8)^\xintiiexpr 12^16\relax + \relax|} + % + to obtain the correct floating point evaluation + % + \leftedline{$\np{1.00000001}^{12^{16}}\approx\np{\xintthefloatexpr + (1+1e-8)^\xintiiexpr 12^16\relax\relax }$} + % + \endgroup + +\item Multiplication and division \raisebox{-.3\height}{|*|}, |/|. The + division is left associative, too: + % + \begingroup\restoreMicroFont + % + |\xinttheiexpr 100/50/2\relax| evaluates to \xinttheiexpr 100/50/2\relax, + not \xinttheiexpr 100/(50/2)\relax. + % + \endgroup + Inside \csbxint{iiexpr}, |/| does \emph{rounded} division. + +\item Truncated division |//| and modulo |/:| (equivalently |'mod'|, quotes + mandatory) are at the same level of priority than multiplication and + division, thus left-associative with them. Apply parentheses for + disambiguation. +\begin{everbatim*} +\xinttheexpr 100000//13, 100000/:13, 100000 'mod' 13, trunc(100000/13,10), + trunc(100000/:13/13,10)\relax +\end{everbatim*} + +\item The list itemwise operators |*[|, |/[|, |^[|, |**[|, |]*|, |]/|, |]^|, + |]**| are at the same precedence level as, respectively, |*| and |/| or |^| + and |**|. + +\item Addition and subtraction |+|, |-|. Again, |-| is left + associative: + % + \begingroup\restoreMicroFont + % + |\xinttheiexpr 100-50-2\relax| evaluates to \xinttheiexpr 100-50-2\relax, + not \xinttheiexpr 100-(50-2)\relax. + % + \endgroup + +\item The list itemwise operators |+[|, |-[|, |]+|, |]-|, are at + the same precedence level as |+| and |-|, + +\item Comparison operators |<|, |>|, |=| (same as |==|), |<=|, |>=|, |!=| all + at the same level of precedence, use parentheses for disambiguation. + +\item Conjunction (logical and): |&&| or equivalently + |'and'| (quotes mandatory). + +\item Inclusive disjunction (logical or): \verb+||+ + and equivalently |'or'| (quotes mandatory). + +\item XOR: |'xor'| with mandatory quotes is at the same level of precedence + as \verb+||+. + +\item The list generation operators |..|, |..[|, |]..| are at the same + (low) precedence level as the \verb+||+ operator of logical disjunction. + +\item The comma: +\restoreMicroFont with |\xinttheexpr 2^3,3^4,5^6\relax| +one obtains as output \xinttheexpr 2^3,3^4,5^6\relax{}. + +\item The parentheses. The list outer brackets |[|, |]| share the same + functional precedence as parentheses. The semi-colon |;| in an |iter| or + |rseq| has the same precedence as a closing parenthesis. +\end{itemize} + + +\subsection{Tacit multiplication} +\label{ssec:tacit multiplication} + +Tacit multiplication (insertion of a |*|) applies when the parser is currently +either scanning the digits of a number (or its decimal part or scientific +part, or hexadecimal input), or is looking for an infix operator, and: +(1.)~\emph{encounters a count or dimen or skip register or variable or an + \eTeX{} expression}, or (2.)~\emph{encounters a sub-\csa{xintexpr}ession}, +or (3.)~\emph{encounters an opening parenthesis}, or (4.)~\emph{encounters a + letter (which is interpreted as signaling the start of either a variable or + a function name)}. + +\begin{framed} + For example, if |x, y, z| are variables all three of |(x+y)z|, |x(y+z)|, + |(x+y)(x+z)| will create a tacit multiplication. + + Furthermore starting with release + |1.2e|,\MyMarginNote[\kern\dimexpr\FrameSep+\FrameRule\relax]{Changed} + whenever tacit multiplication is applied, in all cases it \emph{always} + ``ties'' more\IMPORTANT{} than normal multiplication or division, but + still less than power. Thus |x/2y| is interpreted as |x/(2y)| and + similarly for |x/2max(3,5)| but |x^2y| is still interpreted as |(x^2)*y| + and |2n!| as |2*n!|. + +\begin{everbatim*} +\xintdefvar x:=30;\xintdefvar y:=5;% +\xinttheexpr (x+y)x, x/2y, x^2y, x!, 2x!, x/2max(x,y)\relax +\end{everbatim*} + + The ``tie more'' rule applies to all cases of tacit multiplication. It + impacts only situations when a division was the last seen operator, as the + normal rule for the \xintexprname parsers is left-associativity in case of + equal precedence. +\begin{everbatim*} +\xinttheexpr (1+2)/(3+4)(5+6), 2/x(10), 2/10x, 3/y\xintiiexpr 5+6\relax, 1/x(y)\relax +\end{everbatim*} + + Note that |y\xinttheiiexpr 5+6\relax| would have tried to use a variable + with name |y11| rather than doing |y*11|: tacit multiplication works only + in front of sub-\csbxint{expr}essions, not in front of + \csbxint{theexpr}essions which are unlocked into explicit digits. + + These examples above redeclared the |x| and |y| which thus can not be used as + dummy variables anymore (but see \csbxint{unassignvar}); as this happened + inside a \LaTeX{} environment (for the frame), they will have + recovered their meanings after the frame. In the meantime we use letter + |z| for the next example. Here is an expression whose meaning is + completely modified by the ``tie more'' property of tacit multiplication:\IMPORTANT +\begin{everbatim} +\xintdeffunc e(z):=1+z(1+z/2(1+z/3(1+z/4))); +\end{everbatim} +will be parsed as |1+z*(1+z/(2*(1+z/(3*(1+z/4)))))| which is + not at all like the presumably hoped: +\begin{everbatim} +\xintdeffunc e(z):=1+z(1+z/2*(1+z/3*(1+z/4))); +\end{everbatim} +This form can also be used, alternatively: +\begin{everbatim} +\xintdeffunc e(z):=(((z/4+1)z/3+1)z/2+1)z+1; +\end{everbatim} + + Attention! tacit multiplication before an opening parenthesis applies + always, but tacit multiplication after a closing parenthesis \emph{does + not} apply in front of digits: |(1+1)5| is not legal. But + |subs((1+1)x,x=5)| is, because in that case a variable is following the + closing parenthesis. +\end{framed} + + +\subsection{List operations} +\label{ssec:lists} + +By \emph{list} we hereby mean simply comma-separated values, for example |3, +-7, 1e5|. This section describes some syntax which allows to manipulate such +lists, for example |[3, -7, 1e5][1]| extracts |-7| (we follow the Python +convention of enumerating starting at zero; see the frame next). + +In the context of dummy variables, lists can be used in substitutions: +\begin{everbatim*} +\xinttheiiexpr subs(`+`(L), L = 1, 3, 5, 7, 9)\relax\newline +\end{everbatim*} +and also the |rseq| and |iter| constructs allow |@| to refer to a list: +\begin{everbatim*} +\xinttheiiexpr iter(0, 1; ([@][1], [@][0]+[@][1]), i=1..10)\relax\newline +\end{everbatim*} +where each step constructs a new list with two entries. + +However, despite appearances there is not really internally a notion of a +\emph{list type} and it is currently impossible to create, +manipulate, or return on output a \emph{list of lists}. There is a special +reserved variable |nil| which stands for the empty list: for example |len()| +is not legal but |len(nil)| works. + +The syntax which is explained next includes in particular what are called +\emph{list itemwise operators} such as: +\begin{everbatim*} +\xinttheiiexpr 37+[13,100,1000]\relax\newline +\end{everbatim*}% +This part of the syntax is considered provisory, for the reason that its +presence might make more difficult some extensions in the future. On the other +hand the Python-like slicing syntax should not change. + +\begin{framed} + \emph{A backwards incompatible change.}\IMPORTANT{} + +\medskip + +Up to release |1.2f| inclusive, the item accessor |[list][n]| returned the +|n|th element of a list. The Python-like slices |[list][a:b]| on the other +hand act exactly as in Python where list items are enumerated starting at +zero. For example |[list][:5]| or equivalently |[list][0:5]| have the effect +to keep only the first five elements. Thus |[list][n]| which returned the +|n|th element was akin to |[list][n-1:n]| whereas in Python which enumerates +from zero it would be |[list][n:n+1]|. + +One reason for that choice was that |[list][0]| allowed access to the length, +and there was thus no need to add a new function to the list of recognized +keywords. + +|1.2g|\CHANGED{1.2g} does the backwards incompatible change to adhere more +fully to Python conventions and now |[list][1]| picks the \emph{second} +element of the list and |[list][0]| the \emph{first}. There is |len(list)| for +the length. + +The reason for the change is that the author has become more accustomed to +Python than he was when he first introduced list operations to \xintexprname, +and the difference was becoming distracting. +\end{framed} + +\begin{itemize} + \item |a..b| constructs the \textbf{small} integers from the ceil $\lceil + a\rceil$ to the floor + $\lfloor b\rfloor$ (possibly a decreasing sequence): one has to be careful + if using this for algorithms that |1..0| for example is not empty or |1| + but expands to |1, 0|. Again, |a..b| \emph{can not} be used with |a| and + |b| greater than $2^{31}-1$. Also, only about at most \dtt{5000} integers + can be generated (this depends upon some \TeX{} memory settings). + + The |..| has lower precedence than the arithmetic operations. +\begin{everbatim*} +\xinttheexpr 1.5+0.4..2.3+1.1\relax; \xinttheexpr 1.9..3.4\relax; \xinttheexpr 2..3\relax +\end{everbatim*} + + \item |a..[d]..b| allows to generate big integers, or also fractions, it + proceeds with step (non necessarily integral nor positive) |d|. It does + \emph{not} replace |a| by its ceil, nor |b| by its floor. The generated + list is empty if |b-a| and |d| are of opposite signs; if |d=0| or if |a=b| + the list expands to single element |a|. +\begin{everbatim*} +\xinttheexpr 1.5..[1.01]..11.23\relax +\end{everbatim*} + + \item |[list][n]| extracts the |n+1|th element if |n>=0|.\CHANGED{1.2g} If + |n<0| it extracts from the tail. List items are numbered as in Python. + |len(list)| computes the number of items of the list. +\begin{everbatim*} +\xinttheiexpr \empty[0..10][6], len(0..10), [0..10][-1], [0..10][23*18-22*19]\relax\ +(and 23*18-22*19 has value \the\numexpr 23*18-22*19\relax). +\end{everbatim*} + +See the next frame for why the example above has |\empty| token at start. + +As shown, it is perfectly legal to do operations in the index parameter, which +will be handled by the parser as everything else. The same remark applies to +the next items. + + \item |[list][:n]| extracts the first |n| elements if |n>0|, or suppresses + the last \verb+|n|+ elements if |n<0|. +\begin{everbatim*} +\xinttheiiexpr [0..10][:6]\relax\ and \xinttheiiexpr [0..10][:-6]\relax +\end{everbatim*} + \item |[list][n:]| suppresses the first |n| elements if |n>0|, or extracts + the last \verb+|n|+ elements if |n<0|. +\begin{everbatim*} +\xinttheiiexpr [0..10][6:]\relax\ and \xinttheiiexpr [0..10][-6:]\relax +\end{everbatim*} +\item More generally, |[list][a:b]| works according to the Python ``slicing'' + rules (inclusive of negative indices). Notice though that there is no + optional third argument for the step, which always defaults to |+1|. +\begin{everbatim*} +\xinttheiiexpr [1..20][6:13]\relax\ = \xinttheiiexpr [1..20][6-20:13-20]\relax +\end{everbatim*} +\item It is naturally possible to nest these things: +\begin{everbatim*} +\xinttheexpr [[1..50][13:37]][10:-10]\relax +\end{everbatim*} +\item itemwise operations either on the left or the right are possible: +\begin{everbatim*} +\xinttheiiexpr 123*[1..10]^2\relax +\end{everbatim*} + +\begin{snugframed} + List operations are implemented using square brackets, but the |\xintiexpr| + and |\xintfloatexpr| parsers also check to see if an optional parameter + within brackets is specified before the start of the expression. To avoid the + resulting confusion if this |[| actually serves to delimit + comma separated values for list operations, one can either:\IMPORTANT{} + \begin{itemize} + \item insert something before the bracket such as |\empty| token, +\begin{everbatim*} +\xinttheiexpr \empty [1,3,6,99,100,200][2:4]\relax +\end{everbatim*} + \item use parentheses: +\begin{everbatim*} +\xinttheiexpr ([1,3,6,99,100,200][2:4])\relax +\end{everbatim*} + \end{itemize} + + + Notice though that |([1,3,6,99,100,200])[2:4]| would not work: it is + mandatory for |][| and |][:| not to be interspersed with parentheses. Spaces + are perfectly legal: +\begin{everbatim*} +\xinttheiexpr \empty[1..10 ] [ : 7 ]\relax +\end{everbatim*} + +Similarly all the |+[|, |*[|, \dots and |]**|, |]/|, \dots operators admit +spaces but nothing else between their constituent characters. +\begin{everbatim*} +\xinttheiexpr \empty [ 1 . . 1 0 ] * * 1 1 \relax +\end{everbatim*} +\end{snugframed} + +In an other vein, the parser will be confused by |1..[a,b,c][1]|, and one must +write |1..([a,b,c][1])|. And things such as |[100,300,500,700][2]//11| or +|[100,300,500,700][2]/11| are syntax errors and one must use parentheses, as +in |([100,300,500,700][2])/11|. + +\end{itemize} + + +\subsection{Predefined functions} + + Functions are at the same top level of priority. All functions even + |?| and |!| (as prefix) require parentheses around their arguments. + + \begin{snugframed} + \xintFor #1 in {num, qint, qfrac, qfloat, reduce, abs, sgn, frac, floor, + ceil, sqr, sqrt, sqrtr, factorial, binomial, pfactorial, float, round, + trunc, mod, quo, rem, gcd, lcm, max, min, `+`, `*`, ?, !, not, all, + any, xor, if, ifsgn, even, odd, first, last, reversed, len, + bool, togl}\do + {\ctexttt{#1}\xintifForLast{}{, }} + + |factorial|, |binomial|, |pfactorial|, |quo|, |rem|, |even|, |odd|, + |gcd| and |lcm| will first truncate their arguments to integers; the + latter two require package \xintgcdname; |togl| requires the |etoolbox| + package; |all|, |any|, |xor|, |`+`|, |`*`|, |max|, |min|, |first|, + |last|, |reversed| and |len| are functions with arbitrarily many comma + separated arguments. + + |bool|, |togl| use delimited macros to fetch their argument and the + closing parenthesis which thus must be explicit, not arising from + expansion. + + The same holds for |qint|, |qfrac|, |qfloat|.\NewWith{1.2} + \end{snugframed} + +\begin{description}[parsep=0pt,% pas le temps de regarder labelwidth=\leftmarginiii, + itemindent=0pt, listparindent=\leftmarginiii, + leftmargin=\leftmarginii] + \item[functions with a single (numeric) argument] +\noindent\par +\begin{description} + \item[num] truncates to the nearest integer (truncation towards zero). +\begin{everbatim*} +\xinttheexpr num(3.1415^20)\relax +\end{everbatim*} + + \item[qint] skips the token by token parsing of the input. The ending + parenthesis must be physically present rather than arising from + expansion.\NewWith{1.2} The |q| stands for ``quick''. This ``function'' + handles the input exactly like do the |i| macros of \xintcorename, via + \csbxint{iNum}. Hence leading signs and the leading zeroes (coming next) + will be handled appropriately but spaces will not be systematically + stripped. They should cause no harm and will be removed as soon as the + number is used with one of the basic operators. This input form \emph{does + not accept decimal part or scientific part}. +\begin{everbatim} +\def\x{....many many many ... digits}\def\y{....also many many many digits...} +\xinttheiiexpr qint(\x)*qint(\y)+qint(\y)^2\relax +\end{everbatim} + + \item[qfrac] does the same as \dtt{qint} excepts that it accepts fractions, + decimal numbers, scientific numbers as they are understood by the macros of + package\NewWith{1.2} \xintfracname. Not to be used within an + |\xintiiexpr|-ession, except if hidden inside functions such as + \dtt{round} or \dtt{trunc} which produce integers from fractions. + + \item[qfloat] does the same as \dtt{qfrac} and converts to a float with the + precision given by the setting of |\xintDigits|. + + \item[reduce] reduces a fraction to smallest terms +\begin{everbatim*} +\xinttheexpr reduce(50!/20!/20!/10!)\relax +\end{everbatim*} + +Recall that this is NOT done automatically, for example when adding fractions. + \item[abs] absolute value + \item[sgn] sign + \item[frac] fractional part +\begin{everbatim*} +\xinttheexpr frac(-355/113), frac(-1129.218921791279)\relax +\end{everbatim*} + + \item[floor] floor function. + \item[ceil] ceil function. + \item[sqr] square. + \item[sqrt] in |\xintiiexpr|, truncated square root; in |\xintexpr| or + |\xintfloatexpr| this is the floating point square root, and there is an + optional second argument for the precision. + \item[sqrtr] in |\xintiiexpr| only, rounded square root. + \item[factorial] factorial function, same as previously + available post-fix |!| operator. When used in |\xintexpr| or + |\xintfloatexpr| there is an optional second argument. See discussion later. + \item[?] |?(x)| is the truth value, $1$ if non zero, $0$ if zero. Must use parentheses. + \item[!] |!(x)| is logical not, $0$ if non zero, $1$ if zero. Must use parentheses. + \item[not] logical not. + \item[even] evenness of the truncation. +\begin{everbatim*} +\xinttheexpr seq((x,even(x)), x=-5/2..[1/3]..+5/2)\relax +\end{everbatim*} + + \item[odd] oddness of the truncation. +\begin{everbatim*} +\xinttheexpr seq((x,odd(x)), x=-5/2..[1/3]..+5/2)\relax +\end{everbatim*} +\end{description} + +\item[functions with an alphabetical argument] +\noindent\par + \hypertarget{item:bool}{\ctexttt{bool,togl}}. |bool(name)| returns + $1$ if the \TeX{} conditional |\ifname| would act as |\iftrue| and + $0$ otherwise. This works with conditionals defined by |\newif| (in + \TeX{} or \LaTeX{}) or with primitive conditionals such as + |\ifmmode|. For example: + % + \leftedline{|\xintifboolexpr{25*4-if(bool(mmode),100,75)}{YES}{NO}|} + % + will return $\xintifboolexpr{25*4-if(bool(mmode),100,75)}{YES}{NO}$ + if executed in math mode (the computation is then $100-100=0$) and + \xintifboolexpr{25*4-if(bool(mmode),100,75)}{YES}{NO} if not (the + \ctexttt{if} conditional is described below; the + \csbxint{ifboolexpr} test automatically encapsulates its first + argument in an |\xintexpr| and follows the first branch if the + result is non-zero (see \autoref{xintifboolexpr})). + + The alternative syntax |25*4-\ifmmode100\else75\fi| could have been + used here, the usefulness of |bool(name)| lies in the availability + in the |\xintexpr| syntax of the logic operators of conjunction + |&&|, inclusive disjunction \verb+||+, negation |!| (or |not|), of + the multi-operands functions |all|, |any|, |xor|, of the two + branching operators |if| and |ifsgn| (see also |?| and |??|), which + allow arbitrarily complicated combinations of various |bool(name)|. + + Similarly |togl(name)| returns $1$ if the \LaTeX{} package + \href{http://www.ctan.org/pkg/etoolbox}{etoolbox}% + % + % +% +\footnote{\url{http://www.ctan.org/pkg/etoolbox}} + % + has been used to define a toggle named |name|, and this toggle is + currently set to |true|. Using |togl| in an |\xintexpr..\relax| + without having loaded + \href{http://www.ctan.org/pkg/etoolbox}{etoolbox} will result in an + error from |\iftoggle| being a non-defined macro. If |etoolbox| is + loaded but |togl| is used on a name not recognized by |etoolbox| + the error message will be of the type ``ERROR: Missing |\endcsname| + inserted.'', with further information saying that |\protect| should + have not been encountered (this |\protect| comes from the expansion + of the non-expandable |etoolbox| error message). + + When |bool| or |togl| is encountered by the |\xintexpr| parser, the + argument enclosed in a parenthesis pair is expanded as usual from + left to right, token by token, until the closing parenthesis is + found, but everything is taken literally, no computations are + performed. For example |togl(2+3)| will test the value of a toggle + declared to |etoolbox| with name |2+3|, and not |5|. Spaces are + gobbled in this process. It is impossible to use |togl| on such + names containing spaces, but |\iftoggle{name with spaces}{1}{0}| + will work, naturally, as its expansion will pre-empt the + |\xintexpr| scanner. + + There isn't in |\xintexpr...| a |test| function available analogous + to the |test{\ifsometest}| construct from the |etoolbox| package; + but any \emph{expandable} |\ifsometest| can be inserted directly in + an |\xintexpr|-ession as |\ifsometest10| (or |\ifsometest{1}{0}|), + for example |if(\ifsometest{1}{0},YES,NO)| (see the |if| operator + below) works. + + A straight |\ifsometest{YES}{NO}| would do the same more + efficiently, the point of |\ifsometest10| is to allow arbitrary + boolean combinations using the (described later) \verb+&+ and + \verb+|+ logic operators: + \verb+\ifsometest10 & \ifsomeothertest10 | \ifsomethirdtest10+, + etc... |YES| or |NO| above stand for material compatible with the + |\xintexpr| parser syntax. + + See also \csbxint{ifboolexpr}, in this context. + +\item[functions with one mandatory and a second but optional argument] +\noindent\par + \begin{description} + \item[round] For example + |round(-2^9/3^5,12)=|\dtt{\xinttheexpr round(-2^9/3^5,12)\relax.} + \item[trunc] For example + |trunc(-2^9/3^5,12)=|\dtt{\xinttheexpr trunc(-2^9/3^5,12)\relax.} + \item[float] For example + |float(-2^9/3^5,12)=|\dtt{\xinttheexpr float(-2^9/3^5,12)\relax.} + \item [sqrt] in \csa{xintexpr}|...\relax| and \csa{xintfloatexpr}|...\relax| + it achieves the precision given by the optional second argument. +\begin{everbatim*} +\xinttheexpr sqrt(2,31)\relax\ and \xinttheiiexpr sqrt(num(2e60))\relax +\end{everbatim*} + \item[factorial] when the second optional argument\NewWith {1.2f} is made + use of inside \csa{xintexpr}|...\relax|, this switches to the use of the + float version, rather than the exact one. +\begin{everbatim*} +\xinttheexpr factorial (100,32)\relax, {\xintDigits:=32;\xintthefloatexpr + factorial (100)\relax}\newline +\xinttheexpr factorial (50)\relax\newline +\xinttheexpr factorial (50, 32)\relax +\end{everbatim*} + \end{description} + + \item[functions with two arguments] +\noindent\par + \begin{description} + \item[quo] first truncates the arguments then computes the Euclidean quotient. + \item[rem] first truncates the arguments then computes the Euclidean remainder. + \item[mod] computes the modulo associated to the truncated division, same as + |/:| infix operator. +\begin{everbatim*} +\xinttheexpr mod(11/7,1/13), reduce(((11/7)//(1/13))*1/13+mod(11/7,1/13)), +mod(11/7,1/13)- (11/7)/:(1/13), (11/7)//(1/13)\relax +\end{everbatim*} + \item[binomial] computes binomial coefficients.\NewWith {1.2f} +\begin{everbatim*} +\xinttheexpr seq(binomial(20, i), i=0..20)\relax +\end{everbatim*} +\begin{everbatim*} +\xintthefloatexpr seq(binomial(100, 50+i), i=-5..+5)\relax +\end{everbatim*} +The arguments must be (expand to) short integers. + \item[pfactorial] computes partial factorials.\NewWith {1.2f} +\begin{everbatim*} +\xinttheexpr seq(pfactorial(20, i), i=20..30)\relax +\end{everbatim*} +The arguments must be (expand to) short integers. + + \end{description} + + \item[the if conditional (twofold way)] +\noindent\par +\ctexttt{if}|(cond,yes,no)| + checks if |cond| is true or false and takes the corresponding + branch. Any non zero number or fraction is logical true. The zero + value is logical false. Both ``branches'' are evaluated (they are + not really branches but just numbers). See also the |?| operator. + + \item[the ifsgn conditional (threefold way)] +\noindent\par + \ctexttt{ifsgn}|(cond,<0,=0,>0)| checks the sign of |cond| and + proceeds correspondingly. All three are evaluated. See also the |??| + operator. + + \item[functions with an arbitrary number of arguments] +\noindent\par +This argument may well be generated by one or many |a..b| or |a..[d]..b| +constructs, separated by commas. + \begin{description} +\item[all] inserts a logical |AND| in between arguments and evaluates, +\item[any] inserts a logical |OR| in between all arguments and evaluates, +\item[xor] inserts a logical |XOR| in between all arguments and evaluates, +\item[|`+`|] adds (left ticks mandatory): +\begin{everbatim*} +\xinttheexpr `+`(1,3,19), `+`(1*2,3*4,19*20)\relax +\end{everbatim*} +\item[|`*`|] multiplies (left ticks mandatory): +\begin{everbatim*} +\xinttheexpr `*`(1,3,19), `*`(1^2,3^2,19^2), `*`(1*2,3*4,19*20)\relax +\end{everbatim*} +\item[max] maximum, +\item[min] minimum, +\item[gcd] first truncates to integers then computes the |GCD|, requires \xintgcdname, +\item[lcm] first truncates to integers then computes the |LCM|, requires \xintgcdname, +\item[first] first among comma separated items, |first(list)| is like |[list][:1]|. +\begin{everbatim*} +\xinttheiiexpr first(-7..3), [-7..3][:1]\relax +\end{everbatim*} +\item[last] last among comma separated items, |last(list)| is like |[list][-1:]|. +\begin{everbatim*} +\xinttheiiexpr last(-7..3), [-7..3][-1:]\relax +\end{everbatim*} +\item[reversed] reverses the order +\begin{everbatim*} +\xinttheiiexpr reversed(123..150)\relax +\end{everbatim*} +\item[len] computes\NewWith{1.2g} the number of items in a comma separated + list. Earlier syntax was |[a,b,...,z][0]| but since |1.2g| this now returns + the first element of the list. +\begin{everbatim*} +\xinttheiiexpr len(1..50, 101..150, 1001..1050)\relax +\end{everbatim*} + \end{description} +\end{description} + +\subsection{Constructs with dummy variables} +\label{ssec:dummies} + + \begin{snugframed} + The ``functions'' \xintFor #1 in {add, mul, seq, subs, rseq, iter, rrseq, + iterr} \do {\ctexttt{#1}\xintifForLast{}{, }} use some delimited + macros to fetch the |,<letter>| part, checking the correct balance of + parentheses, and allowing nesting. The |<letter>| (lowercase or + uppercase) will be followed by a |=| sign and then a comma separated + list of values or a list expression such as |a..b|, or both, which will + be treated in the normal manner to provide the values which will be in + succession assigned to the |<letter>|. This |<letter>| must not have + been assigned a value before via \csa{xintdefvar}. + + The functions |rseq|, |iter|, |rrseq| and |iterr| have an additional + mandatory initial comma separated list which is separated by a + semi-colon from the expression to evaluate iteratively. This portion up + to and including the semi-colon may arise entirely from expansion + (contrarily to the |,<letter>=| part discussed above). + + |seq|, |rseq|, |iter|, |rrseq|, |iterr| but + not |add|, |mul|, |subs| admit the |omit|, |abort|, and |break(..)| + keywords, possibly but not necessarily in combination with a potentially + infinite list generated by a |n++| expression. + + They may be nested. + \end{snugframed} + + + +Dummy variables are necessarily single-character letters, and all lowercase and +uppercase Latin letters are pre-configured for that usage. + +\begin{description}[parsep=0pt,% labelwidth=\leftmarginii, + itemindent=0pt, listparindent=\leftmarginiii, + leftmargin=\leftmarginii] +\item [subs] for variable substitution +\begin{everbatim*} +\xinttheexpr subs(subs(seq(x*z,x=1..10),z=y^2),y=10)\relax\newline +\end{everbatim*}% +Attention that |xz| generates an error, one must use explicitely |x*z|, else +the parser expects a variable with name |xz|. + +This is useful for example when defining macros for which some argument |#1| +will be used more than once but may itself be a complicated expression or +macro, and should be evaluated only once, for matters of efficiency. + +The substituted variable may be a comma separated list (this is impossible +with |seq| which will always pick one item after the other from a list). +\begin{everbatim*} +\xinttheexpr subs([x]^2,x=-123,17,32)\relax +\end{everbatim*} + +See the examples related to the |3x3| determinant in the +\autoref{xintNewExpr} for an illustration of list substitution. + +\item[add] addition +\begin{everbatim*} +\xinttheiiexpr add(x^3,x=1..50), add(x(x+1), x=1,3,19)\relax\newline +\end{everbatim*}% +See |`+`| for syntax without a dummy variable. + +\item[mul] multiplication +\begin{everbatim*} +\xinttheiiexpr mul(x^2, x=1,3,19), mul(2n+1,n=1..10)\relax\newline +\end{everbatim*}% +See |`*`| for syntax without a dummy variable. + +\item[seq] comma separated values generated according to a formula +\begin{everbatim*} +\xinttheiiexpr seq(x(x+1)(x+2)(x+3),x=1..10), `*`(seq(3x+2,x=1..10))\relax +\end{everbatim*} +\begin{everbatim*} +\xinttheiiexpr seq(seq(i^2+j^2, i=0..j), j=0..10)\relax +\end{everbatim*} + +\item[rseq] recursive sequence, |@| for the previous value. +\begin{everbatim*} +\printnumber {\xintthefloatexpr subs(rseq (1; @/2+y/2@, i=1..10),y=1000)\relax }\newline +\end{everbatim*}% + Attention: in the example above |y/2@| is interpreted as + |y/(2*@)|.\IMPORTANT{} With versions |1.2c| or earlier it would have been + interpreted as |(y/2)*@|. + +In case the initial stretch is a comma separated list, |@| refers at the first +iteration to the whole list. Use parentheses at each iteration to maintain +this ``nuple''. For example: +\begin{everbatim*} +\printnumber{\xintthefloatexpr rseq(1,10^6; + (sqrt([@][0]*[@][1]),([@][0]+[@][1])/2), i=1..7)\relax } +\end{everbatim*} + +\item[iter] is exactly like |rseq|\CHANGED{1.2g}, except that it only prints + the last iteration. Strangely it was lacking from |1.1| release, or rather + what was available from |1.1| to |1.2f| is what is called now |iterr| + (described below). + +\hypertarget{BrentSalamin}{} + The new |iter| is convenient to handle compactly higher order iterations. + We can illustrate its use with an expandable (!) + implementation of the Brent-Salamin algorithm for the computation of $\pi$: +\begin{everbatim*} +\xintDigits:= 91; +\xintdeffloatfunc BS(a, b, t, p):= (a+b)/2, sqrt(a*b), t-p(a-b)^2, \xintiiexpr 2p\relax; +\xintthefloatexpr [88] % use 3 guard digits (output value is *rounded*) + iter(1, 1/sqrt(2), 1, 1; % initial values + ([@][0]-[@][1]<2[-45])? % if a-b is small enough stop iterating and ... + {break(([@][0]+[@][1])^2/[@][2])} % ... do final computation, + {BS(@)}, % else do iteration via pre-defined (for convenience) function BS. + i=1++) % This generates infinite iteration. The i is not used. +\relax +\xintDigits:=16; +\end{everbatim*} + + You can try with |\xintDigits:=1001;| and |2[-501]|, but don't round to |88| + digits of course ... and better wrap the whole thing in |\message| because + it will run in the right margin (about \dtt{7.4}s on my laptop last time I tried). + +\item[rrseq] recursive sequence with multiple initial terms. Say, there are + |K| of them. Then |@1|, ..., |@4| and then |@@(n)| up to |n=K| refer to the + last |K| values. Notice the difference with |rseq| for which |@| refers to + the complete list of all initial terms if there are more than one and may + thus be a ``list'' object. This is impossible with |rrseq|. This construct + is effective for scalar finite order recursions, and may be perhaps a bit + more efficient than using the |rseq| syntax with a ``list'' value. +\begin{everbatim*} +\xinttheiiexpr rrseq(0,1; @1+@2, i=2..30)\relax +\end{everbatim*} +\begin{everbatim*} +\xinttheiiexpr rseq(1; 2@, i=1..10)\relax +\end{everbatim*} +\begin{everbatim*} +\xinttheiiexpr rseq(1; 2@+1, i=1..10)\relax +\end{everbatim*} +\begin{everbatim*} +\xinttheiiexpr rseq(2; @(@+1)/2, i=1..5)\relax +\end{everbatim*} + +\begin{everbatim*} +\xinttheiiexpr rrseq(0,1,2,3,4,5; @1+@2+@3+@4+@@(5)+@@(6), i=1..20)\relax +\end{everbatim*} + +I implemented an |Rseq| which at all times keeps the memory of \emph{all} +previous items, but decided to drop it as the package was becoming big. + +\item[iterr] same as |rrseq| but does not print any value until the last |K|. +\begin{everbatim*} +\xinttheiiexpr iterr(0,1; @1+@2, i=2..5, 6..10)\relax +% the iterated over list is allowed to have disjoint defining parts. +\end{everbatim*} +\end{description} + +Recursions may be nested, with |@@@(n)| giving access to the values of the +outer recursion\dots and there is even |@@@@(n)| to access the outer outer +recursion but I never tried it! + +With |seq|, |rseq|, |iter|, |rrseq|, |iterr|, \textbf{but not} with |subs|, +|add|, |mul|, one has: +\begin{description} +\item[abort] stop here and now. +\item[omit] omit this value. +\item[break] |break(stuff)| to abort and have |stuff| as last value. +\item[n++] serves to generate a potentially infinite list. 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*} +\xinttheiiexpr iter(1;(@>10^40)?{break(@)}{2@},i=1++)\relax +\end{everbatim*} +is the smallest power of 2 with at least fourty one digits. + + Note that |n++| can not work in the format |i=10,17,30++|, only |<start>++| + nothing before. +\begin{everbatim*} +First Fibonacci number at least |2^31| and its index +% we use iterr to refer via @1 and @2 to the previous and previous to previous. +\xinttheiiexpr iterr(0,1; (@1>=2^31)?{break(i)}{@2+@1}, i=1++)\relax +\end{everbatim*} +\end{description} + +Some additional examples are to be found in \autoref{ssec:moredummies}. + +\subsection{User definable variables and functions} +\label{xintdefvar} +\label{xintdefiivar} +\label{xintdeffloatvar} +\label{xintdeffunc} +\label{xintdefiifunc} +\label{xintdeffloatfunc} +\label{xintunassignvar} +\label{xintverbosetrue} +\label{xintverbosefalse} +\label{ifxintverbose} + +Since release |1.1| it is possible to assign a variable name to let it be +known to the parsers of \xintexprname. +\begin{everbatim*} +\xintdefvar Pi:=3.141592653589793238462643; +\xintthefloatexpr Pi^100\relax +\xintdefvar x_1 := 10;\xintdefvar x_2 := 20;\xintdefvar y@3 := 30; +\quad $x_1\cdot x_2\cdot y@3+1=\xinttheiiexpr x_1*x_2*y@3+1\relax$. +\end{everbatim*} + +As |x_1x| is a licit variable name, as well as |x_1x_| and |x_1x_2| and +|x_1x_2y| etc... we could not count on tacit multiplication being applied to +something like |x_1x_2|; the parser goes not go to the effort of tracing back +its steps. Hence we had to insert explicit |*| infix operators (one often +falls into this trap when playing with variables and counting too much on the +divinatory talents of \xintexprname...). + +The variable definition is done with \csa{xintdefvar}, \csa{xintdefiivar}, or +with \csa{xintdeffloatvar}, the variable will be computed using respectively +\csbxint{expr}, \csbxint{iiexpr} or \csbxint{floatexpr}. The variable +once defined can be used in the other parsers, except naturally that in +\csa{xintiiexpr} only integers are accepted. + +When defining a variable with \csa{xintdeffloatvar}, it is important that +reduction to \csbxint{theDigits} digits of precision happens inside +\csa{xintfloatexpr} only if an operation is executed. Thus, for a variable +declaration with no operations, the value is registered with all its digits. +\begin{everbatim*} +\xintdeffloatvar e:=2.7182818284590452353602874713526624977572470936999595749669676;% +\xinttheexpr e\relax\newline % shows the recorded value +\xintthefloatexpr e\relax\newline % output rounds +\xintthefloatexpr 1+e\relax\newline % the rounding was done by addition (trust me...) +\xintdeffloatvar e:=float(2.7182818284590452353602874713526624977572470936999595749669676);% +\xinttheexpr e\relax\par % use of float forced immediate rounding +\end{everbatim*} + +In the next examples we examine the effect of cumulated float operations on +rounding errors: +\begin{everbatim*} +\xintdefvar e_1:=add(1/i!, i=0..10);% exact sum +\xintdeffloatvar e_2:=add(1/i!, i=0..10);% float sum +\xintthefloatexpr e_1, e_2\relax\newline +\xintdefvar e_3:=e_1+add(1/i!, i=11..20);% exact sum +\xintdeffloatvar e_4:=e_2+add(1/i!, i=11..20);% float sum +\xintthefloatexpr e_3, e_4\relax\newline +\xintdeffloatvar e:=2.7182818284590452353602874713526624977572470936999595749669676;% +\xintDigits:=24; +\xintthefloatexpr[16] e, e^1000, e^1000000\relax (e rounded to 24 digits first)\newline +\xintDigits:=16; +\xintthefloatexpr e, e^1000, e^1000000\relax (e rounded to 16 digits first)\par +\end{everbatim*} + +Legal variable names are composed of letters, digits, |@| and |_| signs. +They can not start with a digit. They may start with |@| or |_|. Currently +|@|, |@1|, |@2|, |@3|, and |@4| are reserved because they have special +meanings for use in iterations. The |@@|, |@@@|, |@@@@| are also reserved but +are technically functions, not variables. Thus a user may possibly use |@@| as +a variable name, but if it is followed by parentheses, the function +interpretation will be applied, rather than doing a tacit multiplication. + +Single letter names |a..z| and |A..Z| are pre-declared by the package for use +as special type of variables called ``dummy variables''. They can be assigned +values via |\xintdefvar| et al., and be later unassigned using +\csa{xintunassign} (see later in this section). + +Since release |1.2c| it is possible to also declare functions: +\begin{everbatim*} +\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/2y; +\end{everbatim*}(notice the numerous tacit multiplications in this expression; +and that |x/2y| is interpreted as |x/(2y)|.) + +\begin{framed} + The (dummy) variables used in the function declaration are necessarily single + letters (lowercase or uppercase) which have \emph{not} been re-declared via + |\xintdefvar| as assigned variables. The choice of the letters is entirely + up to the user and has nil influence on the actual function, naturally. + + A function can have at most nine variables. + + % 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 |iterr|, |rseq|, + |rrseq| must be hidden as |{;}| to not be confused with the |;| ending the + declaration.} + +Let's try the famous \textsc{Rump} test: +\begin{everbatim*} +\xinttheexpr Rump(77617,33096)\relax. +\end{everbatim*} +Nothing problematic for an \emph{exact} evaluation, naturally ! + +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 (it is not quite a polynomial with +its |x/2y| final term) with floats, we \emph{must} also +declare |Rump| as a function to be used there: +\begin{everbatim*} +\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/2y; +\end{everbatim*} +(I used 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; and for float operations this may matter on the rounding). + +The numbers are scanned with the current precision, hence as here it is +\dtt{16}, they are scanned exactly in this case. We can then vary the +precision for the evaluation. +\begin{everbatim*} +\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*} + +It is licit to overload a variable name (all Latin letters are predefined as +dummy variables) with a function name and vice versa. The parsers will decide +from the context if the function or variable interpretation must be used +(dropping various cases of tacit multiplication as normally applied). +\begin{everbatim*} +\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*} + +The mechanism for functions is identical with the one underlying the +\csbxint{NewExpr} command. A function once declared is a first class citizen, +its expression is entirely parsed and converted into a big nested \fexpan +dable macro. When used its action is via this defined macro. For example +\begin{everbatim*} +\xintdeffunc + e(z):=(((((((((z/10+1)z/9+1)z/8+1)z/7+1)z/6+1)z/5+1)z/4+1)z/3+1)z/2+1)z+1; +\end{everbatim*} +creates a macro whose meaning one can find in the log file, after +|\xintverbosetrue|. Here it is: +\begin{everbatim} + Function e for \xintexpr parser associated to \XINT_expr_userfunc_e with me +aning macro:#1,->\xintAdd {\xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd {\x +intDiv {\xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {\xintMul {\ +xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv { +\xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {#1}{10}}{1}}{#1}}{9 +}}{1}}{#1}}{8}}{1}}{#1}}{7}}{1}}{#1}}{6}}{1}}{#1}}{5}}{1}}{#1}}{4}}{1}}{#1}}{3} +}{1}}{#1}}{2}}{1}}{#1}}{1} +\end{everbatim} + + +See \autoref{sssec:limitations} for some limitations of the syntax, shared +with those of the \csbxint{NewExpr} command. Some constructs with dummy +variables will not work, when the iterated-over values depend upon the +function arguments. For example |\xintdeffunc f(x):=add(i^2,i=1..x);| leads to +an unusable |f|. But in this case one can use the alternative syntax with list +operations:\footnote{It turns out |`+`(seq(i^2, i=1..x))| would work here, but + this isn't always the case with |seq| constructs.} +\begin{everbatim*} +\xintdeffunc f(x):=`+`([1..x]^2);\xinttheexpr seq(f(x), x=1..20)\relax +\end{everbatim*} + +Side remark: as the |seq(f(x), x=1..10)| does many times the same +computations, an |rseq| here would be more efficient:\footnote{Note that + |omit| and |abort| are not usable in |add| or |mul| (currently).} +\begin{everbatim*} +\xinttheexpr rseq(1; (x>20)?{abort}{@+x^2}, x=2++)\relax +\end{everbatim*} + +On the other hand a construct like the following has no issue, as the values +iterated over do not depend upon the function parameters: +\begin{everbatim*} +\xintdeffunc f(x):=iter(1{;} @*x/i+1, i=10..1);% one must hide the first semi-colon ! +\xinttheexpr e(1), f(1)\relax +\end{everbatim*} + +It is somewhat frustrating not to be able to use the whole \xintexprname +syntax in \csa{xintdeffunc} and \csa{xintNewExpr}. The explanation is simply +that the implementation of |seq|, |iter|, etc... relies on exhaustive +expansion inside |\csname ... \endcsname| whereas \csa{xintdeffunc} tries to +construct an \fexpan dable macro. Furthermore the |omit| and |abort| keywords +as well as the |break()| function are discovered ``dynamically'' when an +expression is parsed from left to right; if they were to be used with an +abstract value list, the information of their presence would have to be coded +especially. This could end up being not that different from storing the whole +|seq|, |iter|, etc.. thing ``as is'' into a macro definition: +\begin{everbatim} +\def\macro #1#2{\xinttheexpr iter(1{;} @*#2/i+1, i=#1..1)\relax} +\end{everbatim} +which does not all achieve what a function declaration, if possible, would. +Side remark: beware that using it with |#2=1+1| will cause unexpected result, +the definition of \csa{macro} should have employed |(#2)| rather than |#2|. + +With |\xintverbosetrue| the values of the variables and the meanings of the +functions (or rather their associated macros) will be written to the log. For +example the first |Rump| declaration above generates this in the log file: +\begin{everbatim} + Function Rump for \xintexpr parser associated to \XINT_expr_userfunc_Rump w +ith meaning macro:#1,#2,->\xintAdd {\xintAdd {\xintAdd {\xintDiv {\xintMul {133 +5}{\xintPow {#2}{6}}}{4}}{\xintMul {\xintPow {#1}{2}}{\xintSub {\xintSub {\xint +Sub {\xintMul {11}{\xintMul {\xintPow {#1}{2}}{\xintPow {#2}{2}}}}{\xintPow {#2 +}{6}}}{\xintMul {121}{\xintPow {#2}{4}}}}{2}}}}{\xintDiv {\xintMul {11}{\xintPo +w {#2}{8}}}{2}}}{\xintDiv {#1}{\xintMul {2}{#2}}} +\end{everbatim} +and the declaration |\xintdeffunc f(x):=iter(1{;} @*x/i+1, i=10..1);| generates: +\begin{everbatim} + Function f for \xintexpr parser associated to \XINT_expr_userfunc_f with me +aning macro:#1,->\xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {\xintMul {\x +intAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {\ +xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd { +\xintDiv {\xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {\xintMul +{1}{#1}}{10/1[0]}}{1}}{#1}}{9/1[0]}}{1}}{#1}}{8/1[0]}}{1}}{#1}}{7/1[0]}}{1}}{#1 +}}{6/1[0]}}{1}}{#1}}{5/1[0]}}{1}}{#1}}{4/1[0]}}{1}}{#1}}{3/1[0]}}{1}}{#1}}{2/1[ +0]}}{1}}{#1}}{1/1[0]}}{1} +\end{everbatim} + +Starting with |1.2d| the definitions made by \csbxint{NewExpr} have local +scope, hence this is also the case with the definitions made by +\csbxint{deffunc}.\IMPORTANT{} One can not ``undeclare'' a function, but +naturally one can provide a new definition for it. + +Variable declarations also are local. One can not really ``unassign'' a +declared variable, but macro \csa{xintunassignvar} will let it insert a zero +and provoke a \TeX{} ``undefined macro'' error. Also, using +\csa{xintunassignvar}\IMPORTANT{} on a letter will let it recover fully its +original meaning as dummy variable. This may even be used for other +characters, if they are used in expressions with catcode 11. As most every +character in the ascii range already has some meaning for \xintexprname, this +is not really recommended, though. +\begin{everbatim*} +\xintFor #1 in {e_1, e_2, e_3, e_4, e} \do {\xintunassignvar {#1}} +\end{everbatim*} + +It is possible to define functions which expand to comma-separated values, for +example the declarations: +\begin{everbatim*} +\xintdeffunc f(x):= x, x^2, x^3, x^x; +\xintdeffunc g(x):= x^[0..x];% x^[1, 2, 3, x] would be like f above. +\end{everbatim*} +will generate +\begin{everbatim} + Function f for \xintexpr parser associated to \XINT_expr_userfunc_f with me +aning macro:#1,->#1,\xintPow {#1}{2},\xintPow {#1}{3},\xintPow {#1}{#1} + Function g for \xintexpr parser associated to \XINT_expr_userfunc_g with me +aning macro:#1,->\xintApply::csv {\xintPow {#1}}{\xintSeq::csv {0}{#1}} +\end{everbatim} +and we can check that they work: +\begin{everbatim*} +\xinttheexpr f(10)\relax; \xinttheexpr g(10)\relax +\end{everbatim*} + +N.B.: we declared in this section |e|, |f|, |g| as functions. Except naturally +if the function declarations are done in a group or a \LaTeX{} environment +whose scope has ended, they can not be completely undone, and if |e|, |f|, or +|g| are used as dummy variables the tacit multiplication in front of +parentheses will not be applied, it is their function interpretation which will +prevail. However, with an explicit |*| in front of the opening parenthesis, it +does work: +\begin{everbatim*} +\xinttheexpr add(f*(f+f), f= 1..10)\relax % f is used as variable, not function. +\end{everbatim*} + + + \etocdepthtag.toc {commands} -\indescriptionfalse \addtocontents{toc}{\gdef\string\sectioncouleur{{joli}}} \renewcommand{\etocaftertochook}{\addvspace{\bigskipamount}} @@ -10039,6 +11272,9 @@ the only arithmetic package from the \xintname bundle which loads \end{everbatim*} \end{itemize} +Please refer to \autoref{sec:xintexprsyntax} for a more detailed description +of the syntax elements for expressions. + \subsection{The \csbh{xintexpr} expressions} \label{xintexpr} \label{xinttheexpr} @@ -10296,1070 +11532,8 @@ Only integer and half-integer exponents are allowed. \end{itemize} -\subsection{Infix and other operators and their precedence levels} -% \ctexttt is a remnant of 1.09n manual, don't have time to get rid of it now. -\newcommand\ctexttt [1]{\begingroup\color[named]{DarkOrchid}%\bfseries - #1\endgroup} - - -We go through the various syntax elements from highest to lowest precedence. - -\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, - itemindent=0pt, listparindent=\leftmarginiii, - leftmargin=\leftmarginii] -\item Functions share the highest precedence. - - -\item \def\MicroFont{\color[named]{DarkOrchid}\ttfamily}The - |.| as decimal mark; the number scanner treats it as an inherent, - optional and unique component of a being formed number. One can do - things such as - % - \leftedline{\restoreMicroFont|\xinttheexpr 0.^2+2^.0\relax|} - % - which is |0^2+2^0| and produces \dtt{\xinttheexpr 0.^2+2^.0\relax}. - - However a single dot |"."| as in |\xinttheexpr .^2\relax| is now illegal - input.\IMPORTANT - -\item The |e| and |E| for scientific notation. They are parsed - like the decimal mark is. -\begingroup -\restoreMicroFont |1e3^2| is \dtt{\xinttheexpr 1e3^2\relax} -\endgroup - -\item The |"| for hexadecimal numbers: it is treated with highest - priority, allowed only at locations where the parser expects to start - forming a numeric operand, once encountered it triggers the - hexadecimal scanner which looks for successive hexadecimal digits (as - usual skipping spaces and expanding forward everything; letters |A|, ..., |F|, - but not |a|, ..., |f|) possibly a - unique optional dot (allowed directly in front) and then an optional - (possibly empty) fractional part. The dot and fractional part are not - allowed in {\restoreMicroFont|\xintiiexpr..\relax|}. The |"| - functionality \fbox{requires package \xintbinhexname} (there is - no warning, but an ``undefined control sequence'' error will - naturally results if the package has not been loaded). -\begingroup - \restoreMicroFont |"A*"A^"A| is \dtt{\xinttheexpr "A*"A^"A\relax}. -\endgroup - -\item The postfix operators \ctexttt{!} and the branching conditionals \ctexttt{?, ??}. - \begin{description} - \item[{\color[named]{DarkOrchid}!}] computes the factorial of an integer. - - \item[{\color[named]{DarkOrchid}?}] is used as |(cond)?{yes}{no}|. It - evaluates the (numerical) condition (any non-zero value counts as - |true|, zero counts as |false|). It then acts as a macro with two - mandatory arguments within braces (hence this escapes from the - parser scope, the braces can not be hidden in a macro), chooses the - correct branch \emph{without evaluating the wrong one}. Once the - braces are removed, the parser scans and expands the uncovered - material so for example - % - \leftedline{|\xinttheiexpr (3>2)?{5+6}{7-1}2^3\relax|} - % - is legal and computes - |5+62^3=|\dtt{\xinttheiexpr(3>2)?{5+(6}{7-(1}2^3)\relax}. Note - though that it would be better practice to include here the |2^3| - inside the branches. The contents of the branches may be arbitrary - as long as once glued to what is next the syntax is respected: - {|\xintexpr (3>2)?{5+(6}{7-(1}2^3)\relax| also works.} Differs thus - from the |if| conditional in two ways: the false branch is not at - all computed, and the number scanner is still active on exit, more - digits may follow. - - \item[{\color[named]{DarkOrchid}??}] is used as |(cond)??{<0}{=0}{>0}|. - |cond| is anything, its sign is evaluated and depending on the sign the - correct branch is un-braced, the two others are swallowed. The un-braced - branch will then be parsed as usual. Differs from the |ifsgn| conditional - as the two false branches are not evaluated and furthermore the number - scanner is still active on exit. - % - \leftedline{|\def\x{0.33}\def\y{1/3}|} - % - \leftedline{|\xinttheexpr (\x-\y)??{sqrt}{0}{1/}(\y-\x)\relax|% - \dtt{=\def\x{0.33}\def\y{1/3}% - \xinttheexpr (\x-\y)??{sqrt}{0}{1/}(\y-\x)\relax }} - % - \end{description} - -\item The minus sign |-| as prefix unary operator inherits the precedence of - the infix operator it follows. With things such as |5+------2*3|, the - \xintexprname parsers don't try to be efficient: once |2*3| is evaluated the - opposite function will be applied the necessary number of times. On the other - hand the plus sign |+| as prefix unary operator as in, for example - |5-++++++2*3|, is immediately gobbled. - -\item The power operator |^|, or |**|. It is left associative: - {\restoreMicroFont|\xinttheiexpr 2^2^3\relax|} evaluates to \xinttheiexpr - 2^2^3\relax, not \xinttheiexpr 2^(2^3)\relax. Note that if the float - precision is too low, iterated powers within |\xintfloatexpr..\relax| may - fail: for example with the default setting |(1+1e-8)^(12^16)| will be - computed with |12^16| approximated from its $16$ most significant digits - but it has $18$ digits (\dtt{={\xintiiPow{12}{16}}}), hence the result is - wrong: - \begingroup - % - \leftedline{$\np{\xintthefloatexpr (1+1e-8)^(12^16)\relax }$} - % - One should code - % - \leftedline{\restoreMicroFont|\xintthe\xintfloatexpr (1+1e-8)^\xintiiexpr 12^16\relax - \relax|} - % - to obtain the correct floating point evaluation - % - \leftedline{$\np{1.00000001}^{12^{16}}\approx\np{\xintthefloatexpr - (1+1e-8)^\xintiiexpr 12^16\relax\relax }$} - % - \endgroup - -\item Multiplication and division \raisebox{-.3\height}{|*|}, |/|. The - division is left associative, too: - % - \begingroup\restoreMicroFont - % - |\xinttheiexpr 100/50/2\relax| evaluates to \xinttheiexpr 100/50/2\relax, - not \xinttheiexpr 100/(50/2)\relax. - % - \endgroup - Inside \csbxint{iiexpr}, |/| does \emph{rounded} division. - -\item Truncated division |//| and modulo |/:| (equivalently |'mod'|, quotes - mandatory) are at the same level of priority than multiplication and - division, thus left-associative with them. Apply parentheses for - disambiguation. -\begin{everbatim*} -\xinttheexpr 100000//13, 100000/:13, 100000 'mod' 13, trunc(100000/13,10), - trunc(100000/:13/13,10)\relax -\end{everbatim*} - -\item The list itemwise operators |*[|, |/[|, |^[|, |**[|, |]*|, |]/|, |]^|, - |]**| are at the same precedence level as, respectively, |*| and |/| or |^| - and |**|. - -\item Addition and subtraction |+|, |-|. Again, |-| is left - associative: - % - \begingroup\restoreMicroFont - % - |\xinttheiexpr 100-50-2\relax| evaluates to \xinttheiexpr 100-50-2\relax, - not \xinttheiexpr 100-(50-2)\relax. - % - \endgroup - -\item The list itemwise operators |+[|, |-[|, |]+|, |]-|, are at - the same precedence level as |+| and |-|, - -\item Comparison operators |<|, |>|, |=| (same as |==|), |<=|, |>=|, |!=| all - at the same level of precedence, use parentheses for disambiguation. - -\item Conjunction (logical and): |&&| or equivalently - |'and'| (quotes mandatory). - -\item Inclusive disjunction (logical or): \verb+||+ - and equivalently |'or'| (quotes mandatory). - -\item XOR: |'xor'| with mandatory quotes is at the same level of precedence - as \verb+||+. - -\item The list generation operators |..|, |..[|, |]..| are at the same - (low) precedence level as the \verb+||+ operator of logical disjunction. - -\item The comma: -\restoreMicroFont with |\xinttheexpr 2^3,3^4,5^6\relax| -one obtains as output \xinttheexpr 2^3,3^4,5^6\relax{}. - -\item The parentheses. The list outer brackets |[|, |]| share the same - functional precedence as parentheses. The semi-colon |;| in an |iter| or - |rseq| has the same precedence as a closing parenthesis. -\end{itemize} - -\subsection{Available functions} - - Functions are at the same top level of priority. All functions even - |?| and |!| (as prefix) require parentheses around their arguments. - - \begin{snugframed} - \xintFor #1 in {num, qint, qfrac, qfloat, reduce, abs, sgn, frac, floor, - ceil, sqr, sqrt, sqrtr, factorial, binomial, pfactorial, 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} \do - {\ctexttt{#1}\xintifForLast{}{, }} - - |factorial|, |binomial|, |pfactorial|, |quo|, |rem|, |even|, |odd|, - |gcd| and |lcm| will first truncate their arguments to integers; the - latter two require package \xintgcdname; |togl| requires the |etoolbox| - package; |all|, |any|, |xor|, |`+`|, |`*`|, |max|, |min|, |first|, - |last|, |reversed| are functions with arbitrarily many comma separated - arguments. - - |bool|, |togl| use delimited macros to fetch their argument and the - closing parenthesis which thus must be explicit, not arising from - expansion. - - The same holds for |qint|, |qfrac|, |qfloat|.\NewWith{1.2} - - Similarly |add|, |mul|, |subs|, |seq|, |rseq|, |rrseq|, |iter| use some - delimited macros to fetch the |,<letter>| part, checking the correct - balance of parentheses, hence allowing nesting. The |<letter>| - (lowercase or uppercase) will be followed by a |=| sign and then a comma - separated list of values or a list expression such as |a..b|, or both, - which will be treated in the normal manner to provide the values which - will be in succession assigned to the |<letter>|. This |<letter>| must - not have been assigned a value before via \csa{xintdefvar}. - - The functions |rseq|, |rrseq| and |iter| have an additional mandatory - initial comma separated list which is separated by a semi-colon from the - expression to evaluate iteratively. This portion up to and including the - semi-colon may arise entirely from expansion (contrarily to the - |,<letter>=| part discussed above). - - |seq|, |rseq|, |rrseq|, |iter| but - not |add|, |mul|, |subs| admit the |omit|, |abort|, and |break(..)| - keywords, possibly but not necessarily in combination with a potentially - infinite list generated by a |n++| expression. - - They may be nested. - \end{snugframed} - -\begin{description}[parsep=0pt, labelwidth=\leftmarginii, - itemindent=0pt, listparindent=\leftmarginiii, - leftmargin=\leftmarginii] - \item[functions with a single (numeric) argument] -\noindent\par -\begin{description} - \item[num] truncates to the nearest integer (truncation towards zero). -\begin{everbatim*} -\xinttheexpr num(3.1415^20)\relax -\end{everbatim*} - - \item[qint] skips the token by token parsing of the input. The ending - parenthesis must be physically present rather than arising from - expansion.\NewWith{1.2} The |q| stands for ``quick''. This ``function'' - handles the input exactly like do the |i| macros of \xintcorename, via - \csbxint{iNum}. Hence leading signs and the leading zeroes (coming next) - will be handled appropriately but spaces will not be systematically - stripped. They should cause no harm and will be removed as soon as the - number is used with one of the basic operators. This input form \emph{does - not accept decimal part or scientific part}. -\begin{everbatim} -\def\x{....many many many ... digits}\def\y{....also many many many digits...} -\xinttheiiexpr qint(\x)*qint(\y)+qint(\y)^2\relax -\end{everbatim} - - \item[qfrac] does the same as \dtt{qint} excepts that it accepts fractions, - decimal numbers, scientific numbers as they are understood by the macros of - package\NewWith{1.2} \xintfracname. Not to be used within an - |\xintiiexpr|-ession, except if hidden inside functions such as - \dtt{round} or \dtt{trunc} which produce integers from fractions. - - \item[qfloat] does the same as \dtt{qfrac} and converts to a float with the - precision given by the setting of |\xintDigits|. - - \item[reduce] reduces a fraction to smallest terms -\begin{everbatim*} -\xinttheexpr reduce(50!/20!/20!/10!)\relax -\end{everbatim*} - -Recall that this is NOT done automatically, for example when adding fractions. - \item[abs] absolute value - \item[sgn] sign - \item[frac] fractional part -\begin{everbatim*} -\xinttheexpr frac(-355/113), frac(-1129.218921791279)\relax -\end{everbatim*} - - \item[floor] floor function. - \item[ceil] ceil function. - \item[sqr] square. - \item[sqrt] in |\xintiiexpr|, truncated square root; in |\xintexpr| or - |\xintfloatexpr| this is the floating point square root, and there is an - optional second argument for the precision. - \item[sqrtr] in |\xintiiexpr| only, rounded square root. - \item[factorial] factorial function,\NewWith {1.2f} same as previously - available post-fix |!| operator. When used in |\xintexpr| or - |\xintfloatexpr| there is an optional second argument. See discussion later. - \item[?] |?(x)| is the truth value, $1$ if non zero, $0$ if zero. Must use parentheses. - \item[!] |!(x)| is logical not, $0$ if non zero, $1$ if zero. Must use parentheses. - \item[not] logical not. - \item[even] evenness of the truncation. -\begin{everbatim*} -\xinttheexpr seq((x,even(x)), x=-5/2..[1/3]..+5/2)\relax -\end{everbatim*} - - \item[odd] oddness of the truncation. -\begin{everbatim*} -\xinttheexpr seq((x,odd(x)), x=-5/2..[1/3]..+5/2)\relax -\end{everbatim*} -\end{description} - -\item[functions with an alphabetical argument] -\noindent\par - \hypertarget{item:bool}{\ctexttt{bool,togl}}. |bool(name)| returns - $1$ if the \TeX{} conditional |\ifname| would act as |\iftrue| and - $0$ otherwise. This works with conditionals defined by |\newif| (in - \TeX{} or \LaTeX{}) or with primitive conditionals such as - |\ifmmode|. For example: - % - \leftedline{|\xintifboolexpr{25*4-if(bool(mmode),100,75)}{YES}{NO}|} - % - will return $\xintifboolexpr{25*4-if(bool(mmode),100,75)}{YES}{NO}$ - if executed in math mode (the computation is then $100-100=0$) and - \xintifboolexpr{25*4-if(bool(mmode),100,75)}{YES}{NO} if not (the - \ctexttt{if} conditional is described below; the - \csbxint{ifboolexpr} test automatically encapsulates its first - argument in an |\xintexpr| and follows the first branch if the - result is non-zero (see \autoref{xintifboolexpr})). - - The alternative syntax |25*4-\ifmmode100\else75\fi| could have been - used here, the usefulness of |bool(name)| lies in the availability - in the |\xintexpr| syntax of the logic operators of conjunction - |&&|, inclusive disjunction \verb+||+, negation |!| (or |not|), of - the multi-operands functions |all|, |any|, |xor|, of the two - branching operators |if| and |ifsgn| (see also |?| and |??|), which - allow arbitrarily complicated combinations of various |bool(name)|. - - Similarly |togl(name)| returns $1$ if the \LaTeX{} package - \href{http://www.ctan.org/pkg/etoolbox}{etoolbox}% - % - % -% -\footnote{\url{http://www.ctan.org/pkg/etoolbox}} - % - has been used to define a toggle named |name|, and this toggle is - currently set to |true|. Using |togl| in an |\xintexpr..\relax| - without having loaded - \href{http://www.ctan.org/pkg/etoolbox}{etoolbox} will result in an - error from |\iftoggle| being a non-defined macro. If |etoolbox| is - loaded but |togl| is used on a name not recognized by |etoolbox| - the error message will be of the type ``ERROR: Missing |\endcsname| - inserted.'', with further information saying that |\protect| should - have not been encountered (this |\protect| comes from the expansion - of the non-expandable |etoolbox| error message). - - When |bool| or |togl| is encountered by the |\xintexpr| parser, the - argument enclosed in a parenthesis pair is expanded as usual from - left to right, token by token, until the closing parenthesis is - found, but everything is taken literally, no computations are - performed. For example |togl(2+3)| will test the value of a toggle - declared to |etoolbox| with name |2+3|, and not |5|. Spaces are - gobbled in this process. It is impossible to use |togl| on such - names containing spaces, but |\iftoggle{name with spaces}{1}{0}| - will work, naturally, as its expansion will pre-empt the - |\xintexpr| scanner. - - There isn't in |\xintexpr...| a |test| function available analogous - to the |test{\ifsometest}| construct from the |etoolbox| package; - but any \emph{expandable} |\ifsometest| can be inserted directly in - an |\xintexpr|-ession as |\ifsometest10| (or |\ifsometest{1}{0}|), - for example |if(\ifsometest{1}{0},YES,NO)| (see the |if| operator - below) works. - - A straight |\ifsometest{YES}{NO}| would do the same more - efficiently, the point of |\ifsometest10| is to allow arbitrary - boolean combinations using the (described later) \verb+&+ and - \verb+|+ logic operators: - \verb+\ifsometest10 & \ifsomeothertest10 | \ifsomethirdtest10+, - etc... |YES| or |NO| above stand for material compatible with the - |\xintexpr| parser syntax. - - See also \csbxint{ifboolexpr}, in this context. - -\item[functions with one mandatory and a second but optional argument] -\noindent\par - \begin{description} - \item[round] For example - |round(-2^9/3^5,12)=|\dtt{\xinttheexpr round(-2^9/3^5,12)\relax.} - \item[trunc] For example - |trunc(-2^9/3^5,12)=|\dtt{\xinttheexpr trunc(-2^9/3^5,12)\relax.} - \item[float] For example - |float(-2^9/3^5,12)=|\dtt{\xinttheexpr float(-2^9/3^5,12)\relax.} - \item [sqrt] in \csa{xintexpr}|...\relax| and \csa{xintfloatexpr}|...\relax| - it achieves the precision given by the optional second argument. -\begin{everbatim*} -\xinttheexpr sqrt(2,31)\relax\ and \xinttheiiexpr sqrt(num(2e60))\relax -\end{everbatim*} - \item[factorial] when the second optional argument\NewWith {1.2f} is made - use of inside \csa{xintexpr}|...\relax|, this switches to the use of the - float version, rather than the exact one. -\begin{everbatim*} -\xinttheexpr factorial (100,32)\relax, {\xintDigits:=32;\xintthefloatexpr - factorial (100)\relax}\newline -\xinttheexpr factorial (50)\relax\newline -\xinttheexpr factorial (50, 32)\relax -\end{everbatim*} - \end{description} - - \item[functions with two arguments] -\noindent\par - \begin{description} - \item[quo] first truncates the arguments then computes the Euclidean quotient. - \item[rem] first truncates the arguments then computes the Euclidean remainder. - \item[mod] computes the modulo associated to the truncated division, same as - |/:| infix operator. -\begin{everbatim*} -\xinttheexpr mod(11/7,1/13), reduce(((11/7)//(1/13))*1/13+mod(11/7,1/13)), -mod(11/7,1/13)- (11/7)/:(1/13), (11/7)//(1/13)\relax -\end{everbatim*} - \item[binomial] computes binomial coefficients.\NewWith {1.2f} -\begin{everbatim*} -\xinttheexpr seq(binomial(20, i), i=0..20)\relax -\end{everbatim*} -\begin{everbatim*} -\xintthefloatexpr seq(binomial(100, 50+i), i=-5..+5)\relax -\end{everbatim*} -The arguments must be (expand to) short integers. - \item[pfactorial] computes partial factorials.\NewWith {1.2f} -\begin{everbatim*} -\xinttheexpr seq(pfactorial(20, i), i=20..30)\relax -\end{everbatim*} -The arguments must be (expand to) short integers. - - \end{description} - - \item[the if conditional (twofold way)] -\noindent\par -\ctexttt{if}|(cond,yes,no)| - checks if |cond| is true or false and takes the corresponding - branch. Any non zero number or fraction is logical true. The zero - value is logical false. Both ``branches'' are evaluated (they are - not really branches but just numbers). See also the |?| operator. - - \item[the ifsgn conditional (threefold way)] -\noindent\par - \ctexttt{ifsgn}|(cond,<0,=0,>0)| checks the sign of |cond| and - proceeds correspondingly. All three are evaluated. See also the |??| - operator. - - \item[functions with an arbitrary number of arguments] -\noindent\par -This argument may well be generated by one or many |a..b| or |a..[d]..b| -constructs, separated by commas. - \begin{description} -\item[all] inserts a logical |AND| in between arguments and evaluates, -\item[any] inserts a logical |OR| in between all arguments and evaluates, -\item[xor] inserts a logical |XOR| in between all arguments and evaluates, -\item[|`+`|] adds (left ticks mandatory): -\begin{everbatim*} -\xinttheexpr `+`(1,3,19), `+`(1*2,3*4,19*20)\relax -\end{everbatim*} -\item[|`*`|] multiplies (left ticks mandatory): -\begin{everbatim*} -\xinttheexpr `*`(1,3,19), `*`(1^2,3^2,19^2), `*`(1*2,3*4,19*20)\relax -\end{everbatim*} -\item[max] maximum, -\item[min] minimum, -\item[gcd] first truncates to integers then computes the |GCD|, requires \xintgcdname, -\item[lcm] first truncates to integers then computes the |LCM|, requires \xintgcdname, -\item[first] first among comma separated items, |first(list)| is like |[list][:1]|. -\begin{everbatim*} -\xinttheiiexpr first(-7..3), [-7..3][:1]\relax -\end{everbatim*} -\item[last] last among comma separated items, |last(list)| is like |[list][-1:]|. -\begin{everbatim*} -\xinttheiiexpr last(-7..3), [-7..3][-1:]\relax -\end{everbatim*} -\item[reversed] reverses the order -\begin{everbatim*} -\xinttheiiexpr reversed(123..150)\relax -\end{everbatim*} - \end{description} - -\item[functions using dummy variables] -\noindent\par -These constructs are nestable if suitably parenthesized. 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. - -The usable dummy variables are all lowercase and uppercase Latin letters. -\begin{description}[listparindent=\leftmarginiii] -\item [subs] for variable substitution -\begin{everbatim*} -\xinttheexpr subs(subs(seq(x*z,x=1..10),z=y^2),y=10)\relax -\end{everbatim*} -Attention that |xz| generates an error, one must use explicitely |x*z|, else -the parser expects a variable with name |xz|. - -This is useful for example when defining macros for which some argument |#1| -will be used more than once but may itself be a complicated expression or -macro, and should be evaluated only once, for matters of efficiency. - -The substituted variable may be a comma separated list (this is impossible -with |seq| which will always pick one item after the other from a list). -\begin{everbatim*} -\xinttheexpr subs([x]^2,x=-123,17,32)\relax -\end{everbatim*} - -See the examples related to the |3x3| determinant in the -\autoref{xintNewExpr} for an illustration of list substitution. - -\item[add] addition -\begin{everbatim*} -\xinttheiiexpr add(x^3,x=1..50), add(x(x+1), x=1,3,19)\relax -\end{everbatim*} -See |`+`| for syntax without a dummy variable. - -\item[mul] multiplication -\begin{everbatim*} -\xinttheiiexpr mul(x^2, x=1,3,19), mul(2n+1,n=1..10)\relax -\end{everbatim*} -See |`*`| for syntax without a dummy variable. - -\item[seq] comma separated values generated according to a formula -\begin{everbatim*} -\xinttheiiexpr seq(x(x+1)(x+2)(x+3),x=1..10), `*`(seq(3x+2,x=1..10))\relax -\end{everbatim*} -\begin{everbatim*} -\xinttheiiexpr seq(seq(i^2+j^2, i=0..j), j=0..10)\relax -\end{everbatim*} - -\item[rseq] recursive sequence, |@| for the previous value. -\begin{everbatim*} -\printnumber {\xintthefloatexpr subs(rseq (1; @/2+y/2@, i=1..10),y=1000)\relax } -\end{everbatim*}\newline - Attention: in the example above |y/2@| is interpreted as - |y/(2*@)|.\IMPORTANT{} With versions |1.2c| or earlier it would have been - interpreted as |(y/2)*@|. - -In case the initial stretch is a comma separated list, |@| refers at the first -iteration to the whole list. Use parentheses at each iteration to maintain -this ``nuple''. -\begin{everbatim*} -\printnumber{\xintthefloatexpr rseq(1,10^6; - (sqrt([@][1]*[@][2]),([@][1]+[@][2])/2), i=1..10)\relax } -\end{everbatim*} - -\item[rrseq] recursive sequence with multiple initial terms. Say, there are - |K| of them. Then |@1|, ..., |@4| and then |@@(n)| up to |n=K| refer to the - last |K| values. Notice the difference with |rseq| for which |@| refers to - the complete list of all initial terms (if there are more than one). -\begin{everbatim*} -\xinttheiiexpr rrseq(0,1; @1+@2, i=2..30)\relax -\end{everbatim*} -\begin{everbatim*} -\xinttheiiexpr rseq(1; 2@, i=1..10)\relax -\end{everbatim*} -\begin{everbatim*} -\xinttheiiexpr rseq(1; 2@+1, i=1..10)\relax -\end{everbatim*} -\begin{everbatim*} -\xinttheiiexpr rseq(2; @(@+1)/2, i=1..5)\relax -\end{everbatim*} - -\begin{everbatim*} -\xinttheiiexpr rrseq(0,1,2,3,4,5; @1+@2+@3+@4+@@(5)+@@(6), i=1..20)\relax -\end{everbatim*} - -I implemented an |Rseq| which at all times keeps the memory of \emph{all} -previous items, but decided to drop it as the package was becoming big. - -\item[iter] same as |rrseq| but does not print any value until the last |K|. -\begin{everbatim*} -\xinttheiiexpr iter(0,1; @1+@2, i=2..5, 6..10)\relax -% the iterated over list is allowed to have disjoint defining parts. -\end{everbatim*} -\end{description} - -Recursions may be nested, with |@@@(n)| giving access to the values of the -outer recursion\dots and there is even |@@@@(n)| to access the outer outer -recursion but I never tried it! - -With |seq|, |rseq|, |rrseq|, |iter|, \textbf{but not} with |subs|, |add|, -|mul|, one has: -\begin{description} -\item[abort] stop here and now. -\item[omit] omit this value. -\item[break] |break(stuff)| to abort and have |stuff| as last value. -\item[n++] serves to generate a potentially infinite list. 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*} -\xinttheiiexpr iter(1;(@>10^40)?{break(@)}{2@},i=1++)\relax -\end{everbatim*} - Note that |n++| can not work in the format |i=10,17,30++|, only |n++| - nothing before. -\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*} -\end{description} - -Some additional examples are to be found in \autoref{ssec:dummy} -\end{description} - - -\subsection{List operations} -\label{ssec:lists} - -A ``list'' simply refers to comma-separated numbers. There is no notion of -``list of lists'' nor is there an ``nuple'' type. Functions such as |gcd|, -|lcm|, |max|, |min|, |first|, |last|, |reversed| apply to lists as well as the -logical functions |all|, |any|, |xor|, and the |`+`|, |`*`| sum and product -operators. - -\xintexprname provides list constructors and list operators, inclusive of -Python-like slicing operators. - -\begin{itemize} - \item |a..b| constructs the \textbf{small} integers from the ceil $\lceil - a\rceil$ to the floor - $\lfloor b\rfloor$ (possibly a decreasing sequence): one has to be careful - if using this for algorithms that |1..0| for example is not empty or |1| - but expands to |1, 0|. Again, |a..b| \emph{can not} be used with |a| and - |b| greater than $2^{31}-1$. Also, only about at most \dtt{5000} integers - can be generated (this depends upon some \TeX{} memory settings). - - The |..| has lower precedence than the arithmetic operations. -\begin{everbatim*} -\xinttheexpr 1.5+0.4..2.3+1.1\relax; \xinttheexpr 1.9..3.4\relax; \xinttheexpr 2..3\relax -\end{everbatim*} - - \item |a..[d]..b| allows to generate big integers, or also fractions, it - proceeds with step (non necessarily integral nor positive) |d|. It does - \emph{not} replace |a| by its ceil, nor |b| by its floor. The generated - list is empty if |b-a| and |d| are of opposite signs; if |d=0| or if |a=b| - the list expands to single element |a|. -\begin{everbatim*} -\xinttheexpr 1.5..[1.01]..11.23\relax -\end{everbatim*} - - \item |[list][n]| extracts the |n|th element, or give the number of items if - |n=0|. If |n<0| it extracts from the tail. -\begin{everbatim*} -\xinttheiexpr \empty[1..10][6], [1..10][0], [1..10][-1], [1..10][23*18-22*19]\relax\ -(and 23*18-22*19 has value \the\numexpr 23*18-22*19\relax). -\end{everbatim*} - -See the next frame for the reason of the presence of |\empty|. - -As shown, it is perfectly legal to do operations in the index parameter, which -will be handled by the parser as everything else. The same remark applies to -the next items. - - \item |[list][:n]| extracts the first |n| elements if |n>0|, or suppresses - the last \verb+|n|+ elements if |n<0|. -\begin{everbatim*} -\xinttheiiexpr [1..10][:6]\relax\ and \xinttheiiexpr [1..10][:-6]\relax -\end{everbatim*} - \item |[list][n:]| suppresses the first |n| elements if |n>0|, or extracts - the last \verb+|n|+ elements if |n<0|. -\begin{everbatim*} -\xinttheiiexpr [1..10][6:]\relax\ and \xinttheiiexpr [1..10][-6:]\relax -\end{everbatim*} -\item More generally, |[list][a:b]| works according to the Python ``slicing'' - rules (inclusive of negative indices). Notice though that there is no - optional third argument for the step, which always defaults to |+1|. -\begin{everbatim*} -\xinttheiiexpr [1..20][6:13]\relax\ = \xinttheiiexpr [1..20][6-20:13-20]\relax -\end{everbatim*} -\item It is naturally possible to nest these things: -\begin{everbatim*} -\xinttheexpr [[1..50][13:37]][10:-10]\relax -\end{everbatim*} -\item itemwise operations either on the left or the right are possible: -\begin{everbatim*} -\xinttheiiexpr 123*[1..10]^2\relax -\end{everbatim*} - -\begin{snugframed} - As list operations are implemented using square brackets, it is - necessary in |\xintiexpr| and |\xintfloatexpr| to insert something before - the first bracket if it belongs to a list, to avoid confusion with the - bracket of an optional parameter. We need something expandable which does - not leave a trace: the |\empty| does the trick.\IMPORTANT{} - -\begin{everbatim*} -\xinttheiexpr \empty [1,3,6,99,100,200][2:4]\relax -\end{everbatim*} - - An alternative is to use parentheses -\begin{everbatim*} -\xinttheiexpr ([1,3,6,99,100,200][2:4])\relax -\end{everbatim*} - - Notice though that |([1,3,6,99,100,200])[2:4]| would not work. It is - mandatory for |][| and |][:| not to be interspersed with parentheses. On - the other hand spaces are perfectly legal: -\begin{everbatim*} -\xinttheiiexpr [1..10 ] [ : 7 ]\relax -\end{everbatim*} - -Similarly all the |+[|, |*[|, \dots and |]**|, |]/|, \dots operators admit -spaces but nothing else in-between their constituent characters. -\begin{everbatim*} -\xinttheiiexpr [ 1 . . 1 0 ] * * 1 1 \relax -\end{everbatim*} - - In an other vein, the parser will be confused by |1..[list][3]|, one must - write |1..([list][3])|. Also things such as |[100,300,500,700][2]//11| will - be confusing because the |]/| is an operator with higher priority than the - |][|, and then there will a dangling |/11| which does not make sense. In - fact even |[100,300,500,700][2]/11| is a syntax error: one must write - |([100,300,500,700][2])/11|. -\end{snugframed} - -\end{itemize} - - -\subsection{Tacit multiplication} -\label{ssec:tacit multiplication} - -Tacit multiplication (insertion of a |*|) applies when the parser is currently -either scanning the digits of a number (or its decimal part or scientific -part, or hexadecimal input), or is looking for an infix operator, and: -(1.)~\emph{encounters a count or dimen or skip register or variable or an - \eTeX{} expression}, or (2.)~\emph{encounters a sub-\csa{xintexpr}ession}, -or (3.)~\emph{encounters an opening parenthesis}, or (4.)~\emph{encounters a - letter (which is interpreted as signaling the start of either a variable or - a function name)}. - -\begin{framed} - For example, if |x, y, z| are variables all three of |(x+y)z|, |x(y+z)|, - |(x+y)(x+z)| will create a tacit multiplication. - - Furthermore starting with release - |1.2e|,\MyMarginNote[\kern\dimexpr\FrameSep+\FrameRule\relax]{Changed} - whenever tacit multiplication is applied, in all cases it \emph{always} - ``ties'' more\IMPORTANT{} than normal multiplication or division, but - still less than power. Thus |x/2y| is interpreted as |x/(2y)| and - similarly for |x/2max(3,5)| but |x^2y| is still interpreted as |(x^2)*y| - and |2n!| as |2*n!|. - -\begin{everbatim*} -\xintdefvar x:=30;\xintdefvar y:=5;% -\xinttheexpr (x+y)x, x/2y, x^2y, x!, 2x!, x/2max(x,y)\relax -\end{everbatim*} - - The ``tye more'' rule applies to all cases of tacit multiplication. It - impacts only situations when a division was the last seen operator, as the - normal rule for the \xintexprname parsers is left-associativity in case of - equal precedence. -\begin{everbatim*} -\xinttheexpr (1+2)/(3+4)(5+6), 2/x(10), 2/10x, 3/y\xintiiexpr 5+6\relax, 1/x(y)\relax -\end{everbatim*} - - Note that |y\xinttheiiexpr 5+6\relax| would have tried to use a variable - with name |y11| rather than doing |y*11|: tacit multiplication works only - in front of sub-\csbxint{expr}essions, not in front of - \csbxint{theexpr}essions which are unlocked into explicit digits. - - These examples above redeclared the |x| and |y| which thus can not be used as - dummy variables anymore (but see \csbxint{unassignvar}); as this happened - inside a \LaTeX{} environment (for the frame), they will have - recovered their meanings after the frame. In the meantime we use letter - |z| for the next example. Here is an expression whose meaning is - completely modified by the ``tye more'' property of tacit multiplication:\IMPORTANT -\begin{everbatim} -\xintdeffunc e(z):=1+z(1+z/2(1+z/3(1+z/4))); -\end{everbatim} -will be parsed as |1+z*(1+z/(2*(1+z/(3*(1+z/4)))))| which is - not at all like the presumably hoped: -\begin{everbatim} -\xintdeffunc e(z):=1+z(1+z/2*(1+z/3*(1+z/4))); -\end{everbatim} -This form can also be used, alternatively: -\begin{everbatim} -\xintdeffunc e(z):=(((z/4+1)z/3+1)z/2+1)z+1; -\end{everbatim} - - Attention! tacit multiplication before an opening parenthesis applies - always, but tacit multiplication after a closing parenthesis \emph{does - not} apply in front of digits: |(1+1)5| is not legal. But - |subs((1+1)x,x=5)| is, because in that case a variable is following the - closing parenthesis. -\end{framed} - - -\subsection{User definable variables and functions} -\label{xintdefvar} -\label{xintdefiivar} -\label{xintdeffloatvar} -\label{xintdeffunc} -\label{xintdefiifunc} -\label{xintdeffloatfunc} -\label{xintunassignvar} -\label{xintverbosetrue} -\label{xintverbosefalse} -\label{ifxintverbose} - -Since release |1.1| it is possible to assign a variable name to let it be -known to the parsers of \xintexprname. -\begin{everbatim*} -\xintdefvar Pi:=3.141592653589793238462643; -\xintthefloatexpr Pi^100\relax -\xintdefvar x_1 := 10;\xintdefvar x_2 := 20;\xintdefvar y@3 := 30; -\quad $x_1\cdot x_2\cdot y@3+1=\xinttheiiexpr x_1*x_2*y@3+1\relax$. -\end{everbatim*} - -As |x_1x| is a licit variable name, as well as |x_1x_| and |x_1x_2| and -|x_1x_2y| etc... we could not count on tacit multiplication being applied to -something like |x_1x_2|; the parser goes not go to the effort of tracing back -its steps. Hence we had to insert explicit |*| infix operators (one often -falls into this trap when playing with variables and counting too much on the -divinatory talents of \xintexprname...). - -The variable definition is done with \csa{xintdefvar}, \csa{xintdefiivar}, or -with \csa{xintdeffloatvar}, the variable will be computed using respectively -\csbxint{expr}, \csbxint{iiexpr} or \csbxint{floatexpr}. The variable -once defined can be used in the other parsers, except naturally that in -\csa{xintiiexpr} only integers are accepted. - -When defining a variable with \csa{xintdeffloatvar}, it is important that -reduction to \csbxint{theDigits} digits of precision happens inside -\csa{xintfloatexpr} only if an operation is executed. Thus, for a variable -declaration with no operations, the value is registered with all its digits. -\begin{everbatim*} -\xintdeffloatvar e:=2.7182818284590452353602874713526624977572470936999595749669676;% -\xinttheexpr e\relax\newline % shows the recorded value -\xintthefloatexpr e\relax\newline % output rounds -\xintthefloatexpr 1+e\relax\newline % the rounding was done by addition (trust me...) -\xintdeffloatvar e:=float(2.7182818284590452353602874713526624977572470936999595749669676);% -\xinttheexpr e\relax\par % use of float forced immediate rounding -\end{everbatim*} - -In the next examples we examine the effect of cumulated float operations on -rounding errors: -\begin{everbatim*} -\xintdefvar e_1:=add(1/i!, i=0..10);% exact sum -\xintdeffloatvar e_2:=add(1/i!, i=0..10);% float sum -\xintthefloatexpr e_1, e_2\relax\newline -\xintdefvar e_3:=e_1+add(1/i!, i=11..20);% exact sum -\xintdeffloatvar e_4:=e_2+add(1/i!, i=11..20);% float sum -\xintthefloatexpr e_3, e_4\relax\newline -\xintdeffloatvar e:=2.7182818284590452353602874713526624977572470936999595749669676;% -\xintDigits:=24; -\xintthefloatexpr[16] e, e^1000, e^1000000\relax (e rounded to 24 digits first)\newline -\xintDigits:=16; -\xintthefloatexpr e, e^1000, e^1000000\relax (e rounded to 16 digits first)\par -\end{everbatim*} - -Legal variable names are composed of letters, digits, |@| and |_| signs. -They can not start with a digit. They may start with |@| or |_|. Currently -|@|, |@1|, |@2|, |@3|, and |@4| are reserved because they have special -meanings for use in iterations. The |@@|, |@@@|, |@@@@| are also reserved but -are technically functions, not variables. Thus a user may possibly use |@@| as -a variable name, but if it is followed by parentheses, the function -interpretation will be applied, rather than doing a tacit multiplication. - -Single letter names |a..z| and |A..Z| are pre-declared by the package for use -as special type of variables called ``dummy variables''. They can be assigned -values via |\xintdefvar| et al., and be later unassigned using -\csa{xintunassign} (see later in this section). - -Since release |1.2c| it is possible to also declare functions: -\begin{everbatim*} -\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/2y; -\end{everbatim*}(notice the numerous tacit multiplications in this expression; -and that |x/2y| is interpreted as |x/(2y)|.) - -\begin{framed} - The (dummy) variables used in the function declaration are necessarily single - letters (lowercase or uppercase) which have \emph{not} been re-declared via - |\xintdefvar| as assigned variables. The choice of the letters is entirely - up to the user and has nil influence on the actual function, naturally. - - A function can have at most nine variables. - - 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.} - -Let's try the famous \textsc{Rump} test: -\begin{everbatim*} -\xinttheexpr Rump(77617,33096)\relax. -\end{everbatim*} -Nothing problematic for an \emph{exact} evaluation, naturally ! - -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 (it is not quite a polynomial with -its |x/2y| final term) with floats, we \emph{must} also -declare |Rump| as a function to be used there: -\begin{everbatim*} -\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/2y; -\end{everbatim*} -(I used 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; and for float operations this may matter on the rounding). - -The numbers are scanned with the current precision, hence as here it is -\dtt{16}, they are scanned exactly in this case. We can then vary the -precision for the evaluation. -\begin{everbatim*} -\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*} - -It is licit to overload a variable name (all Latin letters are predefined as -dummy variables) with a function name and vice versa. The parsers will decide -from the context if the function or variable interpretation must be used -(dropping various cases of tacit multiplication as normally applied). -\begin{everbatim*} -\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*} - -The mechanism for functions is identical with the one underlying the -\csbxint{NewExpr} command. A function once declared is a first class citizen, -its expression is entirely parsed and converted into a big nested \fexpan -dable macro. When used its action is via this defined macro. For example -\begin{everbatim*} -\xintdeffunc - e(z):=(((((((((z/10+1)z/9+1)z/8+1)z/7+1)z/6+1)z/5+1)z/4+1)z/3+1)z/2+1)z+1; -\end{everbatim*} -creates a macro whose meaning one can find in the log file, after -|\xintverbosetrue|. Here it is: -\begin{everbatim} - Function e for \xintexpr parser associated to \XINT_expr_userfunc_e with me -aning macro:#1,->\xintAdd {\xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd {\x -intDiv {\xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {\xintMul {\ -xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv { -\xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {#1}{10}}{1}}{#1}}{9 -}}{1}}{#1}}{8}}{1}}{#1}}{7}}{1}}{#1}}{6}}{1}}{#1}}{5}}{1}}{#1}}{4}}{1}}{#1}}{3} -}{1}}{#1}}{2}}{1}}{#1}}{1} -\end{everbatim} - - -See \autoref{sssec:limitations} for some limitations of the syntax, shared -with those of the \csbxint{NewExpr} command. Some constructs with dummy -variables will not work, when the iterated-over values depend upon the -function arguments. For example |\xintdeffunc f(x):=add(i^2,i=1..x);| leads to -an unusable |f|. But in this case one can use the alternative syntax with list -operations:\footnote{It turns out |`+`(seq(i^2, i=1..x))| would work here, but - this isn't always the case with |seq| constructs.} -\begin{everbatim*} -\xintdeffunc f(x):=`+`([1..x]^2);\xinttheexpr seq(f(x), x=1..20)\relax -\end{everbatim*} - -Side remark: as the |seq(f(x), x=1..10)| does many times the same -computations, an |rseq| here would be more efficient:\footnote{Note that - |omit| and |abort| are not usable in |add| or |mul| (currently).} -\begin{everbatim*} -\xinttheexpr rseq(1; (x>20)?{abort}{@+x^2}, x=2++)\relax -\end{everbatim*} - -On the other hand a construct like the following has no issue, as the values -iterated over do not depend upon the function parameters: -\begin{everbatim*} -\xintdeffunc f(x):=iter(1{;} @*x/i+1, i=10..1);% one must hide the first semi-colon ! -\xinttheexpr e(1), f(1)\relax -\end{everbatim*} - -It is somewhat frustrating not to be able to use the whole \xintexprname -syntax in \csa{xintdeffunc} and \csa{xintNewExpr}. The explanation is simply -that the implementation of |seq|, |iter|, etc... relies on exhaustive -expansion inside |\csname ... \endcsname| whereas \csa{xintdeffunc} tries to -construct an \fexpan dable macro. Furthermore the |omit| and |abort| keywords -as well as the |break()| function are discovered ``dynamically'' when an -expression is parsed from left to right; if they were to be used with an -abstract value list, the information of their presence would have to be coded -especially. This could end up being not that different from storing the whole -|seq|, |iter|, etc.. thing ``as is'' into a macro definition: -\begin{everbatim} -\def\macro #1#2{\xinttheexpr iter(1{;} @*#2/i+1, i=#1..1)\relax} -\end{everbatim} -which does not all achieve what a function declaration, if possible, would. -Side remark: beware that using it with |#2=1+1| will cause unexpected result, -the definition of \csa{macro} should have employed |(#2)| rather than |#2|. - -With |\xintverbosetrue| the values of the variables and the meanings of the -functions (or rather their associated macros) will be written to the log. For -example the first |Rump| declaration above generates this in the log file: -\begin{everbatim} - Function Rump for \xintexpr parser associated to \XINT_expr_userfunc_Rump w -ith meaning macro:#1,#2,->\xintAdd {\xintAdd {\xintAdd {\xintDiv {\xintMul {133 -5}{\xintPow {#2}{6}}}{4}}{\xintMul {\xintPow {#1}{2}}{\xintSub {\xintSub {\xint -Sub {\xintMul {11}{\xintMul {\xintPow {#1}{2}}{\xintPow {#2}{2}}}}{\xintPow {#2 -}{6}}}{\xintMul {121}{\xintPow {#2}{4}}}}{2}}}}{\xintDiv {\xintMul {11}{\xintPo -w {#2}{8}}}{2}}}{\xintDiv {#1}{\xintMul {2}{#2}}} -\end{everbatim} -and the declaration |\xintdeffunc f(x):=iter(1{;} @*x/i+1, i=10..1);| generates: -\begin{everbatim} - Function f for \xintexpr parser associated to \XINT_expr_userfunc_f with me -aning macro:#1,->\xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {\xintMul {\x -intAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {\ -xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd { -\xintDiv {\xintMul {\xintAdd {\xintDiv {\xintMul {\xintAdd {\xintDiv {\xintMul -{1}{#1}}{10/1[0]}}{1}}{#1}}{9/1[0]}}{1}}{#1}}{8/1[0]}}{1}}{#1}}{7/1[0]}}{1}}{#1 -}}{6/1[0]}}{1}}{#1}}{5/1[0]}}{1}}{#1}}{4/1[0]}}{1}}{#1}}{3/1[0]}}{1}}{#1}}{2/1[ -0]}}{1}}{#1}}{1/1[0]}}{1} -\end{everbatim} - -Starting with |1.2d| the definitions made by \csbxint{NewExpr} have local -scope, hence this is also the case with the definitions made by -\csbxint{deffunc}.\IMPORTANT{} One can not ``undeclare'' a function, but -naturally one can provide a new definition for it. - -Variable declarations also are local. One can not really ``unassign'' a -declared variable, but macro \csa{xintunassignvar} will let it insert a zero -and provoke a \TeX{} ``undefined macro'' error. Also, using -\csa{xintunassignvar}\IMPORTANT{} on a letter will let it recover fully its -original meaning as dummy variable. This may even be used for other -characters, if they are used in expressions with catcode 11. As most every -character in the ascii range already has some meaning for \xintexprname, this -is not really recommended, though. -\begin{everbatim*} -\xintFor #1 in {e_1, e_2, e_3, e_4, e} \do {\xintunassignvar {#1}} -\end{everbatim*} - -It is possible to define functions which expand to comma-separated values, for -example the declarations: -\begin{everbatim*} -\xintdeffunc f(x):= x, x^2, x^3, x^x; -\xintdeffunc g(x):= x^[0..x];% x^[1, 2, 3, x] would be like f above. -\end{everbatim*} -will generate -\begin{everbatim} - Function f for \xintexpr parser associated to \XINT_expr_userfunc_f with me -aning macro:#1,->#1,\xintPow {#1}{2},\xintPow {#1}{3},\xintPow {#1}{#1} - Function g for \xintexpr parser associated to \XINT_expr_userfunc_g with me -aning macro:#1,->\xintApply::csv {\xintPow {#1}}{\xintSeq::csv {0}{#1}} -\end{everbatim} -and we can check that they work: -\begin{everbatim*} -\xinttheexpr f(10)\relax; \xinttheexpr g(10)\relax -\end{everbatim*} - -N.B.: we declared in this section |e|, |f|, |g| as functions. Except naturally -if the function declarations are done in a group or a \LaTeX{} environment -whose scope has ended, they can not be completely undone, and if |e|, |f|, or -|g| are used as dummy variables the tacit multiplication in front of -parentheses will not be applied, it is their function interpretation which will -prevail. However, with an explicit |*| in front of the opening parenthesis, it -does work: -\begin{everbatim*} -\xinttheexpr add(f*(f+f), f= 1..10)\relax % f is used as variable, not function. -\end{everbatim*} - - \subsection{More examples with dummy variables} -\label{ssec:dummy} +\label{ssec:moredummies} These examples were first added to this manual at the time of the |1.1| release (|2014/10/29|). @@ -11387,7 +11561,7 @@ The numbers which survive are the prime numbers. \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{} +\xinttheiiexpr subs(iterr(0,1;(@1>N)?{break(i)}{@1+@2},i=1++),N=2^64)\relax{} and the previous number was its index. \end{everbatim*} @@ -11406,7 +11580,7 @@ The 3x+1 problem: \syr{231}\par OK, a final one: \begin{everbatim*} -\def\syrMax #1{\xinttheiiexpr iter(#1,#1;even(i)? +\def\syrMax #1{\xinttheiiexpr iterr(#1,#1;even(i)? {(@2<=1)?{break(i/2)}{odd(@2)?{3@2+1}{@2//2}}} {(@1>@2)?{@1}{@2}},i=0++)\relax } With initial value 1161, the maximal number attained is \syrMax{1161} and that latter @@ -11424,14 +11598,20 @@ 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 } + subs(seq((i/:3=1)?{omit}{[L][i]},i=0..len(L)-1), + L=rseq(#1;(p^2>[@][0])?{([@][0]>1)?{break(1,[@][0],1)}{abort}} + {(([@][0])/:p)?{omit} + {iter(([@][0])//p; (@/:p)?{break(@,p,e)}{@//p},e=1++)}},p=2++))\relax } \Factors {41^4*59^2*29^3*13^5*17^8*29^2*59^4*37^6} \end{everbatim*} -This might look a bit scary, I admit. \xintexprname has minimal tools and +This might look a bit scary, I admit.% +% +\footnote{Look at the + \hyperlink{BrentSalamin}{Brent-Salamin algorithm implementation} for a much + saner example.} +% +\xintexprname has minimal tools and is obstinate about doing everything expandably! We are hampered by absence of a notion of ``nuple''. The algorithm divides |N| by |2| until no more possible, then by |3|, then by |4| (which is silly), then by |5|, then by |6| (silly @@ -11454,13 +11634,13 @@ 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 +Notice that in |iter(([@][0])//p;| the |@| refers to the previous triplet (or in the first step to |N|), but the latter |@| showing up in |(@/:p)?| refers to the previous value computed by |iter|. \begin{snugframed} Parentheses are essential in |..([y][0])| else the parser will see |..[| and - end up in ultimate confusion, and also in |([@][1])/:p| else the parser will + end up in ultimate confusion, and also in |([@][0])/:p| else the parser will see the itemwise operator |]/| on lists and again be very confused (I could implement a |]/:| on lists, but in this situation this would also be very confusing to the parser.) @@ -11786,7 +11966,7 @@ parameters is produced which is built-up recursively from the necessary to do without the facilities of the \xintexprname package. Notice that since |1.2c| the \csbxint{deffunc} construct allows an alternative -to \csa{xintNewExpr} whose syntax uses arbitrarly letters rather than macro +to \csa{xintNewExpr} whose syntax uses arbitrary letters rather than macro parameters |#1|, |#2|, .... The declared function must still be used inside an expression, thus the |\csname...\endcsname| problem is not completely eliminated, but the computation it realizes will need only as many |\csname|'s @@ -11981,21 +12161,25 @@ b {\xintMul {#4}{#9}}{\xintMul {#6}{#7}}}}}{\xintMul {#3}{\xintSub {\xintMul {# \medskip -Lists, including Python-like selectors, are compatible with \csa{xintNewExpr}: +Lists, including Python-like selectors, are compatible with +\csa{xintNewExpr}:% +% +\footnote{The |\empty| token is optional here, but it would + be needed in case of \csbxint{NewFloatExpr} or \csbxint{NewIExpr}.} +% \begin{everbatim*} -\xintNewExpr\FA[5]{[#1..[#2]..#3][#4:#5]} -And this works: +\xintNewExpr\Foo[5]{\empty[#1..[#2]..#3][#4:#5]} \begin{itemize}[nosep] -\item |\FA{1}{3}{90}{20}{30}|->\FA{1}{3}{90}{20}{30} -\item |\FA{1}{3}{90}{-40}{-15}|->\FA{1}{3}{90}{-40}{-15} -\item |\FA{1.234}{-0.123}{-10}{3}{7}|->\FA{1.234}{-0.123}{-10}{3}{7} +\item |\Foo{1}{3}{90}{20}{30}|->\Foo{1}{3}{90}{20}{30} +\item |\Foo{1}{3}{90}{-40}{-15}|->\Foo{1}{3}{90}{-40}{-15} +\item |\Foo{1.234}{-0.123}{-10}{3}{7}|->\Foo{1.234}{-0.123}{-10}{3}{7} \end{itemize} -\fdef\test {\FA {0}{10}{100}{3}{6}}\meaning\test +++ +\fdef\test {\Foo {0}{10}{100}{3}{6}}\meaning\test +++ \end{everbatim*} -In this last example the macro |\FA| will not be able to handle an empty |#4| +In this last example the macro |\Foo| will not be able to handle an empty |#4| or |#5|: this is only possible in an expression, because the parser identifies -|][:| or |:]| and handles them appropriately. During the construction of |\FA| +|][:| or |:]| and handles them appropriately. During the construction of |\Foo| the parser will find |][#4:| and not |][:|. \begin{framed} @@ -12114,8 +12298,8 @@ the letters used as function arguments. There is a final syntax restriction which however applies only to \csa{xintNewExpr} et. al., and not to \csa{xintdeffunc}, \csa{xintdefiifunc}, -\csa{xintdeffloatfunc} : it is possible to use sub-expressions only if with -\csa{xintexpr}, but not with \csa{xinttheexpr}: +\csa{xintdeffloatfunc} : it is possible to use sub-expressions only if they use +\csa{xintexpr}, those with \csa{xinttheexpr} are illegal. \begin{everbatim*} \xintNewExpr \FC [4] {#1+\xintexpr #2*#3\relax + #4} \printnumber{\fixmeaning\FC} @@ -12260,7 +12444,7 @@ comma separated list of $0$'s and $1$'s. but with the four binary operations and the power function are mapped to \csa{xintFloatAdd}, \csa{xintFloatSub}, \csa{xintFloatMul}, \csa{xintFloatDiv} and \csa{xintFloatPower}, respectively.\footnote{Since |1.2f| the \string^ - handles half-integer exponents, contrarily to \csa{xintFloatPower}} + handles half-integer exponents, contrarily to \csa{xintFloatPower}.} The target precision for the computation is from the current setting of |\xintDigits|. Comma separated lists of expressions are @@ -12339,7 +12523,7 @@ influence on its behaviour. There is the limitation though that the outputs from \csbxint{expr} and \csbxint{floatexpr} can not be used directly in \csbxint{theiiexpr} integer-only parser. But one can do: \begin{everbatim*} -\xinttheiiexpr num(\xintfloatexpr 3.14^10\relax)\relax +\xinttheiiexpr round(\xintfloatexpr 3.14^10\relax)\relax % or trunc \end{everbatim*} @@ -12425,11 +12609,11 @@ The |\escapechar| setting may be arbitrary when using |\xintexpr|. The format of the output of |\xintexpr|\meta{stuff}|\relax| is a |!| (with catcode 11) followed by various things: \begin{everbatim*} -\fdef\f {\xintexpr 1.23^10\relax }\meaning\f +\edef\f {\xintexpr 1.23^10\relax }\meaning\f \end{everbatim*} \begin{framed} - Note that |\xintexpr| is thus compatible with complete expansion, contrarily + Note that |\xintexpr| expands in an |\edef|, contrarily to |\numexpr| which is non-expandable, if not prefixed by |\the|, |\number|, or |\romannumeral| or in some other context where \TeX{} is building a number. See \autoref{ssec:fibonacci} for some illustration. @@ -12465,16 +12649,16 @@ the syntax of the |seq|, |add|, |mul|, |subs|, |rseq| and |rrseq| functions, and missing parentheses may cause the parser to fetch tokens beyond the ending |\relax| necessarily ending up in cryptic low-level \TeX-errors. -Note that the |,<letter>=| part must be visible, it can not arise -from expansion (the equal sign does not have to be an equal sign, it can be -any token and will be gobbled).\IMPORTANT{} However for |iter|, |rseq|, |rrseq|, the -initial values delimited by a |;| are parsed in the normal way, and in -particular may be braced or arise from expansion. This is useful as the |;| -may be hidden from \csa{xintdeffunc} as |{;}| for example. Again, this remark -does \emph{not} apply to the comma |,| which precedes the |<letter>=| part. -The comma will be fetched by delimited macros and must be there. Nesting is -handled by checking (again using suitable delimited macros) that parentheses -are suitably balanced. +Note that the |,<letter>=| part must be visible, it can not arise from +expansion (the equal sign does not have to be an equal sign, it can be any +token and will be gobbled).\IMPORTANT{} However for |iter|, |iterr|, |rseq|, +|rrseq|, the initial values delimited by a |;| are parsed in the normal way, +and in particular may be braced or arise from expansion. This is useful as the +|;| may be hidden from \csa{xintdeffunc} as |{;}| for example. Again, this +remark does \emph{not} apply to the comma |,| which precedes the |<letter>=| +part. The comma will be fetched by delimited macros and must be there. Nesting +is handled by checking (again using suitable delimited macros) that +parentheses are suitably balanced. Note that |\relax| is \emph{mandatory} (contrarily to the situation for |\numexpr|). @@ -13491,16 +13675,18 @@ higher than |100| it is more efficient to use the code using }% | -Let us turn now to Pi, computed with the Machin formula. Again the numbers of -terms to keep in the two |arctg| series were roughly estimated, and some -experimentations showed that removing the last three digits was enough (at least -for |D=0-100| range). And the algorithm does print the correct digits when used -with |D=1000| (to be convinced of that one needs to run it for |D=1000| and -again, say for |D=1010|.) A theoretical analysis could help confirm that this -algorithm always gets better than |10^{-D}| precision, but again, strings of -zeroes or nines encountered in the decimal expansion may falsify the ending -digits, nines may be zeroes (and the last non-nine one should be increased) and -zeroes may be nine (and the last non-zero one should be decreased). +Let us turn now to Pi, computed with the Machin formula (but see also the +approach via the \hyperlink{BrentSalamin}{Brent-Salamin algorithm} with +\csa{xintfloatexpr}) Again the numbers of terms to keep in the two |arctg| +series were roughly estimated, and some experimentations showed that removing +the last three digits was enough (at least for |D=0-100| range). And the +algorithm does print the correct digits when used with |D=1000| (to be +convinced of that one needs to run it for |D=1000| and again, say for +|D=1010|.) A theoretical analysis could help confirm that this algorithm +always gets better than |10^{-D}| precision, but again, strings of zeroes or +nines encountered in the decimal expansion may falsify the ending digits, +nines may be zeroes (and the last non-nine one should be increased) and zeroes +may be nine (and the last non-zero one should be decreased). \hypertarget{MachinCode}{} \begin{everbatim*} @@ -13604,8 +13790,30 @@ laptop (a 2012 model) this took about $5.6$ seconds last time I tried.% seconds; starting with \texttt{1.09j}, and prior to \texttt{1.2}, it was \dtt{16} seconds (this was probably due to a more efficient division with denominators at most $9999$). The |1.2| \xintcorename achieves a further - gain.} + gain at \dtt{5.6} seconds.} +% +\footnote{With |\xintDigits:=1001;|, the non-optimized implementation with the + |iter| of \xintexprname fame using the + \hyperlink{BrentSalamin}{Brent-Salamin algorithm}, took, last time I tried + (1.2g), about \dtt{7.4} seconds on my laptop (the last two digits were + wrong, which is ok as they serve as guard digits), and for obtaining about + \dtt{500} digits, it was of \dtt{1.6}s. This is not bad, taking into account + that the syntax is almost free rolling speech, contrarily to the code above + for the Machin formula computation; we would like to use the quadratically + convergent Brent-Salamin algorithm for more digits, but with such + computations with numbers of one thousand digits we are beyond the border of + the reasonable range for \xintname. Innocent people not knowing what it + means to compute with \TeX, and with the extra constraint of expandability + will wonder why this is at least thousands of times slower than with any + other language (with a little Python program using the |Decimal| library, I + timed the Brent-Salamin algorithm to \dtt{4.4ms} for about |1000| digits and + \dtt{1.14ms} for |500| digits.) I will just say that for example digits are + represented and manipulated via their ascii-code ! all computations must + convert from ascii-code to cpu words; furthermore nothing can be stored + away. And there is no memory storage with |O(1)| time access... if + expandability is to be verified.} % + As mentioned in the introduction, the file \href{http://www.ctan.org/pkg/pi}{pi.tex} by \textsc{D. Roegel} shows that orders of magnitude faster computations are possible within @@ -14657,7 +14865,7 @@ $1$ or $-1$. \fi \XINT_providespackage \ProvidesPackage {xintkernel}% - [2016/03/12 1.2f Paraphernalia for the xint packages (JFB)]% + [2016/03/19 1.2g Paraphernalia for the xint packages (JFB)]% % \end{macrocode} % \subsection{Constants} % |1.2| decides to move them to \xintkernelnameimp from \xintcorenameimp and @@ -14718,12 +14926,24 @@ $1$ or $-1$. \long\def\xint_firstofone #1{#1}% \long\def\xint_firstoftwo #1#2{#1}% \long\def\xint_secondoftwo #1#2{#2}% +\long\def\xint_gobble_thenstop #1{ }% \long\def\xint_firstofone_thenstop #1{ #1}% \long\def\xint_firstoftwo_thenstop #1#2{ #1}% \long\def\xint_secondoftwo_thenstop #1#2{ #2}% -\def\xint_minus_thenstop { -}% \def\xint_exchangetwo_keepbraces #1#2{{#2}{#1}}% % \end{macrocode} +% \lverb|& +% It has taken me three years to realize that \romannumeral0 was stopped by a +% minus sign with no side effect. I had here$newline +% \def\xint_minus_thenstop { -}%$newline +% but obviously it has no real utility ! +% +% I had already started recently removing spaces in front of braces when I +% spotted them in the old code ... but that story of the minus sign is really +% strange. I knew it for a long time but never bothered looking back. +% I had 35 uses in the code. Removed by 1.2g. +% | +% % \subsection{``gob til'' macros and UD style fork} % Some moved here from \xintcorenameimp by release |1.2|. % \begin{macrocode} @@ -14826,7 +15046,9 @@ $1$ or $-1$. % \lverb|\xintReverseOrder: does NOT expand its argument. Thus one must use % some \expandafter if argument is a macro. A faster reverse, but only % applicable to (many) digit tokens has been provided with -% \csh{xintReverseDigits} from 1.2 xintcore.| +% \csh{xintReverseDigits} from 1.2 xintcore. +% +% 1.2g has (not user documented) \xintCSVReverse in xinttools.sty.| % \begin{macrocode} \def\xintReverseOrder {\romannumeral0\xintreverseorder }% \long\def\xintreverseorder #1% @@ -14848,7 +15070,9 @@ $1$ or $-1$. }% % \end{macrocode} % \subsection{\csh{xintLength}} -% \lverb|\xintLength does NOT expand its argument.| +% \lverb|\xintLength does NOT expand its argument. +% +% 1.2g has (not user documented) \xintCSVLength in xinttools.sty.| % \begin{macrocode} \def\xintLength {\romannumeral0\xintlength }% \long\def\xintlength #1% @@ -14969,7 +15193,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xinttools}% - [2016/03/12 1.2f Expandable and non-expandable utilities (JFB)]% + [2016/03/19 1.2g 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.| @@ -15242,7 +15466,7 @@ $1$ or $-1$. \long\def\XINT_lws_end\xint_bye\XINT_lws_loop_b #1#2#3{ #1}% % \end{macrocode} % \subsection{\csh{xintNthElt}} -% \lverb+First included in release 1.06. +% \lverb?First included in release 1.06. % % \xintNthElt {i}{stuff f-expanding to {a}{b}...{z}} (or `tokens' % abcd...z)returns the i th element (one pair of braces removed). The list is @@ -15253,65 +15477,70 @@ $1$ or $-1$. % which is only for numbers (particularly, it checks the sign) and different % from \xintLength which does not f-expand its argument. % -% Negative values return the |i|th element from the end. Release 1.09m -% rewrote the initial bits of the code (which checked the sign of #1 and -% expanded or not #2), ome `improvements' made earlier in 1.09c were quite -% sub-efficient. Now uses \xint_UD$-zero$-minus$-fork, moved from xint.sty.+ +% Negative values return the |i|th element from the end. +% +% When i is out of range, an empty value is returned. +% +% +% 1.2g does some changes possibly improving a bit the speed of token +% shuffling here (particularly when the first argument is negative). +% +% ? % \begin{macrocode} \def\xintNthElt {\romannumeral0\xintnthelt }% \def\xintNthEltNoExpand {\romannumeral0\xintntheltnoexpand }% -\def\xintnthelt #1#2% -{% - \expandafter\XINT_nthelt_a\the\numexpr #1\expandafter.% - \expandafter{\romannumeral`&&@#2}% -}% -\def\xintntheltnoexpand #1% -{% - \expandafter\XINT_nthelt_a\the\numexpr #1.% -}% -\def\XINT_nthelt_a #1#2.% +\long\def\xintnthelt #1#2{\expandafter\XINT_nthelt_a\the\numexpr #1\expandafter.% + \expandafter{\romannumeral`&&@#2}}% +\def\xintntheltnoexpand #1{\expandafter\XINT_nthelt_a\the\numexpr #1.}% +\def\XINT_nthelt_a #1% {% \xint_UDzerominusfork - #1-{\XINT_nthelt_bzero}% - 0#1{\XINT_nthelt_bneg {#2}}% - 0-{\XINT_nthelt_bpos {#1#2}}% + #1-{\XINT_nthelt_zero }% + 0#1{\XINT_nthelt_neg }% + 0-{\XINT_nthelt_pos #1}% \krof }% -\long\def\XINT_nthelt_bzero #1% +\def\XINT_nthelt_zero .{\xintlength }% +\long\def\XINT_nthelt_neg #1.#2% {% - \XINT_length_loop 0.#1\xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye + \expandafter\XINT_nthelt_neg_a\the\numexpr + \XINT_length_loop + 0.#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye +\xint_c_i -#1.% + #2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye }% -\long\def\XINT_nthelt_bneg #1#2% +\def\XINT_nthelt_neg_a #1% {% - \expandafter\XINT_nthelt_loop_a\expandafter {\the\numexpr #1\expandafter}% - \romannumeral0\xintrevwithbracesnoexpand {#2}% - \xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye + \xint_UDzerominusfork + #1-{\XINT_nthelt_none }% + 0#1{\XINT_nthelt_none }% + 0-{\XINT_nthelt_loop_a #1}% + \krof }% -\long\def\XINT_nthelt_bpos #1#2% +\long\def\XINT_nthelt_none #1\xint_bye{ }% +\long\def\XINT_nthelt_pos #1.#2% {% - \XINT_nthelt_loop_a {#1}#2\xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye + \XINT_nthelt_loop_a #1.% + #2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye }% -\def\XINT_nthelt_loop_a #1% +\def\XINT_nthelt_loop_a #1.% {% \ifnum #1>\xint_c_viii \expandafter\XINT_nthelt_loop_b \else - \XINT_nthelt_getit - \fi - {#1}% + \expandafter\XINT_nthelt_getit + \fi #1.% }% -\long\def\XINT_nthelt_loop_b #1#2#3#4#5#6#7#8#9% +\long\def\XINT_nthelt_loop_b #1.#2#3#4#5#6#7#8#9% {% - \xint_gob_til_xint_relax #9\XINT_nthelt_silentend\xint_relax - \expandafter\XINT_nthelt_loop_a\expandafter{\the\numexpr #1-\xint_c_viii}% + \xint_gob_til_xint_relax #9\XINT_nthelt_none\xint_relax + \expandafter\XINT_nthelt_loop_a\the\numexpr #1-\xint_c_viii.% }% -\def\XINT_nthelt_silentend #1\xint_bye { }% -\def\XINT_nthelt_getit\fi #1% +\def\XINT_nthelt_getit #1.% {% - \fi\expandafter\expandafter\expandafter\XINT_nthelt_finish + \expandafter\expandafter\expandafter\XINT_nthelt_finish \csname xint_gobble_\romannumeral\numexpr#1-\xint_c_i\endcsname }% \long\edef\XINT_nthelt_finish #1#2\xint_bye @@ -15319,7 +15548,9 @@ $1$ or $-1$. \noexpand\xint_gobble_ii\xint_relax\space #1}% % \end{macrocode} % \subsection{\csh{xintKeep}} -% \lverb+First included in release 1.09m. +% \lverb?& +% +% First included in release 1.09m. % % \xintKeep {i}{stuff f-expanding to {a}{b}...{z}} (or `tokens' abcd...z, but % each naked token ends up braced in the output, if 0<i<length of token list) @@ -15327,73 +15558,83 @@ $1$ or $-1$. % is first f-expanded. The i is expanded inside \numexpr. The variant % \xintKeepNoExpand does not expand the list argument. % -% With i = 0, the empty sequence is returned. +% With 0<i<length, each item ends up *braced* in the output. % -% With i<0, the last |i| items are returned (in the same order as in -% the original list) AND BRACES ARE NOT ADDED IF NOT ORIGINALLY PRESENT. +% With i = 0, the empty sequence is returned. % % With |i| equal to or bigger than the length of the (f-expanded) list, -% the full list is returned. +% the full list is returned, with no braces added to items. +% +% With -length<i<0, the last |i| items are returned (in the same order as in +% the original list) AND BRACES ARE NOT ADDED IF NOT ORIGINALLY PRESENT. % % 1.2a belatedly corrects the description of what this macro does for i<0 ! % % I have this nagging feeling I should read this code which might be much -% improvable upon, but I just don't have time now (2015/10/19).+ +% improvable upon, but I just don't have time now (2015/10/19). +% +% Some cosmetic code improvements for 1.2g, to minimize token handling. And +% the ending (_finish) which was temporary has finally been redone, fleeting +% thoughts of alternative keep escaping me and I was a bit reluctant to the +% method followed in the end, but still probably better than the older one. +% ? % \begin{macrocode} \def\xintKeep {\romannumeral0\xintkeep }% \def\xintKeepNoExpand {\romannumeral0\xintkeepnoexpand }% -\def\xintkeep #1#2% -{% - \expandafter\XINT_keep_a\the\numexpr #1\expandafter.% - \expandafter{\romannumeral`&&@#2}% -}% -\def\xintkeepnoexpand #1% -{% - \expandafter\XINT_keep_a\the\numexpr #1.% -}% -\def\XINT_keep_a #1#2.% +\long\def\xintkeep #1#2{\expandafter\XINT_keep_a\the\numexpr #1\expandafter.% + \expandafter{\romannumeral`&&@#2}}% +\def\xintkeepnoexpand #1{\expandafter\XINT_keep_a\the\numexpr #1.}% +\def\XINT_keep_a #1% {% \xint_UDzerominusfork - #1-{\expandafter\space\xint_gobble_i }% - 0#1{\XINT_keep_bneg_a {#2}}% - 0-{\XINT_keep_bpos {#1#2}}% + #1-{\XINT_keep_keepnone }% + 0#1{\XINT_keep_neg }% + 0-{\XINT_keep_pos #1}% \krof }% -\long\def\XINT_keep_bneg_a #1#2% +\long\def\XINT_keep_keepnone .#1{ }% +\long\def\XINT_keep_neg #1.#2% {% - \expandafter\XINT_keep_bneg_b \the\numexpr \xintLength{#2}-#1.{#2}% + \expandafter\XINT_keep_neg_a\the\numexpr + \XINT_length_loop + 0.#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye -#1.% + #2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye }% -\def\XINT_keep_bneg_b #1#2.% +\def\XINT_keep_neg_a #1% {% \xint_UDzerominusfork - #1-{\xint_firstofone_thenstop }% - 0#1{\xint_firstofone_thenstop }% - 0-{\XINT_trim_bpos {#1#2}}% + #1-{\XINT_keep_keepall }% + 0#1{\XINT_keep_keepall }% + 0-{\XINT_trim_loop_a #1}% \krof }% -\long\def\XINT_keep_bpos #1#2% +\def\XINT_keep_keepall #1.{\XINT_keep_keepall_a \space}% +\def\XINT_keep_keepall_a #1\xint_relax #2\xint_bye {#1}% +\long\def\XINT_keep_pos #1.#2% {% - \XINT_keep_loop_a {#1}{}#2\xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_bye + \XINT_keep_loop_a #1.% + {}#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_bye }% -\def\XINT_keep_loop_a #1% +\def\XINT_keep_loop_a #1.% {% \ifnum #1>\xint_c_vi \expandafter\XINT_keep_loop_b \else - \XINT_keep_finish + \expandafter\XINT_keep_finish \fi - {#1}% + #1.% }% -\long\def\XINT_keep_loop_b #1#2#3#4#5#6#7#8#9% +\long\def\XINT_keep_loop_b #1.#2#3#4#5#6#7#8#9% {% \xint_gob_til_xint_relax #9\XINT_keep_enda\xint_relax - \expandafter\XINT_keep_loop_c\expandafter{\the\numexpr #1-\xint_c_vii}% + \expandafter\XINT_keep_loop_c\the\numexpr #1-\xint_c_vii.% {{#3}{#4}{#5}{#6}{#7}{#8}{#9}}{#2}% }% -\long\def\XINT_keep_loop_c #1#2#3{\XINT_keep_loop_a {#1}{#3#2}}% -\long\def\XINT_keep_enda\xint_relax - \expandafter\XINT_keep_loop_c\expandafter #1#2#3#4\xint_bye +\long\def\XINT_keep_loop_c #1.#2#3{\XINT_keep_loop_a #1.{#3#2}}% +\long\def\XINT_keep_enda #1.#2#3#4\xint_bye {% \XINT_keep_endb #4\W\W\W\W\W\W\Z #2{#3}% }% @@ -15409,126 +15650,122 @@ $1$ or $-1$. \W\XINT_keep_endc_vi\Z }% \long\def\XINT_keep_endc_ #1\Z #2#3#4#5#6#7#8#9{ #9}% -\long\def\XINT_keep_endc_i #1\Z #2#3#4#5#6#7#8#9{ #9{#2}}% -\long\def\XINT_keep_endc_ii #1\Z #2#3#4#5#6#7#8#9{ #9{#2}{#3}}% -\long\def\XINT_keep_endc_iii #1\Z #2#3#4#5#6#7#8#9{ #9{#2}{#3}{#4}}% -\long\def\XINT_keep_endc_iv #1\Z #2#3#4#5#6#7#8#9{ #9{#2}{#3}{#4}{#5}}% -\long\def\XINT_keep_endc_v #1\Z #2#3#4#5#6#7#8#9{ #9{#2}{#3}{#4}{#5}{#6}}% -\long\def\XINT_keep_endc_vi\Z #1#2#3#4#5#6#7#8{ #8{#1}{#2}{#3}{#4}{#5}{#6}}% -\long\def\XINT_keep_finish\fi #1#2#3#4#5#6#7#8#9\xint_bye -{% - \fi\XINT_keep_finish_loop_a {#1}{}{#3}{#4}{#5}{#6}{#7}{#8}\Z {#2}% -}% -\def\XINT_keep_finish_loop_a #1% -{% - \xint_gob_til_zero #1\XINT_keep_finish_z0% - \expandafter\XINT_keep_finish_loop_b\expandafter {\the\numexpr #1-\xint_c_i}% -}% -\long\def\XINT_keep_finish_z0% - \expandafter\XINT_keep_finish_loop_b\expandafter #1#2#3\Z #4{ #4#2}% -\long\def\XINT_keep_finish_loop_b #1#2#3% -{% - \xint_gob_til_xint_relax #3\XINT_keep_finish_exit\xint_relax - \XINT_keep_finish_loop_c {#1}{#2}{#3}% -}% -\long\def\XINT_keep_finish_exit\xint_relax - \XINT_keep_finish_loop_c #1#2#3\Z #4{ #4#2}% -\long\def\XINT_keep_finish_loop_c #1#2#3% - {\XINT_keep_finish_loop_a {#1}{#2{#3}}}% +\long\def\XINT_keep_endc_i #1\Z #2#3#4#5#6#7#8#9{#9{#2}}% +\long\def\XINT_keep_endc_ii #1\Z #2#3#4#5#6#7#8#9{#9{#2}{#3}}% +\long\def\XINT_keep_endc_iii #1\Z #2#3#4#5#6#7#8#9{#9{#2}{#3}{#4}}% +\long\def\XINT_keep_endc_iv #1\Z #2#3#4#5#6#7#8#9{#9{#2}{#3}{#4}{#5}}% +\long\def\XINT_keep_endc_v #1\Z #2#3#4#5#6#7#8#9{#9{#2}{#3}{#4}{#5}{#6}}% +\long\def\XINT_keep_endc_vi\Z #1#2#3#4#5#6#7#8{#8{#1}{#2}{#3}{#4}{#5}{#6}}% +\long\def\XINT_keep_finish #1.#2#3#4#5#6#7#8#9\xint_bye +{% + \XINT_keep_finish_a #1.% + #3\xint_c_ #4\xint_c_i #5\xint_c_ii #6\xint_c_iii #7\xint_c_iv + #8\xint_c_v\xint_relax\xint_c_vi\xint_bye + {#3}{#4}{#5}{#6}{#7}{#8}\xint_bye {#2}% +}% +\long\def\XINT_keep_finish_a #1.#2\xint_relax #3#4\xint_bye +{% + \csname XINT_keep_finish_b\romannumeral\ifnum#1>#3#3\else#1\fi\endcsname +}% +\long\def\XINT_keep_finish_b #1\xint_bye #2{ #2}% +\long\def\XINT_keep_finish_bi #1#2\xint_bye #3{#3{#1}}% +\long\def\XINT_keep_finish_bii #1#2#3\xint_bye #4{#4{#1}{#2}}% +\long\def\XINT_keep_finish_biii#1#2#3#4\xint_bye #5{#5{#1}{#2}{#3}}% +\long\def\XINT_keep_finish_biv #1#2#3#4#5\xint_bye #6{#6{#1}{#2}{#3}{#4}}% +\long\def\XINT_keep_finish_bv #1#2#3#4#5#6\xint_bye #7{#7{#1}{#2}{#3}{#4}{#5}}% +\long\def\XINT_keep_finish_bvi #1\xint_bye #2{#2#1}% % \end{macrocode} % \subsection{\csh{xintKeepUnbraced}} -% \lverb+1.2a. Same as \xintKeep but will not maintain brace pairs around -% the kept items upfront.+ +% \lverb?1.2a. Same as \xintKeep but will *not* add (or maintain) brace pairs +% around the kept items upfront. +% +% There was actually a bug as \xintkeepunbracednoexpand was never defined, +% rather it is \xintkeepnoexpand which got re-defined... belatedly corrected +% for 1.2g? % \begin{macrocode} \def\xintKeepUnbraced {\romannumeral0\xintkeepunbraced }% \def\xintKeepUnbracedNoExpand {\romannumeral0\xintkeepunbracednoexpand }% -\def\xintkeepunbraced #1#2% -{% - \expandafter\XINT_keepunbraced_a\the\numexpr #1\expandafter.% - \expandafter{\romannumeral`&&@#2}% -}% -\def\xintkeepnoexpand #1% -{% - \expandafter\XINT_keepunbraced_a\the\numexpr #1.% -}% -\def\XINT_keepunbraced_a #1#2.% +\long\def\xintkeepunbraced #1#2% + {\expandafter\XINT_keepunbr_a\the\numexpr #1\expandafter.% + \expandafter{\romannumeral`&&@#2}}% +\def\xintkeepunbracednoexpand #1% + {\expandafter\XINT_keepunbr_a\the\numexpr #1.}% +\def\XINT_keepunbr_a #1% {% \xint_UDzerominusfork - #1-{\expandafter\space\xint_gobble_i }% - 0#1{\XINT_keep_bneg_a {#2}}% - 0-{\XINT_keepunbraced_bpos {#1#2}}% + #1-{\XINT_keep_keepnone }% + 0#1{\XINT_keep_neg }% + 0-{\XINT_keepunbr_pos #1}% \krof }% -\long\def\XINT_keepunbraced_bpos #1#2% +\long\def\XINT_keepunbr_pos #1.#2% {% - \XINT_keepunbraced_loop_a {#1}{}#2% - \xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_bye + \XINT_keepunbr_loop_a #1.% + {}#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_bye }% -\def\XINT_keepunbraced_loop_a #1% +\def\XINT_keepunbr_loop_a #1.% {% \ifnum #1>\xint_c_vi - \expandafter\XINT_keepunbraced_loop_b + \expandafter\XINT_keepunbr_loop_b \else - \XINT_keepunbraced_finish + \expandafter\XINT_keepunbr_finish \fi - {#1}% + #1.% }% -\long\def\XINT_keepunbraced_loop_b #1#2#3#4#5#6#7#8#9% +\long\def\XINT_keepunbr_loop_b #1.#2#3#4#5#6#7#8#9% {% - \xint_gob_til_xint_relax #9\XINT_keepunbraced_enda\xint_relax - \expandafter\XINT_keepunbraced_loop_c\expandafter - {\the\numexpr #1-\xint_c_vii}{#3}{#4}{#5}{#6}{#7}{#8}{#9}.{#2}% + \xint_gob_til_xint_relax #9\XINT_keepunbr_enda\xint_relax + \expandafter\XINT_keepunbr_loop_c\the\numexpr #1-\xint_c_vii.% + {#3}{#4}{#5}{#6}{#7}{#8}{#9}.{#2}% }% -\long\def\XINT_keepunbraced_loop_c #1#2#3#4#5#6#7#8.#9% - {\XINT_keepunbraced_loop_a {#1}{#9#2#3#4#5#6#7#8}}% -\long\def\XINT_keepunbraced_enda\xint_relax - \expandafter\XINT_keepunbraced_loop_c\expandafter #1#2.#3#4\xint_bye +\long\def\XINT_keepunbr_loop_c #1.#2#3#4#5#6#7#8.#9% + {\XINT_keepunbr_loop_a #1.{#9#2#3#4#5#6#7#8}}% +\long\def\XINT_keepunbr_enda #1.#2.#3#4\xint_bye {% - \XINT_keepunbraced_endb #4\W\W\W\W\W\W\Z #2{#3}% + \XINT_keepunbr_endb #4\W\W\W\W\W\W\Z #2{#3}% }% -\def\XINT_keepunbraced_endb #1#2#3#4#5#6#7\Z +\def\XINT_keepunbr_endb #1#2#3#4#5#6#7\Z {% \xint_gob_til_W - #1\XINT_keepunbraced_endc_ - #2\XINT_keepunbraced_endc_i - #3\XINT_keepunbraced_endc_ii - #4\XINT_keepunbraced_endc_iii - #5\XINT_keepunbraced_endc_iv - #6\XINT_keepunbraced_endc_v - \W\XINT_keepunbraced_endc_vi\Z -}% -\long\def\XINT_keepunbraced_endc_ #1\Z #2#3#4#5#6#7#8#9{ #9}% -\long\def\XINT_keepunbraced_endc_i #1\Z #2#3#4#5#6#7#8#9{ #9#2}% -\long\def\XINT_keepunbraced_endc_ii #1\Z #2#3#4#5#6#7#8#9{ #9#2#3}% -\long\def\XINT_keepunbraced_endc_iii #1\Z #2#3#4#5#6#7#8#9{ #9#2#3#4}% -\long\def\XINT_keepunbraced_endc_iv #1\Z #2#3#4#5#6#7#8#9{ #9#2#3#4#5}% -\long\def\XINT_keepunbraced_endc_v #1\Z #2#3#4#5#6#7#8#9{ #9#2#3#4#5#6}% -\long\def\XINT_keepunbraced_endc_vi\Z #1#2#3#4#5#6#7#8{ #8#1#2#3#4#5#6}% -\long\def\XINT_keepunbraced_finish\fi #1#2#3#4#5#6#7#8#9\xint_bye -{% - \fi\XINT_keepunbraced_finish_loop_a {#1}{}{#3}{#4}{#5}{#6}{#7}{#8}\Z {#2}% -}% -\def\XINT_keepunbraced_finish_loop_a #1% -{% - \xint_gob_til_zero #1\XINT_keepunbraced_finish_z0% - \expandafter\XINT_keepunbraced_finish_loop_b\expandafter - {\the\numexpr #1-\xint_c_i}% -}% -\long\def\XINT_keepunbraced_finish_z0% - \expandafter\XINT_keepunbraced_finish_loop_b\expandafter #1#2#3\Z #4{ #4#2}% -\long\def\XINT_keepunbraced_finish_loop_b #1#2#3% -{% - \xint_gob_til_xint_relax #3\XINT_keepunbraced_finish_exit\xint_relax - \XINT_keepunbraced_finish_loop_c {#1}{#2}{#3}% -}% -\long\def\XINT_keepunbraced_finish_exit\xint_relax - \XINT_keepunbraced_finish_loop_c #1#2#3\Z #4{ #4#2}% -\long\def\XINT_keepunbraced_finish_loop_c #1#2#3% - {\XINT_keepunbraced_finish_loop_a {#1}{#2#3}}% + #1\XINT_keepunbr_endc_ + #2\XINT_keepunbr_endc_i + #3\XINT_keepunbr_endc_ii + #4\XINT_keepunbr_endc_iii + #5\XINT_keepunbr_endc_iv + #6\XINT_keepunbr_endc_v + \W\XINT_keepunbr_endc_vi\Z +}% +\long\def\XINT_keepunbr_endc_ #1\Z #2#3#4#5#6#7#8#9{ #9}% +\long\def\XINT_keepunbr_endc_i #1\Z #2#3#4#5#6#7#8#9{ #9#2}% +\long\def\XINT_keepunbr_endc_ii #1\Z #2#3#4#5#6#7#8#9{ #9#2#3}% +\long\def\XINT_keepunbr_endc_iii #1\Z #2#3#4#5#6#7#8#9{ #9#2#3#4}% +\long\def\XINT_keepunbr_endc_iv #1\Z #2#3#4#5#6#7#8#9{ #9#2#3#4#5}% +\long\def\XINT_keepunbr_endc_v #1\Z #2#3#4#5#6#7#8#9{ #9#2#3#4#5#6}% +\long\def\XINT_keepunbr_endc_vi\Z #1#2#3#4#5#6#7#8{ #8#1#2#3#4#5#6}% +\long\def\XINT_keepunbr_finish #1.#2#3#4#5#6#7#8#9\xint_bye +{% + \XINT_keepunbr_finish_a #1.% + #3\xint_c_ #4\xint_c_i #5\xint_c_ii #6\xint_c_iii #7\xint_c_iv + #8\xint_c_v\xint_relax\xint_c_vi\xint_bye + {#3}{#4}{#5}{#6}{#7}{#8}\xint_bye {#2}% +}% +\long\def\XINT_keepunbr_finish_a #1.#2\xint_relax #3#4\xint_bye +{% + \csname XINT_keepunbr_finish_b\romannumeral\ifnum#1>#3#3\else#1\fi\endcsname +}% +\long\def\XINT_keepunbr_finish_b #1\xint_bye #2{ #2}% +\long\def\XINT_keepunbr_finish_bi #1#2\xint_bye #3{ #3#1}% +\long\def\XINT_keepunbr_finish_bii #1#2#3\xint_bye #4{ #4#1#2}% +\long\def\XINT_keepunbr_finish_biii#1#2#3#4\xint_bye #5{ #5#1#2#3}% +\long\def\XINT_keepunbr_finish_biv #1#2#3#4#5\xint_bye #6{ #6#1#2#3#4}% +\long\def\XINT_keepunbr_finish_bv #1#2#3#4#5#6\xint_bye #7{ #7#1#2#3#4#5}% +\long\def\XINT_keepunbr_finish_bvi #1#2#3#4#5#6\xint_bye #7{ #7#1#2#3#4#5#6}% % \end{macrocode} % \subsection{\csh{xintTrim}} -% \lverb+First included in release 1.09m. +% \lverb?& +% +% First included in release 1.09m. % % \xintTrim {i}{stuff f-expanding to {a}{b}...{z}} (or `tokens' abcd...z) % returns (in two expansion steps) the sequence with the first i elements @@ -15538,103 +15775,117 @@ $1$ or $-1$. % With i = 0, the original (expanded) list is returned. % % With i<0, the last |i| items are suppressed. In that case the kept elements -% (coming form the tail) will be braced on output. With i>0, the fist |i| -% items are suppressed: the remaining ones are left as is. +% (coming form the head) will be braced on output. +% +% With i>0, the fist |i| items are suppressed: the remaining ones are left as +% is with no added brace pairs. % % With |i| equal to or bigger than the length of the (f-expanded) list, -% the empty list is returned.+ +% the empty list is returned. +% +% Cosmetic code improvements (which naturally did cost me time, nothing is +% easy with TeX) for 1.2g to speed up some aspects of token processing. +% ? % \begin{macrocode} \def\xintTrim {\romannumeral0\xinttrim }% \def\xintTrimNoExpand {\romannumeral0\xinttrimnoexpand }% -\def\xinttrim #1#2% -{% - \expandafter\XINT_trim_a\the\numexpr #1\expandafter.% - \expandafter{\romannumeral`&&@#2}% -}% -\def\xinttrimnoexpand #1% -{% - \expandafter\XINT_trim_a\the\numexpr #1.% -}% -\def\XINT_trim_a #1#2.% +\long\def\xinttrim #1#2{\expandafter\XINT_trim_a\the\numexpr #1\expandafter.% + \expandafter{\romannumeral`&&@#2}}% +\def\xinttrimnoexpand #1{\expandafter\XINT_trim_a\the\numexpr #1.}% +\def\XINT_trim_a #1% {% \xint_UDzerominusfork - #1-{\xint_firstofone_thenstop }% - 0#1{\XINT_trim_bneg_a {#2}}% - 0-{\XINT_trim_bpos {#1#2}}% + #1-{\XINT_trim_trimnone }% + 0#1{\XINT_trim_neg }% + 0-{\XINT_trim_pos #1}% \krof }% -\long\def\XINT_trim_bneg_a #1#2% +\long\def\XINT_trim_trimnone .#1{ #1}% +\long\def\XINT_trim_neg #1.#2% {% - \expandafter\XINT_trim_bneg_b \the\numexpr \xintLength{#2}-#1.{#2}% + \expandafter\XINT_trim_neg_a\the\numexpr + \XINT_length_loop + 0.#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye -#1.% + {}#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_bye }% -\def\XINT_trim_bneg_b #1#2.% +\def\XINT_trim_neg_a #1% {% \xint_UDzerominusfork - #1-{\expandafter\space\xint_gobble_i }% - 0#1{\expandafter\space\xint_gobble_i }% - 0-{\XINT_keep_bpos {#1#2}}% + #1-{\XINT_trim_trimall }% + 0#1{\XINT_trim_trimall }% + 0-{\XINT_keep_loop_a #1}% \krof }% -\long\def\XINT_trim_bpos #1#2% +\long\def\XINT_trim_trimall #1\xint_bye { }% +\long\def\XINT_trim_pos #1.#2% {% - \XINT_trim_loop_a {#1}#2\xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye + \XINT_trim_loop_a #1.% + #2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye }% -\def\XINT_trim_loop_a #1% +\def\XINT_trim_loop_a #1.% {% \ifnum #1>\xint_c_vii \expandafter\XINT_trim_loop_b \else - \XINT_trim_finish + \expandafter\XINT_trim_finish \fi - {#1}% + #1.% }% -\long\def\XINT_trim_loop_b #1#2#3#4#5#6#7#8#9% +\long\def\XINT_trim_loop_b #1.#2#3#4#5#6#7#8#9% {% \xint_gob_til_xint_relax #9\XINT_trim_silentend\xint_relax - \expandafter\XINT_trim_loop_a\expandafter{\the\numexpr #1-\xint_c_viii}% + \expandafter\XINT_trim_loop_a\the\numexpr #1-\xint_c_viii.% }% \def\XINT_trim_silentend #1\xint_bye { }% -\def\XINT_trim_finish\fi #1% +\def\XINT_trim_finish #1.% {% - \fi\expandafter\expandafter\expandafter\XINT_trim_finish_a + \expandafter\expandafter\expandafter\XINT_trim_finish_a \expandafter\expandafter\expandafter\space % avoids brace removal \csname xint_gobble_\romannumeral\numexpr#1\endcsname }% \long\def\XINT_trim_finish_a #1\xint_relax #2\xint_bye {#1}% % \end{macrocode} % \subsection{\csh{xintTrimUnbraced}} -% \lverb+1.2a+ +% \lverb?1.2a +% +% Missing long for \xinttrimunbraced added belatedly with 1.2g, which also +% modifies a bit the coding style, to match new versions of \xintKeep and +% \xintTrim. +% ? % \begin{macrocode} \def\xintTrimUnbraced {\romannumeral0\xinttrimunbraced }% \def\xintTrimUnbracedNoExpand {\romannumeral0\xinttrimunbracednoexpand }% -\def\xinttrimunbraced #1#2% -{% - \expandafter\XINT_trimunbraced_a\the\numexpr #1\expandafter.% - \expandafter{\romannumeral`&&@#2}% -}% +\long\def\xinttrimunbraced #1#2% + {\expandafter\XINT_trimunbr_a\the\numexpr #1\expandafter.% + \expandafter{\romannumeral`&&@#2}}% \def\xinttrimunbracednoexpand #1% -{% - \expandafter\XINT_trimunbraced_a\the\numexpr #1.% -}% -\def\XINT_trimunbraced_a #1#2.% + {\expandafter\XINT_trimunbr_a\the\numexpr #1.}% +\def\XINT_trimunbr_a #1% {% \xint_UDzerominusfork - #1-{\xint_firstofone_thenstop }% - 0#1{\XINT_trimunbraced_bneg_a {#2}}% - 0-{\XINT_trim_bpos {#1#2}}% + #1-{\XINT_trim_trimnone }% + 0#1{\XINT_trimunbr_neg }% + 0-{\XINT_trim_pos #1}% \krof }% -\long\def\XINT_trimunbraced_bneg_a #1#2% +\long\def\XINT_trimunbr_neg #1.#2% {% - \expandafter\XINT_trimunbraced_bneg_b \the\numexpr \xintLength{#2}-#1.{#2}% + \expandafter\XINT_trimunbr_neg_a\the\numexpr + \XINT_length_loop + 0.#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye -#1.% + {}#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_bye }% -\def\XINT_trimunbraced_bneg_b #1#2.% +\def\XINT_trimunbr_neg_a #1% {% \xint_UDzerominusfork - #1-{\expandafter\space\xint_gobble_i }% - 0#1{\expandafter\space\xint_gobble_i }% - 0-{\XINT_keepunbraced_bpos {#1#2}}% + #1-{\XINT_trim_trimall }% + 0#1{\XINT_trim_trimall }% + 0-{\XINT_keepunbr_loop_a #1}% \krof }% % \end{macrocode} @@ -16365,6 +16616,311 @@ $1$ or $-1$. }% }% \let\xintDigitsOf\xintAssignArray +% \end{macrocode} +%\subsection{CSV (non user documented) variants of Trim, Keep, NthElt, Reverse, Length} +% +% These routines are for use by |\xintListSel:f:csv| from \xintexprnameimp. We +% don't take any precaution here regarding brace stripping or spaces. And the +% macros are short. They will remain undocumented in the user manual for the +% time being for the reasons above and to preserve the possibility to modify +% the interface in case some evolution on the \xintexprnameimp side requires +% it. +% +% Nevertheless, directly usable names are also provided. +% +% All these macros are in the |O(N^2)| style when they need to accumulate +% things. They handle comma separated values. There is no final comma, neither +% on input nor on output. Special care has been taken to handle safely the +% case of an empty list. +% +%\subsubsection{\csh{xintTrim:f:csv}} +% \lverb|1.2g 2016/03/17. +% +%| +% \begin{macrocode} +\def\xintTrim:f:csv {\romannumeral0\xinttrim:f:csv }% +\def\xinttrim:f:csv #1#2% +{% + \expandafter\XINT_trim:f:csv_a\the\numexpr #1\expandafter.% + \romannumeral`&&@#2\xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye +}% +\def\XINT_trim:f:csv_a #1% +{% + \xint_UDzerominusfork + #1-{\XINT_trim:f:csv_zero }% + 0#1{\XINT_trim:f:csv_neg }% + 0-{\XINT_trim:f:csv_loop_a #1}% + \krof +}% +\def\XINT_trim:f:csv_zero .#1\xint_relax #2\xint_bye{ #1}% +\def\XINT_trim:f:csv_neg #1.#2\xint_relax% +{% + \expandafter\XINT_trim:f:csv_neg_b + \the\numexpr\expandafter\XINT_length:f:csv_a\romannumeral`&&@#2% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye + -#1.#2\xint_relax +}% +\def\XINT_trim:f:csv_neg_b #1% +{% + \xint_UDzerominusfork + #1-{\expandafter\space\xint_bye }% + 0#1{\expandafter\space\xint_bye }% + 0-{\XINT_keep:f:csv_pos #1}% + \krof +}% +\def\XINT_trim:f:csv_loop_a #1.% +{% + \ifnum #1>\xint_c_vii + \expandafter\XINT_trim:f:csv_loop_b + \else + \expandafter\XINT_trim:f:csv_finish + \fi + #1.% +}% +\def\XINT_trim:f:csv_loop_b #1.#2,#3,#4,#5,#6,#7,#8,#9,% +{% + \xint_gob_til_xint_relax #9\XINT_trim:f:csv_silentend\xint_relax + \expandafter\XINT_trim:f:csv_loop_a\the\numexpr #1-\xint_c_viii.% +}% +\def\XINT_trim:f:csv_silentend #1\xint_bye { }% +\def\XINT_trim:f:csv_finish #1.% +{% + \expandafter\XINT_trim:f:csv_finish_a + \romannumeral`&&@\csname xint_gobble:csv_\romannumeral\numexpr#1\endcsname +}% +\def\xint_gobble:csv_ {}% +\def\xint_gobble:csv_i #1,{}% +\def\xint_gobble:csv_ii #1,#2,{}% +\def\xint_gobble:csv_iii #1,#2,#3,{}% +\def\xint_gobble:csv_iv #1,#2,#3,#4,{}% +\def\xint_gobble:csv_v #1,#2,#3,#4,#5,{}% +\def\xint_gobble:csv_vi #1,#2,#3,#4,#5,#6,{}% +\def\xint_gobble:csv_vii #1,#2,#3,#4,#5,#6,#7,{}% +\def\XINT_trim:f:csv_finish_a #1\xint_relax #2\xint_bye { #1}% +% \end{macrocode} +%\subsubsection{\csh{xintKeep:f:csv}} +% \lverb|1.2g 2016/03/17. +%| +% \begin{macrocode} +\def\xintKeep:f:csv {\romannumeral0\xintkeep:f:csv }% +\def\xintkeep:f:csv #1#2% +{% + \expandafter\XINT_keep:f:csv_a\the\numexpr #1\expandafter.% + \romannumeral`&&@#2\xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye +}% +\def\XINT_keep:f:csv_a #1% +{% + \xint_UDzerominusfork + #1-{\XINT_keep:f:csv_zero }% + 0#1{\XINT_keep:f:csv_neg }% + 0-{\XINT_keep:f:csv_pos #1}% + \krof +}% +\def\XINT_keep:f:csv_zero .#1\xint_bye{ }% +\def\XINT_keep:f:csv_neg #1.#2\xint_relax% +{% + \expandafter\XINT_keep:f:csv_neg_b + \the\numexpr\expandafter\XINT_length:f:csv_a\romannumeral`&&@#2% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye + -#1.#2\xint_relax +}% +\def\XINT_keep:f:csv_neg_b #1% +{% + \xint_UDzerominusfork + #1-{\XINT_keep:f:csv_all }% + 0#1{\XINT_keep:f:csv_all }% + 0-{\XINT_trim:f:csv_loop_a #1}% + \krof +}% +\def\XINT_keep:f:csv_all #1.#2\xint_relax #3\xint_bye { #2}% +\def\XINT_keep:f:csv_pos #1.{\expandafter\xint_gobble_thenstop + \romannumeral`&&@\XINT_keep:f:csv_loop_a #1.{}}% +\def\XINT_keep:f:csv_loop_a #1.% +{% + \ifnum #1>\xint_c_vi + \expandafter\XINT_keep:f:csv_loop_b + \else + \expandafter\XINT_keep:f:csv_finish + \fi + #1.% +}% +\def\XINT_keep:f:csv_loop_b #1.#2#3,#4,#5,#6,#7,#8,#9,% +{% + \xint_gob_til_xint_relax #9\XINT_keep:f:csv_enda\xint_relax + \expandafter\XINT_keep:f:csv_loop_c\the\numexpr #1-\xint_c_vii.% + {,#3,#4,#5,#6,#7,#8,#9}{#2}% +}% +\def\XINT_keep:f:csv_loop_c #1.#2#3{\XINT_keep:f:csv_loop_a #1.{#3#2}}% +\def\XINT_keep:f:csv_enda #1.#2#3#4\xint_bye +{% + \XINT_keep:f:csv_endb #2\xint_bye {#3}% +}% +\def\XINT_keep:f:csv_endb #1\xint_relax #2\xint_bye #3{ #3#1}% +\def\XINT_keep:f:csv_finish #1.#2#3,#4,#5,#6,#7,#8,#9\xint_bye +{% + \csname XINT_keep:f:csv_finish_\romannumeral#1\endcsname + ,#3,#4,#5,#6,#7,#8,\Z {#2}% +}% +\def\XINT_keep:f:csv_finish_ #1\Z #2{#2}% +\def\XINT_keep:f:csv_finish_i ,#1,#2\Z + {\XINT_keep:f:csv_finish_f ,#1\xint_relax\Z}% +\def\XINT_keep:f:csv_finish_ii ,#1,#2,#3\Z + {\XINT_keep:f:csv_finish_f ,#1,#2\xint_relax\Z}% +\def\XINT_keep:f:csv_finish_iii ,#1,#2,#3,#4\Z + {\XINT_keep:f:csv_finish_f ,#1,#2,#3\xint_relax\Z}% +\def\XINT_keep:f:csv_finish_iv ,#1,#2,#3,#4,#5\Z + {\XINT_keep:f:csv_finish_f ,#1,#2,#3,#4\xint_relax\Z}% +\def\XINT_keep:f:csv_finish_v ,#1,#2,#3,#4,#5,#6\Z + {\XINT_keep:f:csv_finish_f ,#1,#2,#3,#4,#5\xint_relax\Z}% +\def\XINT_keep:f:csv_finish_vi ,#1,#2,#3,#4,#5,#6,#7\Z + {\XINT_keep:f:csv_finish_f ,#1,#2,#3,#4,#5,#6\xint_relax\Z}% +\def\XINT_keep:f:csv_finish_f #1\xint_relax #2\Z #3{#3#1}% +% \end{macrocode} +% \subsubsection{\csh{xintNthEltPy:f:csv}} +% \lverb|1.2g. 2016/03/17. Counts like Python starting at zero. +% | +% \begin{macrocode} +\def\xintNthEltPy:f:csv {\romannumeral0\xintntheltpy:f:csv }% +\def\xintntheltpy:f:csv #1{\expandafter\XINT_ntheltpy:f:csv\the\numexpr #1.}% +\def\XINT_ntheltpy:f:csv #1% +{% + \xint_UDsignfork + #1{\XINT_nthelt:f:csv_neg }% + -{\XINT_nthelt:f:csv_pos #1}% + \krof +}% +\long\def\XINT_nthelt:f:csv_neg #1.#2% +{% + \expandafter\XINT_nthelt:f:csv_neg_a + \the\numexpr\expandafter\XINT_length:f:csv_a\romannumeral`&&@#2% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye + -#1+\xint_c_i\expandafter.\romannumeral`&&@#2% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye +}% +\def\XINT_nthelt:f:csv_neg_a #1% +{% + \xint_UDzerominusfork + #1-{\XINT_nthelt:f:csv_none }% + 0#1{\XINT_nthelt:f:csv_none }% + 0-{\XINT_nthelt:f:csv_loop_a #1}% + \krof +}% +\def\XINT_nthelt:f:csv_none #1\xint_bye { }% +\long\def\XINT_nthelt:f:csv_pos #1.#2% +{% + \expandafter\XINT_nthelt:f:csv_loop_a\the\numexpr #1+\xint_c_i\expandafter.% + \romannumeral`&&@#2% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye +}% +\def\XINT_nthelt:f:csv_loop_a #1.% +{% + \ifnum #1>\xint_c_viii + \expandafter\XINT_nthelt:f:csv_loop_b + \else + \expandafter\XINT_nthelt:f:csv_getit + \fi #1.% +}% +\long\def\XINT_nthelt:f:csv_loop_b #1.#2,#3,#4,#5,#6,#7,#8,#9,% +{% + \xint_gob_til_xint_relax #9\XINT_nthelt:f:csv_none\xint_relax + \expandafter\XINT_nthelt:f:csv_loop_a\the\numexpr #1-\xint_c_viii.% +}% +\def\XINT_nthelt:f:csv_getit #1.% +{% + \expandafter\XINT_nthelt:f:csv_finish + \romannumeral`&&@\csname xint_gobble:csv_\romannumeral + \numexpr#1-\xint_c_i\endcsname +}% +\def\XINT_nthelt:f:csv_finish #1,#2\xint_bye +{% + \XINT_nthelt:f:csv_finishb #1\xint_relax\xint_bye +}% +\def\XINT_nthelt:f:csv_finishb #1\xint_relax #2\xint_bye { #1}% +% \end{macrocode} +% \subsubsection{\csh{xintReverse:f:csv}} +% \lverb|1.2g. Contrarily to \xintReverseOrder from xintkernel.sty, this +% one expands its argument. Handles empty list too. 2016/03/17. +% | +% \begin{macrocode} +\def\xintReverse:f:csv {\romannumeral0\xintreverse:f:csv }% +\def\xintreverse:f:csv #1% +{% + \expandafter\XINT_reverse:f:csv_loop + \expandafter{\expandafter}\romannumeral`&&@#1,% + \xint_relax,% + \xint_bye,\xint_bye,\xint_bye,\xint_bye,% + \xint_bye,\xint_bye,\xint_bye,\xint_bye,% + \xint_relax +}% +\def\XINT_reverse:f:csv_loop #1#2,#3,#4,#5,#6,#7,#8,#9,% +{% + \xint_bye #9\XINT_reverse:f:csv_cleanup\xint_bye + \XINT_reverse:f:csv_loop {,#9,#8,#7,#6,#5,#4,#3,#2#1}% +}% +\def\XINT_reverse:f:csv_cleanup\xint_bye\XINT_reverse:f:csv_loop #1#2\xint_relax +{% + \XINT_reverse:f:csv_finish #1% +}% +\def\XINT_reverse:f:csv_finish #1\xint_relax,{ }% +% \end{macrocode} +% \subsubsection{\csh{xintLength:f:csv}} +% \lverb|1.2g. Contrarily to ancestor \xintLength from xintkernel.sty, this +% one expands its argument. 2016/03/17. +% | +% \begin{macrocode} +\def\xintLength:f:csv {\romannumeral0\xintlength:f:csv }% +\def\xintlength:f:csv #1% +{% + \expandafter\XINT_length:f:csv_a + \romannumeral`&&@#1\xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye +}% +\def\XINT_length:f:csv_a #1% +{% + \xint_gob_til_xint_relax #1\XINT_length:f:csv_empty\xint_relax + \XINT_length:f:csv_loop 0.#1% +}% +\def\XINT_length:f:csv_empty #1\xint_bye { 0}% +\def\XINT_length:f:csv_loop #1.#2,#3,#4,#5,#6,#7,#8,#9,% +{% + \xint_gob_til_xint_relax #9\XINT_length:f:csv_finish_a\xint_relax + \expandafter\XINT_length:f:csv_loop\the\numexpr #1+\xint_c_viii.% +}% +\def\XINT_length:f:csv_finish_a\xint_relax + \expandafter\XINT_length:f:csv_loop\the\numexpr #1+\xint_c_viii.#2\xint_bye +{% + \XINT_length:f:csv_finish_b #2\W,\W,\W,\W,\W,\W,\W,\Z {#1}% +}% +\def\XINT_length:f:csv_finish_b #1,#2,#3,#4,#5,#6,#7,#8\Z +{% + \xint_gob_til_W + #1\XINT_length:f:csv_finish_c \xint_c_i + #2\XINT_length:f:csv_finish_c \xint_c_ii + #3\XINT_length:f:csv_finish_c \xint_c_iii + #4\XINT_length:f:csv_finish_c \xint_c_iv + #5\XINT_length:f:csv_finish_c \xint_c_v + #6\XINT_length:f:csv_finish_c \xint_c_vi + #7\XINT_length:f:csv_finish_c \xint_c_vii + \W\XINT_length:f:csv_finish_c \xint_c_viii\Z +}% +\edef\XINT_length:f:csv_finish_c #1#2\Z #3% + {\noexpand\expandafter\space\noexpand\the\numexpr #3+#1\relax}% +% \end{macrocode} +% \subsubsection{Public names for the undocumented csv macros} +% \lverb|1.2g. 2016/03/17.| +% \begin{macrocode} +\let\xintCSVTrim \xintTrim:f:csv +\let\xintCSVKeep \xintKeep:f:csv +\let\xintCSVNthEltPy \xintNthEltPy:f:csv +\let\xintCSVReverse \xintReverse:f:csv +\let\xintCSVLength \xintLength:f:csv \let\XINT_tmpa\relax \let\XINT_tmpb\relax \let\XINT_tmpc\relax \XINT_restorecatcodes_endinput% % \end{macrocode} @@ -16457,7 +17013,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintcore}% - [2016/03/12 1.2f Expandable arithmetic on big integers (JFB)]% + [2016/03/19 1.2g Expandable arithmetic on big integers (JFB)]% % \end{macrocode} % \subsection{Counts for holding needed constants} % \begin{macrocode} @@ -16809,7 +17365,7 @@ $1$ or $-1$. \def\XINT_reversedigits #1% {% \xint_UDsignfork - #1{\expandafter\xint_minus_thenstop\romannumeral0\XINT_reversedigits_a}% + #1{\expandafter-\romannumeral0\XINT_reversedigits_a}% -{\XINT_reversedigits_a #1}% \krof }% @@ -16851,7 +17407,7 @@ $1$ or $-1$. {% \xint_UDzerominusfork #1-{ 0}% - 0#1{ -1}% + 0#1{-1}% 0-{ 1}% \krof }% @@ -16973,7 +17529,7 @@ $1$ or $-1$. }% \def\XINT_dbl_zero #1\Z { 0}% \def\XINT_dbl_neg - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_dbl_pos }% + {\expandafter-\romannumeral0\XINT_dbl_pos }% \def\XINT_dbl_pos #1\Z {% \expandafter\XINT_dbl_pos_aa @@ -17044,9 +17600,9 @@ $1$ or $-1$. 0-{\XINT_dec_pos #1}% \krof }% -\def\XINT_dec_zero #1\Z { -1}% +\def\XINT_dec_zero #1\Z {-1}% \def\XINT_dec_neg - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_inc_pos }% + {\expandafter-\romannumeral0\XINT_inc_pos }% \def\XINT_dec_pos #1\Z {% \expandafter\XINT_dec_pos_aa @@ -17137,7 +17693,7 @@ $1$ or $-1$. \def\XINT_add_firstiszero #1\krof 0#2#3\Z #4\Z { #2#3}% \def\XINT_add_secondiszero #1\krof #20#3\Z #4\Z { #2#4}% \def\XINT_add_minusminus #1#2% - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_add_pp_a {}{}}% + {\expandafter-\romannumeral0\XINT_add_pp_a {}{}}% \def\XINT_add_minusplus #1#2{\XINT_sub_mm_a {}#2}% \def\XINT_add_plusminus #1#2% {\expandafter\XINT_opp\romannumeral0\XINT_sub_mm_a #1{}}% @@ -17317,7 +17873,7 @@ $1$ or $-1$. \def\XINT_sub_plusplus #1#2% {\expandafter\XINT_opp\romannumeral0\XINT_sub_mm_a #1#2}% \def\XINT_sub_minusplus #1#2% - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_add_pp_a {}#2}% + {\expandafter-\romannumeral0\XINT_add_pp_a {}#2}% \def\XINT_sub_minusminus #1#2{\XINT_sub_mm_a {}{}}% \def\XINT_sub_mm_a #1#2#3\Z {% @@ -17623,9 +18179,9 @@ $1$ or $-1$. \def\XINT_mul_zero #1\krof #2#3\Z #4\Z { 0}% \def\XINT_mul_minusminus #1#2{\XINT_mul_plusplus {}{}}% \def\XINT_mul_minusplus #1#2% - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_mul_plusplus {}#2}% + {\expandafter-\romannumeral0\XINT_mul_plusplus {}#2}% \def\XINT_mul_plusminus #1#2% - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_mul_plusplus #1{}}% + {\expandafter-\romannumeral0\XINT_mul_plusplus #1{}}% \def\XINT_mul_plusplus #1#2#3\Z {% \expandafter\XINT_mul_pre_b @@ -19344,7 +19900,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xint}% - [2016/03/12 1.2f Expandable operations on big integers (JFB)]% + [2016/03/19 1.2g Expandable operations on big integers (JFB)]% % \end{macrocode} % \subsection{More token management} % \begin{macrocode} @@ -19373,24 +19929,22 @@ $1$ or $-1$. }% % \end{macrocode} % \subsection{\csh{xintIsOne}, \csh{xintiiIsOne}} -% \lverb|Added in 1.03. 1.09a defines \xintIsOne. 1.1a adds \xintiiIsOne.| +% \lverb|Added in 1.03. 1.09a defines \xintIsOne. 1.1a adds \xintiiIsOne. +% +% \XINT_isOne rewritten for 1.2g. Works with expanded strict integers, +% positive or negative.| % \begin{macrocode} \def\xintiiIsOne {\romannumeral0\xintiiisone }% -\def\xintiiisone #1{\expandafter\XINT_isone\romannumeral`&&@#1\W\Z }% +\def\xintiiisone #1{\expandafter\XINT_isone\romannumeral`&&@#1XY}% \def\xintIsOne {\romannumeral0\xintisone }% -\def\xintisone #1{\expandafter\XINT_isone\romannumeral0\xintnum{#1}\W\Z }% -\def\XINT_isOne #1{\romannumeral0\XINT_isone #1\W\Z }% -\def\XINT_isone #1#2% -{% - \xint_gob_til_one #1\XINT_isone_b 1% - \expandafter\space\expandafter 0\xint_gob_til_Z #2% -}% -\def\XINT_isone_b #1\xint_gob_til_Z #2% +\def\xintisone #1{\expandafter\XINT_isone\romannumeral0\xintnum{#1}XY}% +\def\XINT_isOne #1{\romannumeral0\XINT_isone #1XY}% +\def\XINT_isone #1#2#3Y% {% - \xint_gob_til_W #2\XINT_isone_yes \W - \expandafter\space\expandafter 0\xint_gob_til_Z + \unless\if#2X\xint_dothis{ 0}\fi + \unless\if#11\xint_dothis{ 0}\fi + \xint_orthat{ 1}% }% -\def\XINT_isone_yes #1\Z { 1}% % \end{macrocode} % \subsection{\csh{xintRev}} % \lverb|& @@ -21640,7 +22194,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintbinhex}% - [2016/03/12 1.2f Expandable binary and hexadecimal conversions (JFB)]% + [2016/03/19 1.2g Expandable binary and hexadecimal conversions (JFB)]% % \end{macrocode} % \subsection{Constants, etc...} % \lverb!1.08! @@ -21789,7 +22343,7 @@ $1$ or $-1$. -{\XINT_dth_P #1}% \krof }% -\def\XINT_dth_N {\expandafter\xint_minus_thenstop\romannumeral0\XINT_dth_P }% +\def\XINT_dth_N {\expandafter-\romannumeral0\XINT_dth_P }% \def\XINT_dth_P {\expandafter\XINT_dth_III\romannumeral`&&@\XINT_dtbh_I {0.}}% \def\xintDecToBin {\romannumeral0\xintdectobin }% \def\xintdectobin #1% @@ -21801,7 +22355,7 @@ $1$ or $-1$. -{\XINT_dtb_P #1}% \krof }% -\def\XINT_dtb_N {\expandafter\xint_minus_thenstop\romannumeral0\XINT_dtb_P }% +\def\XINT_dtb_N {\expandafter-\romannumeral0\XINT_dtb_P }% \def\XINT_dtb_P {\expandafter\XINT_dtb_III\romannumeral`&&@\XINT_dtbh_I {0.}}% \def\XINT_dtbh_I #1#2#3#4#5% {% @@ -21941,8 +22495,7 @@ $1$ or $-1$. -{\XINT_htd_I {0000}#1}% \krof }% -\def\XINT_htd_neg {\expandafter\xint_minus_thenstop - \romannumeral0\XINT_htd_I {0000}}% +\def\XINT_htd_neg {\expandafter-\romannumeral0\XINT_htd_I {0000}}% \def\XINT_htd_I #1#2#3#4#5% {% \xint_gob_til_W #5\XINT_htd_II_a\W @@ -22029,8 +22582,7 @@ $1$ or $-1$. -{\XINT_btd_I {000000}#1}% \krof }% -\def\XINT_btd_neg {\expandafter\xint_minus_thenstop - \romannumeral0\XINT_btd_I {000000}}% +\def\XINT_btd_neg {\expandafter-\romannumeral0\XINT_btd_I {000000}}% \def\XINT_btd_I #1#2#3#4#5#6#7#8#9% {% \xint_gob_til_W #9\XINT_btd_II_a {#2#3#4#5#6#7#8#9}\W @@ -22145,7 +22697,7 @@ $1$ or $-1$. -{\XINT_bth_P #1}% \krof }% -\def\XINT_bth_N {\expandafter\xint_minus_thenstop\romannumeral0\XINT_bth_P }% +\def\XINT_bth_N {\expandafter-\romannumeral0\XINT_bth_P }% \def\XINT_bth_P {\expandafter\XINT_bth_I\expandafter{\expandafter}% \romannumeral0\XINT_OQ {}}% \def\XINT_bth_I #1#2#3#4#5#6#7#8#9% @@ -22183,7 +22735,7 @@ $1$ or $-1$. -{\XINT_htb_P #1}% \krof }% -\def\XINT_htb_N {\expandafter\xint_minus_thenstop\romannumeral0\XINT_htb_P }% +\def\XINT_htb_N {\expandafter-\romannumeral0\XINT_htb_P }% \def\XINT_htb_P {\XINT_htb_I_a {}}% \def\XINT_htb_I_a #1#2#3#4#5#6#7#8#9% {% @@ -22228,7 +22780,7 @@ $1$ or $-1$. -{\XINT_chtb_P #1}% \krof }% -\def\XINT_chtb_N {\expandafter\xint_minus_thenstop\romannumeral0\XINT_chtb_P }% +\def\XINT_chtb_N {\expandafter-\romannumeral0\XINT_chtb_P }% \def\XINT_chtb_P {\expandafter\XINT_chtb_I\expandafter{\expandafter}% \romannumeral0\XINT_OQ {}}% \def\XINT_chtb_I #1#2#3#4#5#6#7#8#9% @@ -22342,7 +22894,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintgcd}% - [2016/03/12 1.2f Euclide algorithm with xint package (JFB)]% + [2016/03/19 1.2g Euclide algorithm with xint package (JFB)]% % \end{macrocode} % \subsection{\csh{xintGCD}, \csh{xintiiGCD}} % \begin{macrocode} @@ -23029,7 +23581,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintfrac}% - [2016/03/12 1.2f Expandable operations on fractions (JFB)]% + [2016/03/19 1.2g 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 @@ -23203,7 +23755,7 @@ $1$ or $-1$. }% % \end{macrocode} % \lverb|An empty [] is not allowed. (this was authorized in 1.2, removed in -% 1.2f). As nobody reads xint documentation, noone will have noticed the +% 1.2f). As nobody reads xint documentation, no one will have noticed the % fleeting possibility.| % \begin{macrocode} \def\XINT_infrac_res_ca #1[#2]/\XINT_W[\XINT_W\XINT_T @@ -23703,7 +24255,7 @@ $1$ or $-1$. }% \def\XINT_sgnfrac_N {% - \expandafter\xint_minus_thenstop\romannumeral0\XINT_sgnfrac_P + \expandafter-\romannumeral0\XINT_sgnfrac_P }% % \end{macrocode} % \subsection{\csh{xintFwOver}} @@ -23757,7 +24309,7 @@ $1$ or $-1$. }% \def\XINT_sgnfwover_N {% - \expandafter\xint_minus_thenstop\romannumeral0\XINT_sgnfwover_P + \expandafter-\romannumeral0\XINT_sgnfwover_P }% % \end{macrocode} % \subsection{\csh{xintREZ}} @@ -23781,7 +24333,7 @@ $1$ or $-1$. \krof }% \def\XINT_rez_zero #1\Z #2#3{ 0/1[0]}% -\def\XINT_rez_neg {\expandafter\xint_minus_thenstop\romannumeral0\XINT_rez_B }% +\def\XINT_rez_neg {\expandafter-\romannumeral0\XINT_rez_B }% \def\XINT_rez_B #1\Z {% \expandafter\XINT_rez_C\romannumeral0\XINT_factortens {#1}% @@ -23835,7 +24387,7 @@ $1$ or $-1$. #2\Z {#3}% }% \def\XINT_irr_denomisone #1\Z #2{ #1/1}% changed in 1.08 -\def\XINT_irr_negative #1\Z #2{\XINT_irr_D #1\Z #2\Z \xint_minus_thenstop}% +\def\XINT_irr_negative #1\Z #2{\XINT_irr_D #1\Z #2\Z -}% \def\XINT_irr_nonneg #1\Z #2{\XINT_irr_D #1\Z #2\Z \space}% \def\XINT_irr_D #1#2\Z #3#4\Z {% @@ -23908,7 +24460,7 @@ $1$ or $-1$. #2\Z {#3}% }% \def\XINT_jrr_denomisone #1\Z #2{ #1/1}% changed in 1.08 -\def\XINT_jrr_negative #1\Z #2{\XINT_jrr_D #1\Z #2\Z \xint_minus_thenstop }% +\def\XINT_jrr_negative #1\Z #2{\XINT_jrr_D #1\Z #2\Z -}% \def\XINT_jrr_nonneg #1\Z #2{\XINT_jrr_D #1\Z #2\Z \space}% \def\XINT_jrr_D #1#2\Z #3#4\Z {% @@ -24039,7 +24591,7 @@ $1$ or $-1$. \krof }% \def\XINT_trunc_Fneg #1.#2{\expandafter\xint_firstoftwo_thenstop - \romannumeral0\XINT_div_prepare {#2}{#1}\Z \xint_minus_thenstop}% + \romannumeral0\XINT_div_prepare {#2}{#1}\Z -}% \def\XINT_trunc_Fpos #1.#2{\expandafter\xint_firstoftwo_thenstop \romannumeral0\XINT_div_prepare {#2}{#1}\Z \space }% \def\XINT_itrunc_G #1#2\Z #3#4% @@ -24916,7 +25468,7 @@ $1$ or $-1$. #1#5{#2/#3[#4]}{#6/#7[#8]}% }% \def\XINT_fmax_minusminus --% - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_fmin_nonneg_b }% + {\expandafter-\romannumeral0\XINT_fmin_nonneg_b }% \def\XINT_fmax_firstneg #1-#2#3{ #1#2}% \def\XINT_fmax_secondneg -#1#2#3{ #1#3}% \def\XINT_fmax_nonneg_a #1#2#3#4% @@ -24966,7 +25518,7 @@ $1$ or $-1$. #1#5{#2/#3[#4]}{#6/#7[#8]}% }% \def\XINT_fmin_minusminus --% - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_fmax_nonneg_b }% + {\expandafter-\romannumeral0\XINT_fmax_nonneg_b }% \def\XINT_fmin_firstneg #1-#2#3{ -#3}% \def\XINT_fmin_secondneg -#1#2#3{ -#2}% \def\XINT_fmin_nonneg_a #1#2#3#4% @@ -25098,7 +25650,7 @@ $1$ or $-1$. % |1.2f| added \csh{xintFloatPFactorial} and \csh{xintFloatBinomial} and % improved the speed of |\xintFloatPow| and |\xintFloatPower|. And its % |\xintFloat| tries to be more efficient in handling inputs which are not -% fractions to start with. +% fractions to start with. (this has been improved again in |1.2g|) % % But some parts of the code in |\xintFloat| are still in the pre-|1.2| style % and could be improved, anyhow in the future quite probably \xintfracnameimp @@ -25120,9 +25672,6 @@ $1$ or $-1$. % But already |1.2f| has changed an important aspect: the four operations % first round their arguments to P-floats, not (P+2)-floats as earlier. % -% -% -% % \subsection{\csh{xintFloat}} % \lverb|1.07. May 2013. The original macro did the exact rounding of the input % fraction to P digits of float precision. @@ -25159,7 +25708,7 @@ $1$ or $-1$. % % 1.2f did some minor improvements to the code, there was in particular a % never-used branch. And it tries to handle more swiftly the case of inputs -% which are not fractions. +% which are not fractions. (improved again in 1.2g) % % This routine uses old macros \XINT_addm_a and \XINT_lenrord_loop. This could % now be penalizing for P exceeding a few dozens, compared to doing it the 1.2 @@ -25167,16 +25716,25 @@ $1$ or $-1$. % % I have always hesitated about the policy of printing 10.00...0 in case of % rounding upwards towards next power of ten. It does make sense because it -% tells the (higher) precision of the rounding and moreover it is not to hard -% easy to test on output, although it is a bit cumbersome not to be certain to -% have exactly P digits. -% -% New: since 1.2f \XINTinFloat (which is the variant of \xintFloat used by -% float macros when they need to round their input or round some pre-final -% result) always guarantees that A exactly has P digits. This simplifies -% things; and goes hand in hand with the fact that I have decided float macros -% should not aim like MPFR at correct rounding from the exact inputs, but only -% from inputs rounded to target precision P. +% tells the (higher) precision of the rounding and moreover it is not too hard +% to test on output, although it is a bit cumbersome not to be certain to have +% exactly P digits. +% +% Since 1.2f only \xintFloat but not \XINTinFloat may have P+1 digits in the +% mantissa on output. \XINTinFloat is the inner macro used for example by all +% operations in float expression to output their result, hence most of the +% time receive it in A[N] shape also, which is quicly parsed --- apart of +% course that each time length of A is computed again. +% +% 1.2g adds \XINTinFloatS which may output A[N] with A having <P digits. This +% is for situations with large P's (say in the hundreds) and has a dramatic +% speed-up effect on things like 2x or x/3. Addition and subtraction will +% still use \XINTinFloat on inputs; anyway this will have to be changed again +% when inner structure will carry up front at least the length of mantissa as +% a data not to recompute. +% +% 1.2g has also re-written both \xintFloat and \XINTinFloat start code to +% intercept more quickly and more satisfactorily B=1 case. % % | % \begin{macrocode} @@ -25202,26 +25760,116 @@ $1$ or $-1$. % \lverb|Note 2015/12/02. Le but de ce code de 1.08 (2013), jusqu'à % l'exécution de \XINT_float_Q, est simplement de tronquer numérateur et % dénominateur à au plus P+2 chiffres en ajustant la partie décimale "n". +% +% 2016/03/19. First thing to do is to intercept denominator=1 case. +% % | % \begin{macrocode} -\def\XINT_float_a #1.#2#3% #1=P, #2=n, #3=A, #4=B +\def\XINT_float_a #1.#2#3#4% {% - \XINT_float_fork #3\Z {#1}{#2}% #1 = precision, #2=n + \if\romannumeral0\XINT_isone#4XY1\expandafter\XINT_float_sp + \else\expandafter\XINT_float_fork\fi #3.{#1}{#2}{#4}% }% % \end{macrocode} -% \lverb?A\Z {P}{n}{B}\XINT_float_Q? +% \lverb|Special quick treatment of B=1 case. The \XINTinFloat variant has +% also optionally the non-addition of zeroes to short inputs. Not for +% \xintFloat. The other difference is that \xintFloat may output 10.0...0eN| % \begin{macrocode} -\def\XINT_float_fork #1% +\def\XINT_float_sp #1% {% \xint_UDzerominusfork - #1-\XINT_float_zero - 0#1\XINT_float_J - 0-{\XINT_float_K #1}% + #1-\XINT_float_spzero + 0#1\XINT_float_spneg + 0-{\XINT_float_sppos #1}% + \krof +}% +\def\XINT_float_spzero .#1#2#3#4{ 0.e0}% +\def\XINT_float_spneg {\expandafter-\romannumeral0\XINT_float_sppos}% +\def\XINT_float_sppos #1.#2#3#4#5% +{% + \expandafter\XINT_float_sp_b\the\numexpr#2-\xintLength{#1}.#1.#2.#3.% +}% +\def\XINT_float_sp_b #1% +{% + \xint_UDzerominusfork + #1-\XINT_float_sp_quick + 0#1\XINT_float_sp_c + 0-{\XINT_float_sp_addzeros #1}% + \krof +}% +\def\XINT_float_sp_quick .#1.#2.#3.% +{% + \expandafter\XINT_float_sp_done\the\numexpr #3+#2-\xint_c_i.#1;% +}% +\def\XINT_float_sp_addzeros #1.#2.#3.#4.% +{% + \expandafter\XINT_float_sp_done + \the\numexpr #4-#1+#3-\xint_c_i\expandafter.% + \romannumeral0\XINT_dsx_addzerosnofuss {#1}{#2};% +}% +\def\XINT_float_sp_done #1.#2#3;{ #2.#3e#1}% +\def\XINT_float_sp_c #1.#2% +{% + \if #29\xint_dothis {\XINT_float_sp_d\XINT_float_Wb }\fi + \xint_orthat {\XINT_float_sp_d\XINT_float_sp_Wa }#1.#2% +}% +\def\XINT_float_sp_d #1#2.#3.#4.#5.% +{% + \expandafter\XINT_float_sp_e + \the\numexpr #5+#2+#4-\xint_c_i\expandafter.% + \romannumeral0\expandafter\XINT_split_fromleft_loop + \the\numexpr #4+\xint_c_i.{}#3\W\W\W\W\W\W\W\W\Z #1% +}% +% \end{macrocode} +% \lverb|Still using old Reverse routine because presumably we are handling +% numbers up to a few dozens digits. But a faster \xintReverseDigits is +% available. No time now. +% #1=exposant final.#2=P+1chiffres de A.#3=junk.#4=\XINT_float_Wb ou +% \XINT_float_sp_Wa +% | +% \begin{macrocode} +\def\XINT_float_sp_e #1.#2.#3.% +{% + \expandafter\XINT_float_sp_f + \romannumeral0\XINT_rord_main {}#2% + \xint_relax + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_relax ;#1.% +}% +\def\XINT_float_sp_f #1% +{% + \ifnum #1<\xint_c_v + \expandafter\XINT_float_sp_ga\else\expandafter\XINT_float_sp_h\fi +}% +\def\XINT_float_sp_ga #1;#2.#3% +{% + \expandafter\XINT_float_sp_Wa + \romannumeral0\XINT_rord_main {}#1% + \xint_relax + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_relax e#2% +}% +\def\XINT_float_sp_h #1;#2.#3% +{% + \expandafter#3% + \romannumeral0\XINT_addm_A 0{}1000\W\X\Y\Z #1000\W\X\Y\Z e#2% +}% +\def\XINT_float_sp_Wa #1{ #1.}% +% \end{macrocode} +%\lverb?A.{P}{n}{B}\XINT_float_Q avec B qui est >1, donc A=0 exclu. +% ? +% \begin{macrocode} +\def\XINT_float_fork #1% +{% + \xint_UDsignfork + #1\XINT_float_J + -{\XINT_float_K #1}% \krof }% -\def\XINT_float_zero #1\Z #2#3#4#5{ 0.e0}% -\def\XINT_float_J {\expandafter\xint_minus_thenstop\romannumeral0\XINT_float_K }% -\def\XINT_float_K #1\Z #2% #1=A, #2=P, #3=n, #4=B +\def\XINT_float_J {\expandafter-\romannumeral0\XINT_float_K }% +\def\XINT_float_K #1.#2% {% \expandafter\XINT_float_L \the\numexpr\xintLength{#1}\expandafter.\the\numexpr #2+\xint_c_ii.{#1}{#2}% @@ -25272,13 +25920,15 @@ $1$ or $-1$. % \end{macrocode} % \lverb?Ce qu'on a fait avec A on le fait maintenant avec B. Mais on va % repérer B=1 avant de faire une division.$newline -% En entrée: |B|.n'.P+2.{B}{|A'|}{A'}{P}\XINT_float_Q? +% En entrée: |B|.n'.P+2.{B}{|A'|}{A'}{P}\XINT_float_Q +% +% 1.2g has already filtered out the case B=1.? % \begin{macrocode} \def\XINT_float_N #1.#2.#3.% {% - \ifnum #1>#3 \xint_dothis\XINT_float_N_Blong\fi - \ifnum #1=\xint_c_i\xint_dothis\XINT_float_N_Bshort\fi - \xint_orthat{\XINT_float_P 0.}% + \ifnum #1>#3 + \expandafter\XINT_float_N_Blong + \else\expandafter\XINT_float_P\fi #1.#2.#3.% }% % \end{macrocode} @@ -25295,31 +25945,18 @@ $1$ or $-1$. % \end{macrocode} % \lverb?n''=n'-(|B|-(P+2)).{B'}.{junk}.{P+2}->0.P+2.n''.P+2.{B'}? % \begin{macrocode} -\def\XINT_float_NaP #1.#2.#3.#4{\XINT_float_P 0.#4.#1.#4.{#2}}% -% \end{macrocode} -% \lverb?Ici B est court, mais on va repérer les cas avec B=1 pour aller plus -% vite.? -% \begin{macrocode} -\def\XINT_float_N_Bshort 1.#1.#2.#3% -{% - \ifnum #3=\xint_c_i \xint_dothis{\XINT_float_P 1.}\fi - \xint_orthat{\XINT_float_P 0.}1.#1.#2.#3% -}% +\def\XINT_float_NaP #1.#2.#3.#4{\XINT_float_P #4.#1.#4.{#2}}% % \end{macrocode} -% \lverb?Si B est de longueur <= P+2 on arrive ici avec en entrée 0 ou -% 1.|B|.n'.P+2.{B}, sinon avec i.P+2.n''.P+2.{B'}, suivi dans les deux cas par -% {|A'|}{A'}{P} et #9=\XINT_float_Q. On va invoquer \XINT_float_Q, mais on lui -% passe l'indicateur i qui repère le cas B=1 que l'on veut traiter plus -% rapidement (en attendant que j'introduise une vraie notion de type pour les -% flottants; à laquelle je ne pourrai pas échapper bien plus longtemps). On -% aura donc \XINT_float_Q i|B|-|A|+P+1.{A}{B}{P}{n} avec les nouveaux A, B, -% n. Ici on a doit passer au-dessus de A et |A| pour aller chercher #9. -% à revoir car pas satisfaisant.? +% \lverb?Si B est de longueur <= P+2 on arrive ici avec en entrée +% |B|.n'.P+2.{B}, sinon avec P+2.n''.P+2.{B'}, suivi dans les deux cas par +% {|A'|}{A'}{P} et #8=\XINT_float_Q. On va invoquer \XINT_float_Q, on +% aura donc \XINT_float_Q |B|-|A|+P+1.{A}{B}{P}{n} avec les nouveaux A, B, n. +% Ici on a doit passer au-dessus de A et |A| pour aller chercher #8. à revoir +% car pas satisfaisant.? % \begin{macrocode} -\def\XINT_float_P #1.#2.#3.#4.#5#6#7#8#9% +\def\XINT_float_P #1.#2.#3.#4#5#6#7#8% {% - \expandafter #9\expandafter#1% - \the\numexpr #2-#6+#4-\xint_c_i.{#7}{#5}{#8}{#3}% + \expandafter #8\the\numexpr #1-#5+#3-\xint_c_i.{#6}{#4}{#7}{#2}% }% % \end{macrocode} % \lverb?On arrive ici avec |B|-|A|+P+1.{A}{B}{P}{n}, les A et B étant ceux @@ -25328,19 +25965,9 @@ $1$ or $-1$. % On calcule maintenant le quotient euclidien de A 10^{|B|-|A|+P+1} (qui a P+1 % chiffres de plus que B) par B. Ce quotient Q aura P+1 ou P+2 chiffres. % -% 2015/12/07: nouveau premier token indicateur i=1 si B=1, i=0 sinon. % ? % \begin{macrocode} -\def\XINT_float_Q #1% -{% - \if 1#1\expandafter\XINT_float_Ri\else\expandafter\XINT_float_Rii\fi -}% -\def\XINT_float_Ri #1.#2#3% -{% - \expandafter\XINT_float_Sa - \romannumeral0\XINT_dsx_addzerosnofuss {#1}{#2}\Z {#1}% -}% -\def\XINT_float_Rii #1.#2#3% +\def\XINT_float_Q #1.#2#3% {% \expandafter\XINT_float_Sa \romannumeral0\xintiiquo{\XINT_dsx_addzerosnofuss {#1}{#2}}{#3}\Z {#1}% @@ -25457,8 +26084,7 @@ $1$ or $-1$. % mantissa 10^P with P+1 digits, but 10^{P-1}. Indeed not knowing for sure the % number of digits of the mantissa caused various complications in other % routines, and I really got tired of this. This means however that it is a -% tiny bit slower than earlier. I need to copy over most of the code of -% \xintFloat because sharing is a bit cumbersome. +% tiny bit slower than earlier. % % 2016/03/11. % 1.2f \XINTinFloat clones somes of the \XINT_infrac start code to handle more @@ -25467,86 +26093,88 @@ $1$ or $-1$. % floats, as I want to conclude now and doing this would need some extra time. % % As this is surgery on pre-existing code where a more complete rewrite would -% be needed it is a bit ugly though. +% be needed it is a bit ugly though. 1.2g has redone it and does not anymore +% tap into \XINT_infrac. % % Each time \XINTinFloat is called it at least computes a length. % Naturally if we had some format for floats that would be dispensed of... +% % Something like <letterP><length of mantissa>.mantissa.exponent, etc... % % Not yet. But obviously we can not go one re-parsing each input that way, % although the situation is better with 1.2f. % +% +% 2016/03/18. +% 1.2g adds a variant \XINTinFloatS which allows its output to be shorter than +% the current precision. Indeed \XINTinFloat is used everywhere but for example +% it is silly to convert 2 into 2<499zeroes>[-499] if we need to do some +% multiplication or division... +% +% 2016/03/19. +% 1.2g uses non-patched \XINT_infrac but then immediately filters out +% all denominator=1 cases (only the A[N] cases were identified by 1.2f). %| % \begin{macrocode} \def\XINTinFloat {\romannumeral0\XINTinfloat }% -\def\XINTinfloat [#1]#2% -{% - \expandafter\XINT_infloat\the\numexpr #1\expandafter.% - \romannumeral0\expandafter\XINT_infloat_in - \romannumeral`&&@#2/\XINT_W[\XINT_W\XINT_T\XINT_infloat_Q -}% -\def\XINT_infloat #1.#2{#2#1.}% -\def\XINT_infloat_in #1[#2% +\def\XINTinfloat + {\expandafter\XINT_infloat_clean\romannumeral0\XINT_infloat}% +\def\XINT_infloat_clean #1% + {\if #1!\xint_dothis\XINT_infloat_clean_a\fi\xint_orthat{ }#1}% +\def\XINT_infloat_clean_a !#1.#2[#3]% {% - \xint_UDXINTWfork - #2\XINT_infloat_gen - \XINT_W\XINT_infloat_res_a - \krof - #1[#2% + \expandafter\XINT_infloat_sp_done + \the\numexpr #3-#1\expandafter.% + \romannumeral0\XINT_dsx_addzerosnofuss {#1}{#2};% }% -\edef\XINT_infloat_gen {\noexpand\expandafter\space\noexpand\expandafter - \noexpand\XINT_infloat_a - \noexpand\romannumeral0\noexpand\XINT_frac_gen }% -\def\XINT_infloat_res_a #1% +\def\XINT_infloat_sp_done #1.#2;{ #2[#1]}% +\def\XINTinFloatS {\romannumeral0\XINTinfloatS}% +\def\XINTinfloatS + {\expandafter\XINT_infloatS_clean\romannumeral0\XINT_infloat}% +\def\XINT_infloatS_clean #1% + {\if #1!\xint_dothis\XINT_infloatS_clean_a\fi\xint_orthat{ }#1}% +\def\XINT_infloatS_clean_a !#1.{ }% +\def\XINT_infloat [#1]#2% {% - \xint_gob_til_zero #1\XINT_infloat_res_zero 0\XINT_infloat_res_b #1% + \expandafter\XINT_infloat_a\the\numexpr #1\expandafter.% + \romannumeral0\XINT_infrac {#2}\XINT_infloat_Q }% -\def\XINT_infloat_res_zero #1\XINT_infloat_Q { \XINT_infloat_sp_zero}% -\def\XINT_infloat_sp_zero #1.{ 0[0]}% -\def\XINT_infloat_res_b #1/#2% +\def\XINT_infloat_a #1.#2#3#4% {% - \xint_UDXINTWfork - #2\XINT_infloat_res_ca - \XINT_W\XINT_infloat_res_cb - \krof - #1/#2% + \if\romannumeral0\XINT_isone#4XY1\expandafter\XINT_infloat_sp + \else\expandafter\XINT_float_fork\fi #3.{#1}{#2}{#4}% }% -\def\XINT_infloat_res_ca #1[#2]/\XINT_W[\XINT_W\XINT_T\XINT_infloat_Q - { \XINT_infloat_sp #1.#2.}% -\def\XINT_infloat_res_cb #1/#2[% - {\expandafter\XINT_infloat_res_cc\romannumeral`&&@#2~#1[}% -\edef\XINT_infloat_res_cc #1~#2[#3]/\XINT_W[\XINT_W\XINT_T - {\noexpand\expandafter\space\noexpand\expandafter - \noexpand\XINT_infloat_a\noexpand\expandafter - {\noexpand\the\numexpr #3}{#2}{#1}}% % \end{macrocode} -% \lverb|1.2f adds (2016/03/11) special quick treatment for A[N] inputs.| +% \lverb|Special quick treatment of B=1 case (1.2f then redone 1.2g).| % \begin{macrocode} -\def\XINT_infloat_sp #1.#2% +\def\XINT_infloat_sp #1% {% - \if-#2\xint_dothis{\expandafter-\romannumeral0\XINT_infloat_sp_a {}}\fi - \xint_orthat{\XINT_infloat_sp_a #2}#1.% + \xint_UDzerominusfork + #1-\XINT_infloat_spzero + 0#1\XINT_infloat_spneg + 0-{\XINT_infloat_sppos #1}% + \krof }% -\def\XINT_infloat_sp_a #1#2.#3.% +\def\XINT_infloat_spzero .#1#2#3#4{ 0[0]}% +\def\XINT_infloat_spneg + {\expandafter\XINT_infloat_spnegend\romannumeral0\XINT_infloat_sppos}% +\def\XINT_infloat_spnegend #1% + {\if#1!\expandafter\XINT_infloat_spneg_needzeros\fi -#1}% +\def\XINT_infloat_spneg_needzeros -!#1.{!#1.-}% +\def\XINT_infloat_sppos #1.#2#3#4#5% {% - \expandafter\XINT_infloat_sp_b\the\numexpr#2-\xintLength{#1#3}.#1#3.#2.% + \expandafter\XINT_infloat_sp_b\the\numexpr#2-\xintLength{#1}.#1.#2.#3.% }% \def\XINT_infloat_sp_b #1% {% \xint_UDzerominusfork #1-\XINT_infloat_sp_quick 0#1\XINT_infloat_sp_c - 0-{\XINT_infloat_sp_addzeroes #1}% + 0-{\XINT_infloat_sp_needzeros #1}% \krof }% \def\XINT_infloat_sp_quick .#1.#2.#3.{ #1[#3]}% -\def\XINT_infloat_sp_addzeroes #1.#2.#3.#4.% -{% - \expandafter\XINT_infloat_sp_done - \the\numexpr #4-#1\expandafter.% - \romannumeral0\XINT_dsx_addzerosnofuss {#1}{#2};% -}% -\def\XINT_infloat_sp_done #1.#2;{ #2[#1]}% +\def\XINT_infloat_sp_needzeros #1.#2.#3.#4.{!#1.#2[#4]}% % \end{macrocode} % \lverb|I should re-use truncating/rounding routines but I wrote them too % much time ago. Faster to do it again.| @@ -25603,33 +26231,12 @@ $1$ or $-1$. \expandafter\XINT_infloat_sp_done\the\numexpr #1+#3+#4.#2;% }% % \end{macrocode} -% \lverb|General branch handling A/B[N] inputs. Still, 1.2f identifies faster -% B=1 case.| +% \lverb|General branch handling A/B possibly with [N] or scientific notation +% inputs. +% +% Since 1.2g this is always with B>1. And A is not zero.| % \begin{macrocode} -\def\XINT_infloat_a #1.#2#3% #1=P, #2=n, #3=A, #4=B -{% - \XINT_infloat_fork #3\Z {#1}{#2}% #1 = precision, #2=n -}% -\def\XINT_infloat_fork #1% -{% - \xint_UDzerominusfork - #1-\XINT_infloat_zero - 0#1\XINT_infloat_J - 0-{\XINT_float_K #1}% - \krof -}% -\def\XINT_infloat_zero #1\Z #2#3#4#5{ 0[0]}% -\def\XINT_infloat_J {\expandafter-\romannumeral0\XINT_float_K }% -\def\XINT_infloat_Q #1% -{% - \if 1#1\expandafter\XINT_infloat_Ri\else\expandafter\XINT_infloat_Rii\fi -}% -\def\XINT_infloat_Ri #1.#2#3% -{% - \expandafter\XINT_infloat_Sa - \romannumeral0\XINT_dsx_addzerosnofuss {#1}{#2}\Z {#1}% -}% -\def\XINT_infloat_Rii #1.#2#3% +\def\XINT_infloat_Q #1.#2#3% {% \expandafter\XINT_infloat_Sa \romannumeral0\xintiiquo{\XINT_dsx_addzerosnofuss {#1}{#2}}{#3}\Z {#1}% @@ -25736,8 +26343,7 @@ $1$ or $-1$. \krof }% \def\XINT_pfloat_zero #1;#2.{ 0.}% -\def\XINT_pfloat_neg - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_pfloat_pos }% +\def\XINT_pfloat_neg {\expandafter-\romannumeral0\XINT_pfloat_pos }% \def\XINT_pfloat_pos #1e#2;#3.% {% \ifnum #2>\xint_c_v \xint_dothis\XINT_pfloat_no\fi @@ -25815,7 +26421,7 @@ $1$ or $-1$. \def\xintFloatAdd {\romannumeral0\xintfloatadd }% \def\xintfloatadd #1{\XINT_fladd_chkopt \xintfloat #1\xint_relax }% \def\XINTinFloatAdd {\romannumeral0\XINTinfloatadd }% -\def\XINTinfloatadd #1{\XINT_fladd_chkopt \XINTinfloat #1\xint_relax }% +\def\XINTinfloatadd #1{\XINT_fladd_chkopt \XINTinfloatS #1\xint_relax }% \def\XINT_fladd_chkopt #1#2% {% \ifx [#2\expandafter\XINT_fladd_opt @@ -25864,7 +26470,7 @@ $1$ or $-1$. \def\xintFloatSub {\romannumeral0\xintfloatsub }% \def\xintfloatsub #1{\XINT_flsub_chkopt \xintfloat #1\xint_relax }% \def\XINTinFloatSub {\romannumeral0\XINTinfloatsub }% -\def\XINTinfloatsub #1{\XINT_flsub_chkopt \XINTinfloat #1\xint_relax }% +\def\XINTinfloatsub #1{\XINT_flsub_chkopt \XINTinfloatS #1\xint_relax }% \def\XINT_flsub_chkopt #1#2% {% \ifx [#2\expandafter\XINT_flsub_opt @@ -25893,12 +26499,15 @@ $1$ or $-1$. % \end{framed} % \lverb|1.07. % -% 1.2f does not use two extra rounding digits on inputs.| +% 1.2f does not use two extra rounding digits on inputs. +% +% 1.2g handles the inputs via \XINTinFloatS which will be more efficient when +% the precision is large and the input is for example a small constant like 2.| % \begin{macrocode} \def\xintFloatMul {\romannumeral0\xintfloatmul }% \def\xintfloatmul #1{\XINT_flmul_chkopt \xintfloat #1\xint_relax }% \def\XINTinFloatMul {\romannumeral0\XINTinfloatmul }% -\def\XINTinfloatmul #1{\XINT_flmul_chkopt \XINTinfloat #1\xint_relax }% +\def\XINTinfloatmul #1{\XINT_flmul_chkopt \XINTinfloatS #1\xint_relax }% \def\XINT_flmul_chkopt #1#2% {% \ifx [#2\expandafter\XINT_flmul_opt @@ -25909,7 +26518,7 @@ $1$ or $-1$. {% #1[\XINTdigits]% {\expandafter\XINT_FL_mul_a - \romannumeral0\XINTinfloat[\XINTdigits]{#2}\XINTdigits.{#3}}% + \romannumeral0\XINTinfloatS[\XINTdigits]{#2}\XINTdigits.{#3}}% }% \def\XINT_flmul_opt #1[\xint_relax #2]%#3#4% {% @@ -25917,23 +26526,26 @@ $1$ or $-1$. }% \def\XINT_flmul_opt_a #1.#2#3#4% {% - #2[#1]{\expandafter\XINT_FL_mul_a\romannumeral0\XINTinfloat[#1]{#3}#1.{#4}}% + #2[#1]{\expandafter\XINT_FL_mul_a\romannumeral0\XINTinfloatS[#1]{#3}#1.{#4}}% }% \def\XINT_FL_mul_a #1[#2]#3.#4% {% - \expandafter\XINT_FL_mul_b\romannumeral0\XINTinfloat [#3]{#4}#1[#2]% + \expandafter\XINT_FL_mul_b\romannumeral0\XINTinfloatS[#3]{#4}#1[#2]% }% \def\XINT_FL_mul_b #1[#2]#3[#4]{\xintE{\xintiiMul {#3}{#1}}{#4+#2}}% % \end{macrocode} % \subsection{\csh{xintFloatDiv}, \csh{XINTinFloatDiv}} % \lverb|1.07. % -% 1.2f does not use two extra rounding digits on inputs.| +% 1.2f does not use two extra rounding digits on inputs. +% +% 1.2g handles the inputs via \XINTinFloatS which will be more efficient when +% the precision is large and the input is for example a small constant like 2.| % \begin{macrocode} \def\xintFloatDiv {\romannumeral0\xintfloatdiv }% \def\xintfloatdiv #1{\XINT_fldiv_chkopt \xintfloat #1\xint_relax }% \def\XINTinFloatDiv {\romannumeral0\XINTinfloatdiv }% -\def\XINTinfloatdiv #1{\XINT_fldiv_chkopt \XINTinfloat #1\xint_relax }% +\def\XINTinfloatdiv #1{\XINT_fldiv_chkopt \XINTinfloatS #1\xint_relax }% \def\XINT_fldiv_chkopt #1#2% {% \ifx [#2\expandafter\XINT_fldiv_opt @@ -25944,7 +26556,7 @@ $1$ or $-1$. {% #1[\XINTdigits]% {\expandafter\XINT_FL_div_a - \romannumeral0\XINTinfloat[\XINTdigits]{#2}\XINTdigits.{#3}}% + \romannumeral0\XINTinfloatS[\XINTdigits]{#2}\XINTdigits.{#3}}% }% \def\XINT_fldiv_opt #1[\xint_relax #2]%#3#4% {% @@ -25952,20 +26564,21 @@ $1$ or $-1$. }% \def\XINT_fldiv_opt_a #1.#2#3#4% {% - #2[#1]{\expandafter\XINT_FL_div_a\romannumeral0\XINTinfloat[#1]{#3}#1.{#4}}% + #2[#1]{\expandafter\XINT_FL_div_a\romannumeral0\XINTinfloatS[#1]{#3}#1.{#4}}% }% \def\XINT_FL_div_a #1[#2]#3.#4% {% - \expandafter\XINT_FL_div_b\romannumeral0\XINTinfloat[#3]{#4}#1[#2]% + \expandafter\XINT_FL_div_b\romannumeral0\XINTinfloatS[#3]{#4}#1[#2]% }% \def\XINT_FL_div_b #1[#2]#3[#4]{\xintE{#3/#1}{#4-#2}}% +% \end{macrocode} % \subsection{\csh{xintFloatPow}, \csh{XINTinFloatPow}} % \lverb|1.07: initial version. 1.09j has re-organized the core loop. % % 2015/12/07. I have hesitated to maintain the mapping of ^ in expressions to % \xintFloatPow rather than \xintFloatPower. But for 1.234567890123456 to the % power 2145678912 with P=16, using Pow rather than Power seems to bring only -% about 5$char$37$space gain. +% about 5$char37 $space gain. % % This routine requires the exponent x to be compatible with \numexpr parsing. % @@ -25978,7 +26591,7 @@ $1$ or $-1$. \def\xintFloatPow {\romannumeral0\xintfloatpow}% \def\xintfloatpow #1{\XINT_flpow_chkopt \xintfloat #1\xint_relax }% \def\XINTinFloatPow {\romannumeral0\XINTinfloatpow }% -\def\XINTinfloatpow #1{\XINT_flpow_chkopt \XINTinfloat #1\xint_relax }% +\def\XINTinfloatpow #1{\XINT_flpow_chkopt \XINTinfloatS #1\xint_relax }% \def\XINT_flpow_chkopt #1#2% {% \ifx [#2\expandafter\XINT_flpow_opt @@ -26157,11 +26770,11 @@ $1$ or $-1$. \def\xintFloatPower {\romannumeral0\xintfloatpower}% \def\xintfloatpower #1{\XINT_flpower_chkopt \xintfloat #1\xint_relax }% \def\XINTinFloatPower {\romannumeral0\XINTinfloatpower }% -\def\XINTinfloatpower #1{\XINT_flpower_chkopt \XINTinfloat #1\xint_relax }% +\def\XINTinfloatpower #1{\XINT_flpower_chkopt \XINTinfloatS #1\xint_relax }% \def\XINTinFloatPowerH {\romannumeral0\XINTinfloatpowerH }% \def\XINTinfloatpowerH #1#2% {\expandafter\XINT_flpowerh_a \romannumeral0\xinttrunc 1{#2}.0;% - \XINTdigits.{#1}{\XINTinfloat[\XINTdigits]}}% + \XINTdigits.{#1}{\XINTinfloatS[\XINTdigits]}}% \def\XINT_flpowerh_a #1.#2% {% \ifnum#2>\xint_c_iv\xint_dothis\XINT_flpowerh_b\fi @@ -26342,11 +26955,11 @@ $1$ or $-1$. 0-{\XINT_FL_fac_fork_b #1}% \krof }% -\def\XINT_FL_fac_iszero #1.#2#3#4#5{#5{1/1[0]}}% +\def\XINT_FL_fac_iszero #1.#2#3#4#5{#5{1[0]}}% % \end{macrocode} % \lverb|1.2f XINT_FL_fac_isneg returns 0, earlier versions used 1 here.| % \begin{macrocode} -\def\XINT_FL_fac_isneg #1.#2#3#4#5{\expandafter\xintError:FactorialOfNegative #5{0/1[0]}}% +\def\XINT_FL_fac_isneg #1.#2#3#4#5{\expandafter\xintError:FactorialOfNegative #5{0[0]}}% \def\XINT_FL_fac_fork_b #1.% {% \ifnum #1>\xint_c_x^viii_mone\xint_dothis\XINT_FL_fac_toobig\fi @@ -26356,7 +26969,7 @@ $1$ or $-1$. \xint_orthat\XINT_FL_fac_small #1.% }% -\def\XINT_FL_fac_toobig #1.#2#3#4#5{\expandafter\xintError:TooBigFactorial #5{1/1[0]}}% +\def\XINT_FL_fac_toobig #1.#2#3#4#5{\expandafter\xintError:TooBigFactorial #5{1[0]}}% % \end{macrocode} % \lverb?Computations are done with Q blocks of eight digits. When a % multiplication has a carry, hence creates Q+1 blocks, the least significant @@ -26383,14 +26996,14 @@ $1$ or $-1$. % than the earlier 5=13-8. Whatever happens, the value computed in % \XINT_FL_fac_increaseP is at least 8. There will always be an extra block. % -% Note: with Digits:=32; Maple gives for 200!:$bgroup$obeylines$obeyspaces +% Note: with Digits:=32; Maple gives for 200!:$bgroup$obeylines$obeyspaces$ttbfamily % > factorial(200.); -% 375 -% 0.78865786736479050355236321393218 10 +% $indent 375 +% $indent 0.78865786736479050355236321393218 10 % My 1.2f routine (and also 1.2) outputs: -% 7.8865786736479050355236321393219e374 +% $indent 7.8865786736479050355236321393219e374 % and this is the correct rounding because for 40 digits it computes -% 7.886578673647905035523632139321850622951e374 +% $indent 7.886578673647905035523632139321850622951e374 % $egroup % Maple's result (contrarily to xint) is thus not the correct rounding but % still it is less than 0.6 ulp wrong. @@ -26620,8 +27233,8 @@ $1$ or $-1$. \xint_dothis\XINT_FL_pfac_outofrange\fi \xint_orthat \XINT_FL_pfac_increaseP #1#2.#3.% }% -\def\XINT_FL_pfac_outofrange #1.#2.#3#4#5{\xintError:OutOfRangePFac #5{0/1[0]}}% -\def\XINT_FL_pfac_one #1.#2.#3#4#5{#5{1/1[0]}}% +\def\XINT_FL_pfac_outofrange #1.#2.#3#4#5{\xintError:OutOfRangePFac #5{0[0]}}% +\def\XINT_FL_pfac_one #1.#2.#3#4#5{#5{1[0]}}% % \end{macrocode} % \lverb|See the comments for \XINT_FL_pfac_increaseP. Case of b=a+1 should be % filtered out perhaps. We only needed here to copy the \xintPFactorial macros and @@ -26811,8 +27424,8 @@ $1$ or $-1$. #1#2.#3#4.#5.% }% \def\XINT_FL_binom_outofrange #1.#2.#3.#4.#5% - {\xintError:OutOfRangeBinomial #5[#4]{0/1[0]}}% -\def\XINT_FL_binom_one #1.#2.#3.#4.#5{#5[#4]{1/1[0]}}% + {\xintError:OutOfRangeBinomial #5[#4]{0[0]}}% +\def\XINT_FL_binom_one #1.#2.#3.#4.#5{#5[#4]{1[0]}}% \def\XINT_FL_binom_aa #1.#2.#3.#4.#5% {% #5[#4]{\xintDiv{\XINT_FL_pfac_increaseP @@ -26924,7 +27537,11 @@ $1$ or $-1$. }% \def\XINT_flsqrt_finish #1#2.#3.#4.#5.#6.#7.#8{#8[#6]{#3#1[#7]}}% \def\XINT_flsqrt_f 5#1.% - {\xintiiifGt{\xintiNum{#1}}{2}{\XINT_flsqrt_finish 5.}{\XINT_flsqrt_again}}% + {\expandafter\XINT_flsqrt_g\romannumeral0\xintinum{#1}\relax.}% +\def\XINT_flsqrt_g #1#2#3.{\if\relax#2\xint_dothis{\XINT_flsqrt_h #1}\fi + \xint_orthat{\XINT_flsqrt_finish 5.}}% +\def\XINT_flsqrt_h #1{\ifnum #1<\xint_c_iii\xint_dothis{\XINT_flsqrt_again}\fi + \xint_orthat{\XINT_flsqrt_finish 5.}}% \def\XINT_flsqrt_again #1.#2.% {% \expandafter\XINT_flsqrt_again_a\the\numexpr #2+\xint_c_viii.% @@ -27052,7 +27669,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintseries}% - [2016/03/12 1.2f Expandable partial sums with xint package (JFB)]% + [2016/03/19 1.2g Expandable partial sums with xint package (JFB)]% % \end{macrocode} % \subsection{\csh{xintSeries}} % \begin{macrocode} @@ -27550,7 +28167,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintcfrac}% - [2016/03/12 1.2f Expandable continued fractions with xint package (JFB)]% + [2016/03/19 1.2g Expandable continued fractions with xint package (JFB)]% % \end{macrocode} % \subsection{\csh{xintCFrac}} % \begin{macrocode} @@ -28669,6 +29286,18 @@ $1$ or $-1$. % % \etocmarkbothnouc {Package \xintexprnameimp implementation} % +% This section contained a kind of cumulative change log, particularly +% detailed for the |1.1| (|2014/10/28|) and |1.2| (|2015/10/10|) releases. As +% this was essentially the same as what is also available in |CHANGES.md|, I +% have suppressed it, to simplify future maintenance, else I had to keep here +% an up-to-date log as well (|2016/03/18|). +% +% I am leaving only general comments describing « les grandes lignes » of the +% implementation, as last updated at the time of the |1.09| releases, prior to +% |1.1|. +% +% \emph{Start of old comments.} +% % The first version was released in June 2013. I was greatly helped in this task % of writing an expandable parser of infix operations by the comments provided % in |l3fp-parse.dtx| (in its version as available in April-May 2013). One will @@ -28681,144 +29310,6 @@ $1$ or $-1$. % retrieving data expandably as \emph{names} of control sequences. Intermediate % computation results are stored as control sequences |\.=a/b[n]|. % -% Release |1.2| |[2015/10/10]| has the following changes: -% \begin{description} -% \item[not anymore limited to 5000 -% digits:] |1.2| replaces chains of |\romannumeral-`0| used earlier to -% gather digits by |\csname| governed expansions. The use of -% |\csname.=A/B[N]\endcsname| storage has been part of the design from the -% start, hence it was very natural and not too hard to gather the number -% directly inside |\csname|. With the chains of |\romannumeral-`0| gone, -% there is no more a limit at about 5000 (with the standard settings of the -% maximal expansion depth at 10000) on the maximal number of digits for each -% gathered number. -% \item[faster gathering of digits:] the previous item and some other changes -% have accelerated the building up of numbers. -% \item[optional accelerated parsing:] the new functions |qint|, |qfrac|, -% |qfloat| allow to skip entirely the digit by digit parsing and hand over -% directly responsability to \csa{xintiNum}, \csa{xintRaw}, or -% \csa{xintFloat} respectively. -% \item[float factorial:] the factorial operator |!| maps to the new macro -% \csa{xintFloatFac} inside \csa{xintfloatexpr}. -% \item[isolated dot now illegal:] the decimal mark must have digits either -% before or after it, an isolated |.| is now illegal input. -% \item[more recognized tokens:] |\ht|, |\dp|, |\wd|, |\fontcharht|, -% |\fontcharwd|, |\fontchardp| and |\fontcharic| are recognized and prefixed -% with |\number| automatically. -% \end{description} -% -% Release |1.1| |[2014/10/28]| has made many extensions, some bug fixes, and -% some breaking changes: -% \begin{description} -% \item[bug fixes] \begin{itemize} -% \item |\xintiiexpr| did not strip leading zeroes, -% \item |\xinttheexpr \xintiexpr 1.23\relax\relax| should have produced |1|, -% but it produced |1.23| -% \item the catcode of |;| was not set at package launching time. -% \end{itemize} -% \item[breaking changes] \begin{itemize} -% \item in |\xintiiexpr|, |/| does \emph{rounded} division, rather than 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 as is 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} -% \item[novelties] They are quite a few. \begin{itemize} -% \item |\xintiexpr|, |\xinttheiexpr| admit an optional argument within brackets -% |[d]|, they round the computation result (or results, if comma separated) -% to |d| digits after decimal mark, (the whole computation is done exactly, -% as in |xintexpr|), -% -% \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|), -% -% \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|, -% -% \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]| allowing negative indices, but no optional step argument, -% and |[list][n]| (|n=0| for the number of items in the list), -% -% \item functions |first|, |last|, |reversed|, -% -% \item itemwise operations on comma separated lists |a*[list]|, etc.., possible -% on both sides |a*[list]^b|, an obeying the same precedence rules as with -% numbers, -% -% \item |add| and |mul| must use a dummy variable: |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 lists 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, -% -% \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|, |protect| function to handle -% external macros. However not all constructs are compatible with -% |\xintNewExpr|. -% -% \end{itemize} -% \end{description} -% -% Comments dating back to earlier releases: % % Roughly speaking, the parser mechanism is as follows: at any given time the % last found ``operator'' has its associated |until| macro awaiting some news @@ -28850,64 +29341,8 @@ $1$ or $-1$. % macro and the fifth is |\.=a/b[n]|. The prefix |\xintthe| makes the output % printable by killing the first three tokens. % -% \begin{description} -% \item[{|1.08b [2013/06/14]|}] corrected a problem originating in the attempt -% to attribute a special rôle to braces: expansion could be stopped by space -% tokens, as various macros tried to expand without grabbing what came next. -% They now have a doubled |\romannumeral-`0|. -% -% \item[{|1.09a| |[2013/09/24]|}] has a better mechanism regarding |\xintthe|, -% more commenting and better organization of the code, and most importantly it -% implements functions, comparison operators, logic operators, conditionals. The -% code was reorganized and expansion proceeds a bit differently in order to have -% the |_getnext| and |_getop| codes entirely shared by |\xintexpr| and -% |\xintfloatexpr|. |\xintNewExpr| was rewritten in order to work with the -% standard macro parameter character |#|, to be catcode protected and to also -% allow comma separated expressions. -% -% \item[{|1.09c| |[2013/10/09]|}] added the |bool| and |togl| operators, -% |\xintboolexpr|, and |\xintNewNumExpr|, |\xintNewBoolExpr|. The code for -% |\xintNewExpr| is shared with |float|, |num|, and |bool|-expressions. Also the -% precedence level of the postfix operators |!|, |?| and |:| has been made lower -% than the one of functions. -% -% \item[{|1.09i| |[2013/12/18]|}] unpacks count and dimen registers and control -% squences, with tacit multiplication. It has also made small improvements. -% (speed gains in macro expansions in quite a few places.) -% -% Also, |1.09i| implements |\xintiiexpr|, |\xinttheiiexpr|. New function |frac|. -% And encapsulation in |\csname..\endcsname| is done with |.=| as first tokens, -% so unpacking with |\string| can be done in a completely escape char agnostic -% way. % -% \item[{|1.09j| |[2014/01/09]|}] extends the tacit multiplication to the case of -% a sub |\xintexpr|-essions. Also, it now |\xint_protect|s the result of the -% |\xintexpr| full expansions, thus, an |\xintexpr| without |\xintthe| prefix -% can be used not only as the first item within an ``|\fdef|'' as previously but -% also now anywhere within an |\edef|. Five tokens are used to pack the -% computation result rather than the possibly hundreds or thousands of digits of -% an |\xintthe| unlocked result. I deliberately omit a second |\xint_protect| -% which, however would be necessary if some macro |\.=digits/digits[digits]| had -% acquired some expandable meaning elsewhere. But this seems not that probable, -% and adding the protection would mean impacting everything only to allow some -% crazy user which has loaded something else than xint to do an |\edef|... the -% |\xintexpr| computations are otherwise in no way affected if such control -% sequences have a meaning. -% -% \item[{|1.09k| |[2014/01/21]|}] does tacit multiplication also for an opening -% parenthesis encountered during the scanning of a number, or at a time when the -% parser expects an infix operator. -% -% And it adds to the syntax recognition of hexadecimal numbers starting with a -% |"|, and having possibly a fractional part (except in |\xintiiexpr|, -% naturally). -% -% \item[{|1.09kb| |[2014/02/13]|}] fixes the bug introduced in |\xintNewExpr| -% in |1.09i| of December 2013: an |\endlinechar -1| was removed, but without -% it there is a spurious trailing space token in the outputs of the created -% macros, and nesting is then impossible. -% -% \end{description} +% \emph{End of old comments.} % % This is release \expandafter|\xintbndlversion| of % \expandafter|\expandafter[\xintbndldate]|. @@ -28980,7 +29415,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintexpr}% - [2016/03/12 1.2f Expandable expression parser (JFB)]% + [2016/03/19 1.2g Expandable expression parser (JFB)]% \catcode`! 11 % \end{macrocode} % \subsection{Locking and unlocking} @@ -29869,7 +30304,9 @@ $1$ or $-1$. % 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.| +% 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 @@ -30197,7 +30634,9 @@ $1$ or $-1$. \csname XINT_#1_op_^[\endcsname }% % \end{macrocode} -% \subsubsection{List selectors: [list][N], [list][:b], [list][a:], [list][a:b]} +% \subsection{Macros for list selectors: [list][N], [list][:b], [list][a:], [list][a:b]} +% \localtableofcontents +% % \lverb|1.1 (27 octobre 2014) I implement Python syntax, see % http://stackoverflow.com/a/13005464/4184837. I do not implement third % argument giving the step. Also, Python [5:2] selector returns empty @@ -30205,11 +30644,23 @@ $1$ or $-1$. % 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. +% This gets the job done, but I would definitely need \xintTrim::csv, +% \xintKeep::csv, \xintNthElt::csv for better efficiency. Not for 1.1. +% +% 2016/03/16. 1.2g decides that as [list][a:b] obeyed already Python syntax, +% for example [list][:n] keeps the first n elements, it was annoying that +% elements were tacitly numbered starting from 1 and not from 0 in the context +% of the [list][N] syntax. Thus now [list][n] returns the (n-1)-eth element. +% And one must use len(list) for the length. +% +% 2016/03/17. I had forgotten the 1.1 code comment above and 1.2g does it at +% last, in f-expandable versions \xintTrim:f:csv, \xintKeep:f:csv, +% \xintNthELtPy:f:csv and \xintLength:f:csv, which are all f-expandable for +% easier use with \xintNewExpr. Also \xintReverse:f:csv. I end up moving them +% all to xinttools.sty. +% % -% 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% {% @@ -30230,8 +30681,9 @@ $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 added for \xintNewExpr + .=\expandafter\xintListSel:f:csv + \romannumeral`&&@\XINT_expr_unlock ##4;% + \XINT_expr_unlock ##1;\endcsname % unlock for \xintNewExpr }% \fi }% @@ -30295,14 +30747,25 @@ $1$ or $-1$. % \begin{macrocode} \edef\XINT_expr_op_][: #1{\xint_c_ii \expandafter\noexpand \csname XINT_expr_itself_][\endcsname #10\string :}% -% \end{macrocode} -% \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_][: +% \end{macrocode} +% \subsubsection{\csh{xintListSel:f:csv}} +% \lverb|Some complications here are due to \xintNewExpr matters. +% +% 2016/03/17. +% 1.2g uses Python numbering not only for slices but also item extractors. +% +% It also implements faster extractors, acting directly on comma separated +% values with custom sub-macros \xintTrim:f:csv, \xintKeep:f:csv, +% \xintNthEltPy:f:csv and \xintLength:f:csv. We currently use here +% f-expandable versions for easier compatibility with \xintNewExpr. Also +% sub-optimal is the way the list argument is grabbed. But still better than +% the 1.1 version which used \xintCSVtoList everywhere for access to the +% routines provided with \xinttoolsnameimp.| +% \begin{macrocode} \catcode`[ 12 \catcode`] 12 -\def\xintListSel::csv #1{% +\def\xintListSel:f: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}% @@ -30310,33 +30773,35 @@ $1$ or $-1$. \def\XINT_listsel:_s #1{\if p#1\expandafter\XINT_listsel:_trim\else \expandafter\XINT_listsel:_keep\fi }% \def\XINT_listsel:_: #1.#2.{\csname XINT_listsel:_#1#2\endcsname }% -\def\XINT_listsel:_trim #1;#2;% - {\xintListWithSep,{\xintTrim {\xintNum{#1}}{\xintCSVtoListNonStripped{#2}}}}% -\def\XINT_listsel:_keep #1;#2;% - {\xintListWithSep,{\xintKeep {\xintNum{#1}}{\xintCSVtoListNonStripped{#2}}}}% -\def\XINT_listsel:_nth#1;#2;% - {\xintNthElt {\xintNum{#1}}{\xintCSVtoListNonStripped{#2}}}% +\def\XINT_listsel:_trim #1;#2;{\xintTrim:f:csv {\xintNum{#1}}{#2}}% +\def\XINT_listsel:_keep #1;#2;{\xintKeep:f:csv {\xintNum{#1}}{#2}}% +\def\XINT_listsel:_nth#1;#2;{\xintNthEltPy:f:csv {\xintNum{#1}}{#2}}% \def\XINT_listsel:_PP #1;#2;#3;% - {\xintListWithSep,% - {\xintTrim {\xintNum{#1}}{\xintKeep {\xintNum{#2}}{\xintCSVtoListNonStripped{#3}}}}% - }% + {\xintTrim:f:csv {\xintNum{#1}}{\xintKeep:f:csv {\xintNum{#2}}{#3}}}% \def\XINT_listsel:_NN #1;#2;#3;% - {\xintListWithSep,% - {\xintTrim {\xintNum{#2}}{\xintKeep {\xintNum{#1}}{\xintCSVtoListNonStripped{#3}}}}% - }% -\def\XINT_listsel:_NP #1;#2;#3;% - {\expandafter\XINT_listsel:_NP_a \the\numexpr #1+% - \xintNthElt{0}{\xintCSVtoListNonStripped{#3}};#2;#3;}% -\def\XINT_listsel:_NP_a #1#2;{\if -#1\expandafter\XINT_listsel:_OP\fi - \XINT_listsel:_PP #1#2;}% + {\xintTrim:f:csv {\xintNum{#2}}{\xintKeep:f:csv {\xintNum{#1}}{#3}}}% +\def\XINT_listsel:_NP #1;#2;#3;{\expandafter\XINT_listsel:_NP_a + \the\numexpr #1+\xintLength:f:csv{#3};#2;#3;}% +\def\XINT_listsel:_NP_a #1#2;% + {\if -#1\expandafter\XINT_listsel:_OP\fi\XINT_listsel:_PP #1#2;}% \def\XINT_listsel:_OP\XINT_listsel:_PP #1;{\XINT_listsel:_PP 0;}% -\def\XINT_listsel:_PN #1;#2;#3;% - {\expandafter\XINT_listsel:_PN_a \the\numexpr #2+% - \xintNthElt{0}{\xintCSVtoListNonStripped{#3}};#1;#3;}% -\def\XINT_listsel:_PN_a #1#2;#3;{\if -#1\expandafter\XINT_listsel:_PO\fi - \XINT_listsel:_PP #3;#1#2;}% +\def\XINT_listsel:_PN #1;#2;#3;{\expandafter\XINT_listsel:_PN_a + \the\numexpr #2+\xintLength:f:csv{#3};#1;#3;}% +\def\XINT_listsel:_PN_a #1#2;#3;% + {\if -#1\expandafter\XINT_listsel:_PO\fi\XINT_listsel:_PP #3;#1#2;}% \def\XINT_listsel:_PO\XINT_listsel:_PP #1;#2;{\XINT_listsel:_PP #1;0;}% % \end{macrocode} +% \subsubsection{\csh{xintTrim:f:csv}} +% \lverb|1.2g 2016/03/17. Code in xinttools.sty| +% \subsubsection{\csh{xintKeep:f:csv}} +% \lverb|1.2g 2016/03/17. Code in xinttools.sty| +% \subsubsection{\csh{xintNthEltPy:f:csv}} +% \lverb|1.2g 2016/03/17. Code in xinttools.sty| +% \subsubsection{\csh{xintReverse:f:csv}} +% \lverb|1.2g 2016/03/17. Code in xinttools.sty| +% \subsubsection{\csh{xintLength:f:csv}} +% \lverb|1.2g 2016/03/17. Code in xinttools.sty| +% %\subsection{Macros for a..b list generation} % \localtableofcontents % @@ -31161,9 +31626,10 @@ $1$ or $-1$. \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.| +% \lverb|If all is omitted or list is empty, _empty? will fetch within the ##1 +% a \endcsname token 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 }}% @@ -31352,6 +31818,93 @@ $1$ or $-1$. \def\XINT_expr_rseq:_Abort #1!#2#3~#4#5{}% \def\XINT_expr_rseq:_Break #1!#2#3~#4#5{,#1}% % \end{macrocode} +% \subsection{iter} +% \localtableofcontents +% +% \lverb|Prior to 1.2g, the iter keyword was what is now called iterr, +% analogous with rrseq. Somehow I forgot an iter functioning like rseq +% with the sole difference of printing only the last iteration. Both rseq and +% iter work well with list selectors, as @ refers to the whole comma separated +% sequence of the initial values. I have thus deliberately done the backwards +% incompatible renaming of iter to iterr, and the new iter.| +% \begin{macrocode} +\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\expandafter + #3\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% +}% +% \end{macrocode} +% \subsubsection{\csh{XINT_expr_iterx}} +% \lverb|The (#5) is for ++ mechanism which must have its closing parenthesis.| +% \begin{macrocode} +\def\XINT_expr_iterx #1#2#3#4#5% +{% + \expandafter\XINT_expr_itery\romannumeral0#1(#5)\relax #3#4#2% +}% +% \end{macrocode} +% \subsubsection{\csh{XINT_expr_itery}} +% \lverb|#1=valeurs pour variable (locked), +% #2=toutes les valeurs initiales (csv,locked), +% #3=variable, #4=expr, +% #5=\xintthebareeval ou \xintthebarefloateval ou \xintthebareiieval| +% \begin{macrocode} +\def\XINT_expr_itery #1#2#3#4#5% +{% + \expandafter \XINT_expr_getop + \csname .=% + \expandafter\XINT_expr_iter:_aa + \romannumeral`&&@\XINT_expr_unlock #1!{#5#4\relax !#3}#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} +\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{\XINT_expr:_unlock #1}% +\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\romannumeral0\XINT_expr_lockit {#1}{#5}}% +\def\XINT_expr_iter:_omit #1!#2#3~{\XINT_expr_iter:_b }% +\def\XINT_expr_iter:_abort #1!#2#3~#4#5#6^,{\XINT_expr_unlock #4}% +\def\XINT_expr_iter:_break #1!#2#3~#4#5#6^,{#1}% +% \end{macrocode} +% \subsubsection{\csh{XINT_expr_iter:_A} etc\dots} +% \lverb |n++ for iter. With 1.2c dummy variables pick a single token.| +% \begin{macrocode} +\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:_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_iter:_Goon #1!#2#3~#4#5% + {\expandafter\XINT_expr_iter:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\expandafter\endcsname + \romannumeral0\XINT_expr_lockit{#1}{#5}}% +\def\XINT_expr_iter:_Omit #1!#2#3~%#4#5% + {\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{\XINT_expr:_unlock #4}% +\def\XINT_expr_iter:_Break #1!#2#3~#4#5{#1}% +% \end{macrocode} % \subsection{rrseq} % \localtableofcontents % @@ -31443,112 +31996,115 @@ $1$ or $-1$. \if #1!\xint_dothis\XINT_expr_rrseq:_Omit\fi \xint_orthat{\XINT_expr_rrseq:_Goon #1}}% % \end{macrocode} -% \subsection{iter} +% \subsection{iterr} % \localtableofcontents % \begin{macrocode} -\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% +\def\XINT_expr_func_iterr {\XINT_allexpr_iterr \xintbareeval \xintthebareeval }% +\def\XINT_flexpr_func_iterr {\XINT_allexpr_iterr \xintbarefloateval \xintthebarefloateval }% +\def\XINT_iiexpr_func_iterr {\XINT_allexpr_iterr \xintbareiieval \xintthebareiieval }% +\def\XINT_allexpr_iterr #1#2#3% {% - \expandafter\XINT_expr_iterx\expandafter #1\expandafter #2\expandafter + \expandafter\XINT_expr_iterrx\expandafter #1\expandafter #2\expandafter #3\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% }% % \end{macrocode} -% \subsubsection{\csh{XINT_expr_iterx}} +% \subsubsection{\csh{XINT_expr_iterrx}} % \lverb|The (#5) is for ++ mechanism which must have its closing parenthesis.| % \begin{macrocode} -\def\XINT_expr_iterx #1#2#3#4#5% +\def\XINT_expr_iterrx #1#2#3#4#5% {% - \expandafter\XINT_expr_itery\romannumeral0#1(#5)\expandafter\relax + \expandafter\XINT_expr_iterry\romannumeral0#1(#5)\expandafter\relax \expandafter{\romannumeral0\xintapply \XINT_expr_lockit {\xintRevWithBraces{\xintCSVtoListNonStripped{\XINT_expr_unlock #3}}}}% #3#4#2% }% % \end{macrocode} -% \subsubsection{\csh{XINT_expr_itery}} +% \subsubsection{\csh{XINT_expr_iterry}} % \lverb|#1=valeurs pour variable (locked), % #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| % \begin{macrocode} -\def\XINT_expr_itery #1#2#3#4#5#6% +\def\XINT_expr_iterry #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 + \expandafter\XINT_expr_iterr:_aa + \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}% +\def\XINT_expr_iterr:_aa #1{\if +#1\expandafter\XINT_expr_iterr:_A\else + \expandafter\XINT_expr_iterr:_a\fi #1}% % \end{macrocode} -% \subsubsection{\csh{XINT_expr_iter:_a} etc\dots} +% \subsubsection{\csh{XINT_expr_iterr:_a} etc\dots} % \begin{macrocode} -\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_iterr:_a #1!#2#3{\XINT_expr_iterr:_b {#3}{#2}#1,^,}% +\def\XINT_expr_iterr:_b #1#2#3#4,{% + \if ,#3\xint_dothis\XINT_expr_iterr:_noop\fi + \if ^#3\xint_dothis\XINT_expr_iterr:_end\fi + \xint_orthat{\expandafter\XINT_expr_iterr:_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% +\def\XINT_expr_iterr:_noop\csname.=,#1\endcsname #2#3{\XINT_expr_iterr:_b {#2}{#3}#1,}% +\def\XINT_expr_iterr:_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 +\def\XINT_expr_iterr:_c #1#2#3% + {\expandafter\XINT_expr_iterr:_d\romannumeral`&&@#3#1~#2?{#3}}% +\def\XINT_expr_iterr:_d #1{% + \if ^#1\xint_dothis\XINT_expr_iterr:_abort\fi + \if ?#1\xint_dothis\XINT_expr_iterr:_break\fi + \if !#1\xint_dothis\XINT_expr_iterr:_omit\fi + \xint_orthat{\XINT_expr_iterr:_goon #1}% +}% +\def\XINT_expr_iterr:_goon #1!#2#3~#4?#5{\expandafter\XINT_expr_iterr:_b\expandafter {\romannumeral0\xinttrim{-1}{\XINT_expr_lockit{#1}#4}}{#5}}% -\def\XINT_expr_iter:_omit #1!#2#3~{\XINT_expr_iter:_b }% -\def\XINT_expr_iter:_abort #1!#2#3~#4?#5#6^,% +\def\XINT_expr_iterr:_omit #1!#2#3~{\XINT_expr_iterr:_b }% +\def\XINT_expr_iterr:_abort #1!#2#3~#4?#5#6^,% {\expandafter\xint_gobble_i\romannumeral0\xintapplyunbraced {,\XINT_expr:_unlock}{\xintReverseOrder{#4\space}}}% -\def\XINT_expr_iter:_break #1!#2#3~#4?#5#6^,% +\def\XINT_expr_iterr:_break #1!#2#3~#4?#5#6^,% {\expandafter\xint_gobble_iv\romannumeral0\xintapplyunbraced {,\XINT_expr:_unlock}{\xintReverseOrder{#4\space}},#1}% \def\XINT_expr:_unlock #1{\XINT_expr_unlock #1}% % \end{macrocode} -% \subsubsection{\csh{XINT_expr_iter:_A} etc\dots} -% \lverb |n++ for iter. ? is of catcode 3 here.| +% \subsubsection{\csh{XINT_expr_iterr:_A} etc\dots} +% \lverb |n++ for iterr. ? is of catcode 3 here.| % \begin{macrocode} -\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 +\def\XINT_expr_iterr:_A +#1!#2#3{\XINT_expr_iterr:_D #1{#3}{#2}}% +\def\XINT_expr_iterr:_D #1#2#3% + {\expandafter\XINT_expr_iterr:_E\romannumeral`&&@#3#1~#2?{#3}}% +\def\XINT_expr_iterr:_Goon #1!#2#3~#4?#5% + {\expandafter\XINT_expr_iterr:_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 +\def\XINT_expr_iterr:_Omit #1!#2#3~%#4?#5% + {\expandafter\XINT_expr_iterr:_D \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\endcsname}% -\def\XINT_expr_iter:_Abort #1!#2#3~#4?#5% +\def\XINT_expr_iterr:_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% +\def\XINT_expr_iterr:_Break #1!#2#3~#4?#5% {\expandafter\xint_gobble_iv\romannumeral0\xintapplyunbraced {,\XINT_expr:_unlock}{\xintReverseOrder{#4\space}},#1}% -\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_iterr:_E #1{\if #1^\xint_dothis\XINT_expr_iterr:_Abort\fi + \if #1?\xint_dothis\XINT_expr_iterr:_Break\fi + \if #1!\xint_dothis\XINT_expr_iterr:_Omit\fi + \xint_orthat{\XINT_expr_iterr:_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 +% \lverb|These 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.| +% would not be the case in the use for the _func_ things. +% +% 1.2g adds (to be continued)| +% % \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.| @@ -31681,7 +32237,7 @@ $1$ or $-1$. % round, trunc, mod, quo, rem, gcd, lcm, max, min, \textasciigrave % +\textasciigrave, \textasciigrave % \texorpdfstring{\protect\lowast}{*}\textasciigrave, ?, !, not, all, any, -% xor, if, ifsgn, first, last, even, odd, reversed, factorial and binomial functions} +% xor, if, ifsgn, even, odd, first, last, len, reversed, factorial and binomial functions} % \localtableofcontents % \begin{macrocode} \def\XINT_expr_twoargs #1,#2,{{#1}{#2}}% @@ -32007,6 +32563,11 @@ $1$ or $-1$. }% \let\XINT_flexpr_func_ifsgn\XINT_expr_func_ifsgn \let\XINT_iiexpr_func_ifsgn\XINT_expr_func_ifsgn +\def\XINT_expr_func_len #1#2#3% + {\expandafter#1\expandafter#2% + \csname.=\xintLength:f:csv {\XINT_expr_unlock#3}\endcsname }% +\let\XINT_flexpr_func_len \XINT_expr_func_len +\let\XINT_iiexpr_func_len \XINT_expr_func_len \def\XINT_expr_func_first #1#2#3% {\expandafter #1\expandafter #2\csname.=\expandafter\XINT_expr_func_firsta \romannumeral`&&@\XINT_expr_unlock #3,^\endcsname }% @@ -32037,15 +32598,14 @@ $1$ or $-1$. % \end{macrocode} % \lverb|1.2c I 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.| +% into \xintReverse::csv. 1.2g opts for the name \xintReverse:f:csv, and +% rewrites it for direct handling of csv lists. 2016/03/17.| % \begin{macrocode} \def\XINT_expr_func_reversed #1#2#3% {\expandafter #1\expandafter #2\csname .=% - \xintReverse::csv {\XINT_expr_unlock #3}\endcsname }% + \xintReverse:f: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\xintReverse::csv #1% should be done directly, of course - {\xintListWithSep,{\xintRevWithBraces {\xintCSVtoListNonStripped{#1}}}}% % \end{macrocode} % \subsection{f-expandable versions of the \csh{xintSeqB::csv} and alike % routines, for \csh{xintNewExpr}} @@ -32426,17 +32986,17 @@ $1$ or $-1$. \expandafter{\the\toks0\expandafter\def\csname #1:csv\endcsname {~#1:csv}}% }% % \end{macrocode} -% \lverb|~xintListSel::csv must have space after it, the reason being in +% \lverb|~xintListSel:f: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. +% reappear later following ~xintListSel:f: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 }% + \def\xintReverse:f:csv {~xintReverse:f:csv }% + \def\xintListSel:f:csv {~xintListSel:f:csv }% }% \odef\XINT_expr_redefinemacros {\the\toks0}% Not \edef ! (subtle) \def\XINT_expr_redefineprints @@ -32619,34 +33179,34 @@ $1$ or $-1$. %<*dtx>----------------------------------------------------------- \iffalse % grep -c -e "^{%" xint*sty -xint.sty:233 +xint.sty:232 xintbinhex.sty:69 xintcfrac.sty:183 xintcore.sty:287 -xintexpr.sty:142 -xintfrac.sty:460 +xintexpr.sty:145 +xintfrac.sty:462 xintgcd.sty:59 xintkernel.sty:7 xintseries.sty:48 -xinttools.sty:128 +xinttools.sty:147 \fi % grep -o "^{%" xint*sty | wc -l -\def\totala{ 1616} +\def\totala{ 1639} \iffalse % grep -c -e "^}%" xint*sty -xint.sty:233 +xint.sty:232 xintbinhex.sty:69 xintcfrac.sty:183 xintcore.sty:287 -xintexpr.sty:172 -xintfrac.sty:460 +xintexpr.sty:176 +xintfrac.sty:462 xintgcd.sty:61 xintkernel.sty:9 xintseries.sty:48 -xinttools.sty:128 +xinttools.sty:147 \fi % grep -o "^}%" xint*sty | wc -l -\def\totalb{ 1650} +\def\totalb{ 1674} \DeleteShortVerb{\|} \def\mymacro #1{\mymacroaux #1} \def\mymacroaux #1#2{\strut \csname #1nameimp\endcsname:& \dtt{ #2.}\tabularnewline } @@ -32683,7 +33243,7 @@ xinttools.sty:128 Right bracket \] Circumflex \^ Underscore \_ Grave accent \` Left brace \{ Vertical bar \| Right brace \} Tilde \~} -\CheckSum {29302}% +\CheckSum {30095}% \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 0dac9845ec7..e7282a0d054 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 1.2f 2016/03/12 +%% The xint bundle 1.2g 2016/03/19 %% Copyright (C) 2013-2016 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 85e1274744c..6cad13c1d89 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 1.2f 2016/03/12 +%% The xint bundle 1.2g 2016/03/19 %% Copyright (C) 2013-2016 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}% - [2016/03/12 1.2f Expandable operations on big integers (JFB)]% + [2016/03/19 1.2g 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}% @@ -90,21 +90,16 @@ \fi }% \def\xintiiIsOne {\romannumeral0\xintiiisone }% -\def\xintiiisone #1{\expandafter\XINT_isone\romannumeral`&&@#1\W\Z }% +\def\xintiiisone #1{\expandafter\XINT_isone\romannumeral`&&@#1XY}% \def\xintIsOne {\romannumeral0\xintisone }% -\def\xintisone #1{\expandafter\XINT_isone\romannumeral0\xintnum{#1}\W\Z }% -\def\XINT_isOne #1{\romannumeral0\XINT_isone #1\W\Z }% -\def\XINT_isone #1#2% +\def\xintisone #1{\expandafter\XINT_isone\romannumeral0\xintnum{#1}XY}% +\def\XINT_isOne #1{\romannumeral0\XINT_isone #1XY}% +\def\XINT_isone #1#2#3Y% {% - \xint_gob_til_one #1\XINT_isone_b 1% - \expandafter\space\expandafter 0\xint_gob_til_Z #2% + \unless\if#2X\xint_dothis{ 0}\fi + \unless\if#11\xint_dothis{ 0}\fi + \xint_orthat{ 1}% }% -\def\XINT_isone_b #1\xint_gob_til_Z #2% -{% - \xint_gob_til_W #2\XINT_isone_yes \W - \expandafter\space\expandafter 0\xint_gob_til_Z -}% -\def\XINT_isone_yes #1\Z { 1}% \let\xintRev\xintReverseDigits \def\xintLen {\romannumeral0\xintlen }% \def\xintlen #1% diff --git a/Master/texmf-dist/tex/generic/xint/xintbinhex.sty b/Master/texmf-dist/tex/generic/xint/xintbinhex.sty index 061e629acca..429bd7fb008 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 1.2f 2016/03/12 +%% The xint bundle 1.2g 2016/03/19 %% Copyright (C) 2013-2016 by Jean-Francois Burnol %% xintbinhex: Expandable binary and hexadecimal conversions %% --------------------------------------------------------------- @@ -70,7 +70,7 @@ \XINTsetupcatcodes% defined in xintkernel.sty \XINT_providespackage \ProvidesPackage{xintbinhex}% - [2016/03/12 1.2f Expandable binary and hexadecimal conversions (JFB)]% + [2016/03/19 1.2g 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 @@ -206,7 +206,7 @@ -{\XINT_dth_P #1}% \krof }% -\def\XINT_dth_N {\expandafter\xint_minus_thenstop\romannumeral0\XINT_dth_P }% +\def\XINT_dth_N {\expandafter-\romannumeral0\XINT_dth_P }% \def\XINT_dth_P {\expandafter\XINT_dth_III\romannumeral`&&@\XINT_dtbh_I {0.}}% \def\xintDecToBin {\romannumeral0\xintdectobin }% \def\xintdectobin #1% @@ -218,7 +218,7 @@ -{\XINT_dtb_P #1}% \krof }% -\def\XINT_dtb_N {\expandafter\xint_minus_thenstop\romannumeral0\XINT_dtb_P }% +\def\XINT_dtb_N {\expandafter-\romannumeral0\XINT_dtb_P }% \def\XINT_dtb_P {\expandafter\XINT_dtb_III\romannumeral`&&@\XINT_dtbh_I {0.}}% \def\XINT_dtbh_I #1#2#3#4#5% {% @@ -354,8 +354,7 @@ -{\XINT_htd_I {0000}#1}% \krof }% -\def\XINT_htd_neg {\expandafter\xint_minus_thenstop - \romannumeral0\XINT_htd_I {0000}}% +\def\XINT_htd_neg {\expandafter-\romannumeral0\XINT_htd_I {0000}}% \def\XINT_htd_I #1#2#3#4#5% {% \xint_gob_til_W #5\XINT_htd_II_a\W @@ -438,8 +437,7 @@ -{\XINT_btd_I {000000}#1}% \krof }% -\def\XINT_btd_neg {\expandafter\xint_minus_thenstop - \romannumeral0\XINT_btd_I {000000}}% +\def\XINT_btd_neg {\expandafter-\romannumeral0\XINT_btd_I {000000}}% \def\XINT_btd_I #1#2#3#4#5#6#7#8#9% {% \xint_gob_til_W #9\XINT_btd_II_a {#2#3#4#5#6#7#8#9}\W @@ -550,7 +548,7 @@ -{\XINT_bth_P #1}% \krof }% -\def\XINT_bth_N {\expandafter\xint_minus_thenstop\romannumeral0\XINT_bth_P }% +\def\XINT_bth_N {\expandafter-\romannumeral0\XINT_bth_P }% \def\XINT_bth_P {\expandafter\XINT_bth_I\expandafter{\expandafter}% \romannumeral0\XINT_OQ {}}% \def\XINT_bth_I #1#2#3#4#5#6#7#8#9% @@ -584,7 +582,7 @@ -{\XINT_htb_P #1}% \krof }% -\def\XINT_htb_N {\expandafter\xint_minus_thenstop\romannumeral0\XINT_htb_P }% +\def\XINT_htb_N {\expandafter-\romannumeral0\XINT_htb_P }% \def\XINT_htb_P {\XINT_htb_I_a {}}% \def\XINT_htb_I_a #1#2#3#4#5#6#7#8#9% {% @@ -625,7 +623,7 @@ -{\XINT_chtb_P #1}% \krof }% -\def\XINT_chtb_N {\expandafter\xint_minus_thenstop\romannumeral0\XINT_chtb_P }% +\def\XINT_chtb_N {\expandafter-\romannumeral0\XINT_chtb_P }% \def\XINT_chtb_P {\expandafter\XINT_chtb_I\expandafter{\expandafter}% \romannumeral0\XINT_OQ {}}% \def\XINT_chtb_I #1#2#3#4#5#6#7#8#9% diff --git a/Master/texmf-dist/tex/generic/xint/xintcfrac.sty b/Master/texmf-dist/tex/generic/xint/xintcfrac.sty index 6f516f56bfb..d4df3400f4b 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 1.2f 2016/03/12 +%% The xint bundle 1.2g 2016/03/19 %% Copyright (C) 2013-2016 by Jean-Francois Burnol %% xintcfrac: Expandable continued fractions with xint package %% --------------------------------------------------------------- @@ -70,7 +70,7 @@ \XINTsetupcatcodes% defined in xintkernel.sty \XINT_providespackage \ProvidesPackage{xintcfrac}% - [2016/03/12 1.2f Expandable continued fractions with xint package (JFB)]% + [2016/03/19 1.2g 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 5088cdefa12..c0ae2f7d5dc 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 1.2f 2016/03/12 +%% The xint bundle 1.2g 2016/03/19 %% Copyright (C) 2013-2016 by Jean-Francois Burnol %% xintcore: Expandable arithmetic on big integers %% --------------------------------------------------------------- @@ -70,7 +70,7 @@ \XINTsetupcatcodes% defined in xintkernel.sty \XINT_providespackage \ProvidesPackage{xintcore}% - [2016/03/12 1.2f Expandable arithmetic on big integers (JFB)]% + [2016/03/19 1.2g 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 @@ -274,7 +274,7 @@ \def\XINT_reversedigits #1% {% \xint_UDsignfork - #1{\expandafter\xint_minus_thenstop\romannumeral0\XINT_reversedigits_a}% + #1{\expandafter-\romannumeral0\XINT_reversedigits_a}% -{\XINT_reversedigits_a #1}% \krof }% @@ -309,7 +309,7 @@ {% \xint_UDzerominusfork #1-{ 0}% - 0#1{ -1}% + 0#1{-1}% 0-{ 1}% \krof }% @@ -416,7 +416,7 @@ }% \def\XINT_dbl_zero #1\Z { 0}% \def\XINT_dbl_neg - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_dbl_pos }% + {\expandafter-\romannumeral0\XINT_dbl_pos }% \def\XINT_dbl_pos #1\Z {% \expandafter\XINT_dbl_pos_aa @@ -481,9 +481,9 @@ 0-{\XINT_dec_pos #1}% \krof }% -\def\XINT_dec_zero #1\Z { -1}% +\def\XINT_dec_zero #1\Z {-1}% \def\XINT_dec_neg - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_inc_pos }% + {\expandafter-\romannumeral0\XINT_inc_pos }% \def\XINT_dec_pos #1\Z {% \expandafter\XINT_dec_pos_aa @@ -552,7 +552,7 @@ \def\XINT_add_firstiszero #1\krof 0#2#3\Z #4\Z { #2#3}% \def\XINT_add_secondiszero #1\krof #20#3\Z #4\Z { #2#4}% \def\XINT_add_minusminus #1#2% - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_add_pp_a {}{}}% + {\expandafter-\romannumeral0\XINT_add_pp_a {}{}}% \def\XINT_add_minusplus #1#2{\XINT_sub_mm_a {}#2}% \def\XINT_add_plusminus #1#2% {\expandafter\XINT_opp\romannumeral0\XINT_sub_mm_a #1{}}% @@ -705,7 +705,7 @@ \def\XINT_sub_plusplus #1#2% {\expandafter\XINT_opp\romannumeral0\XINT_sub_mm_a #1#2}% \def\XINT_sub_minusplus #1#2% - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_add_pp_a {}#2}% + {\expandafter-\romannumeral0\XINT_add_pp_a {}#2}% \def\XINT_sub_minusminus #1#2{\XINT_sub_mm_a {}{}}% \def\XINT_sub_mm_a #1#2#3\Z {% @@ -899,9 +899,9 @@ \def\XINT_mul_zero #1\krof #2#3\Z #4\Z { 0}% \def\XINT_mul_minusminus #1#2{\XINT_mul_plusplus {}{}}% \def\XINT_mul_minusplus #1#2% - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_mul_plusplus {}#2}% + {\expandafter-\romannumeral0\XINT_mul_plusplus {}#2}% \def\XINT_mul_plusminus #1#2% - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_mul_plusplus #1{}}% + {\expandafter-\romannumeral0\XINT_mul_plusplus #1{}}% \def\XINT_mul_plusplus #1#2#3\Z {% \expandafter\XINT_mul_pre_b diff --git a/Master/texmf-dist/tex/generic/xint/xintexpr.sty b/Master/texmf-dist/tex/generic/xint/xintexpr.sty index ab7896f4fe0..b2736c3398b 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 1.2f 2016/03/12 +%% The xint bundle 1.2g 2016/03/19 %% Copyright (C) 2013-2016 by Jean-Francois Burnol %% xintexpr: Expandable expression parser %% --------------------------------------------------------------- @@ -81,7 +81,7 @@ \XINTsetupcatcodes% \XINT_providespackage \ProvidesPackage{xintexpr}% - [2016/03/12 1.2f Expandable expression parser (JFB)]% + [2016/03/19 1.2g 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 @@ -910,8 +910,9 @@ \else \xint_afterfi {\expandafter ##2\expandafter ##3\csname - .=\expandafter\xintListSel::csv \romannumeral`&&@\XINT_expr_unlock ##4;% - \XINT_expr_unlock ##1;\endcsname % unlock added for \xintNewExpr + .=\expandafter\xintListSel:f:csv + \romannumeral`&&@\XINT_expr_unlock ##4;% + \XINT_expr_unlock ##1;\endcsname % unlock for \xintNewExpr }% \fi }% @@ -972,7 +973,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:f: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}% @@ -980,31 +981,22 @@ \def\XINT_listsel:_s #1{\if p#1\expandafter\XINT_listsel:_trim\else \expandafter\XINT_listsel:_keep\fi }% \def\XINT_listsel:_: #1.#2.{\csname XINT_listsel:_#1#2\endcsname }% -\def\XINT_listsel:_trim #1;#2;% - {\xintListWithSep,{\xintTrim {\xintNum{#1}}{\xintCSVtoListNonStripped{#2}}}}% -\def\XINT_listsel:_keep #1;#2;% - {\xintListWithSep,{\xintKeep {\xintNum{#1}}{\xintCSVtoListNonStripped{#2}}}}% -\def\XINT_listsel:_nth#1;#2;% - {\xintNthElt {\xintNum{#1}}{\xintCSVtoListNonStripped{#2}}}% +\def\XINT_listsel:_trim #1;#2;{\xintTrim:f:csv {\xintNum{#1}}{#2}}% +\def\XINT_listsel:_keep #1;#2;{\xintKeep:f:csv {\xintNum{#1}}{#2}}% +\def\XINT_listsel:_nth#1;#2;{\xintNthEltPy:f:csv {\xintNum{#1}}{#2}}% \def\XINT_listsel:_PP #1;#2;#3;% - {\xintListWithSep,% - {\xintTrim {\xintNum{#1}}{\xintKeep {\xintNum{#2}}{\xintCSVtoListNonStripped{#3}}}}% - }% + {\xintTrim:f:csv {\xintNum{#1}}{\xintKeep:f:csv {\xintNum{#2}}{#3}}}% \def\XINT_listsel:_NN #1;#2;#3;% - {\xintListWithSep,% - {\xintTrim {\xintNum{#2}}{\xintKeep {\xintNum{#1}}{\xintCSVtoListNonStripped{#3}}}}% - }% -\def\XINT_listsel:_NP #1;#2;#3;% - {\expandafter\XINT_listsel:_NP_a \the\numexpr #1+% - \xintNthElt{0}{\xintCSVtoListNonStripped{#3}};#2;#3;}% -\def\XINT_listsel:_NP_a #1#2;{\if -#1\expandafter\XINT_listsel:_OP\fi - \XINT_listsel:_PP #1#2;}% + {\xintTrim:f:csv {\xintNum{#2}}{\xintKeep:f:csv {\xintNum{#1}}{#3}}}% +\def\XINT_listsel:_NP #1;#2;#3;{\expandafter\XINT_listsel:_NP_a + \the\numexpr #1+\xintLength:f:csv{#3};#2;#3;}% +\def\XINT_listsel:_NP_a #1#2;% + {\if -#1\expandafter\XINT_listsel:_OP\fi\XINT_listsel:_PP #1#2;}% \def\XINT_listsel:_OP\XINT_listsel:_PP #1;{\XINT_listsel:_PP 0;}% -\def\XINT_listsel:_PN #1;#2;#3;% - {\expandafter\XINT_listsel:_PN_a \the\numexpr #2+% - \xintNthElt{0}{\xintCSVtoListNonStripped{#3}};#1;#3;}% -\def\XINT_listsel:_PN_a #1#2;#3;{\if -#1\expandafter\XINT_listsel:_PO\fi - \XINT_listsel:_PP #3;#1#2;}% +\def\XINT_listsel:_PN #1;#2;#3;{\expandafter\XINT_listsel:_PN_a + \the\numexpr #2+\xintLength:f:csv{#3};#1;#3;}% +\def\XINT_listsel:_PN_a #1#2;#3;% + {\if -#1\expandafter\XINT_listsel:_PO\fi\XINT_listsel:_PP #3;#1#2;}% \def\XINT_listsel:_PO\XINT_listsel:_PP #1;#2;{\XINT_listsel:_PP #1;0;}% \def\xintSeq::csv {\romannumeral0\xintseq::csv }% \def\xintseq::csv #1#2% @@ -1602,6 +1594,64 @@ \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_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\expandafter + #3\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% +}% +\def\XINT_expr_iterx #1#2#3#4#5% +{% + \expandafter\XINT_expr_itery\romannumeral0#1(#5)\relax #3#4#2% +}% +\def\XINT_expr_itery #1#2#3#4#5% +{% + \expandafter \XINT_expr_getop + \csname .=% + \expandafter\XINT_expr_iter:_aa + \romannumeral`&&@\XINT_expr_unlock #1!{#5#4\relax !#3}#2\endcsname +}% +\def\XINT_expr_iter:_aa #1{\if +#1\expandafter\XINT_expr_iter:_A\else + \expandafter\XINT_expr_iter:_a\fi #1}% +\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{\XINT_expr:_unlock #1}% +\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\romannumeral0\XINT_expr_lockit {#1}{#5}}% +\def\XINT_expr_iter:_omit #1!#2#3~{\XINT_expr_iter:_b }% +\def\XINT_expr_iter:_abort #1!#2#3~#4#5#6^,{\XINT_expr_unlock #4}% +\def\XINT_expr_iter:_break #1!#2#3~#4#5#6^,{#1}% +\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:_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_iter:_Goon #1!#2#3~#4#5% + {\expandafter\XINT_expr_iter:_D + \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\expandafter\endcsname + \romannumeral0\XINT_expr_lockit{#1}{#5}}% +\def\XINT_expr_iter:_Omit #1!#2#3~%#4#5% + {\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{\XINT_expr:_unlock #4}% +\def\XINT_expr_iter:_Break #1!#2#3~#4#5{#1}% \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 }% @@ -1665,79 +1715,79 @@ \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 \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% +\def\XINT_expr_func_iterr {\XINT_allexpr_iterr \xintbareeval \xintthebareeval }% +\def\XINT_flexpr_func_iterr {\XINT_allexpr_iterr \xintbarefloateval \xintthebarefloateval }% +\def\XINT_iiexpr_func_iterr {\XINT_allexpr_iterr \xintbareiieval \xintthebareiieval }% +\def\XINT_allexpr_iterr #1#2#3% {% - \expandafter\XINT_expr_iterx\expandafter #1\expandafter #2\expandafter + \expandafter\XINT_expr_iterrx\expandafter #1\expandafter #2\expandafter #3\romannumeral`&&@\XINT_expr_onlitteral_seq_a {}% }% -\def\XINT_expr_iterx #1#2#3#4#5% +\def\XINT_expr_iterrx #1#2#3#4#5% {% - \expandafter\XINT_expr_itery\romannumeral0#1(#5)\expandafter\relax + \expandafter\XINT_expr_iterry\romannumeral0#1(#5)\expandafter\relax \expandafter{\romannumeral0\xintapply \XINT_expr_lockit {\xintRevWithBraces{\xintCSVtoListNonStripped{\XINT_expr_unlock #3}}}}% #3#4#2% }% -\def\XINT_expr_itery #1#2#3#4#5#6% +\def\XINT_expr_iterry #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 -}% -\def\XINT_expr_iter:_aa #1{\if +#1\expandafter\XINT_expr_iter:_A\else - \expandafter\XINT_expr_iter:_a\fi #1}% -\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_expr_iterr:_aa + \romannumeral`&&@\XINT_expr_unlock #1!{#6#5\relax !#4}{#2}\endcsname +}% +\def\XINT_expr_iterr:_aa #1{\if +#1\expandafter\XINT_expr_iterr:_A\else + \expandafter\XINT_expr_iterr:_a\fi #1}% +\def\XINT_expr_iterr:_a #1!#2#3{\XINT_expr_iterr:_b {#3}{#2}#1,^,}% +\def\XINT_expr_iterr:_b #1#2#3#4,{% + \if ,#3\xint_dothis\XINT_expr_iterr:_noop\fi + \if ^#3\xint_dothis\XINT_expr_iterr:_end\fi + \xint_orthat{\expandafter\XINT_expr_iterr:_c}% + \csname.=#3#4\endcsname {#1}{#2}% +}% +\def\XINT_expr_iterr:_noop\csname.=,#1\endcsname #2#3{\XINT_expr_iterr:_b {#2}{#3}#1,}% +\def\XINT_expr_iterr:_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 +\def\XINT_expr_iterr:_c #1#2#3% + {\expandafter\XINT_expr_iterr:_d\romannumeral`&&@#3#1~#2?{#3}}% +\def\XINT_expr_iterr:_d #1{% + \if ^#1\xint_dothis\XINT_expr_iterr:_abort\fi + \if ?#1\xint_dothis\XINT_expr_iterr:_break\fi + \if !#1\xint_dothis\XINT_expr_iterr:_omit\fi + \xint_orthat{\XINT_expr_iterr:_goon #1}% +}% +\def\XINT_expr_iterr:_goon #1!#2#3~#4?#5{\expandafter\XINT_expr_iterr:_b\expandafter {\romannumeral0\xinttrim{-1}{\XINT_expr_lockit{#1}#4}}{#5}}% -\def\XINT_expr_iter:_omit #1!#2#3~{\XINT_expr_iter:_b }% -\def\XINT_expr_iter:_abort #1!#2#3~#4?#5#6^,% +\def\XINT_expr_iterr:_omit #1!#2#3~{\XINT_expr_iterr:_b }% +\def\XINT_expr_iterr:_abort #1!#2#3~#4?#5#6^,% {\expandafter\xint_gobble_i\romannumeral0\xintapplyunbraced {,\XINT_expr:_unlock}{\xintReverseOrder{#4\space}}}% -\def\XINT_expr_iter:_break #1!#2#3~#4?#5#6^,% +\def\XINT_expr_iterr:_break #1!#2#3~#4?#5#6^,% {\expandafter\xint_gobble_iv\romannumeral0\xintapplyunbraced {,\XINT_expr:_unlock}{\xintReverseOrder{#4\space}},#1}% \def\XINT_expr:_unlock #1{\XINT_expr_unlock #1}% -\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 +\def\XINT_expr_iterr:_A +#1!#2#3{\XINT_expr_iterr:_D #1{#3}{#2}}% +\def\XINT_expr_iterr:_D #1#2#3% + {\expandafter\XINT_expr_iterr:_E\romannumeral`&&@#3#1~#2?{#3}}% +\def\XINT_expr_iterr:_Goon #1!#2#3~#4?#5% + {\expandafter\XINT_expr_iterr:_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 +\def\XINT_expr_iterr:_Omit #1!#2#3~%#4?#5% + {\expandafter\XINT_expr_iterr:_D \csname.=\the\numexpr \XINT_expr_unlock#3+\xint_c_i\endcsname}% -\def\XINT_expr_iter:_Abort #1!#2#3~#4?#5% +\def\XINT_expr_iterr:_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% +\def\XINT_expr_iterr:_Break #1!#2#3~#4?#5% {\expandafter\xint_gobble_iv\romannumeral0\xintapplyunbraced {,\XINT_expr:_unlock}{\xintReverseOrder{#4\space}},#1}% -\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_iterr:_E #1{\if #1^\xint_dothis\XINT_expr_iterr:_Abort\fi + \if #1?\xint_dothis\XINT_expr_iterr:_Break\fi + \if #1!\xint_dothis\XINT_expr_iterr:_Omit\fi + \xint_orthat{\XINT_expr_iterr:_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 @@ -2119,6 +2169,11 @@ }% \let\XINT_flexpr_func_ifsgn\XINT_expr_func_ifsgn \let\XINT_iiexpr_func_ifsgn\XINT_expr_func_ifsgn +\def\XINT_expr_func_len #1#2#3% + {\expandafter#1\expandafter#2% + \csname.=\xintLength:f:csv {\XINT_expr_unlock#3}\endcsname }% +\let\XINT_flexpr_func_len \XINT_expr_func_len +\let\XINT_iiexpr_func_len \XINT_expr_func_len \def\XINT_expr_func_first #1#2#3% {\expandafter #1\expandafter #2\csname.=\expandafter\XINT_expr_func_firsta \romannumeral`&&@\XINT_expr_unlock #3,^\endcsname }% @@ -2148,11 +2203,9 @@ \let\XINT_iiexpr_func_nuple\XINT_expr_func_nuple \def\XINT_expr_func_reversed #1#2#3% {\expandafter #1\expandafter #2\csname .=% - \xintReverse::csv {\XINT_expr_unlock #3}\endcsname }% + \xintReverse:f: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\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}}% \def\XINT_seqb:f:csv #1#2{\expandafter\XINT_seqb:f:csv_a\romannumeral`&&@#2#1!}% @@ -2425,8 +2478,8 @@ \expandafter{\the\toks0\expandafter\def\csname #1:csv\endcsname {~#1:csv}}% }% \toks0 \expandafter{\the\toks0 - \def\xintReverse::csv {~xintReverse::csv }% - \def\xintListSel::csv {~xintListSel::csv }% + \def\xintReverse:f:csv {~xintReverse:f:csv }% + \def\xintListSel:f:csv {~xintListSel:f:csv }% }% \odef\XINT_expr_redefinemacros {\the\toks0}% Not \edef ! (subtle) \def\XINT_expr_redefineprints diff --git a/Master/texmf-dist/tex/generic/xint/xintfrac.sty b/Master/texmf-dist/tex/generic/xint/xintfrac.sty index 39b9785986f..ab128c57272 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 1.2f 2016/03/12 +%% The xint bundle 1.2g 2016/03/19 %% Copyright (C) 2013-2016 by Jean-Francois Burnol %% xintfrac: Expandable operations on fractions %% --------------------------------------------------------------- @@ -70,7 +70,7 @@ \XINTsetupcatcodes% defined in xintkernel.sty \XINT_providespackage \ProvidesPackage{xintfrac}% - [2016/03/12 1.2f Expandable operations on fractions (JFB)]% + [2016/03/19 1.2g Expandable operations on fractions (JFB)]% \def\XINT_cntSgnFork #1% {% \ifcase #1\expandafter\xint_secondofthree @@ -596,7 +596,7 @@ }% \def\XINT_sgnfrac_N {% - \expandafter\xint_minus_thenstop\romannumeral0\XINT_sgnfrac_P + \expandafter-\romannumeral0\XINT_sgnfrac_P }% \def\xintFwOver {\romannumeral0\xintfwover }% \def\xintfwover #1% @@ -644,7 +644,7 @@ }% \def\XINT_sgnfwover_N {% - \expandafter\xint_minus_thenstop\romannumeral0\XINT_sgnfwover_P + \expandafter-\romannumeral0\XINT_sgnfwover_P }% \def\xintREZ {\romannumeral0\xintrez }% \def\xintrez @@ -664,7 +664,7 @@ \krof }% \def\XINT_rez_zero #1\Z #2#3{ 0/1[0]}% -\def\XINT_rez_neg {\expandafter\xint_minus_thenstop\romannumeral0\XINT_rez_B }% +\def\XINT_rez_neg {\expandafter-\romannumeral0\XINT_rez_B }% \def\XINT_rez_B #1\Z {% \expandafter\XINT_rez_C\romannumeral0\XINT_factortens {#1}% @@ -708,7 +708,7 @@ #2\Z {#3}% }% \def\XINT_irr_denomisone #1\Z #2{ #1/1}% changed in 1.08 -\def\XINT_irr_negative #1\Z #2{\XINT_irr_D #1\Z #2\Z \xint_minus_thenstop}% +\def\XINT_irr_negative #1\Z #2{\XINT_irr_D #1\Z #2\Z -}% \def\XINT_irr_nonneg #1\Z #2{\XINT_irr_D #1\Z #2\Z \space}% \def\XINT_irr_D #1#2\Z #3#4\Z {% @@ -775,7 +775,7 @@ #2\Z {#3}% }% \def\XINT_jrr_denomisone #1\Z #2{ #1/1}% changed in 1.08 -\def\XINT_jrr_negative #1\Z #2{\XINT_jrr_D #1\Z #2\Z \xint_minus_thenstop }% +\def\XINT_jrr_negative #1\Z #2{\XINT_jrr_D #1\Z #2\Z -}% \def\XINT_jrr_nonneg #1\Z #2{\XINT_jrr_D #1\Z #2\Z \space}% \def\XINT_jrr_D #1#2\Z #3#4\Z {% @@ -893,7 +893,7 @@ \krof }% \def\XINT_trunc_Fneg #1.#2{\expandafter\xint_firstoftwo_thenstop - \romannumeral0\XINT_div_prepare {#2}{#1}\Z \xint_minus_thenstop}% + \romannumeral0\XINT_div_prepare {#2}{#1}\Z -}% \def\XINT_trunc_Fpos #1.#2{\expandafter\xint_firstoftwo_thenstop \romannumeral0\XINT_div_prepare {#2}{#1}\Z \space }% \def\XINT_itrunc_G #1#2\Z #3#4% @@ -1607,7 +1607,7 @@ #1#5{#2/#3[#4]}{#6/#7[#8]}% }% \def\XINT_fmax_minusminus --% - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_fmin_nonneg_b }% + {\expandafter-\romannumeral0\XINT_fmin_nonneg_b }% \def\XINT_fmax_firstneg #1-#2#3{ #1#2}% \def\XINT_fmax_secondneg -#1#2#3{ #1#3}% \def\XINT_fmax_nonneg_a #1#2#3#4% @@ -1651,7 +1651,7 @@ #1#5{#2/#3[#4]}{#6/#7[#8]}% }% \def\XINT_fmin_minusminus --% - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_fmax_nonneg_b }% + {\expandafter-\romannumeral0\XINT_fmax_nonneg_b }% \def\XINT_fmin_firstneg #1-#2#3{ -#3}% \def\XINT_fmin_secondneg -#1#2#3{ -#2}% \def\XINT_fmin_nonneg_a #1#2#3#4% @@ -1773,21 +1773,94 @@ \expandafter\XINT_float_a\the\numexpr #1\expandafter.% \romannumeral0\XINT_infrac {#2}\XINT_float_Q }% -\def\XINT_float_a #1.#2#3% #1=P, #2=n, #3=A, #4=B +\def\XINT_float_a #1.#2#3#4% {% - \XINT_float_fork #3\Z {#1}{#2}% #1 = precision, #2=n + \if\romannumeral0\XINT_isone#4XY1\expandafter\XINT_float_sp + \else\expandafter\XINT_float_fork\fi #3.{#1}{#2}{#4}% }% -\def\XINT_float_fork #1% +\def\XINT_float_sp #1% +{% + \xint_UDzerominusfork + #1-\XINT_float_spzero + 0#1\XINT_float_spneg + 0-{\XINT_float_sppos #1}% + \krof +}% +\def\XINT_float_spzero .#1#2#3#4{ 0.e0}% +\def\XINT_float_spneg {\expandafter-\romannumeral0\XINT_float_sppos}% +\def\XINT_float_sppos #1.#2#3#4#5% +{% + \expandafter\XINT_float_sp_b\the\numexpr#2-\xintLength{#1}.#1.#2.#3.% +}% +\def\XINT_float_sp_b #1% {% \xint_UDzerominusfork - #1-\XINT_float_zero - 0#1\XINT_float_J - 0-{\XINT_float_K #1}% + #1-\XINT_float_sp_quick + 0#1\XINT_float_sp_c + 0-{\XINT_float_sp_addzeros #1}% \krof }% -\def\XINT_float_zero #1\Z #2#3#4#5{ 0.e0}% -\def\XINT_float_J {\expandafter\xint_minus_thenstop\romannumeral0\XINT_float_K }% -\def\XINT_float_K #1\Z #2% #1=A, #2=P, #3=n, #4=B +\def\XINT_float_sp_quick .#1.#2.#3.% +{% + \expandafter\XINT_float_sp_done\the\numexpr #3+#2-\xint_c_i.#1;% +}% +\def\XINT_float_sp_addzeros #1.#2.#3.#4.% +{% + \expandafter\XINT_float_sp_done + \the\numexpr #4-#1+#3-\xint_c_i\expandafter.% + \romannumeral0\XINT_dsx_addzerosnofuss {#1}{#2};% +}% +\def\XINT_float_sp_done #1.#2#3;{ #2.#3e#1}% +\def\XINT_float_sp_c #1.#2% +{% + \if #29\xint_dothis {\XINT_float_sp_d\XINT_float_Wb }\fi + \xint_orthat {\XINT_float_sp_d\XINT_float_sp_Wa }#1.#2% +}% +\def\XINT_float_sp_d #1#2.#3.#4.#5.% +{% + \expandafter\XINT_float_sp_e + \the\numexpr #5+#2+#4-\xint_c_i\expandafter.% + \romannumeral0\expandafter\XINT_split_fromleft_loop + \the\numexpr #4+\xint_c_i.{}#3\W\W\W\W\W\W\W\W\Z #1% +}% +\def\XINT_float_sp_e #1.#2.#3.% +{% + \expandafter\XINT_float_sp_f + \romannumeral0\XINT_rord_main {}#2% + \xint_relax + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_relax ;#1.% +}% +\def\XINT_float_sp_f #1% +{% + \ifnum #1<\xint_c_v + \expandafter\XINT_float_sp_ga\else\expandafter\XINT_float_sp_h\fi +}% +\def\XINT_float_sp_ga #1;#2.#3% +{% + \expandafter\XINT_float_sp_Wa + \romannumeral0\XINT_rord_main {}#1% + \xint_relax + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_relax e#2% +}% +\def\XINT_float_sp_h #1;#2.#3% +{% + \expandafter#3% + \romannumeral0\XINT_addm_A 0{}1000\W\X\Y\Z #1000\W\X\Y\Z e#2% +}% +\def\XINT_float_sp_Wa #1{ #1.}% +\def\XINT_float_fork #1% +{% + \xint_UDsignfork + #1\XINT_float_J + -{\XINT_float_K #1}% + \krof +}% +\def\XINT_float_J {\expandafter-\romannumeral0\XINT_float_K }% +\def\XINT_float_K #1.#2% {% \expandafter\XINT_float_L \the\numexpr\xintLength{#1}\expandafter.\the\numexpr #2+\xint_c_ii.{#1}{#2}% @@ -1820,9 +1893,9 @@ }% \def\XINT_float_N #1.#2.#3.% {% - \ifnum #1>#3 \xint_dothis\XINT_float_N_Blong\fi - \ifnum #1=\xint_c_i\xint_dothis\XINT_float_N_Bshort\fi - \xint_orthat{\XINT_float_P 0.}% + \ifnum #1>#3 + \expandafter\XINT_float_N_Blong + \else\expandafter\XINT_float_P\fi #1.#2.#3.% }% \def\XINT_float_N_Blong #1.#2.#3.#4% @@ -1831,27 +1904,12 @@ \the\numexpr #2-#1+#3\expandafter.% \romannumeral0\XINT_split_fromleft_loop #3.{}#4\W\W\W\W\W\W\W\W\Z {#3}% }% -\def\XINT_float_NaP #1.#2.#3.#4{\XINT_float_P 0.#4.#1.#4.{#2}}% -\def\XINT_float_N_Bshort 1.#1.#2.#3% -{% - \ifnum #3=\xint_c_i \xint_dothis{\XINT_float_P 1.}\fi - \xint_orthat{\XINT_float_P 0.}1.#1.#2.#3% -}% -\def\XINT_float_P #1.#2.#3.#4.#5#6#7#8#9% -{% - \expandafter #9\expandafter#1% - \the\numexpr #2-#6+#4-\xint_c_i.{#7}{#5}{#8}{#3}% -}% -\def\XINT_float_Q #1% +\def\XINT_float_NaP #1.#2.#3.#4{\XINT_float_P #4.#1.#4.{#2}}% +\def\XINT_float_P #1.#2.#3.#4#5#6#7#8% {% - \if 1#1\expandafter\XINT_float_Ri\else\expandafter\XINT_float_Rii\fi + \expandafter #8\the\numexpr #1-#5+#3-\xint_c_i.{#6}{#4}{#7}{#2}% }% -\def\XINT_float_Ri #1.#2#3% -{% - \expandafter\XINT_float_Sa - \romannumeral0\XINT_dsx_addzerosnofuss {#1}{#2}\Z {#1}% -}% -\def\XINT_float_Rii #1.#2#3% +\def\XINT_float_Q #1.#2#3% {% \expandafter\XINT_float_Sa \romannumeral0\xintiiquo{\XINT_dsx_addzerosnofuss {#1}{#2}}{#3}\Z {#1}% @@ -1908,71 +1966,61 @@ }% \def\XINT_float_Y #1.#2{ #2e#1}% \def\XINTinFloat {\romannumeral0\XINTinfloat }% -\def\XINTinfloat [#1]#2% +\def\XINTinfloat + {\expandafter\XINT_infloat_clean\romannumeral0\XINT_infloat}% +\def\XINT_infloat_clean #1% + {\if #1!\xint_dothis\XINT_infloat_clean_a\fi\xint_orthat{ }#1}% +\def\XINT_infloat_clean_a !#1.#2[#3]% {% - \expandafter\XINT_infloat\the\numexpr #1\expandafter.% - \romannumeral0\expandafter\XINT_infloat_in - \romannumeral`&&@#2/\XINT_W[\XINT_W\XINT_T\XINT_infloat_Q + \expandafter\XINT_infloat_sp_done + \the\numexpr #3-#1\expandafter.% + \romannumeral0\XINT_dsx_addzerosnofuss {#1}{#2};% }% -\def\XINT_infloat #1.#2{#2#1.}% -\def\XINT_infloat_in #1[#2% +\def\XINT_infloat_sp_done #1.#2;{ #2[#1]}% +\def\XINTinFloatS {\romannumeral0\XINTinfloatS}% +\def\XINTinfloatS + {\expandafter\XINT_infloatS_clean\romannumeral0\XINT_infloat}% +\def\XINT_infloatS_clean #1% + {\if #1!\xint_dothis\XINT_infloatS_clean_a\fi\xint_orthat{ }#1}% +\def\XINT_infloatS_clean_a !#1.{ }% +\def\XINT_infloat [#1]#2% {% - \xint_UDXINTWfork - #2\XINT_infloat_gen - \XINT_W\XINT_infloat_res_a - \krof - #1[#2% + \expandafter\XINT_infloat_a\the\numexpr #1\expandafter.% + \romannumeral0\XINT_infrac {#2}\XINT_infloat_Q }% -\edef\XINT_infloat_gen {\noexpand\expandafter\space\noexpand\expandafter - \noexpand\XINT_infloat_a - \noexpand\romannumeral0\noexpand\XINT_frac_gen }% -\def\XINT_infloat_res_a #1% +\def\XINT_infloat_a #1.#2#3#4% {% - \xint_gob_til_zero #1\XINT_infloat_res_zero 0\XINT_infloat_res_b #1% + \if\romannumeral0\XINT_isone#4XY1\expandafter\XINT_infloat_sp + \else\expandafter\XINT_float_fork\fi #3.{#1}{#2}{#4}% }% -\def\XINT_infloat_res_zero #1\XINT_infloat_Q { \XINT_infloat_sp_zero}% -\def\XINT_infloat_sp_zero #1.{ 0[0]}% -\def\XINT_infloat_res_b #1/#2% +\def\XINT_infloat_sp #1% {% - \xint_UDXINTWfork - #2\XINT_infloat_res_ca - \XINT_W\XINT_infloat_res_cb + \xint_UDzerominusfork + #1-\XINT_infloat_spzero + 0#1\XINT_infloat_spneg + 0-{\XINT_infloat_sppos #1}% \krof - #1/#2% -}% -\def\XINT_infloat_res_ca #1[#2]/\XINT_W[\XINT_W\XINT_T\XINT_infloat_Q - { \XINT_infloat_sp #1.#2.}% -\def\XINT_infloat_res_cb #1/#2[% - {\expandafter\XINT_infloat_res_cc\romannumeral`&&@#2~#1[}% -\edef\XINT_infloat_res_cc #1~#2[#3]/\XINT_W[\XINT_W\XINT_T - {\noexpand\expandafter\space\noexpand\expandafter - \noexpand\XINT_infloat_a\noexpand\expandafter - {\noexpand\the\numexpr #3}{#2}{#1}}% -\def\XINT_infloat_sp #1.#2% -{% - \if-#2\xint_dothis{\expandafter-\romannumeral0\XINT_infloat_sp_a {}}\fi - \xint_orthat{\XINT_infloat_sp_a #2}#1.% }% -\def\XINT_infloat_sp_a #1#2.#3.% +\def\XINT_infloat_spzero .#1#2#3#4{ 0[0]}% +\def\XINT_infloat_spneg + {\expandafter\XINT_infloat_spnegend\romannumeral0\XINT_infloat_sppos}% +\def\XINT_infloat_spnegend #1% + {\if#1!\expandafter\XINT_infloat_spneg_needzeros\fi -#1}% +\def\XINT_infloat_spneg_needzeros -!#1.{!#1.-}% +\def\XINT_infloat_sppos #1.#2#3#4#5% {% - \expandafter\XINT_infloat_sp_b\the\numexpr#2-\xintLength{#1#3}.#1#3.#2.% + \expandafter\XINT_infloat_sp_b\the\numexpr#2-\xintLength{#1}.#1.#2.#3.% }% \def\XINT_infloat_sp_b #1% {% \xint_UDzerominusfork #1-\XINT_infloat_sp_quick 0#1\XINT_infloat_sp_c - 0-{\XINT_infloat_sp_addzeroes #1}% + 0-{\XINT_infloat_sp_needzeros #1}% \krof }% \def\XINT_infloat_sp_quick .#1.#2.#3.{ #1[#3]}% -\def\XINT_infloat_sp_addzeroes #1.#2.#3.#4.% -{% - \expandafter\XINT_infloat_sp_done - \the\numexpr #4-#1\expandafter.% - \romannumeral0\XINT_dsx_addzerosnofuss {#1}{#2};% -}% -\def\XINT_infloat_sp_done #1.#2;{ #2[#1]}% +\def\XINT_infloat_sp_needzeros #1.#2.#3.#4.{!#1.#2[#4]}% \def\XINT_infloat_sp_c #1.#2% {% \if #29\xint_dothis {\XINT_infloat_sp_d\XINT_infloat_Wb }\fi @@ -2017,30 +2065,7 @@ {% \expandafter\XINT_infloat_sp_done\the\numexpr #1+#3+#4.#2;% }% -\def\XINT_infloat_a #1.#2#3% #1=P, #2=n, #3=A, #4=B -{% - \XINT_infloat_fork #3\Z {#1}{#2}% #1 = precision, #2=n -}% -\def\XINT_infloat_fork #1% -{% - \xint_UDzerominusfork - #1-\XINT_infloat_zero - 0#1\XINT_infloat_J - 0-{\XINT_float_K #1}% - \krof -}% -\def\XINT_infloat_zero #1\Z #2#3#4#5{ 0[0]}% -\def\XINT_infloat_J {\expandafter-\romannumeral0\XINT_float_K }% -\def\XINT_infloat_Q #1% -{% - \if 1#1\expandafter\XINT_infloat_Ri\else\expandafter\XINT_infloat_Rii\fi -}% -\def\XINT_infloat_Ri #1.#2#3% -{% - \expandafter\XINT_infloat_Sa - \romannumeral0\XINT_dsx_addzerosnofuss {#1}{#2}\Z {#1}% -}% -\def\XINT_infloat_Rii #1.#2#3% +\def\XINT_infloat_Q #1.#2#3% {% \expandafter\XINT_infloat_Sa \romannumeral0\xintiiquo{\XINT_dsx_addzerosnofuss {#1}{#2}}{#3}\Z {#1}% @@ -2126,8 +2151,7 @@ \krof }% \def\XINT_pfloat_zero #1;#2.{ 0.}% -\def\XINT_pfloat_neg - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_pfloat_pos }% +\def\XINT_pfloat_neg {\expandafter-\romannumeral0\XINT_pfloat_pos }% \def\XINT_pfloat_pos #1e#2;#3.% {% \ifnum #2>\xint_c_v \xint_dothis\XINT_pfloat_no\fi @@ -2174,7 +2198,7 @@ \def\xintFloatAdd {\romannumeral0\xintfloatadd }% \def\xintfloatadd #1{\XINT_fladd_chkopt \xintfloat #1\xint_relax }% \def\XINTinFloatAdd {\romannumeral0\XINTinfloatadd }% -\def\XINTinfloatadd #1{\XINT_fladd_chkopt \XINTinfloat #1\xint_relax }% +\def\XINTinfloatadd #1{\XINT_fladd_chkopt \XINTinfloatS #1\xint_relax }% \def\XINT_fladd_chkopt #1#2% {% \ifx [#2\expandafter\XINT_fladd_opt @@ -2217,7 +2241,7 @@ \def\xintFloatSub {\romannumeral0\xintfloatsub }% \def\xintfloatsub #1{\XINT_flsub_chkopt \xintfloat #1\xint_relax }% \def\XINTinFloatSub {\romannumeral0\XINTinfloatsub }% -\def\XINTinfloatsub #1{\XINT_flsub_chkopt \XINTinfloat #1\xint_relax }% +\def\XINTinfloatsub #1{\XINT_flsub_chkopt \XINTinfloatS #1\xint_relax }% \def\XINT_flsub_chkopt #1#2% {% \ifx [#2\expandafter\XINT_flsub_opt @@ -2241,7 +2265,7 @@ \def\xintFloatMul {\romannumeral0\xintfloatmul }% \def\xintfloatmul #1{\XINT_flmul_chkopt \xintfloat #1\xint_relax }% \def\XINTinFloatMul {\romannumeral0\XINTinfloatmul }% -\def\XINTinfloatmul #1{\XINT_flmul_chkopt \XINTinfloat #1\xint_relax }% +\def\XINTinfloatmul #1{\XINT_flmul_chkopt \XINTinfloatS #1\xint_relax }% \def\XINT_flmul_chkopt #1#2% {% \ifx [#2\expandafter\XINT_flmul_opt @@ -2252,7 +2276,7 @@ {% #1[\XINTdigits]% {\expandafter\XINT_FL_mul_a - \romannumeral0\XINTinfloat[\XINTdigits]{#2}\XINTdigits.{#3}}% + \romannumeral0\XINTinfloatS[\XINTdigits]{#2}\XINTdigits.{#3}}% }% \def\XINT_flmul_opt #1[\xint_relax #2]%#3#4% {% @@ -2260,17 +2284,17 @@ }% \def\XINT_flmul_opt_a #1.#2#3#4% {% - #2[#1]{\expandafter\XINT_FL_mul_a\romannumeral0\XINTinfloat[#1]{#3}#1.{#4}}% + #2[#1]{\expandafter\XINT_FL_mul_a\romannumeral0\XINTinfloatS[#1]{#3}#1.{#4}}% }% \def\XINT_FL_mul_a #1[#2]#3.#4% {% - \expandafter\XINT_FL_mul_b\romannumeral0\XINTinfloat [#3]{#4}#1[#2]% + \expandafter\XINT_FL_mul_b\romannumeral0\XINTinfloatS[#3]{#4}#1[#2]% }% \def\XINT_FL_mul_b #1[#2]#3[#4]{\xintE{\xintiiMul {#3}{#1}}{#4+#2}}% \def\xintFloatDiv {\romannumeral0\xintfloatdiv }% \def\xintfloatdiv #1{\XINT_fldiv_chkopt \xintfloat #1\xint_relax }% \def\XINTinFloatDiv {\romannumeral0\XINTinfloatdiv }% -\def\XINTinfloatdiv #1{\XINT_fldiv_chkopt \XINTinfloat #1\xint_relax }% +\def\XINTinfloatdiv #1{\XINT_fldiv_chkopt \XINTinfloatS #1\xint_relax }% \def\XINT_fldiv_chkopt #1#2% {% \ifx [#2\expandafter\XINT_fldiv_opt @@ -2281,7 +2305,7 @@ {% #1[\XINTdigits]% {\expandafter\XINT_FL_div_a - \romannumeral0\XINTinfloat[\XINTdigits]{#2}\XINTdigits.{#3}}% + \romannumeral0\XINTinfloatS[\XINTdigits]{#2}\XINTdigits.{#3}}% }% \def\XINT_fldiv_opt #1[\xint_relax #2]%#3#4% {% @@ -2289,17 +2313,17 @@ }% \def\XINT_fldiv_opt_a #1.#2#3#4% {% - #2[#1]{\expandafter\XINT_FL_div_a\romannumeral0\XINTinfloat[#1]{#3}#1.{#4}}% + #2[#1]{\expandafter\XINT_FL_div_a\romannumeral0\XINTinfloatS[#1]{#3}#1.{#4}}% }% \def\XINT_FL_div_a #1[#2]#3.#4% {% - \expandafter\XINT_FL_div_b\romannumeral0\XINTinfloat[#3]{#4}#1[#2]% + \expandafter\XINT_FL_div_b\romannumeral0\XINTinfloatS[#3]{#4}#1[#2]% }% \def\XINT_FL_div_b #1[#2]#3[#4]{\xintE{#3/#1}{#4-#2}}% \def\xintFloatPow {\romannumeral0\xintfloatpow}% \def\xintfloatpow #1{\XINT_flpow_chkopt \xintfloat #1\xint_relax }% \def\XINTinFloatPow {\romannumeral0\XINTinfloatpow }% -\def\XINTinfloatpow #1{\XINT_flpow_chkopt \XINTinfloat #1\xint_relax }% +\def\XINTinfloatpow #1{\XINT_flpow_chkopt \XINTinfloatS #1\xint_relax }% \def\XINT_flpow_chkopt #1#2% {% \ifx [#2\expandafter\XINT_flpow_opt @@ -2452,11 +2476,11 @@ \def\xintFloatPower {\romannumeral0\xintfloatpower}% \def\xintfloatpower #1{\XINT_flpower_chkopt \xintfloat #1\xint_relax }% \def\XINTinFloatPower {\romannumeral0\XINTinfloatpower }% -\def\XINTinfloatpower #1{\XINT_flpower_chkopt \XINTinfloat #1\xint_relax }% +\def\XINTinfloatpower #1{\XINT_flpower_chkopt \XINTinfloatS #1\xint_relax }% \def\XINTinFloatPowerH {\romannumeral0\XINTinfloatpowerH }% \def\XINTinfloatpowerH #1#2% {\expandafter\XINT_flpowerh_a \romannumeral0\xinttrunc 1{#2}.0;% - \XINTdigits.{#1}{\XINTinfloat[\XINTdigits]}}% + \XINTdigits.{#1}{\XINTinfloatS[\XINTdigits]}}% \def\XINT_flpowerh_a #1.#2% {% \ifnum#2>\xint_c_iv\xint_dothis\XINT_flpowerh_b\fi @@ -2634,8 +2658,8 @@ 0-{\XINT_FL_fac_fork_b #1}% \krof }% -\def\XINT_FL_fac_iszero #1.#2#3#4#5{#5{1/1[0]}}% -\def\XINT_FL_fac_isneg #1.#2#3#4#5{\expandafter\xintError:FactorialOfNegative #5{0/1[0]}}% +\def\XINT_FL_fac_iszero #1.#2#3#4#5{#5{1[0]}}% +\def\XINT_FL_fac_isneg #1.#2#3#4#5{\expandafter\xintError:FactorialOfNegative #5{0[0]}}% \def\XINT_FL_fac_fork_b #1.% {% \ifnum #1>\xint_c_x^viii_mone\xint_dothis\XINT_FL_fac_toobig\fi @@ -2645,7 +2669,7 @@ \xint_orthat\XINT_FL_fac_small #1.% }% -\def\XINT_FL_fac_toobig #1.#2#3#4#5{\expandafter\xintError:TooBigFactorial #5{1/1[0]}}% +\def\XINT_FL_fac_toobig #1.#2#3#4#5{\expandafter\xintError:TooBigFactorial #5{1[0]}}% \def\XINT_FL_fac_vbig {\expandafter\XINT_FL_fac_vbigloop_a \the\numexpr \XINT_FL_fac_increaseP \xint_c_i }% @@ -2850,8 +2874,8 @@ \xint_dothis\XINT_FL_pfac_outofrange\fi \xint_orthat \XINT_FL_pfac_increaseP #1#2.#3.% }% -\def\XINT_FL_pfac_outofrange #1.#2.#3#4#5{\xintError:OutOfRangePFac #5{0/1[0]}}% -\def\XINT_FL_pfac_one #1.#2.#3#4#5{#5{1/1[0]}}% +\def\XINT_FL_pfac_outofrange #1.#2.#3#4#5{\xintError:OutOfRangePFac #5{0[0]}}% +\def\XINT_FL_pfac_one #1.#2.#3#4#5{#5{1[0]}}% \def\XINT_FL_pfac_increaseP #1.#2.#3#4% {% \expandafter\XINT_FL_pfac_a @@ -3021,8 +3045,8 @@ #1#2.#3#4.#5.% }% \def\XINT_FL_binom_outofrange #1.#2.#3.#4.#5% - {\xintError:OutOfRangeBinomial #5[#4]{0/1[0]}}% -\def\XINT_FL_binom_one #1.#2.#3.#4.#5{#5[#4]{1/1[0]}}% + {\xintError:OutOfRangeBinomial #5[#4]{0[0]}}% +\def\XINT_FL_binom_one #1.#2.#3.#4.#5{#5[#4]{1[0]}}% \def\XINT_FL_binom_aa #1.#2.#3.#4.#5% {% #5[#4]{\xintDiv{\XINT_FL_pfac_increaseP @@ -3107,7 +3131,11 @@ }% \def\XINT_flsqrt_finish #1#2.#3.#4.#5.#6.#7.#8{#8[#6]{#3#1[#7]}}% \def\XINT_flsqrt_f 5#1.% - {\xintiiifGt{\xintiNum{#1}}{2}{\XINT_flsqrt_finish 5.}{\XINT_flsqrt_again}}% + {\expandafter\XINT_flsqrt_g\romannumeral0\xintinum{#1}\relax.}% +\def\XINT_flsqrt_g #1#2#3.{\if\relax#2\xint_dothis{\XINT_flsqrt_h #1}\fi + \xint_orthat{\XINT_flsqrt_finish 5.}}% +\def\XINT_flsqrt_h #1{\ifnum #1<\xint_c_iii\xint_dothis{\XINT_flsqrt_again}\fi + \xint_orthat{\XINT_flsqrt_finish 5.}}% \def\XINT_flsqrt_again #1.#2.% {% \expandafter\XINT_flsqrt_again_a\the\numexpr #2+\xint_c_viii.% diff --git a/Master/texmf-dist/tex/generic/xint/xintgcd.sty b/Master/texmf-dist/tex/generic/xint/xintgcd.sty index 78537efcf48..fc4a69848d2 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 1.2f 2016/03/12 +%% The xint bundle 1.2g 2016/03/19 %% Copyright (C) 2013-2016 by Jean-Francois Burnol %% xintgcd: Euclidean algorithm with xint package %% --------------------------------------------------------------- @@ -70,7 +70,7 @@ \XINTsetupcatcodes% defined in xintkernel.sty \XINT_providespackage \ProvidesPackage{xintgcd}% - [2016/03/12 1.2f Euclide algorithm with xint package (JFB)]% + [2016/03/19 1.2g 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 9a001625dae..2a5828c2bf1 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 1.2f 2016/03/12 +%% The xint bundle 1.2g 2016/03/19 %% Copyright (C) 2013-2016 by Jean-Francois Burnol %% xintkernel: Paraphernalia for the xint packages %% --------------------------------------------------------------- @@ -156,7 +156,7 @@ \fi \XINT_providespackage \ProvidesPackage {xintkernel}% - [2016/03/12 1.2f Paraphernalia for the xint packages (JFB)]% + [2016/03/19 1.2g Paraphernalia for the xint packages (JFB)]% \chardef\xint_c_ 0 \chardef\xint_c_i 1 \chardef\xint_c_ii 2 @@ -209,10 +209,10 @@ \long\def\xint_firstofone #1{#1}% \long\def\xint_firstoftwo #1#2{#1}% \long\def\xint_secondoftwo #1#2{#2}% +\long\def\xint_gobble_thenstop #1{ }% \long\def\xint_firstofone_thenstop #1{ #1}% \long\def\xint_firstoftwo_thenstop #1#2{ #1}% \long\def\xint_secondoftwo_thenstop #1#2{ #2}% -\def\xint_minus_thenstop { -}% \def\xint_exchangetwo_keepbraces #1#2{{#2}{#1}}% \long\def\xint_gob_til_R #1\R {}% \long\def\xint_gob_til_W #1\W {}% diff --git a/Master/texmf-dist/tex/generic/xint/xintseries.sty b/Master/texmf-dist/tex/generic/xint/xintseries.sty index b9523bf4231..d820b443a62 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 1.2f 2016/03/12 +%% The xint bundle 1.2g 2016/03/19 %% Copyright (C) 2013-2016 by Jean-Francois Burnol %% xintseries: Expandable partial sums with xint package %% --------------------------------------------------------------- @@ -70,7 +70,7 @@ \XINTsetupcatcodes% defined in xintkernel.sty \XINT_providespackage \ProvidesPackage{xintseries}% - [2016/03/12 1.2f Expandable partial sums with xint package (JFB)]% + [2016/03/19 1.2g 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 8fb291a28cd..0a21ba1e579 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 1.2f 2016/03/12 +%% The xint bundle 1.2g 2016/03/19 %% Copyright (C) 2013-2016 by Jean-Francois Burnol %% xinttools: Expandable and non-expandable utilities %% --------------------------------------------------------------- @@ -70,7 +70,7 @@ \XINTsetupcatcodes% defined in xintkernel.sty \XINT_providespackage \ProvidesPackage{xinttools}% - [2016/03/12 1.2f Expandable and non-expandable utilities (JFB)]% + [2016/03/19 1.2g Expandable and non-expandable utilities (JFB)]% \newtoks\XINT_toks \xint_firstofone{\let\XINT_sptoken= } %<- space here! \def\xintgodef {\global\xintodef }% @@ -231,58 +231,58 @@ \long\def\XINT_lws_end\xint_bye\XINT_lws_loop_b #1#2#3{ #1}% \def\xintNthElt {\romannumeral0\xintnthelt }% \def\xintNthEltNoExpand {\romannumeral0\xintntheltnoexpand }% -\def\xintnthelt #1#2% -{% - \expandafter\XINT_nthelt_a\the\numexpr #1\expandafter.% - \expandafter{\romannumeral`&&@#2}% -}% -\def\xintntheltnoexpand #1% -{% - \expandafter\XINT_nthelt_a\the\numexpr #1.% -}% -\def\XINT_nthelt_a #1#2.% +\long\def\xintnthelt #1#2{\expandafter\XINT_nthelt_a\the\numexpr #1\expandafter.% + \expandafter{\romannumeral`&&@#2}}% +\def\xintntheltnoexpand #1{\expandafter\XINT_nthelt_a\the\numexpr #1.}% +\def\XINT_nthelt_a #1% {% \xint_UDzerominusfork - #1-{\XINT_nthelt_bzero}% - 0#1{\XINT_nthelt_bneg {#2}}% - 0-{\XINT_nthelt_bpos {#1#2}}% + #1-{\XINT_nthelt_zero }% + 0#1{\XINT_nthelt_neg }% + 0-{\XINT_nthelt_pos #1}% \krof }% -\long\def\XINT_nthelt_bzero #1% +\def\XINT_nthelt_zero .{\xintlength }% +\long\def\XINT_nthelt_neg #1.#2% {% - \XINT_length_loop 0.#1\xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye + \expandafter\XINT_nthelt_neg_a\the\numexpr + \XINT_length_loop + 0.#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye +\xint_c_i -#1.% + #2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye }% -\long\def\XINT_nthelt_bneg #1#2% +\def\XINT_nthelt_neg_a #1% {% - \expandafter\XINT_nthelt_loop_a\expandafter {\the\numexpr #1\expandafter}% - \romannumeral0\xintrevwithbracesnoexpand {#2}% - \xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye + \xint_UDzerominusfork + #1-{\XINT_nthelt_none }% + 0#1{\XINT_nthelt_none }% + 0-{\XINT_nthelt_loop_a #1}% + \krof }% -\long\def\XINT_nthelt_bpos #1#2% +\long\def\XINT_nthelt_none #1\xint_bye{ }% +\long\def\XINT_nthelt_pos #1.#2% {% - \XINT_nthelt_loop_a {#1}#2\xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye + \XINT_nthelt_loop_a #1.% + #2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye }% -\def\XINT_nthelt_loop_a #1% +\def\XINT_nthelt_loop_a #1.% {% \ifnum #1>\xint_c_viii \expandafter\XINT_nthelt_loop_b \else - \XINT_nthelt_getit - \fi - {#1}% + \expandafter\XINT_nthelt_getit + \fi #1.% }% -\long\def\XINT_nthelt_loop_b #1#2#3#4#5#6#7#8#9% +\long\def\XINT_nthelt_loop_b #1.#2#3#4#5#6#7#8#9% {% - \xint_gob_til_xint_relax #9\XINT_nthelt_silentend\xint_relax - \expandafter\XINT_nthelt_loop_a\expandafter{\the\numexpr #1-\xint_c_viii}% + \xint_gob_til_xint_relax #9\XINT_nthelt_none\xint_relax + \expandafter\XINT_nthelt_loop_a\the\numexpr #1-\xint_c_viii.% }% -\def\XINT_nthelt_silentend #1\xint_bye { }% -\def\XINT_nthelt_getit\fi #1% +\def\XINT_nthelt_getit #1.% {% - \fi\expandafter\expandafter\expandafter\XINT_nthelt_finish + \expandafter\expandafter\expandafter\XINT_nthelt_finish \csname xint_gobble_\romannumeral\numexpr#1-\xint_c_i\endcsname }% \long\edef\XINT_nthelt_finish #1#2\xint_bye @@ -290,58 +290,60 @@ \noexpand\xint_gobble_ii\xint_relax\space #1}% \def\xintKeep {\romannumeral0\xintkeep }% \def\xintKeepNoExpand {\romannumeral0\xintkeepnoexpand }% -\def\xintkeep #1#2% -{% - \expandafter\XINT_keep_a\the\numexpr #1\expandafter.% - \expandafter{\romannumeral`&&@#2}% -}% -\def\xintkeepnoexpand #1% -{% - \expandafter\XINT_keep_a\the\numexpr #1.% -}% -\def\XINT_keep_a #1#2.% +\long\def\xintkeep #1#2{\expandafter\XINT_keep_a\the\numexpr #1\expandafter.% + \expandafter{\romannumeral`&&@#2}}% +\def\xintkeepnoexpand #1{\expandafter\XINT_keep_a\the\numexpr #1.}% +\def\XINT_keep_a #1% {% \xint_UDzerominusfork - #1-{\expandafter\space\xint_gobble_i }% - 0#1{\XINT_keep_bneg_a {#2}}% - 0-{\XINT_keep_bpos {#1#2}}% + #1-{\XINT_keep_keepnone }% + 0#1{\XINT_keep_neg }% + 0-{\XINT_keep_pos #1}% \krof }% -\long\def\XINT_keep_bneg_a #1#2% +\long\def\XINT_keep_keepnone .#1{ }% +\long\def\XINT_keep_neg #1.#2% {% - \expandafter\XINT_keep_bneg_b \the\numexpr \xintLength{#2}-#1.{#2}% + \expandafter\XINT_keep_neg_a\the\numexpr + \XINT_length_loop + 0.#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye -#1.% + #2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye }% -\def\XINT_keep_bneg_b #1#2.% +\def\XINT_keep_neg_a #1% {% \xint_UDzerominusfork - #1-{\xint_firstofone_thenstop }% - 0#1{\xint_firstofone_thenstop }% - 0-{\XINT_trim_bpos {#1#2}}% + #1-{\XINT_keep_keepall }% + 0#1{\XINT_keep_keepall }% + 0-{\XINT_trim_loop_a #1}% \krof }% -\long\def\XINT_keep_bpos #1#2% +\def\XINT_keep_keepall #1.{\XINT_keep_keepall_a \space}% +\def\XINT_keep_keepall_a #1\xint_relax #2\xint_bye {#1}% +\long\def\XINT_keep_pos #1.#2% {% - \XINT_keep_loop_a {#1}{}#2\xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_bye + \XINT_keep_loop_a #1.% + {}#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_bye }% -\def\XINT_keep_loop_a #1% +\def\XINT_keep_loop_a #1.% {% \ifnum #1>\xint_c_vi \expandafter\XINT_keep_loop_b \else - \XINT_keep_finish + \expandafter\XINT_keep_finish \fi - {#1}% + #1.% }% -\long\def\XINT_keep_loop_b #1#2#3#4#5#6#7#8#9% +\long\def\XINT_keep_loop_b #1.#2#3#4#5#6#7#8#9% {% \xint_gob_til_xint_relax #9\XINT_keep_enda\xint_relax - \expandafter\XINT_keep_loop_c\expandafter{\the\numexpr #1-\xint_c_vii}% + \expandafter\XINT_keep_loop_c\the\numexpr #1-\xint_c_vii.% {{#3}{#4}{#5}{#6}{#7}{#8}{#9}}{#2}% }% -\long\def\XINT_keep_loop_c #1#2#3{\XINT_keep_loop_a {#1}{#3#2}}% -\long\def\XINT_keep_enda\xint_relax - \expandafter\XINT_keep_loop_c\expandafter #1#2#3#4\xint_bye +\long\def\XINT_keep_loop_c #1.#2#3{\XINT_keep_loop_a #1.{#3#2}}% +\long\def\XINT_keep_enda #1.#2#3#4\xint_bye {% \XINT_keep_endb #4\W\W\W\W\W\W\Z #2{#3}% }% @@ -357,205 +359,198 @@ \W\XINT_keep_endc_vi\Z }% \long\def\XINT_keep_endc_ #1\Z #2#3#4#5#6#7#8#9{ #9}% -\long\def\XINT_keep_endc_i #1\Z #2#3#4#5#6#7#8#9{ #9{#2}}% -\long\def\XINT_keep_endc_ii #1\Z #2#3#4#5#6#7#8#9{ #9{#2}{#3}}% -\long\def\XINT_keep_endc_iii #1\Z #2#3#4#5#6#7#8#9{ #9{#2}{#3}{#4}}% -\long\def\XINT_keep_endc_iv #1\Z #2#3#4#5#6#7#8#9{ #9{#2}{#3}{#4}{#5}}% -\long\def\XINT_keep_endc_v #1\Z #2#3#4#5#6#7#8#9{ #9{#2}{#3}{#4}{#5}{#6}}% -\long\def\XINT_keep_endc_vi\Z #1#2#3#4#5#6#7#8{ #8{#1}{#2}{#3}{#4}{#5}{#6}}% -\long\def\XINT_keep_finish\fi #1#2#3#4#5#6#7#8#9\xint_bye -{% - \fi\XINT_keep_finish_loop_a {#1}{}{#3}{#4}{#5}{#6}{#7}{#8}\Z {#2}% -}% -\def\XINT_keep_finish_loop_a #1% -{% - \xint_gob_til_zero #1\XINT_keep_finish_z0% - \expandafter\XINT_keep_finish_loop_b\expandafter {\the\numexpr #1-\xint_c_i}% -}% -\long\def\XINT_keep_finish_z0% - \expandafter\XINT_keep_finish_loop_b\expandafter #1#2#3\Z #4{ #4#2}% -\long\def\XINT_keep_finish_loop_b #1#2#3% -{% - \xint_gob_til_xint_relax #3\XINT_keep_finish_exit\xint_relax - \XINT_keep_finish_loop_c {#1}{#2}{#3}% -}% -\long\def\XINT_keep_finish_exit\xint_relax - \XINT_keep_finish_loop_c #1#2#3\Z #4{ #4#2}% -\long\def\XINT_keep_finish_loop_c #1#2#3% - {\XINT_keep_finish_loop_a {#1}{#2{#3}}}% +\long\def\XINT_keep_endc_i #1\Z #2#3#4#5#6#7#8#9{#9{#2}}% +\long\def\XINT_keep_endc_ii #1\Z #2#3#4#5#6#7#8#9{#9{#2}{#3}}% +\long\def\XINT_keep_endc_iii #1\Z #2#3#4#5#6#7#8#9{#9{#2}{#3}{#4}}% +\long\def\XINT_keep_endc_iv #1\Z #2#3#4#5#6#7#8#9{#9{#2}{#3}{#4}{#5}}% +\long\def\XINT_keep_endc_v #1\Z #2#3#4#5#6#7#8#9{#9{#2}{#3}{#4}{#5}{#6}}% +\long\def\XINT_keep_endc_vi\Z #1#2#3#4#5#6#7#8{#8{#1}{#2}{#3}{#4}{#5}{#6}}% +\long\def\XINT_keep_finish #1.#2#3#4#5#6#7#8#9\xint_bye +{% + \XINT_keep_finish_a #1.% + #3\xint_c_ #4\xint_c_i #5\xint_c_ii #6\xint_c_iii #7\xint_c_iv + #8\xint_c_v\xint_relax\xint_c_vi\xint_bye + {#3}{#4}{#5}{#6}{#7}{#8}\xint_bye {#2}% +}% +\long\def\XINT_keep_finish_a #1.#2\xint_relax #3#4\xint_bye +{% + \csname XINT_keep_finish_b\romannumeral\ifnum#1>#3#3\else#1\fi\endcsname +}% +\long\def\XINT_keep_finish_b #1\xint_bye #2{ #2}% +\long\def\XINT_keep_finish_bi #1#2\xint_bye #3{#3{#1}}% +\long\def\XINT_keep_finish_bii #1#2#3\xint_bye #4{#4{#1}{#2}}% +\long\def\XINT_keep_finish_biii#1#2#3#4\xint_bye #5{#5{#1}{#2}{#3}}% +\long\def\XINT_keep_finish_biv #1#2#3#4#5\xint_bye #6{#6{#1}{#2}{#3}{#4}}% +\long\def\XINT_keep_finish_bv #1#2#3#4#5#6\xint_bye #7{#7{#1}{#2}{#3}{#4}{#5}}% +\long\def\XINT_keep_finish_bvi #1\xint_bye #2{#2#1}% \def\xintKeepUnbraced {\romannumeral0\xintkeepunbraced }% \def\xintKeepUnbracedNoExpand {\romannumeral0\xintkeepunbracednoexpand }% -\def\xintkeepunbraced #1#2% -{% - \expandafter\XINT_keepunbraced_a\the\numexpr #1\expandafter.% - \expandafter{\romannumeral`&&@#2}% -}% -\def\xintkeepnoexpand #1% -{% - \expandafter\XINT_keepunbraced_a\the\numexpr #1.% -}% -\def\XINT_keepunbraced_a #1#2.% +\long\def\xintkeepunbraced #1#2% + {\expandafter\XINT_keepunbr_a\the\numexpr #1\expandafter.% + \expandafter{\romannumeral`&&@#2}}% +\def\xintkeepunbracednoexpand #1% + {\expandafter\XINT_keepunbr_a\the\numexpr #1.}% +\def\XINT_keepunbr_a #1% {% \xint_UDzerominusfork - #1-{\expandafter\space\xint_gobble_i }% - 0#1{\XINT_keep_bneg_a {#2}}% - 0-{\XINT_keepunbraced_bpos {#1#2}}% + #1-{\XINT_keep_keepnone }% + 0#1{\XINT_keep_neg }% + 0-{\XINT_keepunbr_pos #1}% \krof }% -\long\def\XINT_keepunbraced_bpos #1#2% +\long\def\XINT_keepunbr_pos #1.#2% {% - \XINT_keepunbraced_loop_a {#1}{}#2% - \xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_bye + \XINT_keepunbr_loop_a #1.% + {}#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_bye }% -\def\XINT_keepunbraced_loop_a #1% +\def\XINT_keepunbr_loop_a #1.% {% \ifnum #1>\xint_c_vi - \expandafter\XINT_keepunbraced_loop_b + \expandafter\XINT_keepunbr_loop_b \else - \XINT_keepunbraced_finish + \expandafter\XINT_keepunbr_finish \fi - {#1}% + #1.% }% -\long\def\XINT_keepunbraced_loop_b #1#2#3#4#5#6#7#8#9% +\long\def\XINT_keepunbr_loop_b #1.#2#3#4#5#6#7#8#9% {% - \xint_gob_til_xint_relax #9\XINT_keepunbraced_enda\xint_relax - \expandafter\XINT_keepunbraced_loop_c\expandafter - {\the\numexpr #1-\xint_c_vii}{#3}{#4}{#5}{#6}{#7}{#8}{#9}.{#2}% + \xint_gob_til_xint_relax #9\XINT_keepunbr_enda\xint_relax + \expandafter\XINT_keepunbr_loop_c\the\numexpr #1-\xint_c_vii.% + {#3}{#4}{#5}{#6}{#7}{#8}{#9}.{#2}% }% -\long\def\XINT_keepunbraced_loop_c #1#2#3#4#5#6#7#8.#9% - {\XINT_keepunbraced_loop_a {#1}{#9#2#3#4#5#6#7#8}}% -\long\def\XINT_keepunbraced_enda\xint_relax - \expandafter\XINT_keepunbraced_loop_c\expandafter #1#2.#3#4\xint_bye +\long\def\XINT_keepunbr_loop_c #1.#2#3#4#5#6#7#8.#9% + {\XINT_keepunbr_loop_a #1.{#9#2#3#4#5#6#7#8}}% +\long\def\XINT_keepunbr_enda #1.#2.#3#4\xint_bye {% - \XINT_keepunbraced_endb #4\W\W\W\W\W\W\Z #2{#3}% + \XINT_keepunbr_endb #4\W\W\W\W\W\W\Z #2{#3}% }% -\def\XINT_keepunbraced_endb #1#2#3#4#5#6#7\Z +\def\XINT_keepunbr_endb #1#2#3#4#5#6#7\Z {% \xint_gob_til_W - #1\XINT_keepunbraced_endc_ - #2\XINT_keepunbraced_endc_i - #3\XINT_keepunbraced_endc_ii - #4\XINT_keepunbraced_endc_iii - #5\XINT_keepunbraced_endc_iv - #6\XINT_keepunbraced_endc_v - \W\XINT_keepunbraced_endc_vi\Z -}% -\long\def\XINT_keepunbraced_endc_ #1\Z #2#3#4#5#6#7#8#9{ #9}% -\long\def\XINT_keepunbraced_endc_i #1\Z #2#3#4#5#6#7#8#9{ #9#2}% -\long\def\XINT_keepunbraced_endc_ii #1\Z #2#3#4#5#6#7#8#9{ #9#2#3}% -\long\def\XINT_keepunbraced_endc_iii #1\Z #2#3#4#5#6#7#8#9{ #9#2#3#4}% -\long\def\XINT_keepunbraced_endc_iv #1\Z #2#3#4#5#6#7#8#9{ #9#2#3#4#5}% -\long\def\XINT_keepunbraced_endc_v #1\Z #2#3#4#5#6#7#8#9{ #9#2#3#4#5#6}% -\long\def\XINT_keepunbraced_endc_vi\Z #1#2#3#4#5#6#7#8{ #8#1#2#3#4#5#6}% -\long\def\XINT_keepunbraced_finish\fi #1#2#3#4#5#6#7#8#9\xint_bye -{% - \fi\XINT_keepunbraced_finish_loop_a {#1}{}{#3}{#4}{#5}{#6}{#7}{#8}\Z {#2}% -}% -\def\XINT_keepunbraced_finish_loop_a #1% -{% - \xint_gob_til_zero #1\XINT_keepunbraced_finish_z0% - \expandafter\XINT_keepunbraced_finish_loop_b\expandafter - {\the\numexpr #1-\xint_c_i}% -}% -\long\def\XINT_keepunbraced_finish_z0% - \expandafter\XINT_keepunbraced_finish_loop_b\expandafter #1#2#3\Z #4{ #4#2}% -\long\def\XINT_keepunbraced_finish_loop_b #1#2#3% -{% - \xint_gob_til_xint_relax #3\XINT_keepunbraced_finish_exit\xint_relax - \XINT_keepunbraced_finish_loop_c {#1}{#2}{#3}% -}% -\long\def\XINT_keepunbraced_finish_exit\xint_relax - \XINT_keepunbraced_finish_loop_c #1#2#3\Z #4{ #4#2}% -\long\def\XINT_keepunbraced_finish_loop_c #1#2#3% - {\XINT_keepunbraced_finish_loop_a {#1}{#2#3}}% + #1\XINT_keepunbr_endc_ + #2\XINT_keepunbr_endc_i + #3\XINT_keepunbr_endc_ii + #4\XINT_keepunbr_endc_iii + #5\XINT_keepunbr_endc_iv + #6\XINT_keepunbr_endc_v + \W\XINT_keepunbr_endc_vi\Z +}% +\long\def\XINT_keepunbr_endc_ #1\Z #2#3#4#5#6#7#8#9{ #9}% +\long\def\XINT_keepunbr_endc_i #1\Z #2#3#4#5#6#7#8#9{ #9#2}% +\long\def\XINT_keepunbr_endc_ii #1\Z #2#3#4#5#6#7#8#9{ #9#2#3}% +\long\def\XINT_keepunbr_endc_iii #1\Z #2#3#4#5#6#7#8#9{ #9#2#3#4}% +\long\def\XINT_keepunbr_endc_iv #1\Z #2#3#4#5#6#7#8#9{ #9#2#3#4#5}% +\long\def\XINT_keepunbr_endc_v #1\Z #2#3#4#5#6#7#8#9{ #9#2#3#4#5#6}% +\long\def\XINT_keepunbr_endc_vi\Z #1#2#3#4#5#6#7#8{ #8#1#2#3#4#5#6}% +\long\def\XINT_keepunbr_finish #1.#2#3#4#5#6#7#8#9\xint_bye +{% + \XINT_keepunbr_finish_a #1.% + #3\xint_c_ #4\xint_c_i #5\xint_c_ii #6\xint_c_iii #7\xint_c_iv + #8\xint_c_v\xint_relax\xint_c_vi\xint_bye + {#3}{#4}{#5}{#6}{#7}{#8}\xint_bye {#2}% +}% +\long\def\XINT_keepunbr_finish_a #1.#2\xint_relax #3#4\xint_bye +{% + \csname XINT_keepunbr_finish_b\romannumeral\ifnum#1>#3#3\else#1\fi\endcsname +}% +\long\def\XINT_keepunbr_finish_b #1\xint_bye #2{ #2}% +\long\def\XINT_keepunbr_finish_bi #1#2\xint_bye #3{ #3#1}% +\long\def\XINT_keepunbr_finish_bii #1#2#3\xint_bye #4{ #4#1#2}% +\long\def\XINT_keepunbr_finish_biii#1#2#3#4\xint_bye #5{ #5#1#2#3}% +\long\def\XINT_keepunbr_finish_biv #1#2#3#4#5\xint_bye #6{ #6#1#2#3#4}% +\long\def\XINT_keepunbr_finish_bv #1#2#3#4#5#6\xint_bye #7{ #7#1#2#3#4#5}% +\long\def\XINT_keepunbr_finish_bvi #1#2#3#4#5#6\xint_bye #7{ #7#1#2#3#4#5#6}% \def\xintTrim {\romannumeral0\xinttrim }% \def\xintTrimNoExpand {\romannumeral0\xinttrimnoexpand }% -\def\xinttrim #1#2% -{% - \expandafter\XINT_trim_a\the\numexpr #1\expandafter.% - \expandafter{\romannumeral`&&@#2}% -}% -\def\xinttrimnoexpand #1% -{% - \expandafter\XINT_trim_a\the\numexpr #1.% -}% -\def\XINT_trim_a #1#2.% +\long\def\xinttrim #1#2{\expandafter\XINT_trim_a\the\numexpr #1\expandafter.% + \expandafter{\romannumeral`&&@#2}}% +\def\xinttrimnoexpand #1{\expandafter\XINT_trim_a\the\numexpr #1.}% +\def\XINT_trim_a #1% {% \xint_UDzerominusfork - #1-{\xint_firstofone_thenstop }% - 0#1{\XINT_trim_bneg_a {#2}}% - 0-{\XINT_trim_bpos {#1#2}}% + #1-{\XINT_trim_trimnone }% + 0#1{\XINT_trim_neg }% + 0-{\XINT_trim_pos #1}% \krof }% -\long\def\XINT_trim_bneg_a #1#2% +\long\def\XINT_trim_trimnone .#1{ #1}% +\long\def\XINT_trim_neg #1.#2% {% - \expandafter\XINT_trim_bneg_b \the\numexpr \xintLength{#2}-#1.{#2}% + \expandafter\XINT_trim_neg_a\the\numexpr + \XINT_length_loop + 0.#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye -#1.% + {}#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_bye }% -\def\XINT_trim_bneg_b #1#2.% +\def\XINT_trim_neg_a #1% {% \xint_UDzerominusfork - #1-{\expandafter\space\xint_gobble_i }% - 0#1{\expandafter\space\xint_gobble_i }% - 0-{\XINT_keep_bpos {#1#2}}% + #1-{\XINT_trim_trimall }% + 0#1{\XINT_trim_trimall }% + 0-{\XINT_keep_loop_a #1}% \krof }% -\long\def\XINT_trim_bpos #1#2% +\long\def\XINT_trim_trimall #1\xint_bye { }% +\long\def\XINT_trim_pos #1.#2% {% - \XINT_trim_loop_a {#1}#2\xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye + \XINT_trim_loop_a #1.% + #2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye }% -\def\XINT_trim_loop_a #1% +\def\XINT_trim_loop_a #1.% {% \ifnum #1>\xint_c_vii \expandafter\XINT_trim_loop_b \else - \XINT_trim_finish + \expandafter\XINT_trim_finish \fi - {#1}% + #1.% }% -\long\def\XINT_trim_loop_b #1#2#3#4#5#6#7#8#9% +\long\def\XINT_trim_loop_b #1.#2#3#4#5#6#7#8#9% {% \xint_gob_til_xint_relax #9\XINT_trim_silentend\xint_relax - \expandafter\XINT_trim_loop_a\expandafter{\the\numexpr #1-\xint_c_viii}% + \expandafter\XINT_trim_loop_a\the\numexpr #1-\xint_c_viii.% }% \def\XINT_trim_silentend #1\xint_bye { }% -\def\XINT_trim_finish\fi #1% +\def\XINT_trim_finish #1.% {% - \fi\expandafter\expandafter\expandafter\XINT_trim_finish_a + \expandafter\expandafter\expandafter\XINT_trim_finish_a \expandafter\expandafter\expandafter\space % avoids brace removal \csname xint_gobble_\romannumeral\numexpr#1\endcsname }% \long\def\XINT_trim_finish_a #1\xint_relax #2\xint_bye {#1}% \def\xintTrimUnbraced {\romannumeral0\xinttrimunbraced }% \def\xintTrimUnbracedNoExpand {\romannumeral0\xinttrimunbracednoexpand }% -\def\xinttrimunbraced #1#2% -{% - \expandafter\XINT_trimunbraced_a\the\numexpr #1\expandafter.% - \expandafter{\romannumeral`&&@#2}% -}% +\long\def\xinttrimunbraced #1#2% + {\expandafter\XINT_trimunbr_a\the\numexpr #1\expandafter.% + \expandafter{\romannumeral`&&@#2}}% \def\xinttrimunbracednoexpand #1% -{% - \expandafter\XINT_trimunbraced_a\the\numexpr #1.% -}% -\def\XINT_trimunbraced_a #1#2.% + {\expandafter\XINT_trimunbr_a\the\numexpr #1.}% +\def\XINT_trimunbr_a #1% {% \xint_UDzerominusfork - #1-{\xint_firstofone_thenstop }% - 0#1{\XINT_trimunbraced_bneg_a {#2}}% - 0-{\XINT_trim_bpos {#1#2}}% + #1-{\XINT_trim_trimnone }% + 0#1{\XINT_trimunbr_neg }% + 0-{\XINT_trim_pos #1}% \krof }% -\long\def\XINT_trimunbraced_bneg_a #1#2% +\long\def\XINT_trimunbr_neg #1.#2% {% - \expandafter\XINT_trimunbraced_bneg_b \the\numexpr \xintLength{#2}-#1.{#2}% + \expandafter\XINT_trimunbr_neg_a\the\numexpr + \XINT_length_loop + 0.#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye -#1.% + {}#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_bye }% -\def\XINT_trimunbraced_bneg_b #1#2.% +\def\XINT_trimunbr_neg_a #1% {% \xint_UDzerominusfork - #1-{\expandafter\space\xint_gobble_i }% - 0#1{\expandafter\space\xint_gobble_i }% - 0-{\XINT_keepunbraced_bpos {#1#2}}% + #1-{\XINT_trim_trimall }% + 0#1{\XINT_trim_trimall }% + 0-{\XINT_keepunbr_loop_a #1}% \krof }% \def\xintApply {\romannumeral0\xintapply }% @@ -1183,6 +1178,263 @@ }% }% \let\xintDigitsOf\xintAssignArray +\def\xintTrim:f:csv {\romannumeral0\xinttrim:f:csv }% +\def\xinttrim:f:csv #1#2% +{% + \expandafter\XINT_trim:f:csv_a\the\numexpr #1\expandafter.% + \romannumeral`&&@#2\xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye +}% +\def\XINT_trim:f:csv_a #1% +{% + \xint_UDzerominusfork + #1-{\XINT_trim:f:csv_zero }% + 0#1{\XINT_trim:f:csv_neg }% + 0-{\XINT_trim:f:csv_loop_a #1}% + \krof +}% +\def\XINT_trim:f:csv_zero .#1\xint_relax #2\xint_bye{ #1}% +\def\XINT_trim:f:csv_neg #1.#2\xint_relax% +{% + \expandafter\XINT_trim:f:csv_neg_b + \the\numexpr\expandafter\XINT_length:f:csv_a\romannumeral`&&@#2% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye + -#1.#2\xint_relax +}% +\def\XINT_trim:f:csv_neg_b #1% +{% + \xint_UDzerominusfork + #1-{\expandafter\space\xint_bye }% + 0#1{\expandafter\space\xint_bye }% + 0-{\XINT_keep:f:csv_pos #1}% + \krof +}% +\def\XINT_trim:f:csv_loop_a #1.% +{% + \ifnum #1>\xint_c_vii + \expandafter\XINT_trim:f:csv_loop_b + \else + \expandafter\XINT_trim:f:csv_finish + \fi + #1.% +}% +\def\XINT_trim:f:csv_loop_b #1.#2,#3,#4,#5,#6,#7,#8,#9,% +{% + \xint_gob_til_xint_relax #9\XINT_trim:f:csv_silentend\xint_relax + \expandafter\XINT_trim:f:csv_loop_a\the\numexpr #1-\xint_c_viii.% +}% +\def\XINT_trim:f:csv_silentend #1\xint_bye { }% +\def\XINT_trim:f:csv_finish #1.% +{% + \expandafter\XINT_trim:f:csv_finish_a + \romannumeral`&&@\csname xint_gobble:csv_\romannumeral\numexpr#1\endcsname +}% +\def\xint_gobble:csv_ {}% +\def\xint_gobble:csv_i #1,{}% +\def\xint_gobble:csv_ii #1,#2,{}% +\def\xint_gobble:csv_iii #1,#2,#3,{}% +\def\xint_gobble:csv_iv #1,#2,#3,#4,{}% +\def\xint_gobble:csv_v #1,#2,#3,#4,#5,{}% +\def\xint_gobble:csv_vi #1,#2,#3,#4,#5,#6,{}% +\def\xint_gobble:csv_vii #1,#2,#3,#4,#5,#6,#7,{}% +\def\XINT_trim:f:csv_finish_a #1\xint_relax #2\xint_bye { #1}% +\def\xintKeep:f:csv {\romannumeral0\xintkeep:f:csv }% +\def\xintkeep:f:csv #1#2% +{% + \expandafter\XINT_keep:f:csv_a\the\numexpr #1\expandafter.% + \romannumeral`&&@#2\xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye +}% +\def\XINT_keep:f:csv_a #1% +{% + \xint_UDzerominusfork + #1-{\XINT_keep:f:csv_zero }% + 0#1{\XINT_keep:f:csv_neg }% + 0-{\XINT_keep:f:csv_pos #1}% + \krof +}% +\def\XINT_keep:f:csv_zero .#1\xint_bye{ }% +\def\XINT_keep:f:csv_neg #1.#2\xint_relax% +{% + \expandafter\XINT_keep:f:csv_neg_b + \the\numexpr\expandafter\XINT_length:f:csv_a\romannumeral`&&@#2% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye + -#1.#2\xint_relax +}% +\def\XINT_keep:f:csv_neg_b #1% +{% + \xint_UDzerominusfork + #1-{\XINT_keep:f:csv_all }% + 0#1{\XINT_keep:f:csv_all }% + 0-{\XINT_trim:f:csv_loop_a #1}% + \krof +}% +\def\XINT_keep:f:csv_all #1.#2\xint_relax #3\xint_bye { #2}% +\def\XINT_keep:f:csv_pos #1.{\expandafter\xint_gobble_thenstop + \romannumeral`&&@\XINT_keep:f:csv_loop_a #1.{}}% +\def\XINT_keep:f:csv_loop_a #1.% +{% + \ifnum #1>\xint_c_vi + \expandafter\XINT_keep:f:csv_loop_b + \else + \expandafter\XINT_keep:f:csv_finish + \fi + #1.% +}% +\def\XINT_keep:f:csv_loop_b #1.#2#3,#4,#5,#6,#7,#8,#9,% +{% + \xint_gob_til_xint_relax #9\XINT_keep:f:csv_enda\xint_relax + \expandafter\XINT_keep:f:csv_loop_c\the\numexpr #1-\xint_c_vii.% + {,#3,#4,#5,#6,#7,#8,#9}{#2}% +}% +\def\XINT_keep:f:csv_loop_c #1.#2#3{\XINT_keep:f:csv_loop_a #1.{#3#2}}% +\def\XINT_keep:f:csv_enda #1.#2#3#4\xint_bye +{% + \XINT_keep:f:csv_endb #2\xint_bye {#3}% +}% +\def\XINT_keep:f:csv_endb #1\xint_relax #2\xint_bye #3{ #3#1}% +\def\XINT_keep:f:csv_finish #1.#2#3,#4,#5,#6,#7,#8,#9\xint_bye +{% + \csname XINT_keep:f:csv_finish_\romannumeral#1\endcsname + ,#3,#4,#5,#6,#7,#8,\Z {#2}% +}% +\def\XINT_keep:f:csv_finish_ #1\Z #2{#2}% +\def\XINT_keep:f:csv_finish_i ,#1,#2\Z + {\XINT_keep:f:csv_finish_f ,#1\xint_relax\Z}% +\def\XINT_keep:f:csv_finish_ii ,#1,#2,#3\Z + {\XINT_keep:f:csv_finish_f ,#1,#2\xint_relax\Z}% +\def\XINT_keep:f:csv_finish_iii ,#1,#2,#3,#4\Z + {\XINT_keep:f:csv_finish_f ,#1,#2,#3\xint_relax\Z}% +\def\XINT_keep:f:csv_finish_iv ,#1,#2,#3,#4,#5\Z + {\XINT_keep:f:csv_finish_f ,#1,#2,#3,#4\xint_relax\Z}% +\def\XINT_keep:f:csv_finish_v ,#1,#2,#3,#4,#5,#6\Z + {\XINT_keep:f:csv_finish_f ,#1,#2,#3,#4,#5\xint_relax\Z}% +\def\XINT_keep:f:csv_finish_vi ,#1,#2,#3,#4,#5,#6,#7\Z + {\XINT_keep:f:csv_finish_f ,#1,#2,#3,#4,#5,#6\xint_relax\Z}% +\def\XINT_keep:f:csv_finish_f #1\xint_relax #2\Z #3{#3#1}% +\def\xintNthEltPy:f:csv {\romannumeral0\xintntheltpy:f:csv }% +\def\xintntheltpy:f:csv #1{\expandafter\XINT_ntheltpy:f:csv\the\numexpr #1.}% +\def\XINT_ntheltpy:f:csv #1% +{% + \xint_UDsignfork + #1{\XINT_nthelt:f:csv_neg }% + -{\XINT_nthelt:f:csv_pos #1}% + \krof +}% +\long\def\XINT_nthelt:f:csv_neg #1.#2% +{% + \expandafter\XINT_nthelt:f:csv_neg_a + \the\numexpr\expandafter\XINT_length:f:csv_a\romannumeral`&&@#2% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye + -#1+\xint_c_i\expandafter.\romannumeral`&&@#2% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye +}% +\def\XINT_nthelt:f:csv_neg_a #1% +{% + \xint_UDzerominusfork + #1-{\XINT_nthelt:f:csv_none }% + 0#1{\XINT_nthelt:f:csv_none }% + 0-{\XINT_nthelt:f:csv_loop_a #1}% + \krof +}% +\def\XINT_nthelt:f:csv_none #1\xint_bye { }% +\long\def\XINT_nthelt:f:csv_pos #1.#2% +{% + \expandafter\XINT_nthelt:f:csv_loop_a\the\numexpr #1+\xint_c_i\expandafter.% + \romannumeral`&&@#2% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye +}% +\def\XINT_nthelt:f:csv_loop_a #1.% +{% + \ifnum #1>\xint_c_viii + \expandafter\XINT_nthelt:f:csv_loop_b + \else + \expandafter\XINT_nthelt:f:csv_getit + \fi #1.% +}% +\long\def\XINT_nthelt:f:csv_loop_b #1.#2,#3,#4,#5,#6,#7,#8,#9,% +{% + \xint_gob_til_xint_relax #9\XINT_nthelt:f:csv_none\xint_relax + \expandafter\XINT_nthelt:f:csv_loop_a\the\numexpr #1-\xint_c_viii.% +}% +\def\XINT_nthelt:f:csv_getit #1.% +{% + \expandafter\XINT_nthelt:f:csv_finish + \romannumeral`&&@\csname xint_gobble:csv_\romannumeral + \numexpr#1-\xint_c_i\endcsname +}% +\def\XINT_nthelt:f:csv_finish #1,#2\xint_bye +{% + \XINT_nthelt:f:csv_finishb #1\xint_relax\xint_bye +}% +\def\XINT_nthelt:f:csv_finishb #1\xint_relax #2\xint_bye { #1}% +\def\xintReverse:f:csv {\romannumeral0\xintreverse:f:csv }% +\def\xintreverse:f:csv #1% +{% + \expandafter\XINT_reverse:f:csv_loop + \expandafter{\expandafter}\romannumeral`&&@#1,% + \xint_relax,% + \xint_bye,\xint_bye,\xint_bye,\xint_bye,% + \xint_bye,\xint_bye,\xint_bye,\xint_bye,% + \xint_relax +}% +\def\XINT_reverse:f:csv_loop #1#2,#3,#4,#5,#6,#7,#8,#9,% +{% + \xint_bye #9\XINT_reverse:f:csv_cleanup\xint_bye + \XINT_reverse:f:csv_loop {,#9,#8,#7,#6,#5,#4,#3,#2#1}% +}% +\def\XINT_reverse:f:csv_cleanup\xint_bye\XINT_reverse:f:csv_loop #1#2\xint_relax +{% + \XINT_reverse:f:csv_finish #1% +}% +\def\XINT_reverse:f:csv_finish #1\xint_relax,{ }% +\def\xintLength:f:csv {\romannumeral0\xintlength:f:csv }% +\def\xintlength:f:csv #1% +{% + \expandafter\XINT_length:f:csv_a + \romannumeral`&&@#1\xint_relax,\xint_relax,\xint_relax,\xint_relax,% + \xint_relax,\xint_relax,\xint_relax,\xint_relax,\xint_bye +}% +\def\XINT_length:f:csv_a #1% +{% + \xint_gob_til_xint_relax #1\XINT_length:f:csv_empty\xint_relax + \XINT_length:f:csv_loop 0.#1% +}% +\def\XINT_length:f:csv_empty #1\xint_bye { 0}% +\def\XINT_length:f:csv_loop #1.#2,#3,#4,#5,#6,#7,#8,#9,% +{% + \xint_gob_til_xint_relax #9\XINT_length:f:csv_finish_a\xint_relax + \expandafter\XINT_length:f:csv_loop\the\numexpr #1+\xint_c_viii.% +}% +\def\XINT_length:f:csv_finish_a\xint_relax + \expandafter\XINT_length:f:csv_loop\the\numexpr #1+\xint_c_viii.#2\xint_bye +{% + \XINT_length:f:csv_finish_b #2\W,\W,\W,\W,\W,\W,\W,\Z {#1}% +}% +\def\XINT_length:f:csv_finish_b #1,#2,#3,#4,#5,#6,#7,#8\Z +{% + \xint_gob_til_W + #1\XINT_length:f:csv_finish_c \xint_c_i + #2\XINT_length:f:csv_finish_c \xint_c_ii + #3\XINT_length:f:csv_finish_c \xint_c_iii + #4\XINT_length:f:csv_finish_c \xint_c_iv + #5\XINT_length:f:csv_finish_c \xint_c_v + #6\XINT_length:f:csv_finish_c \xint_c_vi + #7\XINT_length:f:csv_finish_c \xint_c_vii + \W\XINT_length:f:csv_finish_c \xint_c_viii\Z +}% +\edef\XINT_length:f:csv_finish_c #1#2\Z #3% + {\noexpand\expandafter\space\noexpand\the\numexpr #3+#1\relax}% +\let\xintCSVTrim \xintTrim:f:csv +\let\xintCSVKeep \xintKeep:f:csv +\let\xintCSVNthEltPy \xintNthEltPy:f:csv +\let\xintCSVReverse \xintReverse:f:csv +\let\xintCSVLength \xintLength:f:csv \let\XINT_tmpa\relax \let\XINT_tmpb\relax \let\XINT_tmpc\relax \XINT_restorecatcodes_endinput% \endinput |