From c42b50b291d00f547400888b81ef4d2bcad45142 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Sun, 11 Oct 2015 21:21:00 +0000 Subject: xint (11oct15) git-svn-id: svn://tug.org/texlive/trunk@38612 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/source/generic/xint/xint.dtx | 13051 ++++++++++++----------- Master/texmf-dist/source/generic/xint/xint.ins | 2 +- 2 files changed, 6764 insertions(+), 6289 deletions(-) (limited to 'Master/texmf-dist/source/generic/xint') diff --git a/Master/texmf-dist/source/generic/xint/xint.dtx b/Master/texmf-dist/source/generic/xint/xint.dtx index 3a3a4bc6fe3..553962e7b0a 100644 --- a/Master/texmf-dist/source/generic/xint/xint.dtx +++ b/Master/texmf-dist/source/generic/xint/xint.dtx @@ -1,25 +1,25 @@ % -*- coding: iso-latin-1; time-stamp-format: "%02d-%02m-%:y at %02H:%02M:%02S %Z" -*- % N.B.: this dtx file does NOT use \DocInput, only docstrip. The user manual -% latex source is NOT prefixed with %'s +% latex source is NOT prefixed with percent characters. %<*dtx> -\def\xintdtxtimestamp {Time-stamp: <17-09-2015 at 11:09:20 CEST>} +\def\xintdtxtimestamp {Time-stamp: <10-10-2015 at 23:42:39 CEST>} % %<*drv> %% --------------------------------------------------------------- -\def\xintdocdate {2015/09/17} -\def\xintbndldate{2015/09/12} -\def\xintbndlversion {1.1c} +\def\xintdocdate {2015/10/10} +\def\xintbndldate{2015/10/10} +\def\xintbndlversion {1.2} % %<*dtx> \iffalse % meta-comment % %% README %% CHANGE LOG -%% xint v1.1c -%% 2015/09/12 +%% xint v1.2 +%% 2015/10/10 %<*readme|changes> - Source: xint.dtx v1.1c 2015/09/12 (doc 2015/09/17) + Source: xint.dtx v1.2 2015/10/10 (doc 2015/10/10) Author: Jean-Francois Burnol Info: Expandable operations on big integers, decimals, fractions License: LPPL 1.3c @@ -27,7 +27,7 @@ % %<*!readme&!changes&!dohtmlsh&!dopdfsh&!makefile> %% --------------------------------------------------------------- -%% The xint bundle v1.1c 2015/09/12 +%% The xint bundle v1.2 2015/10/10 %% Copyright (C) 2013-2015 by Jean-Francois Burnol %%% xintkernel: Paraphernalia for the xint packages %%% xinttools: Expandable and non-expandable utilities @@ -49,6 +49,34 @@ Change log is to be found in `CHANGES.pdf` or `CHANGES.html`. The user manual is `xint.pdf`, and the commented source code is available as `sourcexint.pdf`. + +Aim +=== + +The basic aim is provide *expandable* computations on big integers, +and also big fractions. 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 + + \xinttheexpr mul(add(x(x+1)(x+2), x=y..y+15), y=171286,98762,9296)\relax + +evaluates to `15979066346135829902328007959448563667099190784`. + +It is possible to use the package with Plain as well as with LaTeX. + +Sub-units `xintcore`, `xint` and `xintfrac` provide the underlying +macros, and `xintexpr` loads all of them and provides expandable +parsers allowing computations such as the above (and more). A more +light-weight package [bnumexpr](http://www.ctan.org/pkg/bnumexpr) +(LaTeX only) loads only `xintcore` and provides a parser which +handles only big integers, the four operations, the power operation +and the factorial (v1.2). + + Usage ===== @@ -78,7 +106,8 @@ be loaded in any catcode context such that letters, digits, `\` and `xintcore.sty` and `xinttools.sty` both import `xintkernel.sty` which has the catcode handler and package identifier and defines a -few utilities such as `\oodef` or `\xint_dothis/\xint_orthat`. +few utilities such as `\oodef`, `\fdef`, or `\xint_dothis/\xint_orthat`. + Installation ============ @@ -179,6 +208,7 @@ Finishing the installation in a TDS hierarchy: Depending on the destination, it may then be necessary to refresh a filename database. + License ======= @@ -207,6 +237,58 @@ pandoctpl.latex, doHTMLs.sh, doPDFs.sh, xint.dvi, xint.pdf, Makefile.mk. %-------------------------------------------------------- %<*changes>------------------------------------------------------- +`1.2 (2015/10/10)` +---- + + - the basic arithmetic implemented in **xintcore** has been entirely + rewritten. The mathematics remains the elementary school one, but the + `TeX` 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. + + - the inputs must have less than 19959 digits. But computations with + thousands of digits take time. + + - a previously standing limitation of `\xintexpr`, `\xintiiexpr`, and + of `\xintfloatexpr` to numbers of less than 5000 digits has been + lifted. + + - a *qint* 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. + + - new `\xintFloatFac` macro for computing the factorials of integers as + floating point numbers to a given precision. The `!` postfix operator + inside `\xintfloatexpr` maps to this new macro rather than to the + exact factorial as used by `\xintexpr` and `xintiiexpr`. + + - the macros `\xintAdd`, `\xintSub`, ..., now require package + **xintfrac**. With only **xintcore** or **xint** loaded, one _must_ + use `\xintiiAdd`, `\xintiiSub`, ..., or `\xintiAdd`, `\xintiSub`, + etc... + + - there is more flexibility in the parsing done by the macros from + **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`. + + - on the other hand an isolated dot `.` 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 **xintfrac**. + + - added `\ht`, `\dp`, `\wd`, `\fontcharht`, etc... to the tokens + recognized by the parsers and expanded by `\number`. + + - an obscure bug in package **xintkernel** has been fixed, regarding + the sanitization of catcodes: under certain circumstances (which + could not occur in a normal `LaTeX` context), unusual catcodes could + end up being propagated to the external world. + + - an effort at randomly shuffling around various pieces of the + documentation has been done. + + `1.1c (2015/09/12)` ---- @@ -557,13 +639,15 @@ breaking changes the macros * **xinttools** defines `\odef`, `\oodef`, `\fdef` (if the names have - already been assigned, it uses `\xintoodef` etc...). These tools - are provided for the case one uses the package macros in a - non-expandable context, particularly `\oodef` which expands twice - the macro replacement text and is thus a faster alternative to - `\edef` taking into account that the **xint** bundle macros expand - already completely in only two steps. This can be significant when - repeatedly making `\def`-initions expanding to hundreds of digits. + already been assigned, it uses `\xintoodef` etc...). These tools are + provided for the case one uses the package macros in a non-expandable + context. `\oodef` expands twice the macro replacement text, and `\fdef` + applies full expansion. They are useful in situations where one does not + want a full `\edef`. `\fdef` appears to be faster than `\oodef` in almost + all cases (with less than thousand digits in the result), and even faster + than `\edef` for expanding the package macros when the result has a few + dozens of digits. `\oodef` needs that expansion ends up in thousands of + digits to become competitive with the other two. * some across the board slight efficiency improvement as a result of modifications of various types to *fork macros* and *branching @@ -2373,6 +2457,8 @@ pdfpagemode=UseOutlines} \frenchspacing \renewcommand\familydefault\sfdefault +\def\liiibigint{\href{http://latex-project.org/svnroot/experimental/trunk/l3trial/l3bigint}{l3bigint}} + \begin{document}\thispagestyle{empty}% \ttzfamily already done \pdfbookmark[1]{Title page}{TOP} % \makeatletter % @ n'est plus actif dans dtx 1.1, ouf! @@ -2617,37 +2703,57 @@ This section provides recommended reading on first discovering the package. \subsection{The packages of the \xintname bundle} + \begin{framed} The \xintcorename and \xintname packages provide macros dedicated to \emph{expandable} computations on numbers exceeding the \TeX{} (and \eTeX{}) limit of \dtt{\number"7FFFFFFF} (\emph{i.e.} on numbers of $10$ digits or more.) +\medskip + With package \xintfracname also decimal numbers (with a dot \dtt{.} as decimal mark), numbers in scientific notation (with a lowercase \dtt{e}), and even fractions (with a forward slash \dtt{/}) are acceptable inputs. +\medskip + Package \xintexprname handles expressions written with the standard infix notations, thus providing a more convenient - interface. + interface. \begin{everbatim*} -\xinttheexpr (2981279/2662176-317127/17129791)^3\relax\par -\noindent\xintthefloatexpr 1.23456789123456789^123456789\relax{} -(<- notice the exponent size)\par -\end{everbatim*} +\xinttheexpr (2981.279/.2662176e2-3.17127e2/3.129791)^3\relax +\end{everbatim*}\newline +(the |A/B[n]| notation on output means $(A/B)\times 10^n$), or also: +\begin{everbatim*} +\xintthefloatexpr 1.23456789123456789^123456789\relax +\end{everbatim*} (<- notice the size of this exponent). + +\smallskip -\xintexprname is able to do computations with dummy variables, here an example: + Furthermore \xintexprname is also able since release |1.1| of |2014/10/28| to + do computations with dummy variables, as in this example: \begin{everbatim*} -\xinttheexpr reduce(add(1/x, x=1..100))\relax\par +\xinttheexpr seq(1+reduce(add(mul((x-i+1)/i,i=1..j),j=1..floor(x/2))), + x=10..20, 31, 51)\relax \end{everbatim*} -The reasonable range of use of the package arithmetics is with numbers of less -than $\boxed{100}$ digits (integer+decimal parts combined), as it allows to do -hundreds, even thousands of such computations with an acceptable time impact. -When developing in 2013 the basic macros still in \xintcorename, the author's -priority was the speed of operations for numbers in that range. + The reasonable range of use of the package arithmetics is with numbers of + less than \emph{one hundred or perhaps two hundred digits.} Release |1.2| + has significantly improved the speed of the basic operations for numbers + with more than $50$ digits, the speed gains getting better for bigger + numbers. Although numbers up to about \dtt{19950} digits are acceptable + inputs, the package is not at his peak efficiency when confronted with such + really big numbers having thousands of digits.\footnotemark \end{framed} +\footnotetext{The maximal handled size for inputs to multiplication is + \dtt{19959} digits. This limit is observed with the current default values + of some parameters of the tex executable (input save stack size at 5000, + maximal expansion depth at 10000). Nesting of macros will reduce it and it + is best to restrain numbers to at most \dtt{19900} digits. The output, as + naturally is the case with multiplication, may exceed the bound.} + The \eTeX{} extensions (dating back to 1999) must be enabled; this is the case by default in modern distributions, except for the |tex| executable itself which has to be the pure \textsc{D.~Knuth} software with no additions. The @@ -2659,11 +2765,6 @@ All components may be loaded with \LaTeX{} |\usepackage| or |\RequirePackage| or, for any other format based on \TeX{}, directly via \string\input{}, e.g. |\input xint.sty\relax|. There are no package options. -% -% {\makeatother\footnote{\csa{empty}, \csa{space}, \csa{z@}, -% \csa{@ne}, and \csa{m@ne} should have the same meaning as in Plain and -% \LaTeX.}} -% Each package automatically loads those not already loaded it depends on (but in a few rare cases there are some extra dependencies, for example the |gcd| function in \xintexprname expressions requires explicit loading of package @@ -2777,7 +2878,12 @@ Additional derived parsers: bool, togl, add, mul, seq, subs, rseq, rrseq, iter}. And |"| may serve for hexadecimal input (uppercase only; package \xintbinhexname required). - See also \autoref{ssec:syntax}, as well as \autoref{sec:expr11}. + |1.2| has added \dtt{qint, qfrac, qfloat} to tell the parser to skip its usual + token by token expansion when gathering the digits of a number. + + See \autoref{ssec:syntax} for the complete syntax, as well as + \autoref{sec:expr11} which focused on the extensions brought with |xintexpr + 1.1|. \end{framed} Here is an example of a computation: @@ -2818,18 +2924,10 @@ it will naturally not be able to digest a number in scientific notation or a fraction. Fixed point decimal numbers however can be understood by \TeX{} in the context of manipulation of dimensions. -The constraint of expandability exerces its spell on the programmer as a -challenge to raise, and has its rewards: this is my only excuse for pretending -that computing expandably with fractions of dozens of digits has any use. The -initial release of \xintname (|2013/03/28|) was quickly followed by -\xintfracname which handles exactly fractions, decimal numbers, scientific -numbers, hence in a derived way floating point numbers. A bit later -(|2013/05/25|) \xintexprname implemented an expandable parser of expressions -with the usual infix notations for the basic operations. -The core big integer routines (now in \xintcorename) have not been much -changed since (although my knowledge of \TeX{} programming increased a lot), -the effort of development going mainly in \xintexprname which was extended -first in september 2013, then substantially in october 2014. +% The constraint of expandability exerces its spell on the programmer as a +% challenge to raise, and has its rewards: this is my only excuse for pretending +% that computing expandably with fractions of dozens of digits has any use. + % The implementation is also maximally complicated as many functionalities of % the \TeX{} macro language can't be used in the source code of \xintname by the @@ -2844,11 +2942,11 @@ first in september 2013, then substantially in october 2014. % gains could be achieved via a complete rewrite of all basic macros of the % package. -The underlying macros to which |\xinttheexpr ...\relax| maps operations -are thus provided by packages \xintcorename, \xintname (for long) integers and -\xintfracname (for fractions, decimal numbers, scientific numbers). They are -nestable. For example to do |21+32*43|, the syntax would be (only -\xintcorename needed): +The underlying macros to which |\xinttheexpr ...\relax| and the other parsers +map the infix operations are provided by packages \xintcorename, \xintname (for +integers) and \xintfracname (for fractions, decimal numbers, and scientific +numbers). They are nestable. For example to do something like |21+32*43|, the +syntax would be (only \xintcorename is needed): \begin{everbatim*} \xintiiAdd{21}{\xintiiMul{32}{43}}\par \noindent\xintiiMul{21283978192739181739}{\xintiiSub {130938109831081320}{29810810281}} @@ -2862,11 +2960,11 @@ Needless to say this quickly becomes a bit painful. One more example (needs \end{everbatim*} This shows that package \xintfracname knows natively how to handle fractions -|A/B| (notice that |*|, |+| and |-| contrarily to |/| are not generally -accepted in the arguments to the \xintfracname macros; but see -\autoref{sec:inputs} and \autoref{sec:useofcount}) and that it has -a command \csbxint{Irr} to reduce to smallest terms (in an -|\xintexpr..\relax| this would be the |reduce| function). +|A/B|. Notice that |*|, |+| and |-| contrarily to the |/| which is treated as +a special optional delimiter are not accepted in the arguments to the +\xintfracname macros (see \autoref{sec:inputs} and \autoref{sec:useofcount} +for some exceptions). There is \csbxint{Irr} to reduce to smallest terms (in +an |\xintexpr..\relax| this would be the |reduce| function). Again, all computations done by |\xinttheexpr..\relax| are completely exact. Thus, very quickly very big numbers are created (and computation times @@ -2879,8 +2977,8 @@ assignment to |\xintDigits|): (<- notice the size of the power of ten: this surely largely exceeds your pocket calculator abilities). -It is also possible -to do some computer algebra like evaluations (only numerically though): +It is also possible to do some (expandable...) computer algebra like +evaluations (only numerically though): \begin{everbatim*} \xinttheiiexpr add(i^5, i=100..200)\relax\par \noindent\xinttheexpr add(x/(x+1), x = 1000..[3]..1020)\relax @@ -2895,31 +2993,31 @@ Make sure to read \autoref{ssec:userinterface}, \autoref{sec:expr11} and \subsection {Changes} -On |TeXLive| (and presumably |MikTeX|), issue in a console |texdoc --list -xint| to get access to the documentation files, among them |CHANGES.html| -provides the detailed cumulative change log since the initial release. - -It is also available on \href{http://ctan.org}{CTAN} via -\href{http://mirrors.ctan.org/macros/generic/xint/CHANGES.html}{this link}. -Or, running |etex xint.dtx| in a working repertory will extract a |CHANGES.md| -file with Markdown syntax. - -The most recent major changes came with release |1.1| from |2014/10/28|. +The initial \xintname (|2013/03/28|) was followed by \xintfracname +(|2013/04/14|) which handled exactly fractions and decimal numbers. Later came +\xintexprname (|2013/05/25|) and at the same time \xintfracname got extended +to handle floating point numbers. Later, \xinttoolsname was detached +(|2013/11/22|). The main focus of development during late 2013 and early 2014 +was kept on \xintexprname. One year later it got a significant upgrade with +|1.1| of |2014/10/28|. The core integer routines remained essentially +unmodified during all this time (apart from a slight improvement of division +early 2014) until their complete rewrite with release +|1.2| from |2015/10/10|. -Since, |xint| saw only minor modifications such as enhancements to the -documentation and a few bug fixes (|1.1c 2015/09/12| fixed a bug with -\csbxint{Assign}, |1.1b 2015/08/31| transferred some macros which had been -left in |xint.sty| and should have been part of |xintcore.sty|, and earlier -|1.1a 2014/11/07| had corrected a problem with \csbxint{NewExpr}). - -|1.1 2014/10/28| brought many additions, most of them to package -\xintexprname, such as for example the evaluation of expressions with dummy -variables, possibly iteratively, and with allowed nesting. See -\autoref{sec:expr11} for a description of these new functionalities. - -Apart from that, |1.1| brought also two main other changes: +\begin{description} +\item [|1.2 (2015/10/10):|] complete rewrite of the core arithmetic routines. + The efficiency for numbers with less than $20$ or $30$ digits is slightly + compromised (for addition/subtraction) but it is increased for bigger + numbers. For multiplication and division the gains are there for almost all + sizes, and become 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). +\item [|1.1 (2014/10/28):|] many extensions to package \xintexprname, such as + the evaluation of expressions with dummy variables, possibly iteratively, + with allowed nesting. See \autoref{sec:expr11} for a description of + these new functionalities. Also worthy of attention: \begin{enumerate} -\item |\xintiiexpr...\relax| now associates |/| with the \emph{rounded} +\item |\xintiiexpr...\relax| associates |/| with the \emph{rounded} division (the |//| operator being provided for the \emph{truncated} division) to be in synchrony with the habits of |\numexpr|, \item the \xintfracname macro \csbxint{Add} (corresponding to |+| in @@ -2928,13 +3026,24 @@ Apart from that, |1.1| brought also two main other changes: smallest terms, or systematically computing the |LCM| of the denominators would be too costly (I think). \end{enumerate} -Also worth mentioning is that \xintname does not load \xinttoolsname -anymore (only \xintexprname does) and that the core arithmetic macros have -been moved to a new package \xintcorename which is loaded automatically by -\xintname. +\xintname does not load \xinttoolsname +anymore (only \xintexprname does) and the core arithmetic macros are +moved to a new package \xintcorename (loaded automatically by +\xintname, itself loaded by \xintfracname, itself loaded by \xintexprname). Package \href{http://www.ctan.org/pkg/bnumexpr}{bnumexpr} (which is \LaTeX{} only) now also loads only \xintcorename. +\end{description} + +There is a file |CHANGES.html| (also |CHANGES.pdf|) which provides the +detailed cumulative change log since the initial release. To access it, issue +on the command line |texdoc --list xint| (this works |TeXLive| and there is +probably an equivalent in |MikTeX|). + +It is also available on \href{http://ctan.org}{CTAN} via +\href{http://mirrors.ctan.org/macros/generic/xint/CHANGES.html}{this link}. +Or, running |etex xint.dtx| in a working repertory will extract a |CHANGES.md| +file with Markdown syntax. \subsection{Installation instructions} \label{ssec:install} @@ -2979,95 +3088,70 @@ If you have |xint.dtx|, no internet access and can not use the Makefile method: |etex xint.dtx| extracts all files and among them the |README| as a file with name |README.md|. Further help and options will be found therein. -\subsection{FAQ} - -\def\liiibigint{\href{http://latex-project.org/svnroot/experimental/trunk/l3trial/l3bigint}{l3bigint}} +% \subsection{FAQ} -% pour accéder à l'historique des commits: -% https://github.com/latex3/latex3/tree/master/l3trial/l3bigint +% % pour accéder à l'historique des commits: +% % https://github.com/latex3/latex3/tree/master/l3trial/l3bigint -We are honoured to present here this interview with the author, dating back to -late March 2014. -\begin{description} -\item[Will \xintexprname implement \texttt{exp}, \texttt{log}, - \texttt{cos}, \texttt{sin} \dots at some point?] -I guess so. - -\item[\xintseriesname already provides generic tools.] Right, although the - casual user of the \xintname bundle will not quite know how to do variable - reduction expandably in order to use some series or Pad\'e approximants. - Besides I wrote the code at the beginning of the project and perhaps I could - do it better now (I have not looked at it for a while). Anyhow, generic things - do not help much if one wants to optimize. - -\item[Optimizing? isn't \TeX's macro expansion mechanism intrinsically slow?] - Intensive use of \csa{numexpr} and some token manipulation algorithms - exploiting to the best I could \TeX{} macros with parameters grant \xintname - a significant speed up in expandable arithmetic on big integers compared to - previously available implementations. You can do some comparisons with - multiplication on numbers with $100$ digits or division of one of $100$ - digits by another of $50$ digits, for example. However expandability is - antagonist of speed, and I agree it is not very exciting to optimize slow - things. And I was disappointed last year to realize the slowness of \TeX's - mouth when it has to keep hundreds of tokens in cheek to mix them later with - new aliments. -% https://github.com/latex3/latex3/commit/f46e22cb772ee34aeb2fb200f7907ed3e6192bac -% -\footnote{\label{fn:l3bigint2015}\textbf{2015/09/15:} the recent - (experimental, and partially still in progress) new version of \liiibigint{} - by Bruno \textsc{Le Floch} works with comparable speed as \xintname for - numbers with less than (roughly) $100$ digits (the division was not - available for testing a.t.t.o.w.), and its multiplication becomes then much - better: about $5x$ faster for numbers with $400$ digits and $20x$ faster for - numbers with $1000$ digits. Bruno succeeded into implementing expandably - Karatsuba multiplication and he achieves - sub-quadratic growth in the computation time, whereas the xint integer - multiplication time drifts from quadratic to worse than cubic: from $50$ to - $100$ digits the time factor increases by about $4.6$ for \xintname and - about $3.1$ for \liiibigint, in the former case |xint| is the faster, in - the latter it is |l3bigint| the faster. As an illustration squaring a $8000$ - digits number on my computer is $470x$ faster with the new \liiibigint{} - compared to |xint| ($5.5s$ vz $43m$). As \liiibigint{} is still in progress, - this may well evolve further (currently it seems to be limited to numbers up - to $8192$ digits). The addition currently starts getting faster than the one - from |xint| with about $400$ digits (2013 |xint dev| had a variant of - addition which I think would be faster than the new one from \liiibigint{} - in the whole range up to circa $1000$ digits; but it did not make it into - the release as it was a bit slower than the adopted one up to - $50$ digits; and adopting it would have sped up multiplication only by a - factor of $2$ anyhow, and would not have solved the steep shape of the curve - of computation times.)} -% -Believe me, I try not to think too much about the fact that the whole -enterprise is made irrelevant by Lua\LaTeX's ability to access external -libraries. - -\item[Well, why isn't this \texttt{log} etc\dots thing done yet?] -I have to decide on the maximal precision to achieve: $24$, $32$, $48$, -$64$,\dots ; to settle that I would need to implement some initial versions and -benchmark them. - -\item[Fair enough. That's the common lot. So why not yet?] I am a bit - overworked. It is also an opportunity to think over - the basic underlying mathematics, and will need devoted thinking for some not - insignificant amount of time. So far I didn't find the time, or rather I found - out good means to waste it sillily. I also anticipate that originality could - very - well not pay off at all, so small is the window for the precision. - -\item[Any chance this could be done in time for TL2014?] No, - sorry.\newline Release |1.09m| of |[2014/02/26]| was the end of a cycle, and - this |1.09n| of |[2014/04/01]| is only for a bug fix and inclusion of this - |FAQ| in the documentation. - -\footnotesize - -\item[and in time for TL2015?] ... (indistinct mumbles, something like - \emph{too tired}, \emph{I need a life}, \emph{get yourself a calculator}, - \emph{we'll see}\dots) -\end{description} +% We are honoured to present here this interview with the author, dating back to +% late March 2014. +% \begin{description} +% \item[Will \xintexprname implement \texttt{exp}, \texttt{log}, +% \texttt{cos}, \texttt{sin} \dots at some point?] +% I guess so. + +% \item[\xintseriesname already provides generic tools.] Right, although the +% casual user of the \xintname bundle will not quite know how to do variable +% reduction expandably in order to use some series or Pad\'e approximants. +% Besides I wrote the code at the beginning of the project and perhaps I could +% do it better now (I have not looked at it for a while). Anyhow, generic things +% do not help much if one wants to optimize. + +% \item[Optimizing? isn't \TeX's macro expansion mechanism intrinsically slow?] +% Intensive use of \csa{numexpr} and some token manipulation algorithms +% exploiting to the best I could \TeX{} macros with parameters grant \xintname +% a significant speed up in expandable arithmetic on big integers compared to +% previously available implementations. You can do some comparisons with +% multiplication on numbers with $100$ digits or division of one of $100$ +% digits by another of $50$ digits, for example. However expandability is +% antagonist of speed, and I agree it is not very exciting to optimize slow +% things. And I was disappointed last year to realize the slowness of \TeX's +% mouth when it has to keep hundreds of tokens in cheek to mix them later with +% new aliments. +% % https://github.com/latex3/latex3/commit/f46e22cb772ee34aeb2fb200f7907ed3e6192bac +% % +% +% Believe me, I try not to think too much about the fact that the whole +% enterprise is made irrelevant by Lua\LaTeX's ability to access external +% libraries. + +% \item[Well, why isn't this \texttt{log} etc\dots thing done yet?] +% I have to decide on the maximal precision to achieve: $24$, $32$, $48$, +% $64$,\dots ; to settle that I would need to implement some initial versions and +% benchmark them. + +% \item[Fair enough. That's the common lot. So why not yet?] I am a bit +% overworked. It is also an opportunity to think over +% the basic underlying mathematics, and will need devoted thinking for some not +% insignificant amount of time. So far I didn't find the time, or rather I found +% out good means to waste it sillily. I also anticipate that originality could +% very +% well not pay off at all, so small is the window for the precision. + +% \item[Any chance this could be done in time for TL2014?] No, +% sorry.\newline Release |1.09m| of |[2014/02/26]| was the end of a cycle, and +% this |1.09n| of |[2014/04/01]| is only for a bug fix and inclusion of this +% |FAQ| in the documentation. + +% \footnotesize + +% \item[and in time for TL2015?] ... (indistinct mumbles, something like +% \emph{too tired}, \emph{I need a life}, \emph{get yourself a calculator}, +% \emph{we'll see}\dots) +% \end{description} \section{Introduction via examples} +\label{sec:examples} The main goal is to allow expandable computations with integers and fractions of arbitrary sizes. @@ -3108,188 +3192,6 @@ which can be used to achieve this splitting accross lines, and does work in inline math mode (however it doesn't allow to separate digits by groups of three, for example).\par -\subsection{User interface} -\label{ssec:userinterface} - -The user interface for executing operations on numbers is via macros such as -\csbxint{Add} or \csbxint{Mul} which have two arguments, or via expressions -\csbxint{expr}|..\relax| which use infix notations such as |+|, |-|, |*|, |/| -and |^| (or |**|) for the basic operations, and recognize functions of one or -more comma separated arguments (such as |max|, or |round|, or |sqrt|), -parentheses, logic operators of conjunction |&&|, disjunction \verb+||+, as -well as two-way |?| and three-way |??| conditionals and more. A few examples: -% -\begin{everbatim*} -\begin{enumerate}[nosep] - \item \xintiiAdd {2719873981798137981381789317981279}{13819093809180120910390190} - \item \xintiiMul {2719873981798137981381789317981279}{13819093809180120910390190} - \item \xintthefloatexpr (19317/21913+2198/9291)^3\relax - \item \xintDigits:=64;\xintthefloatexpr (19317/21913+2198/9291)^3\relax -% Let's compute the inner sum exactly, not as a float, before raising to third power: - \item \xintDigits:=16;\xintthefloatexpr \xintexpr 19317/21913+2198/9291\relax^3\relax -\end{enumerate} -\end{everbatim*} -In \csbxint{expr}|..\relax| the contents are expanded completely from left to -right until the ending |\relax| is found and swallowed, and spaces and even -(to some extent) catcodes do not matter. Algebraic operations are done -\emph{exactly}. - -The \csbxint{floatexpr} variant is for operations which are done using the -precision set via the |\xintDigits:=N;| assignment (default is with -significands of \dtt{16} digits). - -For all |\xintexpr| variants, prefixing with |\xintthe| allows to print -the result or use it in other contexts. Shortcuts \csbxint{theexpr}, -\csbxint{thefloatexpr}, \csbxint{theiiexpr}, \dots\ are available. - -The \csbxint{iiexpr} variant is only for big integers, it does not know -fractions. - -There are some important differences of syntax between |\numexpr| and -|\xintiiexpr| and variants: -\begin{itemize} -\item Contrarily to |\numexpr|, the |\xintiiexpr| parser will stop expanding - only after having encountered (and swallowed) a \emph{mandatory} |\relax| - token. -\item In particular, spaces between digits (and not only around infix - operators or parentheses) do not stop |\xintiiexpr|, contrarily to the - situation with |numexpr|: |\the\numexpr 7 + 3 5\relax| expands (in one step) - to \dtt{\detokenize\expandafter{\the\numexpr 7 + 3 5\relax}\unskip}, whereas - |\xintthe\xintiiexpr 7 + 3 5\relax| expands (in two steps) to - \dtt{\detokenize\expandafter\expandafter\expandafter {\xintthe\xintiiexpr 7 - + 3 5\relax}}. - \item Also worth mentioning is the fact that |\numexpr -(1)\relax| is - illegal. But this is perfectly legal and with the expected result in - |\xintiiexpr...\relax|. - \item Inside an |\edef|, expressions |\xintiiexpr...\relax| get fully - evaluated, but need the prefix |\xintthe| to get printed or used as - arguments to some macros, whereas expansion of |\numexpr| in an |\edef| - occurs only if prefixed with |\the| or |\number| (or |\romannumeral|, or - the expression is included in a bigger - |\numexpr| which will be the one to have to be prefixed\dots .) -\end{itemize} - -For macros such as \csbxint{Add} or -\csbxint{Mul} the arguments are each subjected to the process of \fexpan sion: -repeated expansion of the first token until finding something unexpandable (or -being stopped by a space token). - -Conversely this process of \fexpan sion always provokes the complete expansion -of the package macros and |\xintexpr..\relax| also will expand completely -under \fexpan sion, but to a private format; the \csbxint{the} prefix allows the -computation result either to be passed as argument to one of the package -macros,\footnote{the \csa{xintthe} prefix \fexpan ds the \csa{xintexpr}-ession - then unlocks it from its private format; it should not be used for - sub-expressions inside a bigger one as it is more efficient for the - expression parser to keep the result in the private format.} or also end up on -the printed page (or in an auxiliary file). -To recapitulate, all macros dealing with computations -\begin{enumerate} -\item \emph{expand completely under the sole process of repeated expansion of - the first token, (and two expansions suffice)},\footnote{see in - \autoref{sec:expansions} for more details.} - -\item \emph{apply this \fexpan sion to each one of their arguments.} -\end{enumerate} -Hence they can be nested one within the other up to arbitrary -depths. Conditional evaluations either within the macro arguments themselves, or -with branches defined in terms of these macros are made possible via macros such -as as \csbxint{ifSgn} or \csbxint{ifCmp}. - -\begin{framed} - There is no notion of \emph{declaration of a variable} to \xintname, - \xintfracname, or \xintexprname. - The user employs the |\def|, |\edef|, or - |\newcommand| (in \LaTeX) as usual, for example: \IMPORTANT -% -\begin{everbatim*} -\def\x{1729728} \def\y{352827927} \edef\z{\xintMul {\x}{\y}} -\meaning\z -\end{everbatim*}\ (see below for the |A/B[N]| output format; with |\xintiiMul| -in place of |\xintMul| there would not be the strange looking |/1[0]|.) - -As a faster alternative to |\edef| (when hundreds of digits are involved), the -package provides |\oodef| which only expands twice its argument. This provokes -full expansion of the \xintname \fexpan dable macros (nested to possibly many -levels), inclusive of |\xintexpr| and variants. -\end{framed} - -\begingroup % pour \z, \zz -The \xintexprname package has a private internal -representation for the evaluated computation result. With -% -\begin{everbatim*} -\oodef\z {\xintexpr 3.141^18\relax} -\end{everbatim*} -% -the macro |\z| is already fully evaluated (two expansions were applied, and this -is enough), and can be reused in other |\xintexpr|-essions, such as for example -% -\begin{everbatim*} -\edef\zz {\xintexpr \z+1/\z\relax} - % (using short macro names such as \z and \zz is not too recommended in real - % life, some may have already definitions; I did it all in a group). -\end{everbatim*} -% -But to print it, or to use it as argument to one of the package macros, -it must be prefixed by |\xintthe| (a synonym for |\xintthe\xintexpr| is -\csbxint{theexpr}). Application of this |\xintthe| prefix outputs the -value in the \xintfracname semi-private internal format -|A/B[N]|,\footnote{there is also the notion of \csbxint{floatexpr}, for - which the output format after the action of \csa{xintthe} is a number in - floating point scientific notation.} representing the fraction -$(A/B)\times 10^N$. The |\zz| above produces a somewhat large output: -\begin{everbatim*} -\printnumber{\xintthe\zz }${}\approx{}$\xintFloat{\xintthe\zz} -\end{everbatim*} -\endgroup % pour \z, \zz - - \begin{framed} - By default, computations done by the macros of \xintfracname or within - |\xintexpr..\relax| are exact. Inputs containing decimal points or - scientific parts do not make the package switch to a `floating-point' mode. - The inputs, however long, are converted into exact internal representations. -% - % Floating point evaluations are done via special macros containing - % `Float' in their names, or inside |\xintfloatexpr|-essions. - - Manipulating exactly big fractions quickly leads to \dots bigger fractions. - There is a command \csbxint{Irr} (or the function |reduce| in an expression) - to reduce to smallest terms, but it has to be explicitely requested. Prior - to release |1.1| addition and subtraction blindly multiplied denominators; - they now check if one is a multiple of the other.\IMPORTANT\ But systematic - reduction of the result to its smallest terms would be too - costly.\def\everbatimindent{0pt } -\begin{everbatim*} -\xinttheexpr 27/25+46/50\relax\ is a bit simpler than \xinttheexpr (27*50+25*46)/(25*50)\relax, -but less so than \xinttheexpr reduce(27/25+46/50)\relax. And \xinttheexpr 3/75+4/50+2/100\relax\ -looks weird, but systematically reducing fractions would be too costly. -\end{everbatim*} - \end{framed} - -% -The |A/B[N]| shape is the output format of most \xintfracname macros, it -benefits from accelerated parsing when used on input, compared to the normal -user syntax which has no |[N]| part. An example of valid user input for a -fraction is -% -\leftedline{|-123.45602e78/+765.987e-123|} -% -where both the decimal parts, the scientific exponent parts, and the whole -denominator are optional components. The corresponding semi-private form in this -case would be -% -\leftedline{\xintRaw{-123.45602e78/+765.987e-123}} -% -The forward slash |/| is simply a delimiter to separate numerator and -denominator, in order to allow inputs having such denominators. - -Reduction to the irreducible form of the output must be asked for explicitely -via the \csbxint{Irr} macro or the |reduce| function within -|\xintexpr..\relax|. Elementary operations on fractions do very little of the -simplifications which could be obvious to (some) human beings. - - \subsection{Randomly chosen examples} Here are some examples of use of the package macros. The first one uses only @@ -3307,42 +3209,29 @@ Some inputs are simplified by the use of the \xintexprname package. |\xintTrunc {1500}{1234/56789}\dots|: \dtt{\printnumber {\xintTrunc {1500}{1234/56789}}\dots } -\item {$0.99^{-100}$ with 200 digits after the decimal point:}\\ -|\xinttheexpr trunc(.99^-100,200)\relax\dots|: -\dtt{\printnumber{\xinttheexpr trunc(.99^-100,200)\relax}\dots } - +\item {$0.99^{-100}$ with 200 (+1) digits after the decimal point.}\\ + |\xinttheiexpr [201] .99^-100\relax|: + \dtt{\printnumber{\xinttheiexpr [201] .99^-100\relax}}\\ + Notice that this is rounded, hence we asked |\xinttheiexpr| for one + additional digit. To get a truncated result with 200 digits after the decimal + mark, we should have issued + |\xinttheexpr trunc(.99^-100,200)\relax|, rather. -\item Just to show off (again), let's print 300 digits (after the decimal - point) of the decimal expansion of $0.7^{-25}$:% +\begin{snugframed} + The fraction |0.99^-100|'s denominator is first evaluated \emph{exactly} + (\emph{i.e.} the integer |99^100| is evaluated exactly and then used to + divide the suitable power of ten to get the requested digits); for + some longer inputs, such as for example |0.7123045678952^-243|, the + exact evaluation before truncation would be costly, and it is more efficient + to use floating point numbers: % -\footnote{the |\np| typesetting macro is from the |numprint| package.} -% -\begin{everbatim*} -% % in the preamble: -% \usepackage[english]{babel} -% \usepackage[autolanguage,np]{numprint} -% \npthousandsep{,\hskip 1pt plus .5pt minus .5pt} -% \usepackage{xintexpr} -% in the body: -\np {\xinttheexpr trunc(.7^-25,300)\relax}\dots -\end{everbatim*} - -This computation is with \csbxint{theexpr} from package \xintexprname, which -allows to use standard infix notations and function names to access the package -macros, such as here |trunc| which corresponds to the \xintfracname macro -\csbxint{Trunc}. - -\begin{snugframed} - The fraction |0.7^-25| is first evaluated \emph{exactly}; for some more - complex inputs, such as |0.7123045678952^-243|, the exact evaluation before - truncation would be rather costly, and one would rather use floating point - numbers: -% -\leftedline{|\xintDigits:=20; - \np{\xintthefloatexpr .7123045678952^-243\relax}|}% +\leftedline{|\xintDigits:=20; + \np{\xintthefloatexpr .7123045678952^-243\relax}|}% % \leftedline{\xintDigits:=20;\dtt{\np{\xintthefloatexpr .7123045678952^-243\relax }}} % +\xintDigits:=16;% +% Side note: the exponent |-243| didn't have to be put inside parentheses, contrarily to what happens with some professional computational software. |;-)| @@ -3351,7 +3240,39 @@ software. |;-)| % = 24: 0.634202211748841612732270 10^36 \end{snugframed} -\xintDigits:=16; +\item {$200!$:}\\ +|\xinttheiiexpr 200!\relax|: +\dtt{\printnumber{\xinttheiiexpr 200!\relax}} + +\item {$2000!$ as a float. As \xintexprname does not handle |exp/log| so far, + the computation is done internally without the Stirling formula, + by repeated multiplications truncated suitably:}\\ + |\xintDigits:=50;|\newline |\xintthefloatexpr 2000!\relax|: + {\xintDigits:=50;\dtt{\printnumber{\xintthefloatexpr 2000!\relax}}} + +\item Just to show off (again), let's print 300 digits (after the decimal + point) of the decimal expansion of $0.7^{-25}$:% +% +\footnote{the |\np| typesetting macro is from the |numprint| package.} +% +\begin{everbatim*} +% % in the preamble: +% \usepackage[english]{babel} +% \usepackage[autolanguage,np]{numprint} +% \npthousandsep{,\hskip 1pt plus .5pt minus .5pt} +% \usepackage{xintexpr} +% in the body: +\np {\xinttheexpr trunc(.7^-25,300)\relax}\dots +\end{everbatim*} + +This computation is with \csbxint{theexpr} from package \xintexprname, which +allows to use standard infix notations and function names to access the package +macros, such as here |trunc| which corresponds to the \xintfracname macro +\csbxint{Trunc}. Regarding this computation, please keep in mind that +\csbxint{theexpr} computes \emph{exactly} the result before truncating. As +powers with fractions lead quickly to very big ones, it is good to know that +\xintexprname also provides \csbxint{thefloatexpr} which does computations +with floating point numbers. \item Computation of a Bezout identity with |7^200-3^200| and |2^200-1|: (with \xintgcdname)\par @@ -3510,51 +3431,57 @@ digits. This is not so many, let us print them here: examples in \autoref{sec:expr11}. \end{itemize} Almost all of the computational results interspersed throughout the -documentation are not hard-coded in the source of the document. They are -the result of evaluation of the package macros, and were selected to not -impact too much the compilation time of this documentation. -Nevertheless, there are so many computations done that compilation time -is significantly increased compared to a \LaTeX\ run on a typical -document of about the same size. - -\section{The \xintname bundle} +documentation are not hard-coded in the source file of this document but are +obtained via the expansion of the package macros during the \TeX{} +run.% +% +\footnote{The CPU of my computer hates me for all those re-compilations + after changing a single letter in the \LaTeX{} source, which require each + time to do all the zillions of evaluations contained in this document\dots} +% +% on examples which were selected to not impact too much the compilation time of +% this documentation. -\subsection{General overview} +% Nevertheless, there are so many computations done that compilation time +% is significantly increased compared to a \LaTeX\ run on a typical +% document of about the same size. -The main characteristics are: -\begin{enumerate} -\item exact algebra on arbitrarily big numbers, integers as well as fractions, -\item floating point variants with user-chosen precision, -\item implemented via macros compatible with expansion-only - context. -\end{enumerate} +\section{The \xintname bundle} -`Arbitrarily big' means with less than - |2^31-1|\dtt{=\number"7FFFFFFF} digits, as most of the macros will - have to compute the length of the inputs and these lengths must be treatable - as \TeX{} integers, which are at most \dtt{\number "7FFFFFFF} - in absolute value. - This is a distant irrelevant upper bound, as no such thing can fit - in \TeX's memory! The \emph{time} taken up by the expansion only - mechanisms is a much more stringent constraint. +\subsection{Characteristics} \begin{framed} - The reasonable range is for operations with numbers of up to about - (integer+decimal part) \dtt{100} digits. + The main characteristics are: + \begin{enumerate} + \item exact algebra on arbitrarily big numbers, integers as well as + fractions, + \item floating point variants with user-chosen precision, + \item implemented via macros compatible with expansion-only context, + \item and with a parser of infix operations implementing features such as + dummy variables, and coming in various incarnations depending on the kind + of computation desired: purely on integers, on integers and fractions, or + on floating point numbers. + \end{enumerate} + + `Arbitrarily big' currently means with less than about \dtt{19950} digits: the + maximal% + \MyMarginNote[\kern\dimexpr\FrameSep+\FrameRule\relax]{Changed!} + number of digits for addition is at \dtt{19968} digits, + and it is \dtt{19959} for multiplication. \end{framed} -As just recalled, ten-digits integers starting with a $3$ already exceed the -\TeX{} bound; and \TeX{} does not have a native processing of -floating point numbers (multiplication by a decimal number of a dimension -register is allowed --- this is used for example by the -\href{http://mirror.ctan.org/graphics/pgf/base}{pgf} basic math -engine.) +Integers with only $10$ digits and starting with a $3$ already exceed the +\TeX{} bound; and \TeX{} does not have a native processing of floating point +numbers (multiplication by a decimal number of a dimension register is allowed +--- this is used for example by the +\href{http://mirror.ctan.org/graphics/pgf/base}{pgf} basic math engine.) \TeX{} elementary operations on numbers are done via the non-expandable -\emph{advance, multiply, \emph{and} divide} assignments. This was changed with -\eTeX{}'s |\numexpr| which does expandable computations using standard infix -notations with \TeX{} integers. But \eTeX{} did not modify the \TeX{} bound on -acceptable integers, and did not add floating point support. +\emph{\char92advance, \char92multiply, \emph{and} \char92divide} assignments. +This was changed with \eTeX{}'s |\numexpr| which does expandable computations +using standard infix notations with \TeX{} integers. But \eTeX{} did not +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| @@ -3581,81 +3508,73 @@ ${}^{\text{,\,}}$% The \LaTeX3 project has implemented expandably floating-point computations with 16 significant figures (\href{http://www.ctan.org/pkg/l3kernel}{l3fp}), including -special functions such as exp, log, sine and cosine.% -% -\footnote{at the time of writing (2014/10/28) the +special functions such as exp, log, sine and cosine.\footnote{at the time of writing (2014/10/28) the \href{http://www.ctan.org/pkg/l3kernel}{l3fp} (exactly represented) floating point numbers have their exponents limited to $\pm$\dtt{9999}.} % -There is -also \liiibigint, which is part of the experimental trunk of the -\href{http://latex-project.org}{\LaTeX3 Project}. Like -\href{http://www.ctan.org/pkg/bigintcalc}{bigintcalc} and \xintname it -provides macros for big integer arithmetics. All three implementations of the -basic arithmetic macros can be mapped to easier infix notations via the -services of the \href{http://www.ctan.org/pkg/bnumexpr}{bnumexpr} -package. -% -\footnote{2015/09/15: the currently available \liiibigint{} is not compatible - with the current latest \href{http://www.ctan.org/pkg/bnumexpr}{bnumexpr} - release (1.1b 2014/10/28).} - -The \xintname package can be used for $24$, $40$, etc\dots{} significant figures -but one rather quickly (not much beyond $100$ figures) hits against a -`wall' created by the constraint of expandability: currently, multiplying out -two one-hundred digits numbers takes circa $80$ or $90$ times longer than for -two ten-digits numbers, which is reasonable, but multiplying out two -one-thousand digits numbers takes more than $500$ times longer than for two one -hundred-digits numbers. This shows that the algorithm is drifting from quadratic -to cubic in that range. On my laptop multiplication of two $1000$-digits numbers -takes some seconds, so it can not be done routinely in a -document.% -% -\footnote{2013/06/07: without entering into too much technical details, the - source of this `wall' is that when dealing with two long operands, when one - wants to pick some digits from the second one, one has to jump above all - digits constituting the first one, which can not be stored away: - expandability forbids assignments to memory storage. One may envision some - sophisticated schemes, dealing with this problem in less naive ways, trying - to move big chunks of data higher up in the input stream and come back to it - later, etc...; but each `better' algorithm adds overhead for the smaller - inputs. For example, I have another version of addition which is twice - faster on inputs with 500 digits or more, but it is slightly less efficient - for 50 digits or less. This `wall' dissuaded me to look into implementing - `intelligent' multiplication which would be sub-quadratic in a model where - storing and retrieving from memory would not cost much.} -\footnote{\textbf{2015/09/15:} the new \liiibigint{} has brilliantly - successfully implemented Karatsuba multiplication, solving the issue faced - by xint in 2013 (the method is based on a clever preparation of the inputs - into a form which allows precisely a ``sophisticated scheme'' as above on - where to locate the data to be manipulated and it has I presume the cost, as - described above, of a slight overhead for small numbers -- but I did not - test that point): the speed gain compared to xint for multiplication of - numbers of about $1000$ digits is about $20x$; for numbers of $100$ digits - \liiibigint{} is only a bit faster than \xintcorename; for small numbers - \xintcorename is probably (not tested) a bit faster. See also - \autoref{fn:l3bigint2015}.} - -The conclusion perhaps could be that it is in the end lucky that the speed gains -brought by \xintname for expandable operations on big numbers do open some -non-empty range of applicability in terms of the number of kept digits for -routine floating point operations. - -The second conclusion, somewhat depressing after all the hard work, is that if -one really wants to do computations with \emph{hundreds} of digits, one should -drop the expandability requirement. Indeed, as clearly demonstrated long ago -by the \href{http://www.ctan.org/pkg/pi}{pi computing file} by \textsc{D. - Roegel} one can program \TeX{} to compute with many digits at a much higher -speed than what \xintname achieves: but, direct access to memory storage in -one form or another seems a necessity for this kind of speed and one has to -renounce at the complete expandability.\footnote{2015/09/15: the latest - developments on the \liiibigint{} side do not really modify this conclusion, - because the computations remain extremely slow compared to what one can do - in other programming structures, and also slow in comparison to what one - could do non-expandably in \TeX{} (although I know to this day no available - macro package which has done this successfully for big integer arithmetics; - perhaps I am too optimistic with respect to what one can achieve without the - burden of expandability?). + +More directly related to the \xintname bundle, there is the promising new +version of the \liiibigint{} package. It was still in development a.t.t.o.w +(2015/10/09, no division yet) and is part of the experimental trunk of the +\href{http://latex-project.org}{\LaTeX3 Project}. It is devoted to expandable +computations on big integers with an associated expression parser. Its author +(Bruno \textsc{Le Floch}) succeeded brilliantly into implementing expandably +the Karatsuba multiplication algorithm and he achieves \emph{sub-quadratic + growth for the computation time}. This shows up very clearly with numbers +having more than one thousand digits (up to the maximum which a.t.t.o.w was at +$8192$ digits). + +I report here briefly on a quick comparison, although as \liiibigint{} is work +in progress, the reported results could well have to be modified soon. The +test was on a comparison of |\bigint_eval:n {#1*#2}| from the \liiibigint{} as +available in September 2015, on one hand, and on the other hand +|\xinttheiiexpr #1*#2\relax| from \xintexprname 1.2 (rather than directly +|\xintiiMul|, to be fairer to the parsing time induced by use of +|\bigint_eval:n|) and the computations were done with +|#1=#2=9999888877999988877...repeated...|. I observed: +\begin{itemize} +\item \csbxint{iiexpr}'s multiplication appears slightly faster (about |1.5x| + or |2x| to give an average order of magnitude) up to about + $900$ digits, +\item at $1000$ digits, \liiibigint{} runs between |15%| and |20%| faster, +\item then its sub-quadratic growth shows up, and at $8000$ digits I observed + it to be about |7.6x| faster (I tried on two computers and on my laptop the + ratio was more like |8.5x--9x|). Its computation time increased from $1000$ + digits to $8000$ digits by a factor smaller than |30|, whereas for + \csbxint{iiexpr} it was a factor only slightly inferior to |200| (|225| on + my laptop) ... + Karatsuba multiplication brilliantly pays off ! +\item One observes the transition at the powers of two for the \liiibigint{} + algorithm, for example I observed \liiibigint{} to be |3.5x| faster at + $4000$ digits but only |3.1x| faster at $5000$ digits. +\end{itemize} + +Once one accepts a small overhead, one can on the basis of the lengths decide +for the best algorithm to use, and it is tempting viewing the above to imagine +that some mixed approach could combine the best of both. But again all this is +a bit premature as both packages may still evolve further. + +Anyhow, all this being said, even the superior multiplication implementation +from \liiibigint{} takes of the order of seconds on my laptop for a single +multiplication of two $5000$-digits numbers. Hence it is not possible to do +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.} + +I remain of the opinion that if one really wants to do computations with +\emph{thousands} of digits, one should drop the expandability requirement. +Indeed, as clearly demonstrated long ago by the +\href{http://www.ctan.org/pkg/pi}{pi computing file} by \textsc{D. Roegel} one +can program \TeX{} to compute with many digits at a much higher speed than +what \xintname achieves: but, direct access to memory storage in one form or +another seems a necessity for this kind of speed and one has to renounce at +the complete expandability.% +% +\footnote{2015/09/15: as I said the latest developments on the \liiibigint{} + side do not really modify this conclusion, because the computations remain + extremely slow compared to what one can do in other programming structures. Another remark one could do is that it would be tremendously easier to enhance \eTeX{} than it is to embark into writing hundreds of lines of sometimes very clever \TeX{} macro programming.} @@ -3712,9 +3631,16 @@ for \csa{numexpr} has ten digits). The present package is the result of this initial questioning. -% \begin{framed}\centering -% \xintname requires the \eTeX{} extensions. -% \end{framed} +For the record, \xintname 1.2 also got its impulse from a fast ``reversing'' +macro, which I wrote after my interest got awakened again as a result of +correspondance with Bruno \textsc{Le Floch}: this new reverse uses a \TeX nique +which \emph{requires} the tokens to be digits. I wrote a routine which works +(expandably) in quasi-linear time, but a less fancy |O(N^2)| variant which I +developed concurrently proved to be faster all the way up to perhaps $7000$ +digits, thus I dropped the quasi-linear one. The less fancy variant has the +advantage that \xintname can handle numbers with more than $19900$ digits (but +not much more than $19950$). This is with the current common values of the input +save stack and maximal expansion depth: $5000$ and $10000$ respectively. \subsection{Expansion matters} \label{sec:expansions} @@ -3893,47 +3819,195 @@ such expandable macros: creates the |\AplusBC| macro doing the above and expanding in two expansion steps. -\subsection{Efficiency; floating point macros} - -The size of the manipulated numbers is limited by two -factors:\footnote{there is an intrinsic limit of - \dtt{\number"7FFFFFFF} on the number of digits, but it is - irrelevant, in view of the other limiting factors.} (1.)~\emph{the -available memory as configured in the |tex| executable}, -(2.)~\emph{the \emph{time} necessary to fully expand the computations - themselves}. -I discovered progressively, during the first few weeks of developing the -package, that the most limiting factor is the second one, the time -needed for multiplication, division (even more for powers). It -explodes with increasing input sizes long before the computations could -get limited by constraints on \TeX's available memory: -computations with $100$ digits are still reasonably fast, but the -situation then deteriorates swiftly and multiplication with $1000$ -digits takes some seconds.% -% -\footnote{Perhaps some faster routines could emerge from an approach - which, while maintaining expandability would renounce at \fexpan - dability (without impacting the input save stack). There is one such - routine \csbxint{XTrunc} which is able to write to a file (or inside - an \csa{edef}) tens of thousands of digits of a (reasonably-sized) - fraction.} -% -\footnote{\textbf{2015/09/15}: faster routines for numbers with more than - (about) $100$ digits (for multiplication) are part of a new (experimental) - release \liiibigint{}. It succeeds in implementing Karatsuba multiplication - (division yet to be done) and this drastically improves the dependency of - time upon size. See \autoref{fn:l3bigint2015}. Some technical limitations - of \TeX{} (which can be lifted from recompiling the binary with changed - settings) currently limit the range to up to $8192$ digits. Nevertheless - multiplication with $5000$ digits takes about the same time as what - \xintcorename achieves for $1000$ digits, \emph{i.e.} some seconds on my - computer. Although the usable range of \liiibigint{} thus goes well into the - hundreds of digits, which improves greatly on the \xintcorename - implementation of multiplication (up to some overhead for numbers of a few - dozen digits), here also computation times become dissuasive far before the - \TeX{} main memory would be saturated.} - -To address this issue, floating +\subsection{User interface} +\label{ssec:userinterface} + +The user interface for executing operations on numbers is via macros such as +\csbxint{Add} or \csbxint{Mul} which have two arguments, or via expressions +\csbxint{expr}|..\relax| which use infix notations such as |+|, |-|, |*|, |/| +and |^| (or |**|) for the basic operations, and recognize functions of one or +more comma separated arguments (such as |max|, or |round|, or |sqrt|), +parentheses, logic operators of conjunction |&&|, disjunction \verb+||+, as +well as two-way |?| and three-way |??| conditionals and more. A few examples: +% +\begin{everbatim*} +\begin{enumerate}[nosep] + \item \xintiiAdd {2719873981798137981381789317981279}{13819093809180120910390190} + \item \xintiiMul {2719873981798137981381789317981279}{13819093809180120910390190} + \item \xintthefloatexpr (19317/21913+2198/9291)^3\relax + \item \xintDigits:=64;\xintthefloatexpr (19317/21913+2198/9291)^3\relax +% Let's compute the inner sum exactly, not as a float, before raising to third power: + \item \xintDigits:=16;\xintthefloatexpr \xintexpr 19317/21913+2198/9291\relax^3\relax +\end{enumerate} +\end{everbatim*} +In \csbxint{expr}|..\relax| the contents are expanded completely from left to +right until the ending |\relax| is found and swallowed, and spaces and even +(to some extent) catcodes do not matter. Algebraic operations are done +\emph{exactly}. + +The \csbxint{floatexpr} variant is for operations which are done using the +precision set via the |\xintDigits:=N;| assignment (default is with +significands of \dtt{16} digits). + +For all |\xintexpr| variants, prefixing with |\xintthe| allows to print +the result or use it in other contexts. Shortcuts \csbxint{theexpr}, +\csbxint{thefloatexpr}, \csbxint{theiiexpr}, \dots\ are available. + +The \csbxint{iiexpr} variant is only for big integers, it does not know +fractions. + +There are some important differences of syntax between |\numexpr| and +|\xintiiexpr| and variants: +\begin{itemize} +\item Contrarily to |\numexpr|, the |\xintiiexpr| parser will stop expanding + only after having encountered (and swallowed) a \emph{mandatory} |\relax| + token. +\item In particular, spaces between digits (and not only around infix + operators or parentheses) do not stop |\xintiiexpr|, contrarily to the + situation with |numexpr|: |\the\numexpr 7 + 3 5\relax| expands (in one step) + to \dtt{\detokenize\expandafter{\the\numexpr 7 + 3 5\relax}\unskip}, whereas + |\xintthe\xintiiexpr 7 + 3 5\relax| expands (in two steps) to + \dtt{\detokenize\expandafter\expandafter\expandafter {\xintthe\xintiiexpr 7 + + 3 5\relax}}. + \item Also worth mentioning is the fact that |\numexpr -(1)\relax| is + illegal. But this is perfectly legal and with the expected result in + |\xintiiexpr...\relax|. + \item Inside an |\edef|, expressions |\xintiiexpr...\relax| get fully + evaluated, but need the prefix |\xintthe| to get printed or used as + arguments to some macros, whereas expansion of |\numexpr| in an |\edef| + occurs only if prefixed with |\the| or |\number| (or |\romannumeral|, or + the expression is included in a bigger + |\numexpr| which will be the one to have to be prefixed\dots .) +\end{itemize} + +For macros such as \csbxint{Add} or +\csbxint{Mul} the arguments are each subjected to the process of \fexpan sion: +repeated expansion of the first token until finding something unexpandable (or +being stopped by a space token). + +Conversely this process of \fexpan sion always provokes the complete expansion +of the package macros and |\xintexpr..\relax| also will expand completely +under \fexpan sion, but to a private format; the \csbxint{the} prefix allows the +computation result either to be passed as argument to one of the package +macros,\footnote{the \csa{xintthe} prefix \fexpan ds the \csa{xintexpr}-ession + then unlocks it from its private format; it should not be used for + sub-expressions inside a bigger one as it is more efficient for the + expression parser to keep the result in the private format.} or also end up on +the printed page (or in an auxiliary file). +To recapitulate, all macros dealing with computations +\begin{enumerate} +\item \emph{expand completely under the sole process of repeated expansion of + the first token, (and two expansions suffice)},\footnote{see in + \autoref{sec:expansions} for more details.} + +\item \emph{apply this \fexpan sion to each one of their arguments.} +\end{enumerate} +Hence they can be nested one within the other up to arbitrary +depths. Conditional evaluations either within the macro arguments themselves, or +with branches defined in terms of these macros are made possible via macros such +as as \csbxint{ifSgn} or \csbxint{ifCmp}. + +\begin{framed} + There is no notion of \emph{declaration of a variable} to \xintname, + \xintfracname, or \xintexprname. + The user employs the |\def|, |\edef|, or + |\newcommand| (in \LaTeX) as usual, for example: \IMPORTANT +% +\begin{everbatim*} +\def\x{1729728} \def\y{352827927} \edef\z{\xintMul {\x}{\y}} +\meaning\z +\end{everbatim*}\ (see below for the |A/B[N]| output format; with |\xintiiMul| +in place of |\xintMul| there would not be the strange looking |/1[0]|.) + +The package provides |\oodef| which only expands twice its argument. This +provokes full expansion of the \xintname macros (nested to possibly many +levels), inclusive of |\xintexpr| and variants. However, it is typically slower +then |\edef| (and quite slower for small things) when the expansion ends up +consisting of less than about one thousand digits. The second utility next to +|\oodef| is |\fdef| which applies full expansion upfront and appears to be +competitive with and even faster than |\edef| already in the case of expansion +leading to a few dozen digits. +\end{framed} + +\begingroup % pour \z, \zz +The \xintexprname package has a private internal +representation for the evaluated computation result. With +% +\begin{everbatim*} +\edef\z {\xintexpr 3.141^18\relax} +\end{everbatim*} +% +the macro |\z| is already fully evaluated (two expansions were applied, and this +is enough), and can be reused in other |\xintexpr|-essions, such as for example +% +\begin{everbatim*} +\edef\zz {\xintexpr \z+1/\z\relax} + % (using short macro names such as \z and \zz is not too recommended in real + % life, some may have already definitions; I did it all in a group). +\end{everbatim*} +% +But to print it, or to use it as argument to one of the package macros, +it must be prefixed by |\xintthe| (a synonym for |\xintthe\xintexpr| is +\csbxint{theexpr}). Application of this |\xintthe| prefix outputs the +value in the \xintfracname semi-private internal format +|A/B[N]|,\footnote{there is also the notion of \csbxint{floatexpr}, for + which the output format after the action of \csa{xintthe} is a number in + floating point scientific notation.} representing the fraction +$(A/B)\times 10^N$. The |\zz| above produces a somewhat large output: +\begin{everbatim*} +\printnumber{\xintthe\zz }${}\approx{}$\xintFloat{\xintthe\zz} +\end{everbatim*} +\endgroup % pour \z, \zz + + \begin{framed} + By default, computations done by the macros of \xintfracname or within + |\xintexpr..\relax| are exact. Inputs containing decimal points or + scientific parts do not make the package switch to a `floating-point' mode. + The inputs, however long, are converted into exact internal representations. +% + % Floating point evaluations are done via special macros containing + % `Float' in their names, or inside |\xintfloatexpr|-essions. + + Manipulating exactly big fractions quickly leads to \dots bigger fractions. + There is a command \csbxint{Irr} (or the function |reduce| in an expression) + to reduce to smallest terms, but it has to be explicitely requested. Prior + to release |1.1| addition and subtraction blindly multiplied denominators; + they now check if one is a multiple of the other.\IMPORTANT\ But systematic + reduction of the result to its smallest terms would be too + costly.\def\everbatimindent{0pt } +\begin{everbatim*} +\xinttheexpr 27/25+46/50\relax\ is a bit simpler than \xinttheexpr (27*50+25*46)/(25*50)\relax, +but less so than \xinttheexpr reduce(27/25+46/50)\relax. And \xinttheexpr 3/75+4/50+2/100\relax\ +looks weird, but systematically reducing fractions would be too costly. +\end{everbatim*} + \end{framed} + +% +The |A/B[N]| shape is the output format of most \xintfracname macros, it +benefits from accelerated parsing when used on input, compared to the normal +user syntax which has no |[N]| part. An example of valid user input for a +fraction is +% +\leftedline{|-123.45602e78/+765.987e-123|} +% +where both the decimal parts, the scientific exponent parts, and the whole +denominator are optional components. The corresponding semi-private form in this +case would be +% +\leftedline{\xintRaw{-123.45602e78/+765.987e-123}} +% +The forward slash |/| is simply a delimiter to separate numerator and +denominator, in order to allow inputs having such denominators. + +Reduction to the irreducible form of the output must be asked for explicitely +via the \csbxint{Irr} macro or the |reduce| function within +|\xintexpr..\relax|. Elementary operations on fractions do very little of the +simplifications which could be obvious to (some) human beings. + + +\subsection{Floating point macros} + +Floating point macros are provided to work with a given arbitrary precision. The default size for significands is $16$ digits. Working with significands of $24$, $32$, $48$, $64$, or even $80$ digits is well within the reach of the package. But @@ -3947,6 +4021,22 @@ values up to $32767$.\footnote{for a one-shot conversion of a fraction to float overflow may occur if the exponents are a bit too close to the \TeX{} bound \dtt{$\pm$\number"7FFFFFFF}.} +\begin{framed} + Currently, the only transcendental operation is the square root + (\csbxint{FloatSqrt}). The elementary functions are not yet implemented. The + power function (\csbxint{FloatPow}, \csbxint{FloatPower}) accept only + (positive or negative) integer exponents. +\end{framed} + +\begin{framed} + Floating point multiplication of two numbers with |P| digits of precision + evaluates \emph{exactly} the exact product with |2P| or |2P-1| digits, + before rounding to |P| digits: obviously this is very wasteful when |P| is + large. But \xintname is initially an exact algebraic operator, not a + floating point one with a fixed maximal size for operands, and the author + hasn't yet had the opportunity to re-examine that point. +\end{framed} + Here is such a floating point computation: % \leftedline{|\xintFloatPower [48] {1.1547}{\xintiiPow {2}{35}}|} @@ -3993,25 +4083,40 @@ exponents. \section{User interface} -Maintaining complete expandability is not for the faint of heart as it excludes -doing macro definitions in the midst of the computation; in many cases, one does -not need complete expandability, and definitions are allowed. In such contexts, -there is no declaration for the user to be made to the package of a ``typed -variable'' such as a long integer, or a (long) fraction, or possibly an -|\xintexpr|-ession. Rather, the user has at its disposal the general tools of -the \TeX{} language: |\def| and |\edef|. In \LaTeX\ there is |\newcommand| as -wrapper to |\def|, -but \LaTeX\ chose not to provide an analogous wrapper for |\edef|. It can still -be used directly of course.\footnote{I don't know if \LaTeX3 will still allow - direct use of |\def| and |\edef|\dots} - -The \xinttoolsname package provides |\oodef| which expands twice the replacement -text\footnote{only for parameter less undelimited macros.}, hence forces -complete expansion when the top level of this replacement -text is a call to one of the \xintname bundle macros, its arguments being -themselves chains of such macros. There is also |\fdef| which will apply \fexpan -sion to the replacement text. Both are in such uses faster alternatives to -|\edef|. +{\etocdefaultlines\etocsettocstyle{}{}\localtableofcontents} + + +% Je ne sais pas ce que faisait ce paragraphe ici: +% +% Maintaining complete expandability is not for the faint of heart as it excludes +% doing macro definitions in the midst of the computation; in many cases, one does +% not need complete expandability, and definitions are allowed. In such contexts, +% there is no declaration for the user to be made to the package of a ``typed +% variable'' such as a long integer, or a (long) fraction, or possibly an +% |\xintexpr|-ession. Rather, the user has at its disposal the general tools of +% the \TeX{} language: |\def| and |\edef|. In \LaTeX\ there is |\newcommand| as +% wrapper to |\def|, +% but \LaTeX\ chose not to provide an analogous wrapper for |\edef|. It can still +% be used directly of course.\footnote{I don't know if \LaTeX3 will still allow +% direct use of |\def| and |\edef|\dots} + +%%%%%%%%%%%%% pas le bon endroit pour cette discussion +% The \xinttoolsname package provides |\oodef|, resp. |\fdef|, which expands +% twice, resp. fully (\fexpan sion), the replacement text\footnote{only for +% parameter less undelimited macros.}, hence forces complete expansion when +% this replacement text is a call to one of the \xintname bundle macros, its +% arguments being either explicit digits or further such macro calls. They are +% useful as sometimes one does not want |\edef| expansion, \emph{e.g.} with a +% macro such as \csbxint{Trim} which acts on lists of braced tokens which one +% might not want to see expanded. Furthermore |\fdef| appears to be faster than +% |\edef| in (non-trivial) situations already with only a few dozens of digits: I +% tested it to be a bit faster than |\edef| for expanding |\xintiiPow {2}{100}| +% (which has $31$ digits). However |\oodef| needs thousands of digits to become +% competitive.% +% % +% \footnote{earlier releases of this manual sort of suggested \csa{oodef} was +% competitive starting with a ``few hundred'' digits but that was perhaps a bit +% optimistic. The better choice is \csa{fdef}.} This section will explain the various inputs which are recognized by the package macros and the format for their outputs. Inputs have mainly five possible @@ -4046,13 +4151,8 @@ Outputs are mostly of the following types: or be used as argument to the package macros. \end{enumerate} -{\etocdefaultlines\etocsettocstyle{}{}\localtableofcontents} - \subsection {Input formats}\label{sec:inputs} -% \edef\z {\xintAdd -% {+--0367.8920280/-++278.289287}{-109.2882/+270.12898}} - Some macro arguments are by nature `short' integers,\ntype{\numx} \emph{i.e.} less than (or equal to) in absolute value \np{\number "7FFFFFFF}. This is generally the case for arguments which serve to count or index something. They @@ -4065,13 +4165,13 @@ the allowed input formats for `long numbers' and `fractions' are: \begin{enumerate} \item the strict format\ntype{f} is for some macros of \xintname which only \fexpan d their arguments. After this \fexpan sion the input should be a - string of digits, optionally preceded by a unique minus sign. The first digit - can be zero only if the number is zero. A plus sign is not accepted. |-0| is - not legal in the strict format. A count register can serve as argument of such - a macro only if prefixed by |\the| or |\number|. Most macros of \xintname are - like \csbxint{Add} and accept the extended format described in the next item; - they may have a `strict' variant such as \csbxint{iiAdd} which remains - available even with \xintfracname loaded, for optimization purposes. + string of digits, optionally preceded by a unique minus sign. The first + digit can be zero only if the number is zero. A plus sign is not accepted. + |-0| is not legal in the strict format. A count register can serve as + argument of such a macro only if prefixed by |\the| or |\number|. Macros of + \xintname such as \csbxint{iiAdd} with a double |ii| require this `strict' + format for the inputs. The macros such as \csbxint{iAdd} with a single |i| + will apply the \csbxint{Num} normalizer described in the next item. \item the macro \csbxint{Num} normalizes into strict format an input having arbitrarily many minus and plus signs, followed by a string of zeroes, then @@ -4086,90 +4186,126 @@ the allowed input formats for `long numbers' and `fractions' are: \csbxint{Num}.% % \footnote{A - \LaTeX{} \texttt{\char 92value\{countername\}} is accepted as macro + \LaTeX{} |\value{countername}| is accepted as macro argument.} -\item the fraction format\ntype{\Ff} is what is expected by the macros of - \xintfracname: a fraction is constituted of a numerator |A| and optionally a - denominator |B|, separated by a forward slash |/| and |A| and |B| may be - macros which will be automatically given to \csbxint{Num}. Each of |A| and |B| - may be decimal numbers (the decimal mark must be a |.|). Here is an - example:% - % - \footnote{the square brackets one sees in various outputs are - explained - near the end of this section.} % - % - \leftedline{|\xintAdd - {+--0367.8920280/-++278.289287}{-109.2882/+270.12898}|} +\item the fraction format\ntype{\Ff} is what is expected on input by the + macros of \xintfracname. It has two variants: + \begin{description} + \item[general:] these are inputs of the shape |A.BeC/D.EeF|. Example: +\begin{everbatim*} +\noindent\xintRaw{+--0367.8920280e17/-++278.289287e-15}\newline +\xintRaw{+--+1253.2782e++--3/---0087.123e---5}\par +\end{everbatim*} + Notice that the input process does not reduce fractions to smallest terms. + Here are the rules of the format:\footnote{Earlier releases were slightly + more strict, the optional decimal parts |B|, |E| were not individually + \fexpan ded.} + \begin{itemize} + \item everything is optional, absent numbers are treated as zero, here are + some extreme cases: +\begin{everbatim*} +\xintRaw{}, \xintRaw{.}, \xintRaw{./1.e}, \xintRaw{-.e}, \xintRaw{e/-1} +\end{everbatim*} + \item |AB| and |DE| may start with pluses and minuses, then leading + zeroes, then digits. + \item |C| and |F| will be given to |\numexpr| and can be anything + recognized as such and not provoking arithmetic overflow (the lengths of + |B| and |E| will also intervene to build the final exponent naturally + which must obeys the \TeX{} bound). + \item the |/|, |.| (numerator and/or denominator) and |e| + (numerator and/or denominator) are all optional components. + \item each of |A|, |B|, |C|, |D|, |E| and |F| may arise from \fexpan sion + of a macro. + \item the whole thing may arise from \fexpan sion, however the |/|, |.|, + and |e| should all come from this initial expansion. The |e| of + scientific notation is mandatorily lowercased. + \end{itemize} + \item[restricted:] these are inputs either of the shape |A[N]| or |A/B[N]| + (representing the fraction |A/B| times |10^N|) where the whole thing or + each of |A|, |B|, |N| (but then not |/| or |[|) may arise from \fexpan + sion, |A| (after expansion) \emph{must} have a unique optional minus sign + and no leading zeroes, |B| (after expansion) if present \emph{must} be a + positive integer with no signs and no leading zeroes, |N| (which may be + empty) will be given to |\numexpr|. This format is parsed with smaller + overhead than the general one, thus allowing more efficient nesting of + macros as it is the one used on output (except for the floating macros). + Any deviation from the rules above will result in errors.\footnote{With + earlier releases the |N| could not be empty and had to be given as + explicit digits, not some macro or expression expanded in |\numexpr|.} + \end{description} + Examples of inputs and outputs: +\begin{everbatim*} + \xintAdd{+--0367.8920280/-++278.289287}{-109.2882/+270.12898}\newline + \xintAdd{10.1e1}{101.010e3}\newline + \xintFloatAdd{10.1e1}{101.010e3}\newline + \xintiiPow {2}{100}\newline + \xintPow {2}{100}\newline + \xintFloatPow {2}{100}\par +\end{everbatim*} % - Scientific notation is accepted for both numerator and denominator of a - fraction, and is produced on output by \csbxint{Float}: + Produced fractions having a denominator equal to one are, as a general + rule, nevertheless printed as fractions. In math mode \csbxint{Frac} + will remove such dummy denominators, and in inline text mode one has + \csbxint{PRaw} with the similar effect. % \begin{quote} - |\xintAdd{10.1e1}{101.010e3}|\dtt{=\xintAdd{10.1e1}{101.010e3}}\\ - % - |\xintFloatAdd{10.1e1}{101.010e3}|\dtt{=\xintFloatAdd{10.1e1}{101.010e3}}\\ - % - |\xintPow {2}{100}|\dtt{=\xintPow {2}{100}}\\ - % - |\xintFloat{\xintPow {2}{100}}|\dtt{=\xintFloat{\xintPow {2}{100}}}\\ - % - |\xintFloatPow {2}{100}|\dtt{=\xintFloatPow {2}{100}} - \end{quote} - % - Produced fractions having a denominator equal to one are, as a general - rule, nevertheless printed as fractions. In math mode \csbxint{Frac} - will remove such dummy denominators, and in inline text mode one has - \csbxint{PRaw} with the similar effect. - % - \begin{quote} - |\xintPRaw{\xintAdd{10.1e1}{101.010e3}}|\dtt{=\xintPRaw{\xintAdd{10.1e1}{101.010e3}}}\\ + |\xintPRaw{\xintAdd{10.1e1}{101.010e3}}|\dtt{=\xintPRaw{\xintAdd{10.1e1}{101.010e3}}}\\ % |\xintRaw{1.234e5/6.789e3}|\dtt{=\xintRaw{1.234e5/6.789e3}}% \end{quote} \item the \hyperref[xintexpr]{expression format} is for inclusion in an \csbxint{expr}|...\relax|, it uses infix notations, function names, complete - expansion, and is described in \autoref{sec:expr11} and \autoref{sec:expr}. + expansion, recognizes decimal and scientific numbers, and is described in + \autoref{sec:expr11} and \autoref{sec:expr}.% +% +\footnote{The isolated dot |"."| is not legal anymore\MyMarginNote{Changed!} in expressions with + release |1.2|: there must be digits either before or after.} \end{enumerate} +Even with \xintfracname loaded, some macros by their nature cannot accept +fractions on input. Those parsing their inputs through \csbxint{Num} will now +accept fractions, truncating them first to integers. + +% The scientific notation is necessarily (except in |\xintexpr..\relax|) with a +% lowercase |e|. It may appear both at the numerator and at the denominator of a +% fraction. + Generally speaking, there should be no spaces among the digits in the inputs -(in arguments to the package macros). -Although most would be harmless in most macros, there are some cases -where spaces could break havoc. So the best is to avoid them entirely. +(in arguments to the package macros). Although most would be harmless in most +macros, there are some cases where spaces could break havoc.% +\footnote{The \csbxint{Num} macro does not remove spaces between digits beyond + the first non zero ones; however this should not really alter the subsequent + functioning of the arithmetic macros, and besides, since \xintcorename v1.2 + there is an initial parsing of the entire number, during which spaces will + be gobbled. However I have not done a complete review of the legacy code to + be certain of all possibilities after |v1.2| release. One thing to be aware + of is that \csa{numexpr} stops on spaces between digits (although it + provokes an expansion to see if an infix operator follows); the exponent for + \csbxint{iiPow} or the argument of the factorial \csbxint{iFac} are only + subjected to such a \csa{numexpr} (there are a few other macros with such + input types in \xintname). If the input is given as, say |1 2\x| where + \csa{x} is a macro, the macro \csa{x} will not be expanded by the + \csa{numexpr}, and this will surely cause problems afterwards. Perhaps a + later \xintname will force \csa{numexpr} to expand beyond spaces, but I + decided that was not really worth the effort. Another immediate cause of + problems is an input of the type |\xintiiAdd{\x}{\y}|, because the + space will stop the initial expansion; this will most certainly cause an + arithmetic overflow later when the \csa{x} will be expanded in a + \csa{numexpr}. Thus in conclusion, damages due to spaces are unlikely if + only explicit digits are involved in the inputs, or arguments are single + macros with no preceding space.} +% +% j'avais oublié que mon |...| savait gérer les \ dans les footnote pas besoin +% de \char92 ou autre! +% +So the best is to avoid them entirely. This is entirely otherwise inside an |\xintexpr|-ession, where spaces are ignored (except when they occur inside arguments to some macros, thus escaping the |\xintexpr| parser). See the \hyperref[sec:expr]{documentation}. -Even with \xintfracname loaded, some macros by their nature can not accept -fractions on input. Those parsing their inputs through \csbxint{Num} will now -accept fractions, truncating them first to integers. - -With \xintfracname loaded, a number may be empty or start directly with a -decimal point: -\begin{quote} - |\xintRaw{}=\xintRaw{.}|\dtt{=\xintRaw{}}\\ - |\xintPow{-.3/.7}{11}|\dtt{=\xintPow{-.3/+.7}{11}}\\ - |\xinttheexpr (-.3/.7)^11\relax|\dtt{=\xinttheexpr (-.3/.7)^11\relax} -\end{quote} -It is also licit to use |\A/\B| as -input if each of |\A| and |\B| expands (in the sense previously described) to a -``decimal number'' as examplified above by the numerators and denominators -(thus, possibly with a `scientific' exponent part, with a lowercase `e'). Or one -may have just one macro |\C| which expands to such a ``fraction with optional -decimal points'', or mixed things such as |\A 245/7.77|, where the numerator -will be the concatenation of the expansion of |\A| and |245|. But, as explained -already |123\A| is a no-go, \emph{except inside an |\xintexpr|-ession}! - -The scientific notation is necessarily (except in |\xintexpr..\relax|) with a -lowercase |e|. It may appear both at the numerator and at the denominator of a -fraction. -% -\leftedline{|\xintRaw {+--+1253.2782e++--3/---0087.123e---5}|\dtt{=\xintRaw - {+--+1253.2782e++--3/---0087.123e---5}}} - Arithmetic macros of \xintname which parse their arguments automatically through \csbxint{Num} are signaled by a special symbol%\ntype{\Numf{\unskip\kern\dimexpr\FrameSep+\FrameRule\relax}} @@ -4182,79 +4318,39 @@ contain to some extent infix algebra with count registers, see the section full fraction format with no restriction there is the corresponding symbol in the margin\ntype{\Ff}. -The \xintfracname macros generally output -their result in |A/B[n]| format, representing the fraction |A/B| times |10^n|. - -This format with a trailing |[n]| (possibly, |n=0|) is accepted on input -but it presupposes that the numerator and denominator |A| and |B| are in -the strict integer format described above. So |16000/289072[17]| or -|3[-4]| are authorized and it is even possible to use |\A/\B[17]| if -|\A| expands to |16000| and |\B| to |289072|, or |\A| if |\A| expands to -|3[-4]|. However, NEITHER the numerator NOR the denominator may then -have a decimal point\IMPORTANT{}. And, for this format, ONLY the -numerator may carry a UNIQUE minus sign (and no superfluous leading -zeroes; and NO plus sign). - -It is allowed for user input but the parsing is minimal and it is mandatory to -follow the above rules. This reduced flexibility, compared to the format without -the square brackets, allows nesting package macros without too much speed -impact. - \subsection{Output formats} -With package \xintfracname loaded, the routines \csbxint{Add}, \csbxint{Sub}, -\csbxint{Mul}, \csbxint{Pow}, initiallly synonyms in \xintname of -\csbxint{iAdd}, \csbxint{iSub}, \csbxint{iMul}, \csbxint{iPow}, are modified -to become the fraction handling routines.% -% -\footnote{the power function does not accept a fractional - exponent. Or rather, does not expect, and errors will result if one is - provided.} -% -\footnote{as commented upon more later, for that very reason use of - \csbxint{Add} etc\dots when only \xintname is loaded is strongly - discouraged.}\,% -% -% \footnote{macros \csbxint{iAdd}, \csbxint{iSub}, \csbxint{iMul}, -% \csbxint{iPow}, are the original ones dealing only with integers. They are -% available as synonyms, also when \xintfracname is not loaded. With -% \xintfracname loaded they accept on input also fractions, which they first -% truncate to integers, and then the output format is the integer one. The macros \csbxint{iiAdd}, \csbxint{iiSub}, \csbxint{iiMul}, -% \csbxint{iiPow}, \csbxint{iiSum}, \csbxint{iiPrd} are strictly integer-only: -% they skip the overhead of parsing their arguments via -% \csbxint{Num}.}\,% -% -% \footnote{also \csbxint{Cmp}, \csbxint{Sgn}, \csbxint{Geq}, -% \csbxint{Opp}, \csbxint{Abs}, \csbxint{Max}, \csbxint{Min} are extended to -% fractions; and the last four have the integer-only variants \csbxint{iOpp}, -% \csbxint{iAbs}, \csbxint{iMax}, \csbxint{iMin}.}\,% -% % -% \footnote{and \csbxint{Fac}, -% \csbxint{Quo}, \csbxint{Rem}, \csbxint{Division}, \csbxint{FDg}, -% \csbxint{LDg}, \csbxint{Odd}, \csbxint{MON}, \csbxint{MMON} all accept a -% fractional input as long as it reduces to an integer.} -% -They produce on output a -fractional number |f=A/B[n]| where |A| and |B| are integers, with |B| positive, -and |n| is a ``short'' integer. -% -% (\emph{i.e} less in absolute value than |2^{31}-9|). +Package \xintcorename provides macros \csbxint{iiAdd}, \csbxint{iiSub}, +\csbxint{iiMul}, \csbxint{iiPow}, which only \fexpan d their arguments and +\csbxint{iAdd}, \csbxint{iSub}, \csbxint{iMul}, \csbxint{iPow} which +normalize them first to strict format, thus have a bit of overhead. These +macros always produce integers on output. + +With \xintfracname loaded \csbxint{iiAdd}, \csbxint{iiSub}, \csbxint{iiMul}, +... are not modified, and \csbxint{iAdd}, \csbxint{iSub}, \csbxint{iMul}, ... +are only extended to the extent of accepting fraction inputs but they will be +truncated to integers.% % -This represents |(A/B)| times |10^n|. +\footnote{the power function does not accept a fractional exponent. Or rather, + does not expect, and errors will result if one is provided.} % -\footnote{at each stage of the - computations, the sum of |n| and the length of |A|, or of the absolute value - of |n| and the length of |B|, must be kept less than - |2^{31}-9|.} +The output will be an integer. \begin{framed} - The fraction output format for most \xintfracname macros is {|A/B[n]|} which - stands for |(A/B)|$\times$|10^n|. The |A| and |B| may end in zeroes - (\emph{i.e}, |n| does not represent all powers of ten), and will generally - have a common factor. The denominator |B| is always strictly positive. - Conversely, this format is accepted on input and is parsed more quickly than - fractions containing decimal points or in scientific notation; the input - denominator is optional. + The fraction handling macros from \xintfracname are called \csbxint{Add}, + \csbxint{Sub}, \csbxint{Mul}, etc... they are \emph{not} defined in the + absence of \xintfracname.\MyMarginNote[\kern\dimexpr\FrameSep+\FrameRule\relax]{Changed!} + + They produce on output a fractional number |f=A/B[n]| (which stands for + |(A/B)|$\times$|10^n|) where |A| and |B| are integers, with |B| positive, + and |n| is a ``short'' integer (\emph{i.e} less in absolute value than + \dtt{\number"7FFFFFFF}.) + + The output fraction is not reduced to smallest terms. The |A| and |B| may + end in zeroes (\emph{i.e}, |n| does not represent all powers of ten). The + denominator |B| is always strictly positive. There is no |+| sign on output + but only possibly a |-| at the numerator. The output will be expressed as + a fraction even if the inputs are both integers. \end{framed} \begin{itemize} @@ -4291,8 +4387,8 @@ $\xintIrr{273.3734e5/3395.7200e-2}$ \item The \csbxint{iiAdd}, \csbxint{iiSub}, \csbxint{iiMul}, \csbxint{iiPow}, and others with `\textcolor{blue}{ii}' in their names accept on input only - integers in the strict format (they skip the overhead of the \csbxint{Num} - parsing) and naturally they output an integer, with no fraction slash nor + integers in the strict format. They skip the overhead of the \csbxint{Num} + parsing and naturally they output integers, with no fraction slash nor trailing |[n]|. \end{itemize} @@ -4658,7 +4754,7 @@ naturally! (but \dtt{F(\xintiiPow2{31}}) would be rather big anyhow...). In practice, whenever one typesets things, one has left the expansion only contexts; hence there is no objection to, on the contrary it is recommended, assign the result of earlier computations to macros via an |\edef| (or an -|\oodef|, see \ref{oodef}), for later use. The above could thus be coded +|\fdef|, see \ref{fdef}), for later use. The above could thus be coded \begin{everbatim} \begingroup \def\A {1859} \def\B {1573} \edef\C {\xintiiGCD\A\B} @@ -4700,28 +4796,33 @@ others are more annoying as they may pass through unsignaled. \item using one pair of braces too many |\xintIrr{{\xintiPow {3}{13}}/243}| (the computation goes through with no error signaled, but the result is completely wrong). +\item things like |\xintiiAdd { \x}{\y}| as the space will cause \csa{x} to be + expanded later, most probably within a |\numexpr| thus provoking possibly an + arithmetic overflow. \item using |[]| and decimal points at the same time |1.5/3.5[2]|, or with a sign in the denominator |3/-5[7]|. The scientific notation has no such restriction, the two inputs |1.5/-3.5e-2| and |-1.5e2/3.5| are equivalent: |\xintRaw{1.5/-3.5e-2}|\dtt{=\xintRaw{1.5/-3.5e-2}}, |\xintRaw{-1.5e2/3.5}|\dtt{=\xintRaw{-1.5e2/3.5}}. -\item specifying numerators and - denominators with macros producing fractions when \xintfracname is loaded: - |\edef\x{|\allowbreak|\xintMul {3}{5}/\xintMul{7}{9}}|. This expands to - \texttt{\x} which is - invalid on input. Using this |\x| in a fraction macro will most certainly - cause a compilation error, with its usual arcane and undecipherable - accompanying message. The fix here would be to use |\xintiMul|. The simpler - alternative with package \xintexprname: - |\xinttheexpr 3*5/(7*9)\relax|. +% \item specifying numerators and +% denominators with macros producing fractions when \xintfracname is loaded: +% |\edef\x{|\allowbreak|\xintMul {3}{5}/\xintMul{7}{9}}|. This expands to +% \texttt{\x} which is +% invalid on input. Using this |\x| in a fraction macro will most certainly +% cause a compilation error, with its usual arcane and undecipherable +% accompanying message. The fix here would be to use |\xintiMul|. The simpler +% alternative with package \xintexprname: +% |\xinttheexpr 3*5/(7*9)\relax|. \item generally speaking, using in a context expecting an integer (possibly restricted to the \TeX{} bound) a macro or expression which returns a fraction: |\xinttheexpr 4/2\relax| outputs \dtt{\xinttheexpr 4/2\relax}, not $2$. Use |\xintNum {\xinttheexpr 4/2\relax}| or |\xinttheiexpr 4/2\relax| (which rounds the result to the nearest integer, here, the result is already - an integer) or |\xinttheiiexpr 4/2\relax|. -\item use of square brackets |[|, |]| in |\xintexpr...\name| has some traps, see - \autoref{sec:expr}. + an integer) or |\xinttheiiexpr 4/2\relax|. Or, divide in your head |4| by + |2| and insert the result directly in the \TeX{} source. +% trop technique +% \item use of square brackets |[|, |]| in |\xintexpr...\name| has some traps, see +% \autoref{sec:expr}. \end{itemize} \subsection{Error messages} @@ -4772,6 +4873,29 @@ sequences: % par ailleurs il y a trop d'espace vertical avant le multicols, mais % bon. +There are now a few more if for example one attempts to use |\xintAdd| without +having loaded \xintfracname (with only \xintname loaded, only |\xintiAdd| and +|\xintiiAdd| are legal).\MyMarginNote{Changed!} +\begin{multicols}{2}\parskip0pt\relax +\begin{everbatim} +\Did_you_mean_iiAbs?or_load_xintfrac +\Did_you_mean_iiOpp?or_load_xintfrac +\Did_you_mean_iiAdd?or_load_xintfrac +\Did_you_mean_iiSub?or_load_xintfrac +\Did_you_mean_iiMul?or_load_xintfrac +\Did_you_mean_iiPow?or_load_xintfrac +\Did_you_mean_iiSqr?or_load_xintfrac +\Did_you_mean_iiMax?or_load_xintfrac +\Did_you_mean_iiMin?or_load_xintfrac +\Did_you_mean_iMaxof?or_load_xintfrac +\Did_you_mean_iMinof?or_load_xintfrac +\Did_you_mean_iiSum?or_load_xintfrac +\Did_you_mean_iiPrd?or_load_xintfrac +\Did_you_mean_iiPrdExpr?or_load_xintfrac +\Did_you_mean_iiSumExpr?or_load_xintfrac +\end{everbatim} +\end{multicols} + Don't forget to set |\errorcontextlines| to at least |2| to get from \LaTeX\ more meaningful error messages. Errors occuring during the parsing of |\xintexpr-essions| try to provide helpful information about the offending @@ -4786,9 +4910,11 @@ daring experienced \TeX/\LaTeX\ user. \subsection{Package namespace, catcodes} -The \xintname bundle packages presuppose that the \csa{space}, \csa{empty} and -|\m@ne| control sequences are pre-defined with meanings as in Plain -\TeX{} or \LaTeX2e. +% note: v1.2 définit \m@ne si ce count n'existe pas. + +The bundle packages needs that the \csa{space} and \csa{empty} control +sequences are pre-defined with the identical meanings as in Plain \TeX{} or +\LaTeX2e. Private macros of \xintkernelname, \xintcorename, \xinttoolsname, \xintname, \xintfracname, \xintexprname, \xintbinhexname, \xintgcdname, @@ -4945,7 +5071,7 @@ $2^{100}$ (=\xintiPow {2}{100}) has \xintLen{\xintiPow {2}{100}} digits and the \end{everbatim*} It would be more efficient to do once and for all -|\oodef\z{\xintiPow {2}{100}}|, and then use |\z| in place of +|\edef\z{\xintiPow {2}{100}}|, and then use |\z| in place of |\xintiPow {2}{100}| everywhere as this would spare the CPU some repetitions. Expandably computing primes is done in \autoref{xintSeq}. @@ -4979,613 +5105,189 @@ expandability. Check it out (\autoref{xintiloop}). % \noindent\kern\parindent\input README.md % \endgroup }\x -\section{New features of the \xintexprname package} -\label{sec:expr11} +\etocdepthtag.toc {commands} +\indescriptionfalse +\addtocontents{toc}{\gdef\string\sectioncouleur{{joli}}} -Release |1.1| brought many changes to \xintexprname. This chapter is -for people already familiar with earlier versions. A more systematic -item per item syntax description is provided in \autoref{sec:expr}. But be -sure to come back here as the latter chapter has not been compeletely updated. +\renewcommand{\etocaftertochook}{\addvspace{\bigskipamount}} -First, there were some breaking changes: -\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, - itemindent=\leftmarginii, leftmargin=0em] - \item in |\xintiiexpr|, |/| does \emph{rounded} division, rather than as - in earlier releases the - Euclidean division (for positive arguments, this is truncated division). - The new |//| operator does truncated division, - \item the |:| operator for three-way branching is gone, replaced with |??|, - \item |1e(3+5)| is now illegal. The number parser identifies |e| and |E| - in the same way it does for the decimal mark, earlier versions treated - |e| as |E| rather as postfix operators, - \item the |add| and |mul| have a new syntax, old syntax is with |`+`| and - |`*`| (quotes mandatory), |sum| and |prd| are gone, - \item no more special treatment for encountered brace pairs |{..}| by the - number scanner, |a/b[N]| notation can be used without use of braces (the - |N| will end up space-stripped in a |\numexpr|, it is not parsed by the - |\xintexpr|-ession scanner). - \item although |&| and \verb+|+ are still available as Boolean operators the - use of |&&| and \verb+||+ is strongly recommended. The single - letter operators might be assigned some other meaning in later releases - (bitwise operations, perhaps). Do not use them. - \item place holders for |\xintNewExpr| - could be denoted |#1|, |#2|, ... or also, for special purposes |$1|, |$2|, - ... Only the first form is now accepted and the special cases previously - treated via the second form are now managed via a |protect(...)| function. -\end{itemize} -Let's now describle some of the numerous additional functionalities. +\section{Commands of the \xintkernelname package} +\label{sec:kernel} -\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, - itemindent=\leftmarginii, leftmargin=0em] - \item |\xintiexpr|, |\xinttheiexpr| admit an optional argument within - brackets |[d]|, it then presents the computation result (or results, if - comma separated) after rounding to |d| digits after decimal mark, (the - whole computation is done exactly, as in |xintexpr|), -\begin{everbatim*} -\xinttheiexpr [32] 1.23^50, 1.231^50\relax -\end{everbatim*} - \item |\xintfloatexpr|, |\xintthefloatexpr| similarly admit an optional - argument which serves to keep only |d| digits of precision, getting rid - of cumulated uncertainties in the last digits (the whole computation is - done according to the precision set via |\xintDigits|), -\begin{everbatim*} -\xintDigits:=32;\xintthefloatexpr 1.010101^10-1.0101^10\relax +\localtableofcontents -\xintDigits:=16;\xintthefloatexpr 1.010101^10-1.0101^10\relax +The \xintkernelname package contains mainly the common code base for handling +the load-order of the bundle packages, the management of catcodes at loading +time, definition of common constants and macro utilities which are used +throughout the code etc ... it is automatically loaded by all packages of the +bundle. -\xintthefloatexpr [12] 1.010101^10-1.0101^10\relax -\end{everbatim*} +It provides a few macros possibly useful in other contexts. - \item |\xinttheexpr| and |\xintthefloatexpr| ``pretty-print'' if possible, - the former removing unit denominator or |[0]| brackets, the latter - avoiding scientific notation if decimal notation is practical, - \item the |//| does truncated division and |/:| is the associated modulo, - \item multi-character operators |&&|, \verb+||+, |==|, |<=|, |>=|, |!=|, - |**|, - \item multi-letter infix binary words |'and'|, |'or'|, |'xor'|, |'mod'| - (quotes mandatory), - \item functions |even|, |odd|, |first|, |last|, - \item |\xintdefvar A3:=3.1415;| for variable definitions (non expandable, - naturally), usable in subsequent expressions; variable names may contain - letters, digits, underscores. They should not start with a digit, the - |@| is reserved, and single lowercase and uppercase Latin letters are - predefined to work as dummy variables (see next), - \item generation of comma separated lists |a..b|, |a..[d]..b|, - \item Python syntax-like list extractors |[list][n:]|, |[list][:n]|, |[list][a:b]| - and |[list][n]| (|n=0| for the number of list items), the step is always - |+1|, - \item function |reversed|, to reverse the order of list items, - \item itemwise sequence operations |a*[list]|, etc.., on both sides |a*[list]^b|, - \item dummy variables in |add| and |mul|: |add(x(x+1)(x-1), x=-10..10)|, - \item variable substitutions with |subs|: |subs(subs(add(x^2+y^2,x=1..y),y=t),t=20)|, - \item sequence generation using |seq| with a dummy variable: |seq(x^3, x=-10..10)|, - \item simple recursive sequences with |rseq|, with |@| given the last value, - |rseq(1;2@+1,i=1..10)|, - \item higher recursion with |rrseq|, |@1|, |@2|, |@3|, |@4|, and |@@(n)| - for earlier values, up to |n=K| where |K| is the number of terms of the - initial stretch |rrseq(0,1;@1+@2,i=2..100)|, - \item iteration with |iter| which is like |rrseq| but outputs only the - last |K| terms, where |K| was the number of initial terms, - \item inside |seq|, |rseq|, |rrseq|, |iter|, possibility to use |omit|, - |abort| and |break| to control termination, - \item |n++| potentially infinite index generation for |seq|, |rseq|, - |rrseq|, and |iter|, it is advised to use |abort| or |break(..)| at - some point, - \item the |add|, |mul|, |seq|, ... are nestable, - \item |\xintthecoords| converts a comma separated list of an even number - of items to the format as expected by the |TikZ| |coordinates| syntax, - \item completely rewritten |\xintNewExpr|, new |protect| function to handle - external macros. However not all constructs are compatible with - |\xintNewExpr|. -\end{itemize} +\subsection{\csbh{odef}, \csbh{oodef}, \csbh{fdef}} +\label{odef} +\label{oodef} +\label{fdef} -% \subsection{Examples with the \texorpdfstring{\unexpanded{\unexpanded{|v1.1|}}}{v1.1} \csh{xintexpr}} +\csa{oodef}|\controlsequence {}| does +\everb|@ + \expandafter\expandafter\expandafter\def + \expandafter\expandafter\expandafter\controlsequence + \expandafter\expandafter\expandafter{} +| -And now some examples: +This works only for a single +|\controlsequence|, with no parameter text, even without parameters. An +alternative would be: +\everb|@ +\def\oodef #1#{\def\oodefparametertext{#1}% + \expandafter\expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\def + \expandafter\expandafter\expandafter\oodefparametertext + \expandafter\expandafter\expandafter } +| -\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, - itemindent=\leftmarginii, leftmargin=0em] -\item One can define variables (the definition itself is a non expandable - step). The allowed names are composed of letters, digits, and underscores. - The variable should not start with a digit and single letters |a..z|, |A..Z| - are predefined for use as dummy variables --- see below. The |@| is - reserved. -\begin{everbatim*} -\begingroup - \xintdefvar a_1 := 3.14159;\xintdefvar a2 := 2.71828;\xinttheiexpr [5] a_1+a2\relax -\endgroup -\end{everbatim*} -\item |add| and |mul| have a new syntax requiring a dummy variable: -\begin{everbatim*} -\xinttheexpr add(x, x=1,3,19), mul(x^2, x=1,3,19), add(x(x+1), x= 1,3,19)\relax -\end{everbatim*} +\noindent +but it does not allow |\global| as prefix, and, besides, would have anyhow its +use (almost) limited to parameter texts without macro parameter tokens +(except if the expanded thing does not see them, or is designed to deal with +them). -Use |`+`| and |`*`| (left ticks mandatory) for syntax without dummy variables: -\begin{everbatim*} -\xinttheexpr `+`(1,3,19), `*`(1^2,3^2,19^2), `+`(1*2,3*4,19*20)\relax -\end{everbatim*} -\item The |seq| function generates sequences according to a given formula: -\begin{everbatim*} -\xinttheexpr seq(x(x+1)(x+2), x=1,3,19), `+`(seq(x(x+1)(x+2), x=1,3,19)), - add(x(x+1)(x+2), x=1,3,19)\relax -\end{everbatim*} -\begin{everbatim*} -And this is nestable! -\xinttheexpr seq(seq(x^y, y=1..5),x=1..5), add(mul(x^y,y=1..5), x=1..5), - add(x^15, x=1..5)\relax % 15 = 1+2+3+4+5 -\end{everbatim*} +There is a similar macro |\odef| with only one expansion of the replacement text +||, and |\fdef| which expands fully || using |\romannumeral-`0|. -One should use parentheses appropriately. The \csbxint{expr} parser in normal -operation is not bad at identifying missing or extra opening or closing -parentheses, but when it handles |seq|, |add|, |mul| or similar constructs it -switches to another mode of operation (it starts using delimited macros, -something which is almost non-existent in all its other operations) and ill-formed -expressions are much more likely to let the parser fetch tokens from beyond the -mandatory ending |\relax|. Thus, in case of a missing parenthesis in such -circumstances the error message from \TeX{} might be very cryptic, even for -the seasoned \xintname user. +% These tools are provided as it is sometimes wasteful (from the point of view +% of running time) to do an |\edef| when one knows that the contents expand in +% only two steps for example, as is the case with all (except \csbxint{loop} +% and \csbxint{iloop}) the expandable macros of the \xintname packages. Each +% will be defined only if \xintkernelname finds them currently undefined. -\item As seen in the last example |a..b| constructs the integers from |a| to - |b|. This is (small) integer only. A more general |a..[d]..b| works with big - integers, or fractions, from |a| to |b| with step |d|. -\begin{everbatim*} -\xinttheexpr seq(2x+1, x=1..10, 100..110, 3/5..[1/5]..7/5)\relax -\end{everbatim*} -\item itemwise operations on lists are possible, as well as item extractions: -\begin{everbatim*} -\xinttheiiexpr 2*[1,10,100]^3, 5+[2*[1,10,100]^3]*100 \relax -\end{everbatim*} -\begin{everbatim*} -\xinttheiiexpr 1+[seq(3^j, j=1..10, 21..30)][17], 1+3^27\relax -\end{everbatim*} +They can be prefixed with |\global|. It appears than |\fdef| is generally a bit +faster than |\edef| when expanding macros from the \xintname bundle, when the +result has a few dozens of digits. |\oodef| needs thousands of digits it seems +to become competitive. -We used the |[list][n]| construct which gives the nth item from the list. In -this context there are also the functions |last| and |first|. There is no real -concept of a list object, nor list operations, although itemwise manipulation -are made possible as shown above via the |[..]| constructor. The list -manipulation utilities are so far a bit limited. There is no notion of an -``nuple'' object. The variable |nil| is reserved, it represents an empty list. -\item |subs| is similar to |seq| in syntax but is for variable substitution: -\begin{everbatim*} -\xinttheexpr subs(100*subs(10*subs(3*x+5,x=y+50)+2,y=z^2),z=10)\relax % 100(10(3*150+5)+2) -\end{everbatim*} -\begin{everbatim*} -\xinttheexpr subs(subs(add(x^2+y^2,x=1..y),y=t),t=20)\relax -\end{everbatim*} +\subsection{\csbh{xintReverseOrder}}\label{xintReverseOrder} -The substituted variable may be a comma separated list (this is impossible -with |seq| which will always pick one item after the other of a list). -\begin{everbatim*} -\xinttheexpr subs([x]^2,x=-123,17,32)\relax -\end{everbatim*} +\csa{xintReverseOrder}\marg{list}\etype{n} does not do any expansion of its +argument and just reverses the order of the tokens in the \meta{list}. Braces +are removed once and the enclosed material, now unbraced, does not get +reversed. Unprotected spaces (of any character code) are gobbled. +% +\leftedline{|\xintReverseOrder{\xintDigitsOf\xintiPow {2}{100}\to\Stuff}|} +% +\leftedline{gives: + \ttfamily{\string\Stuff\string\to1002\string\xintiPow\string\xintDigitsOf}} -\item last but not least, |seq| has variants |rseq| and |rrseq| which allow - recursive definitions. They start with at least one initial value, then a - semi-colon, then the formula, then the list of indices to iterate over. |@| - (or |@1|) evaluates to the last computed item, and |rrseq| keeps the memory - of the |K| last results, where |K| was the number of initial terms. One - accesses them via |@1, @2, @3, @4| and |@@(N)| for |N>4|. It is even - possible to nest them and use |@@@| to access the values of the master - recursion... -\begin{everbatim*} -\xinttheiiexpr rseq(1; 2*@, i=1..10), `+`(rseq(1; 2*@, i=1..10))\relax -\end{everbatim*} -\begin{everbatim*} -\xinttheiiexpr rseq(2; @(@+1)/2, i=1..5)\relax -\end{everbatim*} -\begin{everbatim*} -\xinttheiiexpr rseq(0,1; (@1,add(x,x=@1)), y=2..10)\relax -\end{everbatim*} - -Some Fibonacci fun -\begin{everbatim*} -\xinttheiiexpr rrseq(0,1; @1+@2, x=2..10), last(rrseq(0,1; @1+@2, x=2..100))\relax -\end{everbatim*} -\begin{everbatim*} -Sum of previous last three: \xinttheiiexpr rrseq(0,0,1; @1+@2+@3, i=1..20)\relax -\end{everbatim*} -\begin{everbatim*} -Big numbers: \printnumber{\xinttheexpr rseq(1; @(@+1), j=1..10)\relax } -\end{everbatim*} +\subsection{\csbh{xintLength}}\label{xintLength} -Nested recursion often quickly leads to gigantic outputs. This is an -experimental feature, susceptible to be removed or altered in the future. -\begin{everbatim*} -\xinttheexpr rrseq(1; `+`(rrseq(0,1; @@@(1)+@1+@2, i=1..10)), j=1..5)\relax -\end{everbatim*} +\csa{xintLength}\marg{list}\etype{n} does not do \emph{any} expansion of its +argument and just counts how many tokens there are (possibly none). So to use +it to count things in the replacement text of a macro one should do +|\expandafter\xintLength\expandafter{\x}|. One may also use it inside macros +as |\xintLength{#1}|. Things enclosed in braces count as one. Blanks between +tokens are not counted. See \csbxint{NthElt}|{0}| (from \xinttoolsname) for a +variant which first \fexpan ds its argument. +% +\leftedline{|\xintLength {\xintiPow {2}{100}}|\dtt{=\xintLength + {\xintiPow{2}{100}}}} +% +\leftedline{${}\neq{}$|\xintLen {\xintiPow {2}{100}}|\dtt{=\xintLen + {\xintiPow{2}{100}}}} -\item The special keywords |omit|, |abort| and |break(..)| are available - inside |seq|, |rseq|, |rrseq|, as well as the |n++| for a potentially - infinite iteration. The |n++| construct in conjunction with an |abort| or - |break| is often more efficient, because in other cases the list to iterate - over is first completely constructed. -\begin{everbatim*} -First Fibonacci number at least |2^31| and its index -\xinttheiiexpr iter(0,1; (@1>=2^31)?{break(i)}{@2+@1}, i=1++)\relax -\end{everbatim*} +\section{Commands of the \xinttoolsname package} +\label{sec:tools} -\begin{everbatim*} -Prime numbers are always cool -\xinttheiiexpr seq((seq((subs((x/:m)?{(m*m>x)?{1}{0}}{-1},m=2n+1)) - ??{break(0)}{omit}{break(1)},n=1++))?{x}{omit}, - x=10001..[2]..10200)\relax -\end{everbatim*} +\localtableofcontents -The syntax in this last example may look a bit involved. First |x/:m| computes -|x modulo m| (this is the modulo with respect to truncated division, which -here for positive arguments is like Euclidean division; in -|\xintexpr...\relax|, |a/:b| is such that |a = b*(a//b)+a/:b|, with |a//b| the -algebraic quotient |a/b| truncated to an integer.). The |(x)?{yes}{no}| -construct checks if |x| (which \emph{must} be within parentheses) is true or -false, i.e. non zero or zero. It then executes either the |yes| or the |no| -branch, the non chosen branch is \emph{not} evaluated. Thus if |m| divides |x| -we are in the second (``false'') branch. This gives a |-1|. This |-1| is the -argument to a |??| branch which is of the type |(y)??{y<0}{y=0}{y>0}|, thus here -the |y<0|, i.e., |break(0)| is chosen. This |0| is thus given to another |?| -which consequently chooses |omit|, hence the number is not kept in the list. -The numbers which survive are the prime numbers. +\def\n{|{N}|} +\def\m{|{M}|} +\def\x{|{x}|} -% A006877 In the `3x+1' problem, these values for the starting value set new -% records for number of steps to reach 1. (Formerly M0748) 14 1, 2, 3, 6, 7, -% 9, 18, 25, 27, 54, 73, 97, 129, 171, 231, 313, 327, 649, 703, 871, 1161, -% 2223, 2463, 2919, 3711, 6171, 10971, 13255, 17647, 23529, 26623, 34239, -% 35655, 52527, 77031, 106239, 142587, 156159, 216367, 230631, 410011, 511935, -% 626331, 837799 +These utilities used to be provided within the \xintname package; since |1.09g| +(|2013/11/22|) they have been moved to an independently usable package +\xinttoolsname, which has none of the \xintname facilities regarding big +numbers. Whenever relevant release |1.09h| has made the macros |\long| so they +accept |\par| tokens on input. -\item The |iter| function is like |rrseq| but does not leave a trace of earlier items, - it starts with |K| initial values, then it iterates: either a fixed number of times, - or until aborting or breaking. And ultimately it prints |K| final values. -\begin{everbatim*} -The first Fibonacci number beyond the \TeX{} bound is -\xinttheiiexpr subs(iter(0,1;(@1>N)?{break(i)}{@1+@2},i=1++),N=2^31)\relax{} -and the previous number was its index. -\end{everbatim*}But this was a bit too easy, what is the smallest Fibonacci number not representable on 64 bits? -\begin{everbatim*} -The first Fibonacci number beyond |2^64| bound is -\xinttheiiexpr subs(iter(0,1;(@1>N)?{break(i)}{@1+@2},i=1++),N=2^64)\relax{} -and the previous number was its index. -\end{everbatim*} +First the completely expandable utilities up to \csbxint{iloop}, then the non +expandable utilities. -One more recursion: -\begin{everbatim*} -\def\syr #1{\xinttheiiexpr rseq(#1; (@<=1)?{break(i)}{odd(@)?{3@+1}{@//2}},i=0++)\relax} -The 3x+1 problem: \syr{231}\par -\end{everbatim*} +This section contains various concrete examples and ends with a +\hyperref[ssec:quicksort]{completely expandable implementation of the Quick Sort + algorithm} together with a graphical illustration of its action. -Ok, a final one: -\begin{everbatim*} -\def\syrMax #1{\xinttheiiexpr iter(#1,#1;even(i)? - {(@2<=1)?{break(i/2)}{odd(@2)?{3@2+1}{@2//2}}} - {(@1>@2)?{@1}{@2}},i=0++)\relax } -With initial value 1161, the maximal number attained is \syrMax{1161} and that latter -number is the number of steps which was needed to reach 1.\par -\end{everbatim*} +See also \ref{xintReverseOrder} and \ref{xintLength} which come with package +\xintkernelname, automatically loaded by \xinttoolsname. -Well, one more: +\subsection{\csbh{xintRevWithBraces}}\label{xintRevWithBraces} -\begin{everbatim*} -\newcommand\GCD [2]{\xinttheiiexpr rrseq(#1,#2; (@1=0)?{abort}{@2/:@1}, i=1++)\relax } -\GCD {13^10*17^5*29^5}{2^5*3^6*17^2} -\end{everbatim*} +%{\small New in release |1.06|.\par} -and the ultimate: +\edef\X{\xintRevWithBraces{12345}} +\edef\y{\xintRevWithBraces\X} +\expandafter\def\expandafter\w\expandafter + {\romannumeral0\xintrevwithbraces{{\A}{\B}{\C}{\D}{\E}}} -\begin{everbatim*} -\newcommand\Factors [1]{\xinttheiiexpr - subs(seq((i/:3=2)?{omit}{[L][i]},i=1..([L][0])), - L=rseq(#1;(p^2>[@][1])?{([@][1]>1)?{break(1,[@][1],1)}{abort}} - {(([@][1])/:p)?{omit} - {iter(([@][1])//p; (@/:p)?{break(@,p,e)}{@//p},e=1++)}},p=2++))\relax } -\Factors {41^4*59^2*29^3*13^5*17^8*29^2*59^4*37^6} -\end{everbatim*} +% +\csa{xintRevWithBraces}\marg{list}\etype{f} first does the \fexpan sion of its +argument then it reverses the order of the tokens, or braced material, it +encounters, maintaining existing braces and adding a brace pair around each +naked token encountered. Space tokens (in-between top level braces or naked +tokens) are gobbled. This macro is mainly thought out for use on a \meta{list} +of such braced material; with such a list as argument the \fexpan sion will only +hit against the first opening brace, hence do nothing, and the braced stuff may +thus be macros one does not want to expand. +% +\leftedline{|\edef\x{\xintRevWithBraces{12345}}|} +% +\leftedline{|\meaning\x:|\dtt{\meaning\X}} +% +\leftedline{|\edef\y{\xintRevWithBraces\x}|} +% +\leftedline{|\meaning\y:|\dtt{\meaning\y}} +% +The examples above could be defined with |\edef|'s because the braced material +did not contain macros. Alternatively: +% +\leftedline{|\expandafter\def\expandafter\w\expandafter|} +% +\leftedline{|{\romannumeral0\xintrevwithbraces{{\A}{\B}{\C}{\D}{\E}}}|} +% +\leftedline{|\meaning\w:|\dtt{\meaning\w}} +% +The macro \csa{xintReverseWithBracesNoExpand}\etype{n} does the same job +without the initial expansion of its argument. -This might look a bit scary, I admit. \xintexprname has minimal tools and -is obstinate about doing everything expandably! We are hampered by absence of a -notion of ``nuple''. The algorithm divides |N| by |2| until no more possible, -then by |3|, then by |4| (which is silly), then by |5|, then by |6| (silly -again), \dots. -The variable |L=rseq(#1;...)| expands, if one follows the steps, to a comma -separated list starting with the initial (evaluated) |N=#1| and then -pseudo-triplets where the first item is |N| trimmed of small primes, the -second item is the last prime divisor found, and the third item is its -exponent in original |N|. +\subsection{\csbh{xintZapFirstSpaces}, \csbh{xintZapLastSpaces}, \csbh{xintZapSpaces}, \csbh{xintZapSpacesB}} +\label{xintZapFirstSpaces} +\label{xintZapLastSpaces} +\label{xintZapSpaces} +\label{xintZapSpacesB} +%{\small New with release |1.09f|.\par} -The algorithm needs to keep handy the last computed quotient by prime powers, -hence all of them, but at the very end it will be cleaner to get rid of them -(this corresponds to the first line in the code above). This is achieved in a -cumbersome inefficient way; indeed each item extraction |[L][i]| is costly: it -is not like accessing an array stored in memory, due to expandability, nothing -can be stored in memory! Nevertheless, this step could be done here in a far -less inefficient manner if there was a variant of |seq| which, in the spirit -of \csbxint{iloopindex}, would know how many steps it had been through so far. -This is a feature to be added to |\xintexpr|! (as well as a |++| construct -allowing a non unit step). +\csa{xintZapFirstSpaces}\marg{stuff}\etype{n} does not do \emph{any} expansion +of its argument, nor brace removal of any sort, nor does it alter \meta{stuff} +in anyway apart from stripping away all \emph{leading} spaces. -Notice that in |iter(([@][1])//p;| the |@| refers to the previous triplet (or -in the first step to |N|), but the latter |@| showing up in |(@/:p)?| refers -to the previous value computed by |iter|. +This macro will be mostly of interest to programmers who will know what I will +now be talking about. \emph{The essential points, naturally, are the complete + expandability and the fact that no brace removal nor any other alteration is + done to the input.} -\begin{snugframed} - Parentheses are essential in |..([y][0])| else the parser will see |..[| and - end up in ultimate confusion, and also in |([@][1])/:p| else the parser will - see the itemwise operator |]/| on lists and again be very confused (I could - implement a |]/:| on lists, but in this situation this would also be very - confusing to the parser.) -\end{snugframed} +\TeX's input scanner already converts consecutive blanks into single space +tokens, but |\xintZapFirstSpaces| handles successfully also inputs with +consecutive multiple space tokens. +However, it is assumed that \meta{stuff} does not contain (except inside braced +sub-material) space tokens of character code distinct from $32$. -For comparison, here is an \fexpan dable macro expanding to the same result, -but coded directly with the \xintname macros. Here |#1| can not be itself an -expression, naturally. But at least we let |\Factorize| \fexpan d its -argument. -\begin{everbatim} -\makeatletter -\newcommand\Factorize [1] - {\romannumeral0\expandafter\factorize\expandafter{\romannumeral-`0#1}}% -\newcommand\factorize [1]{\xintiiifOne{#1}{ 1}{\factors@a #1.{#1};}}% -\def\factors@a #1.{\xintiiifOdd{#1} - {\factors@c 3.#1.}% - {\expandafter\factors@b \expandafter1\expandafter.\romannumeral0\xinthalf{#1}.}}% -\def\factors@b #1.#2.{\xintiiifOne{#2} - {\factors@end {2, #1}}% - {\xintiiifOdd{#2}{\factors@c 3.#2.{2, #1}}% - {\expandafter\factors@b \the\numexpr #1+\@ne\expandafter.% - \romannumeral0\xinthalf{#2}.}}% -}% -\def\factors@c #1.#2.{% - \expandafter\factors@d\romannumeral0\xintiidivision {#2}{#1}{#1}{#2}% -}% -\def\factors@d #1#2#3#4{\xintiiifNotZero{#2} - {\xintiiifGt{#3}{#1} - {\factors@end {#4, 1}}% ultimate quotient is a prime with power 1 - {\expandafter\factors@c\the\numexpr #3+\tw@.#4.}}% - {\factors@e 1.#3.#1.}% -}% -\def\factors@e #1.#2.#3.{\xintiiifOne{#3} - {\factors@end {#2, #1}}% - {\expandafter\factors@f\romannumeral0\xintiidivision {#3}{#2}{#1}{#2}{#3}}% -}% -\def\factors@f #1#2#3#4#5{\xintiiifNotZero{#2} - {\expandafter\factors@c\the\numexpr #4+\tw@.#5.{#4, #3}}% - {\expandafter\factors@e\the\numexpr #3+\@ne.#4.#1.}% -}% -\def\factors@end #1;{\xintlistwithsep{, }{\xintRevWithBraces {#1}}}% -\makeatother -\end{everbatim} - -The macro |\Factorize| puts a little stress on the input save stack in order -not be bothered with previously gathered things. I timed it to be about eight -times faster than |\Factors| in test cases such as -|16246355912554185673266068721806243461403654781833| and others. Among the -various things explaining the speed-up, there is fact that we step by -increments of two, not one, and also that we divide only once, obtaining -quotient and remainder in one go. These two things already make for a speed-up -factor of about four. Thus, our earlier |\Factors| was not completely -inefficient, and was quite easier to come up with than |\Factorize|. - -If we only considered small integers, we could write pure |\numexpr| methods -which would be very much faster (especially if we had a table of small primes -prepared first) but still ridiculously slow compared to any non expandable -implementation, not to mention use of programming languages directly accessing -the CPU registers\dots -\end{itemize} - -%\phantomsection -\phantomsection\label{sec:expr11coords} - -To conclude with this overview of the new features in \xintexprname |1.1|, I -will mention {\bfseries |\xintthecoords|} which converts a comma separated -list as produced by |\xintfloatexpr| or |\xintiexpr [d]| to the format -expected by the |TikZ| |coordinates| syntax. -\begin{everbatim*} -{\centering\begin{tikzpicture}[scale=10]\xintDigits:=8; - \clip (-1.1,-.25) rectangle (.3,.25); - \draw [blue] (-1.1,0)--(1,0); - \draw [blue] (0,-1)--(0,+1); - \draw [red] plot[smooth] coordinates {\xintthecoords - % converts into (x1, y1) (x2, y2)... format - \xintfloatexpr seq((x^2-1,mul(x-t,t=-1+[0..4]/2)),x=-1.2..[0.1]..+1.2) \relax }; -\end{tikzpicture}\par } -\end{everbatim*} - -% Notice: if x goes no take exactly value 1 or -1, the origin appears slightly -% off the curve, not MY fault!!! - -\csbxint{thecoords} should be followed immediately by \csbxint{floatexpr} or -\csbxint{iexpr} or \csbxint{iiexpr}, but not |\xintthefloatexpr|, etc\dots - -Besides, as |TikZ| will not understand the |A/B[N]| format which is used on -output by |\xintexpr|, |\xintexpr| is not really usable with |\xintthecoords| -for a |TikZ| picture, but one may use it on its own, and the reason for the -spaces in and between coordinate pairs is to allow if necessary to print on -the page for examination with about correct line-breaks. - -\begin{everbatim*} -\oodef\x{\xintthecoords \xintexpr rrseq(1/2,1/3; @1+@2, x=1..20)\relax } -\meaning\x +++ -\end{everbatim*} - -\etocdepthtag.toc {commands} -\indescriptionfalse -\addtocontents{toc}{\gdef\string\sectioncouleur{{joli}}} - -\renewcommand{\etocaftertochook}{\addvspace{\bigskipamount}} - - -\section{Commands of the \xintkernelname package} -\label{sec:kernel} - -\localtableofcontents - -The \xintkernelname package contains mainly the common code base for handling -the load-order of the bundle packages, the management of catcodes at loading -time, definition of common constants and macro utilities which are used -throughout the code etc ... it is automatically loaded by all packages of the -bundle. - -It provides a few macros possibly useful in other contexts. - -\subsection{\csbh{odef}, \csbh{oodef}, \csbh{fdef}} -\label{odef} -\label{oodef} -\label{fdef} - -\csa{oodef}|\controlsequence {}| does -\everb|@ - \expandafter\expandafter\expandafter\def - \expandafter\expandafter\expandafter\controlsequence - \expandafter\expandafter\expandafter{} -| - -This works only for a single -|\controlsequence|, with no parameter text, even without parameters. An -alternative would be: -\everb|@ -\def\oodef #1#{\def\oodefparametertext{#1}% - \expandafter\expandafter\expandafter\expandafter - \expandafter\expandafter\expandafter\def - \expandafter\expandafter\expandafter\oodefparametertext - \expandafter\expandafter\expandafter } -| - -\noindent -but it does not allow |\global| as prefix, and, besides, would have anyhow its -use (almost) limited to parameter texts without macro parameter tokens -(except if the expanded thing does not see them, or is designed to deal with -them). - -There is a similar macro |\odef| with only one expansion of the replacement text -||, and |\fdef| which expands fully || using |\romannumeral-`0|. - -These tools are provided as it is sometimes wasteful (from the point of view -of running time) to do an |\edef| when one knows that the contents expand in -only two steps for example, as is the case with all (except \csbxint{loop} and -\csbxint{iloop}) the expandable macros of the \xintname packages. Each will be -defined only if \xintkernelname finds them currently undefined. They can be -prefixed with |\global|. - - -\subsection{\csbh{xintReverseOrder}}\label{xintReverseOrder} - -\csa{xintReverseOrder}\marg{list}\etype{n} does not do any expansion of its -argument and just reverses the order of the tokens in the \meta{list}. Braces -are removed once and the enclosed material, now unbraced, does not get -reversed. Unprotected spaces (of any character code) are gobbled. -% -\leftedline{|\xintReverseOrder{\xintDigitsOf\xintiPow {2}{100}\to\Stuff}|} -% -\leftedline{gives: - \ttfamily{\string\Stuff\string\to1002\string\xintiPow\string\xintDigitsOf}} - -\subsection{\csbh{xintLength}}\label{xintLength} - -\csa{xintLength}\marg{list}\etype{n} does not do \emph{any} expansion of its -argument and just counts how many tokens there are (possibly none). So to use -it to count things in the replacement text of a macro one should do -|\expandafter\xintLength\expandafter{\x}|. One may also use it inside macros -as |\xintLength{#1}|. Things enclosed in braces count as one. Blanks between -tokens are not counted. See \csbxint{NthElt}|{0}| (from \xinttoolsname) for a -variant which first \fexpan ds its argument. -% -\leftedline{|\xintLength {\xintiPow {2}{100}}|\dtt{=\xintLength - {\xintiPow{2}{100}}}} -% -\leftedline{${}\neq{}$|\xintLen {\xintiPow {2}{100}}|\dtt{=\xintLen - {\xintiPow{2}{100}}}} - -\section{Commands of the \xinttoolsname package} -\label{sec:tools} - -\localtableofcontents - -\def\n{|{N}|} -\def\m{|{M}|} -\def\x{|{x}|} - -These utilities used to be provided within the \xintname package; since |1.09g| -(|2013/11/22|) they have been moved to an independently usable package -\xinttoolsname, which has none of the \xintname facilities regarding big -numbers. Whenever relevant release |1.09h| has made the macros |\long| so they -accept |\par| tokens on input. - -First the completely expandable utilities up to \csbxint{iloop}, then the non -expandable utilities. - -This section contains various concrete examples and ends with a -\hyperref[ssec:quicksort]{completely expandable implementation of the Quick Sort - algorithm} together with a graphical illustration of its action. - -See also \ref{xintReverseOrder} and \ref{xintLength} which come with package -\xintkernelname, automatically loaded by \xinttoolsname. - -\subsection{\csbh{xintRevWithBraces}}\label{xintRevWithBraces} - -%{\small New in release |1.06|.\par} - -\edef\X{\xintRevWithBraces{12345}} -\edef\y{\xintRevWithBraces\X} -\expandafter\def\expandafter\w\expandafter - {\romannumeral0\xintrevwithbraces{{\A}{\B}{\C}{\D}{\E}}} - -% -\csa{xintRevWithBraces}\marg{list}\etype{f} first does the \fexpan sion of its -argument then it reverses the order of the tokens, or braced material, it -encounters, maintaining existing braces and adding a brace pair around each -naked token encountered. Space tokens (in-between top level braces or naked -tokens) are gobbled. This macro is mainly thought out for use on a \meta{list} -of such braced material; with such a list as argument the \fexpan sion will only -hit against the first opening brace, hence do nothing, and the braced stuff may -thus be macros one does not want to expand. -% -\leftedline{|\edef\x{\xintRevWithBraces{12345}}|} -% -\leftedline{|\meaning\x:|\dtt{\meaning\X}} -% -\leftedline{|\edef\y{\xintRevWithBraces\x}|} -% -\leftedline{|\meaning\y:|\dtt{\meaning\y}} -% -The examples above could be defined with |\edef|'s because the braced material -did not contain macros. Alternatively: -% -\leftedline{|\expandafter\def\expandafter\w\expandafter|} -% -\leftedline{|{\romannumeral0\xintrevwithbraces{{\A}{\B}{\C}{\D}{\E}}}|} -% -\leftedline{|\meaning\w:|\dtt{\meaning\w}} -% -The macro \csa{xintReverseWithBracesNoExpand}\etype{n} does the same job -without the initial expansion of its argument. - - -\subsection{\csbh{xintZapFirstSpaces}, \csbh{xintZapLastSpaces}, \csbh{xintZapSpaces}, \csbh{xintZapSpacesB}} -\label{xintZapFirstSpaces} -\label{xintZapLastSpaces} -\label{xintZapSpaces} -\label{xintZapSpacesB} -%{\small New with release |1.09f|.\par} - -\csa{xintZapFirstSpaces}\marg{stuff}\etype{n} does not do \emph{any} expansion -of its argument, nor brace removal of any sort, nor does it alter \meta{stuff} -in anyway apart from stripping away all \emph{leading} spaces. - -This macro will be mostly of interest to programmers who will know what I will -now be talking about. \emph{The essential points, naturally, are the complete - expandability and the fact that no brace removal nor any other alteration is - done to the input.} - -\TeX's input scanner already converts consecutive blanks into single space -tokens, but |\xintZapFirstSpaces| handles successfully also inputs with -consecutive multiple space tokens. -However, it is assumed that \meta{stuff} does not contain (except inside braced -sub-material) space tokens of character code distinct from $32$. - -It expands in two steps, and if the goal is to apply it to the -expansion text of |\x| to define |\y|, then one should do: -|\expandafter\def\expandafter\y\expandafter - {\romannumeral0\expandafter\xintzapfirstspaces\expandafter{\x}}|. +It expands in two steps, and if the goal is to apply it to the +expansion text of |\x| to define |\y|, then one should do: +|\expandafter\def\expandafter\y\expandafter + {\romannumeral0\expandafter\xintzapfirstspaces\expandafter{\x}}|. Other use case: inside a macro as |\edef\x{\xintZapFirstSpaces {#1}}| assuming naturally that |#1| is compatible with such an |\edef| once the leading spaces @@ -5869,7 +5571,7 @@ then |\xintNthElt| returns nothing. \subsection{\csbh{xintKeep}}\label{xintKeep} \csa{xintKeep\x}\marg{list}\etype{\numx f} expands the list argument and returns -a new list containing only the first |x| elements.\NewWith {1.09m} If |x<0| the +a new list containing only the first |x| elements. If |x<0| the macro returns the last \verb+|x|+ elements (in the same order as in the initial list). If \verb+|x|+ equals or exceeds the length of the list, the list (as arising from expansion of the second argument) is returned. For |x=0| the empty @@ -5884,7 +5586,7 @@ brace pairs (either added to a naked token, or initially present), one may use argument. % \begin{everbatim*} -\oodef\test {\xintKeep {17}{\xintKeep {-69}{\xintSeq {1}{100}}}}\meaning\test +\fdef\test {\xintKeep {17}{\xintKeep {-69}{\xintSeq {1}{100}}}}\meaning\test \end{everbatim*} % @@ -5892,7 +5594,7 @@ argument. \csa{xintTrim\x}\marg{list}\etype{\numx f} expands the list argument and gobbles its first |x| elements. If |x<0| the macro gobbles the last -\verb+|x|+ elements.\NewWith {1.09m} If \verb+|x|+ equals or exceeds +\verb+|x|+ elements. If \verb+|x|+ equals or exceeds the length of the list, the empty list is returned. For |x=0| the full list is returned. @@ -5902,7 +5604,7 @@ up braced in the output (if present there). \csa{xintTrimNoExpand} does the same without first \fexpan ding its list argument. \begin{everbatim*} -\oodef\test {\xintTrim {17}{\xintTrim {-69}{\xintSeq {1}{100}}}}\meaning\test +\fdef\test {\xintTrim {17}{\xintTrim {-69}{\xintSeq {1}{100}}}}\meaning\test \end{everbatim*} \subsection{\csbh{xintListWithSep}}\label{xintListWithSep} @@ -6569,7 +6271,6 @@ to illustrate use of the general purpose \csbxint{iloop}. A little table giving the first values of |\SmallestFactor| follows, its coding uses \csbxint{For}, which is described later; none of this uses count registers. % -%\tracingmacros1 \begin{everbatim*} \let\IsPrime\undefined \let\SmallestFactor\undefined % clean up possible previous mess @@ -7673,9 +7374,9 @@ an optional parameter to \csa{xintAssign}, see \emph{infra}. \noindent\csa{xintAssign} admits since |1.09i| an optional parameter, for example |\xintAssign [e]...| or |\xintAssign [oo] -...|. The latter means that the definitions of the macros initially on the -right of |\to| will be made with \hyperref[oodef]{\ttfamily\char92oodef} which -expands twice the replacement text. The default is simply to make the +...|. With |[f]| for example the definitions of the macros initially on the +right of |\to| will be made with \hyperref[fdef]{\ttfamily\char92fdef} which +\fexpan ds the replacement text. The default is simply to make the definitions with |\def|, corresponding to an empty optional paramter |[]|. Possibilities: |[], [g], [e], [x], [o], [go], [oo], [goo], [f], [gf]|. @@ -7739,6 +7440,19 @@ here to make the definitions global. For this, one should rather do Note that prior to release |1.09j| each item (token or braced material) was submitted to an |\edef|, but the default is now to use |\def|. +\subsection{\csbh{xintDigitsOf}}\label{xintDigitsOf} + +This is a synonym for \csbxint{AssignArray},\ntype{fN} to be used to define +an array giving all the digits of a given (positive, else the minus sign will +be treated as first item) number. +\begingroup\xintDigitsOf\xintiPow {7}{500}\to\digits +% +\leftedline{|\xintDigitsOf\xintiPow {7}{500}\to\digits|} +\noindent $7^{500}$ has |\digits{0}=|\digits{0} digits, and the 123rd among them +(starting from the most significant) is +|\digits{123}=|\digits{123}. +\endgroup + \subsection{\csbh{xintRelaxArray}}\label{xintRelaxArray} \csa{xintRelaxArray}\csa{myArray} %\ntype{N} @@ -7986,33 +7700,30 @@ expression, in the arguments to the package macros, see the \hyperref[sec:useofcount]{Use of count} section. \begin{framed} - \xintcorename also provides macros |\xintAdd|, |\xintMul|,\dots as synonyms - to |\xintiAdd|, |\xintiMul|,\dots. Their usage is - \fbox{deprecated}\IMPORTANT{} for the following reason: with \xintfracname - loaded they become the routines dealing fully with fractions on input. But - this means that they now use fraction format on output, even with integer - arguments. - - Due to this variability of the output format on whether the document uses - only \xintname or loads additionally \xintfracname, code using these macros - is fragile, because loading at some later date a package which itself loads - \xintfracname or \xintexprname will modify their output format, and this is - catastrophic for example in locations expanded by |\ifnum|, or even in - arguments to those other macros of \xintname with |ii| in their names. - - Prefer thus, when writing code loading only \xintcorename or \xintname, to - use the macros \csbxint{iAdd}, \csbxint{iMul}, \dots, or \csbxint{iiAdd}, - \csbxint{iiMul}, \dots. They are guaranteed to always output an integer - without a trailing |/B[n]|. The latter have the less overhead, and the - former do not complain, if \xintfracname is loaded, even if used with true - fractions, as they will then truncate their arguments to - integers. - -%\MyMarginNote[\kern\dimexpr\FrameSep+\FrameRule\relax]{Changed} - - It was an error for the \xintname package (now \xintcorename) to provide - macros |\xintAdd|, |\xintMul|, |\xintSub| \dots. They should be used only - with \xintfracname loaded. + Earlier releases of \xintcorename also provided macros |\xintAdd|, + |\xintMul|,\dots as synonyms to |\xintiAdd|, |\xintiMul|,\dots, destined to + be re-defined by \xintfracname.\IMPORTANT{} It was announced some time ago + that their usage was deprecated, because the output formats depended on + whether \xintfracname was loaded or not. They now have been \fbox{removed.} + \MyMarginNote[\kern\dimexpr\FrameSep+\FrameRule\relax]{Changed} + + % Due to this variability of the output format on whether the document uses + % only \xintname or loads additionally \xintfracname, code using these macros + % is fragile, because loading at some later date a package which itself loads + % \xintfracname or \xintexprname will modify their output format, and this is + % catastrophic for example in locations expanded by |\ifnum|, or even in + % arguments to those other macros of \xintname with |ii| in their names. + + The macros \csbxint{iAdd}, \csbxint{iMul}, \dots, or \csbxint{iiAdd}, + \csbxint{iiMul}, \dots which come with \xintcorename are guaranteed to + always output an integer without a trailing |/B[n]|. The latter have the + lesser overhead, and the former do not complain, if \xintfracname is loaded, + even if used with true fractions, as they will then truncate their arguments + to integers. But their output format remains unmodified: integers with no + fraction slash nor |[N]| thingy. + % It was an error for the \xintname package (now \xintcorename) to provide + % macros |\xintAdd|, |\xintMul|, |\xintSub| \dots. They should be used only + % with \xintfracname loaded. \end{framed} The {\color[named]{PineGreen}$\star$}'s in the margin are there to remind of @@ -8045,15 +7756,13 @@ extended by \xintfracname to fractions. \subsection{\csbh{xintiOpp}, \csbh{xintiiOpp}}\label{xintiOpp}\label{xintiiOpp} |\xintiOpp|\n\etype{\Numf} return the opposite |-N| of the number |N|. -\csbxint{Opp} is initially a synonym but gets extended by \xintfracname to -fractions (its output format will be a fraction even if the argument is an -integer) and \csa{xintiiOpp} is the strict integer-only variant which skips +\csa{xintiiOpp} is the strict integer-only variant which skips the \csbxint{Num} overhead.\etype{f} \subsection{\csbh{xintiAbs}, \csbh{xintiiAbs}}\label{xintiAbs}\label{xintiiAbs} |\xintiAbs|\n\etype{\Numf} returns the absolute value of the number. -\csbxint{Abs} is a synonym but gets modified by \xintfracname. \csa{xintiiAbs} +\csa{xintiiAbs} skips the \csbxint{Num} overhead.\etype{f} \subsection{\csbh{xintiiFDg}}\label{xintFDg}\label{xintiiFDg} @@ -8090,67 +7799,63 @@ of parsing via \csbxint{Num}. \subsection{\csbh{xintiAdd}, \csbh{xintiiAdd}}\label{xintiAdd}\label{xintiiAdd} |\xintiAdd|\n\m\etype{\Numf\Numf} returns the sum of the two numbers. -\csbxint{Add} is initially a synonym but gets extended by \xintfracname. \csa{xintiiAdd} skips the \csbxint{Num} overhead.\etype{ff} \subsection{\csbh{xintiSub}, \csbh{xintiiSub}}\label{xintiSub}\label{xintiiSub} -|\xintiSub|\n\m\etype{\Numf\Numf} returns the difference |N-M|. \csbxint{Sub} -is initially a synonym but gets extended by \xintfracname. +|\xintiSub|\n\m\etype{\Numf\Numf} returns the difference |N-M|. \csa{xintiiSub} skips the \csbxint{Num} overhead.\etype{ff} \subsection{\csbh{xintiMul}, \csbh{xintiiMul}}\label{xintiMul}\label{xintiiMul} %{\small Modified in release |1.03|.\par} |\xintiMul|\n\m\etype{\Numf\Numf} returns the product of the two numbers. -\csbxint{Mul} is the initial synonym modified by \xintfracname, and \csa{xintiiMul} skips the \csbxint{Num} overhead.\etype{ff} \subsection{\csbh{xintiSqr}, \csbh{xintiiSqr}}\label{xintiSqr}\label{xintiiSqr} -|\xintiSqr|\n\etype{\Numf} returns the square. \csbxint{Sqr} is the initial -synonym extended by \xintfracname to fractions. \csa{xintiiSqr} skips the +|\xintiSqr|\n\etype{\Numf} returns the square. \csa{xintiiSqr} skips the \csbxint{Num} overhead.\etype{f} \subsection{\csbh{xintiPow}, \csbh{xintiiPow}}\label{xintiPow}\label{xintiiPow} |\xintiPow|\n\x\etype{\Numf\numx} returns |N^x|. When |x| is zero, this is 1. -If |N=0| and |x<0|, if \verb+|N|>1+ and |x<0|, or if \verb+|N|>1+ -and |x>100000|, then an error is raised. +If |N=0| and |x<0|, if \verb+|N|>1+ and |x<0|, an error is raised. There will +also be an error naturally if |x| exceeds the maximal \eTeX{} number +\dtt{\number"7FFFFFFF}, but the real limit for huge exponents comes from +either the computation time or the settings of some tex memory parameters. -The |x>100000| condition should perhaps be made more strict: as it stands it -allows launching operations taking hours to complete. Indeed, observe that -|2^50000| already has \dtt{\xintLen{\xintFloatPow [1]{2}{50000}}} digits; as -it turns out each exact multiplication done via \csbxint{iiMul} of two -numbers with one thousand digits each already takes of the order of seconds, -and it would take hours for arguments each with circa $15000$ digits. Perhaps -some completely expandable but not \fexpan dable variants could fare better? +\begin{framed} + Indeed, the maximal power of $2$ which \xintname is able to compute + explicitely is |2^(2^17)=2^131072| which has \dtt{39457} digits. This + exceeds the maximal size on input for the \xintcorename multiplication, hence + any |2^N| with a higher |N| will fail. On the other hand |2^(2^16)| has + \dtt{19729} digits, thus it can be squared once to obtain |2^(2^17)| or + multiplied by anything smaller, thus all exponents up and including |2^17| + are allowed (because the power operation works by squaring things and making + products). +\end{framed} + +Side remark: after all it does pay to think! I almost melted my CPU trying by +dichotomy to pin-point the exact maximal allowable |N| for |\xintiiPow 2{N}| +before finally making the reasoning above. Indeed, each such computation with +|N>130000| activates the fan of my laptop and results in so warm a keyboard +that I can hardly go on working on it! And it takes about 12 minutes for each +|\xintiiPow2{N}| with such |N|'s of the order of $130000$ (a.t.t.o.w.). \csa{xintiiPow} is an integer only variant skipping the \csbxint{Num} overhead\etype{f\numx}, it produces the same result as \csa{xintiPow} with stricter assumptions on the inputs, and is thus a tiny bit faster. -\csbxint{Pow} is the initial synonym of \csa{xintiPow} which gets extended by -\xintfracname to fractions (see -also \csbxint{FloatPow} for which the exponent must still obey the \TeX{} bound -and \csbxint{FloatPower} which has no restriction at all on the size of the -exponent). Negative exponents do not then raise errors anymore. The float -version is able to deal with things such as |2^999999999| without any problem. -For example |\xintFloatPow[4]{2}{50000}|\dtt{=\xintFloatPow[4]{2}{50000}} -and |\xintFloatPow[4]{2}{999999999}| -\dtt{=\xintFloatPow[4]{2}{999999999}}.% -% -\footnote{On my laptop \texttt{\detokenize{\xintiiPow {2}{9999}}} - obtains all |3010| digits in about ten or eleven seconds. In contrast, - the float versions for |8|, |16|, |24|, or even more significant - figures, do their jobs in less than one hundredth of a second - (|1.09j|; we used in the text only four significant digits only for - reasons of space, not time.) This is done without |log|/|exp| which - are not (yet?) implemented in \xintfracname. The \LaTeX3 - \href{http://www.ctan.org/pkg/l3kernel}{l3fp} package does this with - |log|/|exp| and is ten times faster, but allows only |16| significant - figures and the (exactly represented) floating point numbers must have - their exponents limited to $\pm$\dtt{9999}.} +\xintfracname also provides the floating variants \csbxint{FloatPow} (for +which the exponent must still obey the \TeX{} bound) and \csbxint{FloatPower} +(which has no restriction at all on the size of the exponent). Negative +exponents do not then raise errors anymore. The float version is able to deal +with things such as |2^999999999| without any problem. +\begin{everbatim*} +$\xintFloatPow[32]{2}{50000}<\xintFloatPow[32]{2}{999999999}$ +\end{everbatim*}% +and both are computed swiftly!\footnote{see however \autoref{fn:floatpow}.} Within an \csbxint{iiexpr}|..\relax| the infix operator |^| is mapped to \csa{xintiiPow}; within an \csbxint{expr}-ession it is mapped to \csbxint{Pow} @@ -8254,18 +7959,31 @@ significance of the \textcolor[named]{PineGreen}{\Numf}, and \textcolor[named]{PineGreen}{$\star$} margin annotations and some important background information. -\subsection{\csbh{xintRev}} \label{xintRev} +\subsection{\csbh{xintReverseDigits}} \label{xintReverseDigits} -|\xintRev|\n\etype{f} will reverse the order of the digits of the number, -keeping the optional sign. Leading zeroes -resulting from the operation are not removed (see the -\csa{xintNum} macro for this). This macro and all other -macros dealing with numbers first expand `fully' their arguments. -% -\leftedline{|\xintRev{-123000}|\dtt{=\xintRev{-123000}}} -% -\leftedline{|\xintNum{\xintRev{-123000}}|% - \dtt{=\xintNum{\xintRev{-123000}}}} +|\xintReverseDigits|\n\etype{f} will reverse the order of the digits of the +number, preserving an optional upfront minus sign. \csa{xintRev} is the former +denomination and is kept as an alias to it. Leading zeroes resulting from the +operation are not removed. Contrarily to \csbxint{ReverseOrder} this macro can +only be used with digits and it first expands its argument (but beware that +|-\x| will give an unexpected result as the minus sign immediately stops this +expansion; one can use |\xintiiOpp{\x}| as argument.) + +This command has been rewritten for |1.2| and is faster for very long inputs. +It is (almost) not used internally by the \xintcorename code, but the use +of related routines explains to some extent the higher speed of release |1.2|. + +\begingroup +\begin{everbatim*} +\fdef\x{\xintReverseDigits + {-98765432109876543210987654321098765432109876543210}}\meaning\x\par +\noindent\fdef\x{\xintReverseDigits {\xintReverseDigits + {-98765432109876543210987654321098765432109876543210}}}\meaning\x\par +\end{everbatim*} +\endgroup + +Notice that the output in this case with its leading zero is not in the strict +integer format expected by the `|ii|' arithmetic macros. \subsection{\csbh{xintLen}}\label{xintiLen} @@ -8288,23 +8006,11 @@ have been returned by \csbxint{Raw}: |\xintRaw {-1e3/5.425}|\dtt{=\xintRaw Let's point out that the whole thing should sum up to less than circa $2^{31}$, but this is a bit theoretical. -|\xintLen| is only for numbers or fractions. See \csbxint{Length} for counting +|\xintLen| is only for numbers or fractions. See also \csbxint{NthElt} from +\xinttoolsname. See also \csbxint{Length} from \xintkernelname for counting tokens (or rather braced groups), more generally. -\subsection{\csbh{xintDigitsOf}}\label{xintDigitsOf} - -This is a synonym for \csbxint{AssignArray},\ntype{fN} to be used to define -an array giving all the digits of a given (positive, else the minus sign will -be treated as first item) number. -\begingroup\xintDigitsOf\xintiPow {7}{500}\to\digits -% -\leftedline{|\xintDigitsOf\xintiPow {7}{500}\to\digits|} -\noindent $7^{500}$ has |\digits{0}=|\digits{0} digits, and the 123rd among them -(starting from the most significant) is -|\digits{123}=|\digits{123}. -\endgroup - -\subsection{\csbh{xintCmp}, \csbh{xintiiCmp}} +\subsection{\csbh{xintCmp}, \csbh{xintiiCmp}} |\xintCmp|\n\m\etype{\Numf\Numf} returns \dtt{1} if |N>M|, \dtt{0} if |N=M|, and \dtt{-1} if |N|, |=|, |(|, |)|, |"|, |]|, |[|, |@| - and the comma |,| should not (if used in the expression) be active. For - example, the French language in |Babel| system, for pdf\LaTeX, activates |!|, - |?|, |;| and |:|. Turn off the activity before the expressions. + \item |\xintiexpr|, |\xinttheiexpr| admit an optional argument within + brackets |[d]|, it then presents the computation result (or results, if + comma separated) after rounding to |d| digits after decimal mark, (the + whole computation is done exactly, as in |xintexpr|), +\begin{everbatim*} +\xinttheiexpr [32] 1.23^50, 1.231^50\relax +\end{everbatim*} + \item |\xintfloatexpr|, |\xintthefloatexpr| similarly admit an optional + argument which serves to keep only |d| digits of precision, getting rid + of cumulated uncertainties in the last digits (the whole computation is + done according to the precision set via |\xintDigits|), +\begin{everbatim*} +\xintDigits:=32;\xintthefloatexpr 1.010101^10-1.0101^10\relax - Alternatively the command \csbxint{exprSafeCatcodes} resets all - characters potentially needed by \csbxint{expr} to their standard catcodes - and \csbxint{exprRestoreCatcodes} restores the status prevailing at the time - of the previous \csa{xintexprSafeCatcodes}. +\xintDigits:=16;\xintthefloatexpr 1.010101^10-1.0101^10\relax -\item The infix operators are |+|, |-|, |*|, |/|, |^| (or |**|) for exact or - floating point algebra (only integer exponents for power operations), |&&| - and \verb+||+ \footnote{with releases earlier than |1.1|, only single - character operators |&| and \verb+|+ were available, because the parser - did not handle multi-character operators. Their usage in this rôle is now - deprecated,\IMPORTANT{} as they may be assigned some new meaning in the - future.} for combining ``true'' (non zero) and ``false'' (zero) - conditions, as can be formed for example with the |=| (or |==|), |<|, |>|, - |<=|, |>=|, |!=| comparison operators. +\xintthefloatexpr [12] 1.010101^10-1.0101^10\relax +\end{everbatim*} -\item The |!| is either a - function (the logical not) requiring an argument within parentheses, or a - post-fix operator which does the factorial (so far, no float version). + \item |\xinttheexpr| and |\xintthefloatexpr| ``pretty-print'' if possible, + the former removing unit denominator or |[0]| brackets, the latter + avoiding scientific notation if decimal notation is practical, + \item the |//| does truncated division and |/:| is the associated modulo, + \item multi-character operators |&&|, \verb+||+, |==|, |<=|, |>=|, |!=|, + |**|, + \item multi-letter infix binary words |'and'|, |'or'|, |'xor'|, |'mod'| + (quotes mandatory), + \item functions |even|, |odd|, |first|, |last|, + \item |\xintdefvar A3:=3.1415;| for variable definitions (non expandable, + naturally), usable in subsequent expressions; variable names may contain + letters, digits, underscores. They should not start with a digit, the + |@| is reserved, and single lowercase and uppercase Latin letters are + predefined to work as dummy variables (see next), + \item generation of comma separated lists |a..b|, |a..[d]..b|, + \item Python syntax-like list extractors |[list][n:]|, |[list][:n]|, |[list][a:b]| + and |[list][n]| (|n=0| for the number of list items), the step is always + |+1|, + \item function |reversed|, to reverse the order of list items, + \item itemwise sequence operations |a*[list]|, etc.., on both sides |a*[list]^b|, + \item dummy variables in |add| and |mul|: |add(x(x+1)(x-1), x=-10..10)|, + \item variable substitutions with |subs|: |subs(subs(add(x^2+y^2,x=1..y),y=t),t=20)|, + \item sequence generation using |seq| with a dummy variable: |seq(x^3, x=-10..10)|, + \item simple recursive sequences with |rseq|, with |@| given the last value, + |rseq(1;2@+1,i=1..10)|, + \item higher recursion with |rrseq|, |@1|, |@2|, |@3|, |@4|, and |@@(n)| + for earlier values, up to |n=K| where |K| is the number of terms of the + initial stretch |rrseq(0,1;@1+@2,i=2..100)|, + \item iteration with |iter| which is like |rrseq| but outputs only the + last |K| terms, where |K| was the number of initial terms, + \item inside |seq|, |rseq|, |rrseq|, |iter|, possibility to use |omit|, + |abort| and |break| to control termination, + \item |n++| potentially infinite index generation for |seq|, |rseq|, + |rrseq|, and |iter|, it is advised to use |abort| or |break(..)| at + some point, + \item the |add|, |mul|, |seq|, ... are nestable,% +\footnote{but |add(seq(x,x=1..t),t=1..2)| fails for the reason that |add| will + receive not a list of numbers but a list of lists.} + \item |\xintthecoords| converts a comma separated list of an even number + of items to the format as expected by the |TikZ| |coordinates| syntax, + \item completely rewritten |\xintNewExpr|, new |protect| function to handle + external macros. However not all constructs are compatible with + |\xintNewExpr|. +\end{itemize} -\item The |?| may serve either as a function (the truth value) requiring an - argument within parentheses), or as two-way post-fix branching operator - |(cond)?{YES}{NO}|. The false branch will \emph{not} be evaluated. +% \subsection{Examples with the \texorpdfstring{\unexpanded{\unexpanded{|v1.1|}}}{v1.1} \csh{xintexpr}} -\item There is also |??| which branches according to the scheme - |(x)??{<0}{=0}{>0}|. +And now some examples: -\item Comma separated lists may be generated with |a..b| and |a..[d]..b| and - they may be - manipulated to some extent once put into brackets: - \begin{itemize} - \item |a..b| constructs the \textbf{small} integers from $\lceil a\rceil$ to - $\lfloor b\rfloor$ (possibly a decreasing sequence), +\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, + itemindent=\leftmarginii, leftmargin=0em] +\item One can define variables (the definition itself is a non expandable + step). The allowed names are composed of letters, digits, and underscores. + The variable should not start with a digit and single letters |a..z|, |A..Z| + are predefined for use as dummy variables --- see below. The |@| is + reserved. \begin{everbatim*} -\xinttheexpr 1.5..11.23\relax +\begingroup + \xintdefvar a_1 := 3.14159;\xintdefvar a2 := 2.71828;\xinttheiexpr [5] a_1+a2\relax +\endgroup \end{everbatim*} - - \item |a..[d]..b| allows big integers, or fractions, it proceeds by step of |d|. +\item |add| and |mul| have a new syntax requiring a dummy variable: \begin{everbatim*} -\xinttheexpr 1.5..[0.97]..11.23\relax +\xinttheexpr add(x, x=1,3,19), mul(x^2, x=1,3,19), add(x(x+1), x= 1,3,19)\relax \end{everbatim*} - \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. +Use |`+`| and |`*`| (left ticks mandatory) for syntax without dummy variables: \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). +\xinttheexpr `+`(1,3,19), `*`(1^2,3^2,19^2), `+`(1*2,3*4,19*20)\relax \end{everbatim*} - -See the frame coming next for the |\empty| token. -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|. +\item The |seq| function generates sequences according to a given formula: \begin{everbatim*} -\xinttheiiexpr [1..10][:6]\relax\ and \xinttheiiexpr [1..10][:-6]\relax +\xinttheexpr seq(x(x+1)(x+2), x=1,3,19), `+`(seq(x(x+1)(x+2), x=1,3,19)), + add(x(x+1)(x+2), x=1,3,19)\relax \end{everbatim*} - \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 +And this is nestable! +\xinttheexpr seq(seq(x^y, y=1..5),x=1..5), add(mul(x^y,y=1..5), x=1..5), + add(x^15, x=1..5)\relax % 15 = 1+2+3+4+5 \end{everbatim*} -\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|. + +One should use parentheses appropriately. The \csbxint{expr} parser in normal +operation is not bad at identifying missing or extra opening or closing +parentheses, but when it handles |seq|, |add|, |mul| or similar constructs it +switches to another mode of operation (it starts using delimited macros, +something which is almost non-existent in all its other operations) and ill-formed +expressions are much more likely to let the parser fetch tokens from beyond the +mandatory ending |\relax|. Thus, in case of a missing parenthesis in such +circumstances the error message from \TeX{} might be very cryptic, even for +the seasoned \xintname user. + +\item As seen in the last example |a..b| constructs the integers from |a| to + |b|. This is (small) integer only. A more general |a..[d]..b| works with big + integers, or fractions, from |a| to |b| with step |d|. \begin{everbatim*} -\xinttheiiexpr [1..20][6:13]\relax\ = \xinttheiiexpr [1..20][6-20:13-20]\relax +\xinttheexpr seq(2x+1, x=1..10, 100..110, 3/5..[1/5]..7/5)\relax \end{everbatim*} -\item It is naturally possible to nest these things: +\item itemwise operations on lists are possible, as well as item extractions: \begin{everbatim*} -\xinttheexpr [[1..50][13:37]][10:-10]\relax +\xinttheiiexpr 2*[1,10,100]^3, 5+[2*[1,10,100]^3]*100 \relax \end{everbatim*} -\item itemwise operations either on the left or the right are possible: \begin{everbatim*} -\xinttheiiexpr 123*[1..10]^2\relax +\xinttheiiexpr 1+[seq(3^j, j=1..10, 21..30)][17], 1+3^27\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{} +We used the |[list][n]| construct which gives the nth item from the list. In +this context there are also the functions |last| and |first|. There is no real +concept of a list object, nor list operations, although itemwise manipulation +are made possible as shown above via the |[..]| constructor. The list +manipulation utilities are so far a bit limited. There is no notion of an +``nuple'' object. The variable |nil| is reserved, it represents an empty list. +\item |subs| is similar to |seq| in syntax but is for variable substitution: \begin{everbatim*} -\xinttheiexpr \empty [1,3,6,99,100,200][2:4]\relax +\xinttheexpr subs(100*subs(10*subs(3*x+5,x=y+50)+2,y=z^2),z=10)\relax % 100(10(3*150+5)+2) +\end{everbatim*} +\begin{everbatim*} +\xinttheexpr subs(subs(add(x^2+y^2,x=1..y),y=t),t=20)\relax \end{everbatim*} - An alternative is to use parentheses +The substituted variable may be a comma separated list (this is impossible +with |seq| which will always pick one item after the other of a list). \begin{everbatim*} -\xinttheiexpr ([1,3,6,99,100,200][2:4])\relax +\xinttheexpr subs([x]^2,x=-123,17,32)\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: +\item last but not least, |seq| has variants |rseq| and |rrseq| which allow + recursive definitions. They start with at least one initial value, then a + semi-colon, then the formula, then the list of indices to iterate over. |@| + (or |@1|) evaluates to the last computed item, and |rrseq| keeps the memory + of the |K| last results, where |K| was the number of initial terms. One + accesses them via |@1, @2, @3, @4| and |@@(N)| for |N>4|. It is even + possible to nest them and use |@@@| to access the values of the master + recursion... \begin{everbatim*} -\xinttheiiexpr [1..10 ] [ : 7 ]\relax +\xinttheiiexpr rseq(1; 2*@, i=1..10), `+`(rseq(1; 2*@, i=1..10))\relax +\end{everbatim*} +\begin{everbatim*} +\xinttheiiexpr rseq(2; @(@+1)/2, i=1..5)\relax +\end{everbatim*} +\begin{everbatim*} +\xinttheiiexpr rseq(0,1; (@1,add(x,x=@1)), y=2..10)\relax \end{everbatim*} -Similarly all the |+[|, |*[|, \dots and |]**|, |]/|, \dots operators admit -spaces but nothing else in-between their constituent characters. +Some Fibonacci fun \begin{everbatim*} -\xinttheiiexpr [ 1 . . 1 0 ] * * 1 1 \relax +\xinttheiiexpr rrseq(0,1; @1+@2, x=2..10), last(rrseq(0,1; @1+@2, x=2..100))\relax +\end{everbatim*} +\begin{everbatim*} +Sum of previous last three: \xinttheiiexpr rrseq(0,0,1; @1+@2+@3, i=1..20)\relax +\end{everbatim*} +\begin{everbatim*} +Big numbers: \printnumber{\xinttheexpr rseq(1; @(@+1), j=1..10)\relax } \end{everbatim*} - 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} +Nested recursion often quickly leads to gigantic outputs. This is an +experimental feature, susceptible to be removed or altered in the future. +\begin{everbatim*} +\xinttheexpr rrseq(1; `+`(rrseq(0,1; @@@(1)+@1+@2, i=1..10)), j=1..5)\relax +\end{everbatim*} -\end{itemize} +\item The special keywords |omit|, |abort| and |break(..)| are available + inside |seq|, |rseq|, |rrseq|, as well as the |n++| for a potentially + infinite iteration. The |n++| construct in conjunction with an |abort| or + |break| is often more efficient, because in other cases the list to iterate + over is first completely constructed. +\begin{everbatim*} +First Fibonacci number at least |2^31| and its index +\xinttheiiexpr iter(0,1; (@1>=2^31)?{break(i)}{@2+@1}, i=1++)\relax +\end{everbatim*} -\item count registers and |\numexpr|-essions are accepted (LaTeX{}'s counters - can be inserted using |\value|) natively without |\the| or |\number| as prefix. - Also dimen registers and control sequences, skip registers and control - sequences (\LaTeX{}'s lengths), |\dimexpr|-essions, |\glueexpr|-essions are - automatically unpacked using |\number|, discarding the stretch and shrink - components and giving the dimension value in |sp| units ($1/65536$th of a - \TeX{} point). Furthermore, tacit multiplication is implied, when the - register, variable, or expression is immediately prefixed by a (decimal) - number. +\begin{everbatim*} +Prime numbers are always cool +\xinttheiiexpr seq((seq((subs((x/:m)?{(m*m>x)?{1}{0}}{-1},m=2n+1)) + ??{break(0)}{omit}{break(1)},n=1++))?{x}{omit}, + x=10001..[2]..10200)\relax +\end{everbatim*} -\item tacit multiplication (the parser inserts a |*|) applies when the parser is - currently scanning the digits of a number (or its decimal part or scientific - part), or is looking - for an infix operator, and: (1.)~\emph{encounters a register, - variable or \eTeX{} expression (as described in the previous item)}, - (2.)~\emph{encounters a sub-\csa{xintexpr}-ession}, or - (3.)~\emph{encounters an opening parenthesis.} +The syntax in this last example may look a bit involved. First |x/:m| computes +|x modulo m| (this is the modulo with respect to truncated division, which +here for positive arguments is like Euclidean division; in +|\xintexpr...\relax|, |a/:b| is such that |a = b*(a//b)+a/:b|, with |a//b| the +algebraic quotient |a/b| truncated to an integer.). The |(x)?{yes}{no}| +construct checks if |x| (which \emph{must} be within parentheses) is true or +false, i.e. non zero or zero. It then executes either the |yes| or the |no| +branch, the non chosen branch is \emph{not} evaluated. Thus if |m| divides |x| +we are in the second (``false'') branch. This gives a |-1|. This |-1| is the +argument to a |??| branch which is of the type |(y)??{y<0}{y=0}{y>0}|, thus here +the |y<0|, i.e., |break(0)| is chosen. This |0| is thus given to another |?| +which consequently chooses |omit|, hence the number is not kept in the list. +The numbers which survive are the prime numbers. -\item when defining a macro to expand to an expression either via - % - \leftedline{|\def\x {\xintexpr \a + \b \relax}| or |\edef\x {\xintexpr - \a+\b\relax}|} - % - one may then do |\xintthe\x|, either for printing the result on the page or - to use it in some other macros expanding their arguments. The |\edef| does - the computation but keeps it in an internal private format. Naturally, the - |\edef| is only possible if |\a| and |\b| are already defined, either as - macros expanding to legal syntax like |37^23*17| or themselves in the same - way |\x| above was defined. Indeed in both cases (the `yet-to-be computed' - and the `already computed') |\x| can then be inserted in other expressions, - as for example - % - \leftedline {|\edef\y {\xintexpr \x^3\relax}|} - % - This would have worked also with |\x| defined as |\def\x {(\a+\b)}| but - |\edef\x| would not have been an option then, and |\x| could have been used - only inside an |\xintexpr|-ession, whereas the previous |\x| can also be - used as |\xintthe\x| in any context triggering the expansion of |\xintthe|. +% A006877 In the `3x+1' problem, these values for the starting value set new +% records for number of steps to reach 1. (Formerly M0748) 14 1, 2, 3, 6, 7, +% 9, 18, 25, 27, 54, 73, 97, 129, 171, 231, 313, 327, 649, 703, 871, 1161, +% 2223, 2463, 2919, 3711, 6171, 10971, 13255, 17647, 23529, 26623, 34239, +% 35655, 52527, 77031, 106239, 142587, 156159, 216367, 230631, 410011, 511935, +% 626331, 837799 -\item there is also \csbxint{boolexpr}| ... \relax| and - \csbxint{theboolexpr}| ... \relax|. Same as |\xintexpr| with the final - result converted to $1$ if it is not zero. See also - \csbxint{ifboolexpr} (\autoref{xintifboolexpr}) and the - \hyperlink{item:bool}{discussion} of the |bool| and |togl| functions - in \autoref{sec:expr}. Here is an example: -\catcode`| 12 % \xintNewBoolExpr le fait mais ça sera trop tard - % après le \scantokens qui aura redonné à | son - % caractère actif... avant j'utilisais ici \everb - % avec délimiteur ! +\item The |iter| function is like |rrseq| but does not leave a trace of earlier items, + it starts with |K| initial values, then it iterates: either a fixed number of times, + or until aborting or breaking. And ultimately it prints |K| final values. \begin{everbatim*} -\xintNewBoolExpr \AssertionA[3]{ #1 && (#2|#3) } -\xintNewBoolExpr \AssertionB[3]{ #1 || (#2) } -\xintNewBoolExpr \AssertionC[3]{ xor(#1,#2,#3) } -{\centering\normalcolor\xintFor #1 in {0,1} \do {% - \xintFor #2 in {0,1} \do {% - \xintFor #3 in {0,1} \do {% - #1 AND (#2 OR #3) is \textcolor[named]{OrangeRed}{\AssertionA {#1}{#2}{#3}}\hfil - #1 OR (#2 AND #3) is \textcolor[named]{OrangeRed}{\AssertionB {#1}{#2}{#3}}\hfil - #1 XOR #2 XOR #3 is \textcolor[named]{OrangeRed}{\AssertionC {#1}{#2}{#3}}\\}}}} -\end{everbatim*}\catcode`| 13 - - This example used for efficiency \csbxint{NewBoolExpr}. See also the - \autoref{xintNewExpr}. - -\item there is \csbxint{floatexpr}| ... \relax| where the algebra is done - in floating point approximation (also for each intermediate result). Use the - syntax |\xintDigits:=N;| to set the precision. Default: $16$ digits. - % - \leftedline{|\xintthefloatexpr 2^100000\relax:| \dtt{\xintthefloatexpr - 2^100000\relax }} - % - The square-root operation can be used in |\xintexpr|, it is computed - as a float with the precision set by |\xintDigits| or by the optional - second argument: - % +The first Fibonacci number beyond the \TeX{} bound is +\xinttheiiexpr subs(iter(0,1;(@1>N)?{break(i)}{@1+@2},i=1++),N=2^31)\relax{} +and the previous number was its index. +\end{everbatim*}But this was a bit too easy, what is the smallest Fibonacci number not representable on 64 bits? \begin{everbatim*} -\xinttheexpr sqrt(2,60)\relax - -Here the [60] is to avoid truncation to |\xintDigits| of precision on output. -\printnumber{\xintthefloatexpr [60] sqrt(2,60)\relax} +The first Fibonacci number beyond |2^64| bound is +\xinttheiiexpr subs(iter(0,1;(@1>N)?{break(i)}{@1+@2},i=1++),N=2^64)\relax{} +and the previous number was its index. \end{everbatim*} - -\item - Floats are quickly indispensable when using the power function (which - can only have an integer exponent), as exact results will easily have - hundreds, if not thousands, of digits. - % + +One more recursion: \begin{everbatim*} -\xintDigits:=48;\xintthefloatexpr 2^100000\relax +\def\syr #1{\xinttheiiexpr rseq(#1; (@<=1)?{break(i)}{odd(@)?{3@+1}{@//2}},i=0++)\relax} +The 3x+1 problem: \syr{231}\par \end{everbatim*} -\item hexadecimal \TeX{} number denotations (\emph{i.e.}, with a |"| prefix) - are recognized by the |\xintexpr| parser and its variants. \fbox{This - requires \xintbinhexname}. Except in |\xintiiexpr|, a (possibly empty) - fractional part with the dot |.| as ``hexadecimal'' mark is allowed. - % - \leftedline{|\xinttheexpr "FEDCBA9876543210\relax|$\to$\dtt{\xinttheexpr - "FEDCBA9876543210\relax}} - % - \leftedline{|\xinttheiexpr - 16^5-("F75DE.0A8B9+"8A21.F5746+16^-5)\relax|$\to$\dtt{\xinttheiexpr - 16^5-("F75DE.0A8B9+"8A21.F5746+16^-5)\relax}} - % - Letters must be uppercased, as with standard \TeX{} hexadecimal - denotations. -\end{itemize} - +Ok, a final one: +\begin{everbatim*} +\def\syrMax #1{\xinttheiiexpr iter(#1,#1;even(i)? + {(@2<=1)?{break(i/2)}{odd(@2)?{3@2+1}{@2//2}}} + {(@1>@2)?{@1}{@2}},i=0++)\relax } +With initial value 1161, the maximal number attained is \syrMax{1161} and that latter +number is the number of steps which was needed to reach 1.\par +\end{everbatim*} -Note that |2^-10| is perfectly accepted input, no need for parentheses; -operators of power |^|, division |/|, and subtraction |-| are all -left-associative: |2^4^8| is evaluated as |(2^4)^8|. The minus sign as prefix -has various precedence levels: |\xintexpr -3-4*-5^-7\relax| evaluates as -|(-3)-(4*(-(5^(-7))))| and |-3^-4*-5-7| as |(-((3^(-4))*(-5)))-7|. +Well, one more: -If one uses directly macros within |\xintexpr..\relax|, rather than the -operators or the functions which are described next, one should obviously take -into account that the parser will \emph{not} see the macro arguments. +\begin{everbatim*} +\newcommand\GCD [2]{\xinttheiiexpr rrseq(#1,#2; (@1=0)?{abort}{@2/:@1}, i=1++)\relax } +\GCD {13^10*17^5*29^5}{2^5*3^6*17^2} +\end{everbatim*} -Here is, listed from the highest priority to the lowest, the complete list of -operators and functions. +and the ultimate: -% \ctexttt is a remnant of 1.09n manual, don't have time to get rid of it now. +\begin{everbatim*} +\newcommand\Factors [1]{\xinttheiiexpr + subs(seq((i/:3=2)?{omit}{[L][i]},i=1..([L][0])), + L=rseq(#1;(p^2>[@][1])?{([@][1]>1)?{break(1,[@][1],1)}{abort}} + {(([@][1])/:p)?{omit} + {iter(([@][1])//p; (@/:p)?{break(@,p,e)}{@//p},e=1++)}},p=2++))\relax } +\Factors {41^4*59^2*29^3*13^5*17^8*29^2*59^4*37^6} +\end{everbatim*} -\newcommand\ctexttt [1]{\begingroup\color[named]{DarkOrchid}%\bfseries - #1\endgroup} +This might look a bit scary, I admit. \xintexprname has minimal tools and +is obstinate about doing everything expandably! We are hampered by absence of a +notion of ``nuple''. The algorithm divides |N| by |2| until no more possible, +then by |3|, then by |4| (which is silly), then by |5|, then by |6| (silly +again), \dots. -\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, - itemindent=0pt, leftmargin=\leftmarginii] -\item - Functions are at the same top level of priority. All functions even - |?| and |!| (as prefix) require parentheses around their arguments. +The variable |L=rseq(#1;...)| expands, if one follows the steps, to a comma +separated list starting with the initial (evaluated) |N=#1| and then +pseudo-triplets where the first item is |N| trimmed of small primes, the +second item is the last prime divisor found, and the third item is its +exponent in original |N|. - \begin{snugframed} - \ctexttt{num, reduce, abs, sgn, frac, floor, ceil, sqr, sqrt, sqrtr, float, - round, trunc, mod, quo, rem, gcd, lcm, max, min, `+`, `*`, ?, !, not, - all, any, xor, if, ifsgn, even, odd, first, last, reversed, bool, - togl, add, mul, seq, subs, rseq, rrseq, iter} +The algorithm needs to keep handy the last computed quotient by prime powers, +hence all of them, but at the very end it will be cleaner to get rid of them +(this corresponds to the first line in the code above). This is achieved in a +cumbersome inefficient way; indeed each item extraction |[L][i]| is costly: it +is not like accessing an array stored in memory, due to expandability, nothing +can be stored in memory! Nevertheless, this step could be done here in a far +less inefficient manner if there was a variant of |seq| which, in the spirit +of \csbxint{iloopindex}, would know how many steps it had been through so far. +This is a feature to be added to |\xintexpr|! (as well as a |++| construct +allowing a non unit step). - |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| and |min| are functions with arbitrarily many comma - separated arguments. +Notice that in |iter(([@][1])//p;| the |@| refers to the previous triplet (or +in the first step to |N|), but the latter |@| showing up in |(@/:p)?| refers +to the previous value computed by |iter|. - |bool| and |togl| use delimited macros to fetch their argument whose - closing parenthesis thus must be explicit, not arising from expansion. +\begin{snugframed} + Parentheses are essential in |..([y][0])| else the parser will see |..[| and + end up in ultimate confusion, and also in |([@][1])/:p| else the parser will + see the itemwise operator |]/| on lists and again be very confused (I could + implement a |]/:| on lists, but in this situation this would also be very + confusing to the parser.) +\end{snugframed} - Similarly |add|, |mul|, |subs|, |seq|, |rseq|, |rrseq|, |iter| use at - some stages delimited macros. They work with \emph{dummy variables}, - represented as one Latin letter (lowercase or uppercase) followed by a - mandatory |=| sign, then a comma separated list of values to assign in - turn to the dummy variable, which will be substituted in the expression - which was parsed as the first, comma delimited, argument to the - function; additionally |rseq|, |rrseq| and |iter| have a mandatory - initial comma separated list which is separated by a semi-colon from the - expression to evaluate iteratively. |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. +For comparison, here is an \fexpan dable macro expanding to the same result, +but coded directly with the \xintname macros. Here |#1| can not be itself an +expression, naturally. But at least we let |\Factorize| \fexpan d its +argument. +\begin{everbatim} +\makeatletter +\newcommand\Factorize [1] + {\romannumeral0\expandafter\factorize\expandafter{\romannumeral-`0#1}}% +\newcommand\factorize [1]{\xintiiifOne{#1}{ 1}{\factors@a #1.{#1};}}% +\def\factors@a #1.{\xintiiifOdd{#1} + {\factors@c 3.#1.}% + {\expandafter\factors@b \expandafter1\expandafter.\romannumeral0\xinthalf{#1}.}}% +\def\factors@b #1.#2.{\xintiiifOne{#2} + {\factors@end {2, #1}}% + {\xintiiifOdd{#2}{\factors@c 3.#2.{2, #1}}% + {\expandafter\factors@b \the\numexpr #1+\@ne\expandafter.% + \romannumeral0\xinthalf{#2}.}}% +}% +\def\factors@c #1.#2.{% + \expandafter\factors@d\romannumeral0\xintiidivision {#2}{#1}{#1}{#2}% +}% +\def\factors@d #1#2#3#4{\xintiiifNotZero{#2} + {\xintiiifGt{#3}{#1} + {\factors@end {#4, 1}}% ultimate quotient is a prime with power 1 + {\expandafter\factors@c\the\numexpr #3+\tw@.#4.}}% + {\factors@e 1.#3.#1.}% +}% +\def\factors@e #1.#2.#3.{\xintiiifOne{#3} + {\factors@end {#2, #1}}% + {\expandafter\factors@f\romannumeral0\xintiidivision {#3}{#2}{#1}{#2}{#3}}% +}% +\def\factors@f #1#2#3#4#5{\xintiiifNotZero{#2} + {\expandafter\factors@c\the\numexpr #4+\tw@.#5.{#4, #3}}% + {\expandafter\factors@e\the\numexpr #3+\@ne.#4.#1.}% +}% +\def\factors@end #1;{\xintlistwithsep{, }{\xintRevWithBraces {#1}}}% +\makeatother +\end{everbatim} - They may be nested. - \end{snugframed} +The macro |\Factorize| puts a little stress on the input save stack in order +not be bothered with previously gathered things. I timed it to be about eight +times faster than |\Factors| in test cases such as +|16246355912554185673266068721806243461403654781833| and others. Among the +various things explaining the speed-up, there is fact that we step by +increments of two, not one, and also that we divide only once, obtaining +quotient and remainder in one go. These two things already make for a speed-up +factor of about four. Thus, our earlier |\Factors| was not completely +inefficient, and was quite easier to come up with than |\Factorize|. -\begin{description}[leftmargin=0pt] - \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*} +If we only considered small integers, we could write pure |\numexpr| methods +which would be very much faster (especially if we had a table of small primes +prepared first) but still ridiculously slow compared to any non expandable +implementation, not to mention use of programming languages directly accessing +the CPU registers\dots +\end{itemize} - \item[reduce] reduces a fraction to smallest terms -\begin{everbatim*} -\xinttheexpr reduce(50!/20!/20!/10!)\relax -\end{everbatim*} +%\phantomsection +\phantomsection\label{sec:expr11coords} -Recall that this is NOT done automatically, for example when adding fractions. - \item[abs] absolute value - \item[sgn] sign - \item[frac] fractional part +To conclude with this overview of the new features in \xintexprname |1.1|, I +will mention {\bfseries |\xintthecoords|} which converts a comma separated +list as produced by |\xintfloatexpr| or |\xintiexpr [d]| to the format +expected by the |TikZ| |coordinates| syntax. \begin{everbatim*} -\xinttheexpr frac(-355/113), frac(-1129.218921791279)\relax +{\centering\begin{tikzpicture}[scale=10]\xintDigits:=8; + \clip (-1.1,-.25) rectangle (.3,.25); + \draw [blue] (-1.1,0)--(1,0); + \draw [blue] (0,-1)--(0,+1); + \draw [red] plot[smooth] coordinates {\xintthecoords + % converts into (x1, y1) (x2, y2)... format + \xintfloatexpr seq((x^2-1,mul(x-t,t=-1+[0..4]/2)),x=-1.2..[0.1]..+1.2) \relax }; +\end{tikzpicture}\par } \end{everbatim*} - \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[?] |?(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*} +% Notice: if x goes no take exactly value 1 or -1, the origin appears slightly +% off the curve, not MY fault!!! + +\csbxint{thecoords} should be followed immediately by \csbxint{floatexpr} or +\csbxint{iexpr} or \csbxint{iiexpr}, but not |\xintthefloatexpr|, etc\dots + +Besides, as |TikZ| will not understand the |A/B[N]| format which is used on +output by |\xintexpr|, |\xintexpr| is not really usable with |\xintthecoords| +for a |TikZ| picture, but one may use it on its own, and the reason for the +spaces in and between coordinate pairs is to allow if necessary to print on +the page for examination with about correct line-breaks. - \item[odd] oddness of the truncation \begin{everbatim*} -\xinttheexpr seq((x,odd(x)), x=-5/2..[1/3]..+5/2)\relax +\edef\x{\xintthecoords \xintexpr rrseq(1/2,1/3; @1+@2, x=1..20)\relax } +\meaning\x +++ \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})). +\subsection{The syntax}\label{ssec:syntax} - 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)|. +An expression is enclosed between either \csbxint{expr}, or \csbxint{iexpr}, +or \csbxint{iiexpr}, or \csbxint{floatexpr}, or \csbxint{boolexpr} and a +\emph{mandatory} ending |\relax|. An expression may be a sub-unit of another +one. - 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). +Apart from \csbxint{floatexpr} the evaluations of algebraic operations are +\emph{exact}. The variant \csbxint{iiexpr} does not know fractions and is +provided for integer-only calculations. The variant \csbxint{iexpr} is exactly +like \csbxint{expr} except that it either rounds the final result to an +integer, or in case of an optional parameter |[d]|, rounds to a fixed point +number with |d| digits after decimal mark. The variant \csbxint{floatexpr} +does float calculations according to the current value of the precision set by +|\xintDigits|. - 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. +The whole expression should be prefixed by |\xintthe| when it is destined to +be printed on the typeset page, or given as argument to a macro (assuming this +macro systematically expands its argument). As a shortcut to +|\xintthe\xintexpr| there is |\xinttheexpr|. One gets used to not forget the +two |t|'s. - 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. +|\xintexpr|-essions and |\xinttheexpr|-essions are completely expandable, in two steps. - 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. +\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, + itemindent=0pt, leftmargin=\leftmarginii] +\item An expression is built the standard way with opening and closing + parentheses, infix operators, and (big) numbers, with possibly a fractional + part, and/or scientific notation (except for \csbxint{iiexpr} which only + admits big integers). All variants work with comma separated expressions. On + output each comma will be followed by a space. A decimal number must have + digits either before or after the decimal mark.\MyMarginNote{Changed!} - See also \csbxint{ifboolexpr}, in this context. +\item as everything gets expanded, the characters |.|, |+|, |-|, |*|, |/|, |^|, + |!|, |&|, \verb+|+, |?|, |:|, |<|, |>|, |=|, |(|, |)|, |"|, |]|, |[|, |@| + and the comma |,| should not (if used in the expression) be active. For + example, the French language in |Babel| system, for pdf\LaTeX, activates |!|, + |?|, |;| and |:|. Turn off the activity before the expressions. -\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(-20^9/3^5,12)=|\dtt{\xinttheexpr float(-20^9/3^5,12)\relax.} - \item [sqrt] in \csbxint{expr} and \csbxint{floatexpr}, uses the float evaluation - with the precision given by the optional second argument. -\begin{everbatim*} -\xinttheexpr sqrt(2,31)\relax\ and \xinttheiiexpr sqrt(num(2e60))\relax -\end{everbatim*} - \end{description} + Alternatively the command \csbxint{exprSafeCatcodes} resets all + characters potentially needed by \csbxint{expr} to their standard catcodes + and \csbxint{exprRestoreCatcodes} restores the status prevailing at the time + of the previous \csa{xintexprSafeCatcodes}. - \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*} - \end{description} +\item The infix operators are |+|, |-|, |*|, |/|, |^| (or |**|) for exact or + floating point algebra (only integer exponents for power operations), |&&| + and \verb+||+ \footnote{with releases earlier than |1.1|, only single + character operators |&| and \verb+|+ were available, because the parser + did not handle multi-character operators. Their usage in this rôle is now + deprecated,\IMPORTANT{} as they may be assigned some new meaning in the + future.} for combining ``true'' (non zero) and ``false'' (zero) + conditions, as can be formed for example with the |=| (or |==|), |<|, |>|, + |<=|, |>=|, |!=| comparison operators. - \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 |!| is either a + function (the logical not) requiring an argument within parentheses, or a + post-fix operator which does the factorial. In \csbxint{floatexpr} it is + mapped to \csbxint{FloatFac}, else it computes the exact factorial. - \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 The |?| may serve either as a function (the truth value) requiring an + argument within parentheses), or as two-way post-fix branching operator + |(cond)?{YES}{NO}|. The false branch will \emph{not} be evaluated. - \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), -\item[|`*`|] multiplies (left ticks mandatory), -\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:]|. +\item There is also |??| which branches according to the scheme + |(x)??{<0}{=0}{>0}|. + +\item Comma separated lists may be generated with |a..b| and |a..[d]..b| and + they may be + manipulated to some extent once put into brackets: + \begin{itemize} + \item |a..b| constructs the \textbf{small} integers from $\lceil a\rceil$ to + $\lfloor b\rfloor$ (possibly a decreasing sequence), \begin{everbatim*} -\xinttheiiexpr last(-7..3), [-7..3][-1:]\relax +\xinttheexpr 1.5..11.23\relax \end{everbatim*} -\item[reversed] reverses the order + + \item |a..[d]..b| allows big integers, or fractions, it proceeds by step of |d|. \begin{everbatim*} -\xinttheiiexpr reversed(123..150)\relax +\xinttheexpr 1.5..[0.97]..11.23\relax \end{everbatim*} - \end{description} -\item[functions using dummy variables] -\noindent\par -They are nestable to arbitrary depth if suitably parenthesized. -\begin{description} -\item [subs] for variable substitution, useful to get something evaluated only - once + \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*} -% ATTENTION that xz generates an error, 'unknown variable xz', one must use x*z -\xinttheexpr subs(subs(seq(x*z,x=1..10),z=y^2),y=10)\relax +\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*} -\item[add] addition -\begin{everbatim*} -\xinttheiiexpr add(x^3,x=1..50)\relax -\end{everbatim*} +See the frame coming next for the |\empty| token. +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[mul] multiplication + \item |[list][:n]| extracts the first |n| elements if |n>0|, or suppresses + the last \verb+|n|+ elements if |n<0|. \begin{everbatim*} -\xinttheiiexpr subs(mul(2n+1,n=1..N),N=30)\relax +\xinttheiiexpr [1..10][:6]\relax\ and \xinttheiiexpr [1..10][:-6]\relax \end{everbatim*} - -\item[seq] comma separated values generated according to a formula + \item |[list][n:]| suppresses the first |n| elements if |n>0|, or extracts + the last \verb+|n|+ elements if |n<0|. \begin{everbatim*} -\xinttheiiexpr seq(x(x+1)(x+2)(x+3),x=1..10)\relax +\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 seq(seq(i^2+j^2, i=0..j), j=0..10)\relax +\xinttheiiexpr [1..20][6:13]\relax\ = \xinttheiiexpr [1..20][6-20:13-20]\relax \end{everbatim*} - -\item[rseq] recursive sequence, |@| for the previous value. +\item It is naturally possible to nest these things: \begin{everbatim*} -% ATTENTION y/2@ would give (y/2)@, that is (y/2)*@ !! -\printnumber {\xintthefloatexpr subs(rseq (1; @/2+y/(2@), i=1..10),y=1000)\relax } +\xinttheexpr [[1..50][13:37]][10:-10]\relax \end{everbatim*} - -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''. +\item itemwise operations either on the left or the right are possible: \begin{everbatim*} -\printnumber{\xintthefloatexpr rseq(1,10^6; - (sqrt([@][1]*[@][2]),([@][1]+[@][2])/2), i=1..10)\relax } +\xinttheiiexpr 123*[1..10]^2\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{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*} -\xinttheiiexpr rrseq(0,1; @1+@2, i=2..30)\relax +\xinttheiexpr \empty [1,3,6,99,100,200][2:4]\relax \end{everbatim*} + An alternative is to use parentheses \begin{everbatim*} -\xinttheiiexpr rrseq(0,1,2,3,4,5; @1+@2+@3+@4+@@(5)+@@(6), i=1..20)\relax +\xinttheiexpr ([1,3,6,99,100,200][2:4])\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|. + 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 iter(0,1; @1+@2, i=2..5, 6..10)\relax -% the iterated over list is allowed to have disjoint defining parts. +\xinttheiiexpr [1..10 ] [ : 7 ]\relax \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)| but I never tried it! -With |seq|, |rseq|, -|rrseq|, |iter|, 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 +Similarly all the |+[|, |*[|, \dots and |]**|, |]/|, \dots operators admit +spaces but nothing else in-between their constituent characters. \begin{everbatim*} -\xinttheiiexpr iter(1;(@>10^40)?{break(@)}{2@},i=1++)\relax -% this would not work with i=1,2,3++. Only n++ syntax, nothing before. +\xinttheiiexpr [ 1 . . 1 0 ] * * 1 1 \relax \end{everbatim*} -\end{description} -Refer to \autoref{sec:expr11} for more examples. -\end{description} + 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} -\item The postfix operators \ctexttt{!} and the branching conditionals \ctexttt{?, ??}. - \begin{description} - \item[{\color[named]{DarkOrchid}!}] computes the factorial of an integer. - This is the exact factorial even when used inside |\xintfloatexpr|. +\end{itemize} - \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 count registers and |\numexpr|-essions are accepted (LaTeX{}'s counters + can be inserted using |\value|) natively without |\the| or |\number| as prefix. + Also dimen registers and control sequences, skip registers and control + sequences (\LaTeX{}'s lengths), |\dimexpr|-essions, |\glueexpr|-essions are + automatically unpacked using |\number|, discarding the stretch and shrink + components and giving the dimension value in |sp| units ($1/65536$th of a + \TeX{} point). Furthermore, tacit multiplication is implied, when the + register, variable, or expression is immediately prefixed by a (decimal) + number. - \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 tacit multiplication (the parser inserts a |*|) applies when the parser is + currently scanning the digits of a number (or its decimal part or scientific + part), or is looking + for an infix operator, and: (1.)~\emph{encounters a register, + variable or \eTeX{} expression (as described in the previous item)}, + (2.)~\emph{encounters a sub-\csa{xintexpr}-ession}, or + (3.)~\emph{encounters an opening parenthesis.} -\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 +\item when defining a macro to expand to an expression either via % - \leftedline{\restoreMicroFont|\xinttheexpr .^2+2^.\relax|} + \leftedline{|\def\x {\xintexpr \a + \b \relax}| or |\edef\x {\xintexpr + \a+\b\relax}|} % - which is |0^2+2^0| and produces \dtt{\xinttheexpr .^2+2^.\relax}. - -\item The |e| and |E| for scientific notation. They are parsed - like the decimal mark is. Thus |1e(3+2)| is no legal syntax anymore, one - must use |10^(3+2)| in such cases. -\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) 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 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: - % REVOIR CECI - \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|} + one may then do |\xintthe\x|, either for printing the result on the page or + to use it in some other macros expanding their arguments. The |\edef| does + the computation but keeps it in an internal private format. Naturally, the + |\edef| is only possible if |\a| and |\b| are already defined, either as + macros expanding to legal syntax like |37^23*17| or themselves in the same + way |\x| above was defined. Indeed in both cases (the `yet-to-be computed' + and the `already computed') |\x| can then be inserted in other expressions, + as for example % - to obtain the correct floating point evaluation - % REVOIR CECI - % - \leftedline{$\np{1.00000001}^{12^{16}}\approx\np{\xintthefloatexpr - (1+1e-8)^\xintiiexpr 12^16\relax\relax }$} + \leftedline {|\edef\y {\xintexpr \x^3\relax}|} % - \endgroup + This would have worked also with |\x| defined as |\def\x {(\a+\b)}| but + |\edef\x| would not have been an option then, and |\x| could have been used + only inside an |\xintexpr|-ession, whereas the previous |\x| can also be + used as |\xintthe\x| in any context triggering the expansion of |\xintthe|. -\item Multiplication and division \raisebox{-.3\height}{|*|}, |/|. The - division is left associative, too: +\item there is also \csbxint{boolexpr}| ... \relax| and + \csbxint{theboolexpr}| ... \relax|. Same as |\xintexpr| with the final + result converted to $1$ if it is not zero. See also + \csbxint{ifboolexpr} (\autoref{xintifboolexpr}) and the + \hyperlink{item:bool}{discussion} of the |bool| and |togl| functions + in \autoref{sec:expr}. Here is an example: +\catcode`| 12 % \xintNewBoolExpr le fait mais ça sera trop tard + % après le \scantokens qui aura redonné à | son + % caractère actif... avant j'utilisais ici \everb + % avec délimiteur ! +\begin{everbatim*} +\xintNewBoolExpr \AssertionA[3]{ #1 && (#2|#3) } +\xintNewBoolExpr \AssertionB[3]{ #1 || (#2) } +\xintNewBoolExpr \AssertionC[3]{ xor(#1,#2,#3) } +{\centering\normalcolor\xintFor #1 in {0,1} \do {% + \xintFor #2 in {0,1} \do {% + \xintFor #3 in {0,1} \do {% + #1 AND (#2 OR #3) is \textcolor[named]{OrangeRed}{\AssertionA {#1}{#2}{#3}}\hfil + #1 OR (#2 AND #3) is \textcolor[named]{OrangeRed}{\AssertionB {#1}{#2}{#3}}\hfil + #1 XOR #2 XOR #3 is \textcolor[named]{OrangeRed}{\AssertionC {#1}{#2}{#3}}\\}}}} +\end{everbatim*}\catcode`| 13 + + This example used for efficiency \csbxint{NewBoolExpr}. See also the + \autoref{xintNewExpr}. + +\item there is \csbxint{floatexpr}| ... \relax| where the algebra is done + in floating point approximation (also for each intermediate result). Use the + syntax |\xintDigits:=N;| to set the precision. Default: $16$ digits. % - \begingroup\restoreMicroFont + \leftedline{|\xintthefloatexpr 2^100000\relax:| \dtt{\xintthefloatexpr + 2^100000\relax }} % - |\xinttheiexpr 100/50/2\relax| evaluates to \xinttheiexpr 100/50/2\relax, - not \xinttheiexpr 100/(50/2)\relax. + The square-root operation can be used in |\xintexpr|, it is computed + as a float with the precision set by |\xintDigits| or by the optional + second argument: % - \endgroup - Inside \csbxint{iiexpr}, |/| does \emph{rounded} division. +\begin{everbatim*} +\xinttheexpr sqrt(2,60)\relax -\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. +Here the [60] is to avoid truncation to |\xintDigits| of precision on output. +\printnumber{\xintthefloatexpr [60] sqrt(2,60)\relax} +\end{everbatim*} + +\item + Floats are quickly indispensable when using the power function (which + can only have an integer exponent), as exact results will easily have + hundreds, if not thousands, of digits. + % \begin{everbatim*} -\xinttheexpr 100000//13, 100000/:13, 100000 'mod' 13, trunc(100000/13,10), - trunc(100000/:13/13,10)\relax +\xintDigits:=48;\xintthefloatexpr 2^100000\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: +\item hexadecimal \TeX{} number denotations (\emph{i.e.}, with a |"| prefix) + are recognized by the |\xintexpr| parser and its variants. \fbox{This + requires \xintbinhexname}. Except in |\xintiiexpr|, a (possibly empty) + fractional part with the dot |.| as ``hexadecimal'' mark is allowed. % - \begingroup\restoreMicroFont + \leftedline{|\xinttheexpr "FEDCBA9876543210\relax|$\to$\dtt{\xinttheexpr + "FEDCBA9876543210\relax}} % - |\xinttheiexpr 100-50-2\relax| evaluates to \xinttheiexpr 100-50-2\relax, - not \xinttheiexpr 100-(50-2)\relax. + \leftedline{|\xinttheiexpr + 16^5-("F75DE.0A8B9+"8A21.F5746+16^-5)\relax|$\to$\dtt{\xinttheiexpr + 16^5-("F75DE.0A8B9+"8A21.F5746+16^-5)\relax}} % - \endgroup - -\item The list itemwise operators |+[|, |-[|, |]+|, |]-|, are at - the same precedence level as |+| and |-|, + Letters must be uppercased, as with standard \TeX{} hexadecimal + denotations. +\end{itemize} -\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). +Note that |2^-10| is perfectly accepted input, no need for parentheses; +operators of power |^|, division |/|, and subtraction |-| are all +left-associative: |2^4^8| is evaluated as |(2^4)^8|. The minus sign as prefix +has various precedence levels: |\xintexpr -3-4*-5^-7\relax| evaluates as +|(-3)-(4*(-(5^(-7))))| and |-3^-4*-5-7| as |(-((3^(-4))*(-5)))-7|. -\item Inclusive disjunction (logical or): \verb+||+ - and equivalently |'or'| (quotes mandatory). +If one uses directly macros within |\xintexpr..\relax|, rather than the +operators or the functions which are described next, one should obviously take +into account that the parser will \emph{not} see the macro arguments. -\item XOR: |'xor'| with mandatory quotes is at the same level of precedence - as \verb+||+. +Here is, listed from the highest priority to the lowest, the complete list of +operators and functions. -\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{}. +% \ctexttt is a remnant of 1.09n manual, don't have time to get rid of it now. -\item The parentheses. -\end{itemize} +\newcommand\ctexttt [1]{\begingroup\color[named]{DarkOrchid}%\bfseries + #1\endgroup} -% See \autoref{ssec:countinexpr} for count and dimen registers and variables. +\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, + itemindent=0pt, leftmargin=\leftmarginii] +\item + Functions are at the same top level of priority. All functions even + |?| and |!| (as prefix) require parentheses around their arguments. -\subsection{\texorpdfstring{\texttt{\protect\string\numexpr}}{\textbackslash - numexpr} or \texorpdfstring{\texttt{\protect\string\dimexpr}}{\textbackslash - dimexpr} expressions, count and dimension registers and variables} -\label{ssec:countinexpr} + \begin{snugframed} + \ctexttt{num, qint, qfrac, qfloat, reduce, abs, sgn, frac, floor, ceil, + sqr, sqrt, sqrtr, float, round, trunc, mod, quo, rem, gcd, lcm, max, + min, `+`, `*`, ?, !, not, all, any, xor, if, ifsgn, even, odd, first, + last, reversed, bool, togl, add, mul, seq, subs, rseq, rrseq, iter} -Count registers, count control sequences, dimen registers, -dimen control sequences, skips and skip control sequences, |\numexpr|, -|\dimexpr|, |\glueexpr| can be inserted directly, they will be unpacked using -|\number| (which gives the internal value in terms of scaled points for the -dimensional variables: $1$\,|pt|${}=65536$\,|sp|; stretch and shrink -components are thus discarded). Tacit multiplication is implied, when a -number or decimal number prefixes such a register or control sequence. + |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| and |min| are functions with arbitrarily many comma + separated arguments. -\LaTeX{} lengths are skip control sequences and \LaTeX{} counters should be -inserted using |\value|. + |bool|, |togl| use delimited macros to fetch their argument and the + closing parenthesis which thus must be explicit, not arising from + expansion. -In the case of numbered registers like |\count255| or |\dimen0|, the resulting -digits will be re-parsed, so for example |\count255 0| is like |100| if -|\the\count255| would give |10|. Control sequences define complete numbers, thus -cannot be extended that way with more digits, on the other hand they are more -efficient as they avoid the re-parsing of their unpacked contents. + The same holds for |qint|, |qfrac|, |qfloat|.\NewWith{1.2} -A token list variable must be prefixed by |\the|, it will not be unpacked -automatically (the parser will actually try |\number|, and thus fail). Do not -use |\the| but only |\number| with a dimen or skip, as the |\xintexpr| parser -doesn't understand |pt| and its presence is a syntax error. To use a dimension -expressed in terms of points or other \TeX{} recognized units, incorporate it in -|\dimexpr...\relax|. + Similarly |add|, |mul|, |subs|, |seq|, |rseq|, |rrseq|, |iter| use at + some stages delimited macros. They work with \emph{dummy variables}, + represented as one Latin letter (lowercase or uppercase) followed by a + mandatory |=| sign, then a comma separated list of values to assign in + turn to the dummy variable, which will be substituted in the expression + which was parsed as the first, comma delimited, argument to the + function; additionally |rseq|, |rrseq| and |iter| have a mandatory + initial comma separated list which is separated by a semi-colon from the + expression to evaluate iteratively. |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. -% REVOIR -% If one needs to optimize, |1.72\dimexpr 3.2pt\relax| is less efficient -% than |1.72*{\number\dimexpr 3.2pt\relax}| as the latter avoids re-parsing the -% digits of the representation of the dimension as scaled points. -% \centeredline{|\xinttheexpr 1.72\dimexpr 3.2pt\relax/2.71828\relax=|} -% \centeredline{|\xinttheexpr 1.72*{\number\dimexpr 3.2pt\relax}/2.71828\relax|} -% \centeredline{\dtt{\xinttheexpr 1.72\dimexpr -% 3.2pt\relax/2.71828\relax=\xinttheexpr 1.72*{\number\dimexpr -% 3.2pt\relax}/2.71828\relax}} -Regarding how dimensional expressions are converted by \TeX{} into scaled points -see \autoref{sec:Dimensions}. + They may be nested. + \end{snugframed} -\subsection{Catcodes and spaces} +\begin{description}[leftmargin=0pt] + \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*} -Active characters may (and will) break the functioning of \csbxint{expr}. -Inside an expression one may prefix, for example a |:| with |\string|. Or, for -a more radical way, there is \csbxint{exprSafeCatcodes}. This is a -non-expandable step as it changes catcodes. + \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} -\subsubsection{\csbh{xintexprSafeCatcodes}} -\label{xintexprSafeCatcodes} -%{\small New with release |1.09a|.\par} + \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. -This command sets the catcodes of -the relevant characters to safe values. This is used internally by -\csbxint{NewExpr} (restoring the catcodes on exit), hence \csbxint{NewExpr} does -not have to be protected against active characters. + \item[qfloat] does the same as \dtt{qfrac} and converts to a float with the + precision given by the setting of |\xintDigits|. -\subsubsection{\csbh{xintexprRestoreCatcodes}}\label{xintexprRestoreCatcodes} -%{\small New with release |1.09a|.\par} + \item[reduce] reduces a fraction to smallest terms +\begin{everbatim*} +\xinttheexpr reduce(50!/20!/20!/10!)\relax +\end{everbatim*} -Restores the catcodes to the earlier state. +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*} -\bigskip + \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[?] |?(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*} -Spaces inside an |\xinttheexpr...\relax| should mostly be -innocuous (except inside macro arguments). + \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} -|\xintexpr| and |\xinttheexpr| are for the most part agnostic regarding -catcodes: (unbraced) digits, binary operators, minus and plus signs as -prefixes, dot as decimal mark, parentheses, may be indifferently of catcode -letter or other or subscript or superscript, ..., it doesn't matter.% -% -\footnote{Furthermore, although \csbxint{expr} uses \csa{string}, it is - (we hope) escape-char agnostic.} +\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 characters |+|, |-|, |*|, |/|, |^|, |!|, |&|, \verb+|+, |?|, |:|, |<|, |>|, -|=|, |(|, |)|, |"|, |[|, |]|, |;|, the dot and the comma should not be active if -in the expression, as everything is expanded along the way. If one of them is -active, it should be prefixed with |\string|. + The 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)|. -The |!| as either logical negation or postfix factorial operator must be a -standard (\emph{i.e.} catcode $12$) |!|, more precisely a catcode $11$ -exclamation point |!| must be avoided as it is used internally by |\xintexpr| -for various special purposes. + 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). -Digits, slash, square brackets, minus sign, in the output from an |\xinttheexpr| -are all of catcode 12. For |\xintthefloatexpr| the `e' in the output has its standard catcode ``letter''. + 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. -A macro with arguments will expand and grab its arguments before the -parser may get a chance to see them, so the situation with catcodes and spaces -is not the same within such macro arguments. + 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. -\subsection{Expandability, \csh{xinteval}} + 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. -As is the case with all other package macros |\xintexpr| \fexpan ds (in two -steps) to its final (non-printable) result; and |\xinttheexpr| \fexpan ds (in -two steps) to the chain of digits (and possibly minus sign |-|, decimal mark -|.|, fraction slash |/|, scientific |e|, square brackets |[|, |]|) representing -the result. + See also \csbxint{ifboolexpr}, in this context. -Starting with |1.09j|, an |\xintexpr..\relax| can be inserted without -|\xintthe| prefix inside an |\edef|, or a |\write|. It expands to a private -more compact representation (five tokens) than |\xinttheexpr| or -|\xintthe\xintexpr|. +\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(-20^9/3^5,12)=|\dtt{\xinttheexpr float(-20^9/3^5,12)\relax.} + \item [sqrt] in \csbxint{expr} and \csbxint{floatexpr}, uses the float evaluation + with the precision given by the optional second argument. +\begin{everbatim*} +\xinttheexpr sqrt(2,31)\relax\ and \xinttheiiexpr sqrt(num(2e60))\relax +\end{everbatim*} + \end{description} -The material between |\xintexpr| and |\relax| should contain only expandable -material. + \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*} + \end{description} -The once expanded |\xintexpr| is |\romannumeral0\xinteval|. And there is -similarly |\xintieval|, |\xintiieval|, and |\xintfloateval|. For the other -cases one can use |\romannumeral-`0| as prefix. For an example of expandable -algorithms making use of chains of |\xinteval|-uations connected via -|\expandafter| see \autoref{ssec:fibonacci}. + \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. -An expression can only be legally finished by a |\relax| token, which -will be absorbed. + \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. -It is quite possible to nest expressions among themselves; for example, if one -needs inside an |\xintiiexpr...\relax| to do some computations with fractions, -rounding the final result to an integer, on just has to insert -|\xintiexpr...\relax|. The functioning of the infix operators will not be in -the least affected from the fact that the surrounding ``environment'' is the -|\xintiiexpr| one. + \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), +\item[|`*`|] multiplies (left ticks mandatory), +\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} -\subsection{Memory considerations} +\item[functions using dummy variables] +\noindent\par +They are nestable to arbitrary depth if suitably parenthesized. +\begin{description} +\item [subs] for variable substitution, useful to get something evaluated only + once +\begin{everbatim*} +% ATTENTION that xz generates an error, 'unknown variable xz', one must use x*z +\xinttheexpr subs(subs(seq(x*z,x=1..10),z=y^2),y=10)\relax +\end{everbatim*} -The parser creates an undefined control sequence for each intermediate -computation evaluation: addition, subtraction, etc\dots Thus, a moderately sized -expression might create 10, or 20 such control sequences. On my \TeX{} -installation, the memory available for such things is of circa \np{200000} -multi-letter control words. So this means that a document containing hundreds, -perhaps even thousands of expressions will compile with no problem. +\item[add] addition +\begin{everbatim*} +\xinttheiiexpr add(x^3,x=1..50)\relax +\end{everbatim*} -Besides the hash table, also \TeX{} main memory is impacted. Thus, if -\xintexprname is used for computing plots% -% -\footnote{this is not very probable as so far \xintname does not include - a mathematical library with floating point calculations, but provides - only the basic operations of algebra.}% -% -, this may cause a problem. +\item[mul] multiplication +\begin{everbatim*} +\xinttheiiexpr subs(mul(2n+1,n=1..N),N=30)\relax +\end{everbatim*} -There is a (partial) solution.% -% -\footnote{which convinced me that I could stick with the parser - implementation despite its potential impact on the hash-table and - other parts of \TeX{}'s memory.} +\item[seq] comma separated values generated according to a formula +\begin{everbatim*} +\xinttheiiexpr seq(x(x+1)(x+2)(x+3),x=1..10)\relax +\end{everbatim*} +\begin{everbatim*} +\xinttheiiexpr seq(seq(i^2+j^2, i=0..j), j=0..10)\relax +\end{everbatim*} -A -document can possibly do tens of thousands of evaluations only -if some formulas are being used repeatedly, for example inside loops, with -counters being incremented, or with data being fetched from a file. So it is the -same formula used again and again with varying numbers inside. +\item[rseq] recursive sequence, |@| for the previous value. +\begin{everbatim*} +% ATTENTION y/2@ would give (y/2)@, that is (y/2)*@ !! +\printnumber {\xintthefloatexpr subs(rseq (1; @/2+y/(2@), i=1..10),y=1000)\relax } +\end{everbatim*} -With the \csbxint{NewExpr} command, it is possible to convert once and -for all an expression containing parameters into an expandable macro -with parameters. Only this initial definition of this macro actually -activates the \csbxint{expr} parser and will (very moderately) impact -the hash-table: once this unique parsing is done, a macro with -parameters is produced which is built-up recursively from the -\csbxint{Add}, \csbxint{Mul}, etc... macros, exactly as it would be -necessary to do without the facilities of the \xintexprname package. +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*} -\subsection{The \csbh{xintNewExpr} command}\label{xintNewExpr} +\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*} -% This allows to define a completely expandable macro with parameters, expanding -% in two steps to its final evaluation, and corresponding to the given -% \xintname{}expression where the parameters are input using the usual -% macro-parameter: |#1|, ..., |#9|. +\begin{everbatim*} +\xinttheiiexpr rrseq(0,1,2,3,4,5; @1+@2+@3+@4+@@(5)+@@(6), i=1..20)\relax +\end{everbatim*} -The command is used as: -% -\leftedline{|\xintNewExpr{\myformula}[n]|\marg{stuff}, where} -\begin{itemize} -\item \meta{stuff} will be inserted inside |\xinttheexpr . . . \relax|, -\item |n| is an integer between zero and nine, inclusive, and tells how many - parameters will |\myformula| have (it is \emph{mandatory} even if - |n=0|% -% -\footnote{there is some use for \csa{xintNewExpr}|[0]| compared to an - \csa{edef} as \csa{xintNewExpr} has some built-in catcode protection.}) -% -\item the placeholders |#1|, |#2|, ..., |#n| are used inside \meta{stuff} in - their usual r\^ole.\footnote{such \#'s may be of category code other or have - their usual catcode.} -\end{itemize} - -The macro |\myformula| is defined without checking if it -already exists, \LaTeX{} users might prefer to do first |\newcommand*\myformula -{}| to get a reasonable error message in case |\myformula| already exists. +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. -The definition of |\myformula| made by |\xintNewExpr| is global (i.e. it does -not obey the scope of environments). The protection against active characters -is done automatically. +\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} -It will be a completely expandable macro entirely built-up using |\xintAdd|, -|\xintSub|, |\xintMul|, |\xintDiv|, |\xintPow|, etc\dots as corresponds to the -expression written with the infix operators. -Macros created by |\xintNewExpr| can thus be nested. +Recursions may be nested, with |@@@(n)| giving access to the values of the +outer recursion\dots and there is even |@@@@(n)| but I never tried it! +With |seq|, |rseq|, +|rrseq|, |iter|, 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 \begin{everbatim*} - \xintNewFloatExpr \FA [2]{(#1+#2)^10} - \xintNewFloatExpr \FB [2]{sqrt(#1*#2)} -\begin{enumerate}[nosep] - \item \FA {5}{5} - \item \FB {30}{10} - \item \FA {\FB {30}{10}}{\FB {40}{20}} -\end{enumerate} +\xinttheiiexpr iter(1;(@>10^40)?{break(@)}{2@},i=1++)\relax +% this would not work with i=1,2,3++. Only n++ syntax, nothing before. \end{everbatim*} +\end{description} -\begin{framed} - The whole point of using \csbxint{NewExpr} is to produce a macro whose - execution will not populate the hash table contrarily to what |\xintexpr| - does to some extent (this impact on some of \TeX{}'s memory gets noticeable - only if many of thousands of \csbxint{expr}-essions are evaluated). +Refer to \autoref{sec:expr11} for more examples. +\end{description} - A ``formula'' created by |\xintNewExpr| is thus a macro whose parameters are - given to a possibly very complicated combination of the various macros of - \xintname and \xintfracname. Consequently, one can not use at all any infix - notation there, but only the input format recognized by the \xintfracname - macros. +\item The postfix operators \ctexttt{!} and the branching conditionals \ctexttt{?, ??}. + \begin{description} + \item[{\color[named]{DarkOrchid}!}] computes the factorial of an integer. -The situation is thus quite distinct from a macro with parameters defined via -a simple |\def| such as: + \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 \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{|\def\myformula #1{\xinttheexpr (#1)^3\relax}|} -\end{framed} + \leftedline{\restoreMicroFont|\xinttheexpr 0.^2+2^.0\relax|} + % + which is |0^2+2^0| and produces \dtt{\xinttheexpr 0.^2+2^.0\relax}. -|\xintNewExpr| tries to do as many evaluations as are possible at the time the -macro parameters are still parameters. Let's see a few examples. For this I -will use |\meaning| which reveals the contents of a macro. We will thus see -some private macros of the \xintname bundle, which should not be directly -used. If the things look a bit complicated, it is because they have to cater -for many possibilities. With |\meaning| we will see what has already been -evaluated. + However a single dot |"."| as in |\xinttheexpr .^2\relax| is now illegal + input.\MyMarginNote{Changed!} -\emph{Remark:} In these examples we sometimes use |\printnumber| to avoid for -the meaning to go into the right margin, but this zaps all spaces originally -in the output from |\meaning|. +\item The |e| and |E| for scientific notation. They are parsed + like the decimal mark is.% Thus |1e(3+2)| is no legal syntax anymore, one + % must use |10^(3+2)| in such cases. +\begingroup +\restoreMicroFont |1e3^2| is \dtt{\xinttheexpr 1e3^2\relax} +\endgroup -\begin{everbatim*} -\xintNewIIExpr\FA [1]{13*25*78*#1+2826*292}\meaning\FA -\end{everbatim*} -\smallskip +\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) 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 -\begin{everbatim*} -\xintNewIExpr\FA [2]{(3/5*9/7*13/11*#1-#2)*3^7} -\printnumber{\meaning\FA} -\end{everbatim*} -\smallskip +\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: + % REVOIR CECI + \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 + % REVOIR CECI + % + \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*} -% an example with optional parameter -\xintNewIExpr\FA [3]{[24] (#1+#2)/(#1-#2)^#3} -\printnumber{\meaning\FA} +\xinttheexpr 100000//13, 100000/:13, 100000 'mod' 13, trunc(100000/13,10), + trunc(100000/:13/13,10)\relax \end{everbatim*} -\smallskip +\item The list itemwise operators |*[|, |/[|, |^[|, |**[|, |]*|, |]/|, |]^|, + |]**| are at the same precedence level as, respectively, |*| and |/| or |^| + and |**|. -\begin{everbatim*} -\xintNewFloatExpr\FA [2]{[12] 3.1415^3*#1-#2^5} -\printnumber{\meaning\FA} -\end{everbatim*} +\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 -\smallskip +\item The list itemwise operators |+[|, |-[|, |]+|, |]-|, are at + the same precedence level as |+| and |-|, -\begin{everbatim*} -\xintNewExpr\DET[9]{ #1*#5*#9+#2*#6*#7+#3*#4*#8-#1*#6*#8-#2*#4*#9-#3*#5*#7 } -\printnumber{\meaning\DET} -\end{everbatim*} +\item Comparison operators |<|, |>|, |=| (same as |==|), |<=|, |>=|, |!=| all + at the same level of precedence, use parentheses for disambiguation. -\smallskip +\item Conjunction (logical and): |&&| or equivalently + |'and'| (quotes mandatory). -\begin{everbatim*} -\xintNewExpr\FA[3]{ #1*#1+#2*#2+#3*#3-(#1*#2+#2*#3+#3*#1) } -\printnumber{\meaning\FA } -\end{everbatim*} +\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+||+. -One can even do some quite daring things: -\begin{everbatim*} -\xintNewExpr\FA[5]{[#1..[#2]..#3][#4:#5]} -And this works: -\begin{itemize}[nosep] -\item \FA{1}{3}{90}{20}{30} -\item \FA{1}{3}{90}{-40}{-15} -\item \FA{1.234}{-0.123}{-10}{3}{7} +\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. \end{itemize} -\oodef\test {\FA {0}{10}{100}{3}{6}}\meaning\test +++ -\end{everbatim*} -In the last example though, do not hope to use empty |#4| or |#5|: this is -possible in an expression, because the parser identifies |][:| or |:]| and -handles them appropriately. Here the macro |\FA| is built with idea that there -is something non-empty as it found the place holders |#4| and |#5|. +% See \autoref{ssec:countinexpr} for count and dimen registers and variables. +\subsection{\texorpdfstring{\texttt{\protect\string\numexpr}}{\textbackslash + numexpr} or \texorpdfstring{\texttt{\protect\string\dimexpr}}{\textbackslash + dimexpr} expressions, count and dimension registers and variables} +\label{ssec:countinexpr} -\subsubsection {Conditional operators and \csbh{NewExpr}} +Count registers, count control sequences, dimen registers, dimen control +sequences (like |\parindent|), skips and skip control sequences, |\numexpr|, +|\dimexpr|, |\glueexpr|, |\fontdimen| can be inserted directly, they will be +unpacked using |\number| which gives the internal value in terms of scaled +points for the dimensional variables: $1$\,|pt|${}=65536$\,|sp| (stretch and +shrink components are thus discarded). + +Tacit multiplication is implied, when a number or decimal number prefixes such +a register or control sequence. \LaTeX{} lengths are skip control sequences +and \LaTeX{} counters should be inserted using |\value|. + +Release |1.2| of the |\xintexpr| parser also recognizes and prefixes with +|\number| the |\ht|, |\dp|, and |\wd| \TeX{} primitives as well as the +|\fontcharht|, |\fontcharwd|, |\fontchardp| and |\fontcharit| \eTeX{} +primitives. + +In the case of numbered registers like |\count255| or |\dimen0| (or |\ht0|), +the resulting digits will be re-parsed, so for example |\count255 0| is like +|100| if |\the\count255| would give |10|. The same happens with inputs such +as |\fontdimen6\font|. And |\numexpr 35+52\relax| will be exactly as if |87| +as been encountered by the parser, thus more digits may follow: |\numexpr +35+52\relax 000| is like |87000|. If a new |\numexpr| follows, it is treated +as what would happen when |\xintexpr| scans a number and finds a non-digit: it +does a tacit multiplication. +\begin{everbatim*} +\xinttheexpr \numexpr 351+877\relax\numexpr 1000-125\relax\relax{} is the same +as \xinttheexpr 1228*875\relax. +\end{everbatim*} -The |?| and |??| conditional operators cannot be parsed by |\xintNewExpr| when -they contain macro parameters |#1|,\dots, |#9| within their scope. However -replacing them with the functions |if| and, respectively |ifsgn|, the parsing -should succeed. And the created macro will \emph{not evaluate the branches to - be skipped}, thus behaving exactly like |?| and |??| would have in the -|\xintexpr|. +Control sequences however (such as |\parindent|) are picked up as a whole by +|\xintexpr|, and the numbers they define cannot be extended extra digits, a +syntax error is raised if the parser finds digits rather than a legal +operation after such a control sequence. -\begin{everbatim*} -\xintNewExpr\Formula [3]{ if((#1>#2) && (#2>#3), sqrt(#1-#2)*sqrt(#2-#3), #1^2+#3/#2) }% -\printnumber{\meaning\Formula } -\end{everbatim*} +A token list variable must be prefixed by |\the|, it will not be unpacked +automatically (the parser will actually try |\number|, and thus fail). Do not +use |\the| but only |\number| with a dimen or skip, as the |\xintexpr| parser +doesn't understand |pt| and its presence is a syntax error. To use a dimension +expressed in terms of points or other \TeX{} recognized units, incorporate it in +|\dimexpr...\relax|. -This formula (with its |\xintiiifNotZero|) will gobble the false branch without -evaluating it when used with given arguments. +Regarding how dimensional expressions are converted by \TeX{} into scaled points +see also \autoref{sec:Dimensions}. -Remark: the meaning above reveals some of the private macros used by the -package. They are not for direct use. +\subsection{Catcodes and spaces} -Another example +Active characters may (and will) break the functioning of \csbxint{expr}. +Inside an expression one may prefix, for example a |:| with |\string|. Or, for +a more radical way, there is \csbxint{exprSafeCatcodes}. This is a +non-expandable step as it changes catcodes. -\begin{everbatim*} -\xintNewExpr\myformula[3]{ ifsgn(#1,#2/#3,#2-#3,#2*#3) }% -\meaning\myformula -\end{everbatim*} +\subsubsection{\csbh{xintexprSafeCatcodes}} +\label{xintexprSafeCatcodes} +%{\small New with release |1.09a|.\par} -Again, this macro gobbles the false branches, as would have the operator |??| -inside an |\xintexpr|-ession. +This command sets the catcodes of +the relevant characters to safe values. This is used internally by +\csbxint{NewExpr} (restoring the catcodes on exit), hence \csbxint{NewExpr} does +not have to be protected against active characters. -\subsubsection{External macros and \csbh{NewExpr}; the protect function} -\label{sssec:protect} +\subsubsection{\csbh{xintexprRestoreCatcodes}}\label{xintexprRestoreCatcodes} +%{\small New with release |1.09a|.\par} -For macros within such a created \xintname-formula command, there -are two cases: -\begin{itemize} -\item the macro does not involve the numbered parameters in its arguments: it - may then be left as is, and will be evaluated once during the construction of - the formula, -\item it does involve at least one of the macro parameters as argument. Then: - \begin{snugframed} - the whole thing (macro + argument) should be |protect|-ed, not in the - \LaTeX{} sense (!), but in the following way: |protect(\macro {#1})|.\IMPORTANT - \end{snugframed} -\end{itemize} +Restores the catcodes to the earlier state. -Here is a silly example illustrating the general principle: the macros here have -equivalent functional forms which are more convenient; but some of the more -obscure package macros of \xintname dealing with integers do not have functions -pre-defined to be in correspondance with them, use this mechanism could be -applied to them. +\bigskip -\begin{everbatim*} -\xintNewExpr\myformI[2]{protect(\xintRound{#1}{#2}) - protect(\xintTrunc{#1}{#2})}% -\meaning\myformI +Spaces inside an |\xinttheexpr...\relax| should mostly be +innocuous (except inside macro arguments). -\xintNewIIExpr\formula [3]{rem(#1,quo(protect(\the\numexpr #2\relax),#3))}% -\noindent\meaning\formula -\end{everbatim*} +|\xintexpr| and |\xinttheexpr| are for the most part agnostic regarding +catcodes: (unbraced) digits, binary operators, minus and plus signs as +prefixes, dot as decimal mark, parentheses, may be indifferently of catcode +letter or other or subscript or superscript, ..., it doesn't matter.% +% +\footnote{Furthermore, although \csbxint{expr} uses \csa{string}, it is + (we hope) escape-char agnostic.} -Only macros involving the |#1|, |#2|, etc\dots should be protected in this -way; the |+|, |*|, etc\dots symbols, the functions from the \csbxint{expr} -syntax, none should ever be included in a protected string. +The characters |+|, |-|, |*|, |/|, |^|, |!|, |&|, \verb+|+, |?|, |:|, |<|, |>|, +|=|, |(|, |)|, |"|, |[|, |]|, |;|, the dot and the comma should not be active if +in the expression, as everything is expanded along the way. If one of them is +active, it should be prefixed with |\string|. +The exclamation mark should have its standard catcode, because it is used for +internal purposes with a different one. -\subsubsection{Limitations of \csbxint{NewExpr}} +% TOO TECHNICAL +% +% The |!| as either logical negation or postfix factorial operator must be a +% standard (\emph{i.e.} catcode $12$) |!|, more precisely a catcode $11$ +% exclamation point |!| must be avoided as it is used internally by |\xintexpr| +% for various special purposes. -All depends on where the macro parameters arise |#1|, |#2|, ... we went to some -effort to allow many things but not everything goes through. |\xintNewExpr| -tries to evaluate completely as many things as possible which do not involve the -macro parameters. A somewhat elaborate scheme allows to handle also -complicated situations with list operations: +Digits, slash, square brackets, minus sign, in the output from an |\xinttheexpr| +are all of catcode 12. For |\xintthefloatexpr| the `e' in the output has its standard catcode ``letter''. -\begin{everbatim*} -\xintNewIExpr \FA [3] {[3] `+`([1.5..[3.5+#1]..#2]*#3)} -\begin{itemize}[nosep] -\item \FA {3.5}{50}{100} (cf. \xinttheiexpr [3] 1.5..[7]..50\relax) -\item \FA {-15}{-100}{20} (cf. \xinttheiexpr [3] 1.5..[-11.5]..-100\relax) -\item \FA {0}{20}{1} (cf. \xinttheiexpr [3] 1.5..[3.5]..20\relax) -\end{itemize} -\end{everbatim*} +A macro with arguments will expand and grab its arguments before the +parser may get a chance to see them, so the situation with catcodes and spaces +is not the same within such macro arguments. -Some things are definitely expected not to work therein: particularly the -|seq|, |rseq|, |rrseq|, |iter| with |omit|, |abort|, -|break|. Also, but this is quite anecdotical, |first| and |last| should not -work (I did not try; actually I did not try the functions with dummy letters -either, because each time I think about compatibility with \csbxint{NewExpr}, -my head starts spinning.) +\subsection{Expandability, \csh{xinteval}} -Also, using sub-|\xintexpr|-essions (including some of the macro parameters) -inside something given to |\xintNewExpr| will probably not work. +As is the case with all other package macros |\xintexpr| \fexpan ds (in two +steps) to its final (non-printable) result; and |\xinttheexpr| \fexpan ds (in +two steps) to the chain of digits (and possibly minus sign |-|, decimal mark +|.|, fraction slash |/|, scientific |e|, square brackets |[|, |]|) representing +the result. -Naturally, it is always possible to use, after the macro has been constructed, -|\xinttheexpr...\relax| among the arguments. +Starting with |1.09j|, an |\xintexpr..\relax| can be inserted without +|\xintthe| prefix inside an |\edef|, or a |\write|. It expands to a private +more compact representation (five tokens) than |\xinttheexpr| or +|\xintthe\xintexpr|. -\subsection{\csbh{xintiexpr}, \csbh{xinttheiexpr}} -\label{xintiexpr}\label{xinttheiexpr} -% \label{xintnumexpr}\label{xintthenumexpr} +The material between |\xintexpr| and |\relax| should contain only expandable +material. -Equivalent\etype{x} to doing |\xintexpr round(...)\relax|. Thus, \emph{only} the -final result is rounded to an integer. Half integers are rounded towards -$+\infty$ for positive numbers and towards $-\infty$ for negative ones. Comma -separated lists of expressions are allowed. +The once expanded |\xintexpr| is |\romannumeral0\xinteval|. And there is +similarly |\xintieval|, |\xintiieval|, and |\xintfloateval|. For the other +cases one can use |\romannumeral-`0| as prefix. For an example of expandable +algorithms making use of chains of |\xinteval|-uations connected via +|\expandafter| see \autoref{ssec:fibonacci}. -An optional parameter within brackets is allowed: if strictly positive it -instructs the expression to do its final rounding to the nearest value with -that many digits after the decimal mark. +An expression can only be legally finished by a |\relax| token, which +will be absorbed. -% Le temps est venu pour leur obsolescence +It is quite possible to nest expressions among themselves; for example, if one +needs inside an |\xintiiexpr...\relax| to do some computations with fractions, +rounding the final result to an integer, on just has to insert +|\xintiexpr...\relax|. The functioning of the infix operators will not be in +the least affected from the fact that the surrounding ``environment'' is the +|\xintiiexpr| one. -% Initially baptized |\xintnumexpr|, -% |\xintthenumexpr| but -% I am not too happy about this choice of name; one should keep in mind that -% |\numexpr|'s integer division rounds, whereas in |\xintiexpr|, the |/| is an -% exact fractional operation, and only the final result is rounded to an integer. +\subsection{Memory considerations} -% So |\xintnumexpr|, |\xintthenumexpr| are deprecated, and although still provided -% for the time being this might change in the future. +The parser creates an undefined control sequence for each intermediate +computation evaluation: addition, subtraction, etc\dots Thus, a moderately sized +expression might create 10, or 20 such control sequences. On my \TeX{} +installation, the memory available for such things is of circa \np{200000} +multi-letter control words. So this means that a document containing hundreds, +perhaps even thousands of expressions will compile with no problem. -\subsection{\csbh{xintiiexpr}, \csbh{xinttheiiexpr}} -\label{xintiiexpr}\label{xinttheiiexpr} +Besides the hash table, also \TeX{} main memory is impacted. Thus, if +\xintexprname is used for computing plots% +% +\footnote{this is not very probable as so far \xintname does not include + a mathematical library with floating point calculations, but provides + only the basic operations of algebra.}% +% +, this may cause a problem. -This variant\etype{x} does not know fractions. It deals almost only with long -integers. Comma separated lists of expressions are allowed. +There is a (partial) solution.% +% +\footnote{which convinced me that I could stick with the parser + implementation despite its potential impact on the hash-table and + other parts of \TeX{}'s memory.} -\begin{framed} - It maps |/| to the \emph{rounded} quotient. The operator - |//| is, like in |\xintexpr...\relax|, mapped to \emph{truncated} division. - The euclidean quotient (which for positive operands is like the truncated - quotient) was, prior to release |1.1|, associated to |/|. The function - |quo(a,b)| can still be employed. -\end{framed} +A +document can possibly do tens of thousands of evaluations only +if some formulas are being used repeatedly, for example inside loops, with +counters being incremented, or with data being fetched from a file. So it is the +same formula used again and again with varying numbers inside. -The \csbxint{iiexpr}-essions use the `ii' macros for addition, subtraction, -multiplication, power, square, sums, products, euclidean quotient and -remainder. +With the \csbxint{NewExpr} command, it is possible to convert once and +for all an expression containing parameters into an expandable macro +with parameters. Only this initial definition of this macro actually +activates the \csbxint{expr} parser and will (very moderately) impact +the hash-table: once this unique parsing is done, a macro with +parameters is produced which is built-up recursively from the +\csbxint{Add}, \csbxint{Mul}, etc... macros, exactly as it would be +necessary to do without the facilities of the \xintexprname package. -The |round|, |trunc|, |floor|, |ceil| functions are still available, and are -about the only places where fractions can be used, but |/| can not be used! -This dilemma is solved using |protect|. For understanding the -next example, recall that |round| and |trunc| have a second (non negative) -optional argument. In a normal \csbxint{expr}-essions, |round| and |trunc| are -mapped to \csbxint{Round} and \csbxint{Trunc}, in \csbxint{iiexpr}-essions, -they are mapped to \csbxint{iRound} and \csbxint{iTrunc}. +\subsection{The \csbh{xintNewExpr} command}\label{xintNewExpr} +% This allows to define a completely expandable macro with parameters, expanding +% in two steps to its final evaluation, and corresponding to the given +% \xintname{}expression where the parameters are input using the usual +% macro-parameter: |#1|, ..., |#9|. -\begin{everbatim*} -\xinttheiiexpr 5/3, round(5/3,3), trunc(5/3,3), trunc(\xintDiv {5}{3},3), -trunc(\xintRaw {5/3},3)\relax{}, -but \xinttheiiexpr 5/3, round(protect(5/3),3), trunc(protect(5/3),3), floor(protect(5/3)), -ceil(protect(5/3))\relax{} works! +The command is used as: +% +\leftedline{|\xintNewExpr{\myformula}[n]|\marg{stuff}, where} +\begin{itemize} +\item \meta{stuff} will be inserted inside |\xinttheexpr . . . \relax|, +\item |n| is an integer between zero and nine, inclusive, and tells how many + parameters will |\myformula| have (it is \emph{mandatory} even if + |n=0|% +% +\footnote{there is some use for \csa{xintNewExpr}|[0]| compared to an + \csa{edef} as \csa{xintNewExpr} has some built-in catcode protection.}) +% +\item the placeholders |#1|, |#2|, ..., |#n| are used inside \meta{stuff} in + their usual r\^ole.\footnote{such \#'s may be of category code other or have + their usual catcode.} +\end{itemize} -\noindent And with negative numbers: \xinttheiiexpr -5/3, round(protect(-5/3),3), -trunc(protect(-5/3),3), floor(protect(-5/3)), ceil(protect(-5/3))\relax. -\end{everbatim*} +The macro |\myformula| is defined without checking if it +already exists, \LaTeX{} users might prefer to do first |\newcommand*\myformula +{}| to get a reasonable error message in case |\myformula| already exists. +The definition of |\myformula| made by |\xintNewExpr| is global (i.e. it does +not obey the scope of environments). The protection against active characters +is done automatically. -Decimal numbers and numbers using scientific notations must be given as -arguments to one of the |num|, or |round|, or etc\dots functions, which will truncate -them to an integer.% - Internally the number will be represented with as many zeros -as is necessary, thus one does not want to do |num(1e100000)| for example! +It will be a completely expandable macro entirely built-up using |\xintAdd|, +|\xintSub|, |\xintMul|, |\xintDiv|, |\xintPow|, etc\dots as corresponds to the +expression written with the infix operators. +Macros created by |\xintNewExpr| can thus be nested. -% \begin{everbatim*} -\xinttheiiexpr num(13.4567e3)+num(10000123e-3)\relax % should compute 13456+10000 + \xintNewFloatExpr \FA [2]{(#1+#2)^10} + \xintNewFloatExpr \FB [2]{sqrt(#1*#2)} +\begin{enumerate}[nosep] + \item \FA {5}{5} + \item \FB {30}{10} + \item \FA {\FB {30}{10}}{\FB {40}{20}} +\end{enumerate} \end{everbatim*} -% - -The |reduce| function is not available and will raise un error. The |frac| -function also. The |sqrt| function is mapped to \csbxint{iiSqrt} which gives -a truncated square root. The |sqrtr| function is mapped to \csbxint{iiSqrtR} -which gives a rounded square root. -One can use the Float macros if one is careful to use |num|, or |round| on -their output, - -\begin{everbatim*} +\begin{framed} + The whole point of using \csbxint{NewExpr} is to produce a macro whose + execution will not populate the hash table contrarily to what |\xintexpr| + does to some extent (this impact on some of \TeX{}'s memory gets noticeable + only if many of thousands of \csbxint{expr}-essions are evaluated). + + A ``formula'' created by |\xintNewExpr| is thus a macro whose parameters are + given to a possibly very complicated combination of the various macros of + \xintname and \xintfracname. Consequently, one can not use at all any infix + notation there, but only the input format recognized by the \xintfracname + macros. + +The situation is thus quite distinct from a macro with parameters defined via +a simple |\def| such as: + % + \leftedline{|\def\myformula #1{\xinttheexpr (#1)^3\relax}|} +\end{framed} + +|\xintNewExpr| tries to do as many evaluations as are possible at the time the +macro parameters are still parameters. Let's see a few examples. For this I +will use |\meaning| which reveals the contents of a macro. We will thus see +some private macros of the \xintname bundle, which should not be directly +used. If the things look a bit complicated, it is because they have to cater +for many possibilities. With |\meaning| we will see what has already been +evaluated. + +\emph{Remark:} In these examples we sometimes use |\printnumber| to avoid for +the meaning to go into the right margin, but this zaps all spaces originally +in the output from |\meaning|. + +\begin{everbatim*} +\xintNewIIExpr\FA [1]{13*25*78*#1+2826*292}\meaning\FA +\end{everbatim*} +\smallskip + +\begin{everbatim*} +\xintNewIExpr\FA [2]{(3/5*9/7*13/11*#1-#2)*3^7} +\printnumber{\meaning\FA} +\end{everbatim*} + +\smallskip + +\begin{everbatim*} +% an example with optional parameter +\xintNewIExpr\FA [3]{[24] (#1+#2)/(#1-#2)^#3} +\printnumber{\meaning\FA} +\end{everbatim*} + +\smallskip + +\begin{everbatim*} +\xintNewFloatExpr\FA [2]{[12] 3.1415^3*#1-#2^5} +\printnumber{\meaning\FA} +\end{everbatim*} + +\smallskip + +\begin{everbatim*} +\xintNewExpr\DET[9]{ #1*#5*#9+#2*#6*#7+#3*#4*#8-#1*#6*#8-#2*#4*#9-#3*#5*#7 } +\printnumber{\meaning\DET} +\end{everbatim*} + +\smallskip + +\begin{everbatim*} +\xintNewExpr\FA[3]{ #1*#1+#2*#2+#3*#3-(#1*#2+#2*#3+#3*#1) } +\printnumber{\meaning\FA } +\end{everbatim*} + + +One can even do some quite daring things: +\begin{everbatim*} +\xintNewExpr\FA[5]{[#1..[#2]..#3][#4:#5]} +And this works: +\begin{itemize}[nosep] +\item \FA{1}{3}{90}{20}{30} +\item \FA{1}{3}{90}{-40}{-15} +\item \FA{1.234}{-0.123}{-10}{3}{7} +\end{itemize} +\fdef\test {\FA {0}{10}{100}{3}{6}}\meaning\test +++ +\end{everbatim*} + +In the last example though, do not hope to use empty |#4| or |#5|: this is +possible in an expression, because the parser identifies |][:| or |:]| and +handles them appropriately. Here the macro |\FA| is built with idea that there +is something non-empty as it found the place holders |#4| and |#5|. + + +\subsubsection {Conditional operators and \csbh{NewExpr}} + +The |?| and |??| conditional operators cannot be parsed by |\xintNewExpr| when +they contain macro parameters |#1|,\dots, |#9| within their scope. However +replacing them with the functions |if| and, respectively |ifsgn|, the parsing +should succeed. And the created macro will \emph{not evaluate the branches to + be skipped}, thus behaving exactly like |?| and |??| would have in the +|\xintexpr|. + +\begin{everbatim*} +\xintNewExpr\Formula [3]{ if((#1>#2) && (#2>#3), sqrt(#1-#2)*sqrt(#2-#3), #1^2+#3/#2) }% +\printnumber{\meaning\Formula } +\end{everbatim*} + +This formula (with its |\xintiiifNotZero|) will gobble the false branch without +evaluating it when used with given arguments. + +Remark: the meaning above reveals some of the private macros used by the +package. They are not for direct use. + +Another example + +\begin{everbatim*} +\xintNewExpr\myformula[3]{ ifsgn(#1,#2/#3,#2-#3,#2*#3) }% +\meaning\myformula +\end{everbatim*} + +Again, this macro gobbles the false branches, as would have the operator |??| +inside an |\xintexpr|-ession. + +\subsubsection{External macros and \csbh{NewExpr}; the protect function} +\label{sssec:protect} + +For macros within such a created \xintname-formula command, there +are two cases: +\begin{itemize} +\item the macro does not involve the numbered parameters in its arguments: it + may then be left as is, and will be evaluated once during the construction of + the formula, +\item it does involve at least one of the macro parameters as argument. Then: + \begin{snugframed} + the whole thing (macro + argument) should be |protect|-ed, not in the + \LaTeX{} sense (!), but in the following way: |protect(\macro {#1})|.\IMPORTANT + \end{snugframed} +\end{itemize} + +Here is a silly example illustrating the general principle: the macros here have +equivalent functional forms which are more convenient; but some of the more +obscure package macros of \xintname dealing with integers do not have functions +pre-defined to be in correspondance with them, use this mechanism could be +applied to them. + +\begin{everbatim*} +\xintNewExpr\myformI[2]{protect(\xintRound{#1}{#2}) - protect(\xintTrunc{#1}{#2})}% +\meaning\myformI + +\xintNewIIExpr\formula [3]{rem(#1,quo(protect(\the\numexpr #2\relax),#3))}% +\noindent\meaning\formula +\end{everbatim*} + +Only macros involving the |#1|, |#2|, etc\dots should be protected in this +way; the |+|, |*|, etc\dots symbols, the functions from the \csbxint{expr} +syntax, none should ever be included in a protected string. + + +\subsubsection{Limitations of \csbxint{NewExpr}} + +All depends on where the macro parameters arise |#1|, |#2|, ... we went to some +effort to allow many things but not everything goes through. |\xintNewExpr| +tries to evaluate completely as many things as possible which do not involve the +macro parameters. A somewhat elaborate scheme allows to handle also +complicated situations with list operations: + +\begin{everbatim*} +\xintNewIExpr \FA [3] {[3] `+`([1.5..[3.5+#1]..#2]*#3)} +\begin{itemize}[nosep] +\item \FA {3.5}{50}{100} (cf. \xinttheiexpr [3] 1.5..[7]..50\relax) +\item \FA {-15}{-100}{20} (cf. \xinttheiexpr [3] 1.5..[-11.5]..-100\relax) +\item \FA {0}{20}{1} (cf. \xinttheiexpr [3] 1.5..[3.5]..20\relax) +\end{itemize} +\end{everbatim*} + +Some things are definitely expected not to work therein: particularly the +|seq|, |rseq|, |rrseq|, |iter| with |omit|, |abort|, +|break|. Also, but this is quite anecdotical, |first| and |last| should not +work (I did not try; actually I did not try the functions with dummy letters +either, because each time I think about compatibility with \csbxint{NewExpr}, +my head starts spinning.) + +Also, using sub-|\xintexpr|-essions (including some of the macro parameters) +inside something given to |\xintNewExpr| will probably not work. + +Naturally, it is always possible to use, after the macro has been constructed, +|\xinttheexpr...\relax| among the arguments. + +\subsection{\csbh{xintiexpr}, \csbh{xinttheiexpr}} +\label{xintiexpr}\label{xinttheiexpr} +% \label{xintnumexpr}\label{xintthenumexpr} + +Equivalent\etype{x} to doing |\xintexpr round(...)\relax|. Thus, \emph{only} the +final result is rounded to an integer. Half integers are rounded towards +$+\infty$ for positive numbers and towards $-\infty$ for negative ones. Comma +separated lists of expressions are allowed. + +An optional parameter within brackets is allowed: if strictly positive it +instructs the expression to do its final rounding to the nearest value with +that many digits after the decimal mark. + +% Le temps est venu pour leur obsolescence + +% Initially baptized |\xintnumexpr|, +% |\xintthenumexpr| but +% I am not too happy about this choice of name; one should keep in mind that +% |\numexpr|'s integer division rounds, whereas in |\xintiexpr|, the |/| is an +% exact fractional operation, and only the final result is rounded to an integer. + +% So |\xintnumexpr|, |\xintthenumexpr| are deprecated, and although still provided +% for the time being this might change in the future. + +\subsection{\csbh{xintiiexpr}, \csbh{xinttheiiexpr}} +\label{xintiiexpr}\label{xinttheiiexpr} + +This variant\etype{x} does not know fractions. It deals almost only with long +integers. Comma separated lists of expressions are allowed. + +\begin{framed} + It maps |/| to the \emph{rounded} quotient. The operator + |//| is, like in |\xintexpr...\relax|, mapped to \emph{truncated} division. + The euclidean quotient (which for positive operands is like the truncated + quotient) was, prior to release |1.1|, associated to |/|. The function + |quo(a,b)| can still be employed. +\end{framed} + +The \csbxint{iiexpr}-essions use the `ii' macros for addition, subtraction, +multiplication, power, square, sums, products, euclidean quotient and +remainder. + +The |round|, |trunc|, |floor|, |ceil| functions are still available, and are +about the only places where fractions can be used, but |/| within, if not +somehow hidden will be executed as integer rounded division. To avoid this one +can wrap the input in \dtt{qfrac}: this means however that none of the normal +expression parsing will be executed on the argument. + +To understand the illustrative examples, recall that |round| and |trunc| have +a second (non negative) optional argument. In a normal \csbxint{expr}-essions, +|round| and |trunc| are mapped to \csbxint{Round} and \csbxint{Trunc}, in +\csbxint{iiexpr}-essions, they are mapped to \csbxint{iRound} and +\csbxint{iTrunc}. + + +\begin{everbatim*} +\xinttheiiexpr 5/3, round(5/3,3), trunc(5/3,3), trunc(\xintDiv {5}{3},3), +trunc(\xintRaw {5/3},3)\relax{} are problematic, but +% +\xinttheiiexpr 5/3, round(qfrac(5/3),3), trunc(qfrac(5/3),3), floor(qfrac(5/3)), +ceil(qfrac(5/3))\relax{} work! +\end{everbatim*} + +On the other hand decimal numbers and scientific numbers can be used directly +as arguments to the |num|, |round|, or any function producing an integer. + +\begin{framed} + Scientific numbers are either rounded (in case of negative exponent) or + represented with as many zeroes as necessary, thus one does not want to + insert \dtt{num(1e100000)} for example in an \csa{xintiiexpr}ession ! +\end{framed} + +% +\begin{everbatim*} +\xinttheiiexpr num(13.4567e3)+num(10000123e-3)\relax % should compute 13456+10000 +\end{everbatim*} +% + +The |reduce| function is not available and will raise un error. The |frac| +function also. The |sqrt| function is mapped to \csbxint{iiSqrt} which gives +a truncated square root. The |sqrtr| function is mapped to \csbxint{iiSqrtR} +which gives a rounded square root. + +One can use the Float macros if one is careful to use |num|, or |round| +etc\dots on their output. + +\begin{everbatim*} \xinttheiiexpr \xintFloatSqrt [20]{2}, \xintFloatSqrt [20]{3}\relax % no operations \noindent The next example requires the |round|, and one could not put the |+| inside it: @@ -11207,14 +11480,17 @@ their output, decimal mark one should keep.) \end{everbatim*} -The whole point of \csbxint{iiexpr} is to gain some speed in \emph{integer-only} -algorithms, and the above explanations related to how to nevertheless use -fractions therein are a bit peripheral. We observed of the order of -$30$\% speed gain when dealing with numbers with circa one hundred digits, but this -gain decreases the longer the manipulated numbers become and becomes negligible -for numbers with thousand digits: the overhead from parsing fraction format is -little compared to other expensive aspects of the expandable shuffling of -tokens. +The whole point of \csbxint{iiexpr} is to gain some speed in +\emph{integer-only} algorithms, and the above explanations related to how to +nevertheless use fractions therein are a bit peripheral. We observed +(2013/12/18) of the order of $30$\% speed gain when dealing with numbers with +circa one hundred digits (v1.2: this info may be obsolete). + +% but this gain decreases the longer the manipulated +% numbers become and becomes negligible for numbers with thousand digits: the +% overhead from parsing fraction format is little compared to other expensive +% aspects of the expandable shuffling of tokens + \subsection{\csbh{xintboolexpr}, \csbh{xinttheboolexpr}}\label{xintboolexpr}\label{xinttheboolexpr} @@ -11239,10 +11515,6 @@ An optional parameter within brackets is allowed: the final float will have that many digits of precision. This is provided to get rid of non-relevant last digits. -Currently, the factorial function hasn't yet a float version; so inside -|\xintthefloatexpr . . . \relax|, |n!| will be computed exactly. Perhaps this -will be improved in a future release. - \xintDigits:= 9; Note that |1.000000001| and |(1+1e-9)| will not be equivalent for @@ -11414,7 +11686,7 @@ 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*} -\oodef\f {\xintexpr 1.23^10\relax }\meaning\f +\fdef\f {\xintexpr 1.23^10\relax }\meaning\f \end{everbatim*} \begin{framed} @@ -11443,11 +11715,6 @@ his/her expansion control. possibility. \end{framed} -% \begin{framed} -% This implementation and user interface are still to be considered -% \emph{experimental}. -% \end{framed} - Syntax errors in the input such as using a one-argument function with two arguments will generate low-level \TeX{} processing unrecoverable errors, with cryptic accompanying message. @@ -11748,8 +12015,8 @@ needed.% \begin{everbatim*} \def\coeff #1{\xintiiMON{#1}/#1.5} % (-1)^n/(n+1/2) -\oodef\w {\xintSeries {0}{50}{\coeff}} % we want to re-use it -\oodef\z {\xintJrr {\w}[0]} % the [0] for a microsecond gain. +\fdef\w {\xintSeries {0}{50}{\coeff}} % we want to re-use it +\fdef\z {\xintJrr {\w}[0]} % the [0] for a microsecond gain. % \xintJrr preferred to \xintIrr: a big common factor is suspected. % But numbers much bigger would be needed to show the greater efficiency. \[ \sum_{n=0}^{n=50} \frac{(-1)^n}{n+\frac12} = \xintFrac\z \] @@ -11773,7 +12040,7 @@ A more efficient way to code |\coeff| is illustrated next. \def\coeff #1{\the\numexpr\ifodd #1 -2\else2\fi\relax/\the\numexpr 2*#1+1\relax [0]}% % The [0] in \coeff is a tiny optimization: in its presence the \xintfracname parser % sees something which is already in internal format. -\oodef\w {\xintSeries {0}{50}{\coeff}} +\fdef\w {\xintSeries {0}{50}{\coeff}} \[\sum_{n=0}^{n=50} \frac{(-1)^n}{n+\frac12}=\xintFrac\w\] \end{everbatim*} The reduced form |\z| as displayed above only differs from this one by a @@ -11882,7 +12149,7 @@ expressions built with such; they must obey the \TeX{} \def\ratio #1{2/#1[0]}% 2/n, to compute exp(2) \cnta 0 % previously declared count \begin{quote} -\loop \oodef\z {\xintRationalSeries {0}{\cnta}{1}{\ratio }}% +\loop \fdef\z {\xintRationalSeries {0}{\cnta}{1}{\ratio }}% \noindent$\sum_{n=0}^{\the\cnta} \frac{2^n}{n!}= \xintTrunc{12}\z\dots= \xintFrac\z=\xintFrac{\xintIrr\z}$\vtop to 5pt{}\par @@ -11895,7 +12162,7 @@ expressions built with such; they must obey the \TeX{} \cnta 0 % previously declared count \begin{quote} \loop -\oodef\z {\xintRationalSeries {0}{\cnta}{1}{\ratio }}% +\fdef\z {\xintRationalSeries {0}{\cnta}{1}{\ratio }}% \noindent$\sum_{n=0}^{\the\cnta} \frac{(-1)^n}{n!}= \xintTrunc{20}\z\dots=\xintFrac{\z}=\xintFrac{\xintIrr\z}$% \vtop to 5pt{}\par @@ -11942,12 +12209,12 @@ Here is a slightly more complicated evaluation: \begin{everbatim*} \cnta 1 \begin{multicols}{2} -\loop \oodef\z {\xintRationalSeries +\loop \fdef\z {\xintRationalSeries {\cnta} {2*\cnta-1} {\xintiPow {\the\cnta}{\cnta}/\xintFac{\cnta}} {\ratioexp{\the\cnta}}}% -\oodef\w {\xintRationalSeries {0}{2*\cnta-1}{1}{\ratioexp{\the\cnta}}}% +\fdef\w {\xintRationalSeries {0}{2*\cnta-1}{1}{\ratioexp{\the\cnta}}}% \noindent $\sum_{n=\the\cnta}^{\the\numexpr 2*\cnta-1\relax} \frac{\the\cnta^n}{n!}/% \sum_{n=0}^{\the\numexpr 2*\cnta-1\relax} \frac{\the\cnta^n}{n!} = @@ -12012,19 +12279,19 @@ next section. These completely exact operations rapidly create numbers with many digits. Let us print in full the raw fractions created by the operation illustrated above: -\oodef\z{\xintRationalSeriesX {0}{9}{\firstterm} +\fdef\z{\xintRationalSeriesX {0}{9}{\firstterm} {\ratioexp}{\xintPowerSeries{1}{10}{\coefflog}{1[-1]}}} |E(L(1[-1]))=|\dtt{\printnumber{\z}} (length of numerator: \xintLen {\xintNumerator \z}) -\oodef\z{\xintRationalSeriesX {0}{9}{\firstterm} +\fdef\z{\xintRationalSeriesX {0}{9}{\firstterm} {\ratioexp}{\xintPowerSeries{1}{10}{\coefflog}{12[-2]}}} |E(L(12[-2]))=|\dtt{\printnumber{\z}} (length of numerator: \xintLen {\xintNumerator \z}) -\oodef\z{\xintRationalSeriesX {0}{9}{\firstterm} +\fdef\z{\xintRationalSeriesX {0}{9}{\firstterm} {\ratioexp}{\xintPowerSeries{1}{10}{\coefflog}{123[-3]}}} |E(L(123[-3]))=|\dtt{\printnumber{\z}} (length of numerator: @@ -12036,21 +12303,21 @@ only, as we can see) powers of ten. Notice that 1 more digit in an input denominator seems to mean 90 more in the raw output. We can check that with some other test cases: -\oodef\z{\xintRationalSeriesX {0}{9}{\firstterm} +\fdef\z{\xintRationalSeriesX {0}{9}{\firstterm} {\ratioexp}{\xintPowerSeries{1}{10}{\coefflog}{1/7}}} |E(L(1/7))=|\dtt{\printnumber{\z}} (length of numerator: \xintLen {\xintNumerator \z}; length of denominator: \xintLen {\xintDenominator \z}) -\oodef\z{\xintRationalSeriesX {0}{9}{\firstterm} +\fdef\z{\xintRationalSeriesX {0}{9}{\firstterm} {\ratioexp}{\xintPowerSeries{1}{10}{\coefflog}{1/71}}} |E(L(1/71))=|\dtt{\printnumber{\z}} (length of numerator: \xintLen {\xintNumerator \z}; length of denominator: \xintLen {\xintDenominator \z}) -\oodef\z{\xintRationalSeriesX {0}{9}{\firstterm} +\fdef\z{\xintRationalSeriesX {0}{9}{\firstterm} {\ratioexp}{\xintPowerSeries{1}{10}{\coefflog}{1/712}}} |E(L(1/712))=|\dtt{\printnumber{\z}} (length of numerator: @@ -12245,7 +12512,7 @@ $\xintFxPtPowerSeries {0}{\cnta}{\coeffexp}{\f}{20}$\\ % \leftedline{|\xintFxPtPowerSeries {0}{19}{\coeffexp}{\f}{25}=| \dtt{\xintFxPtPowerSeries {0}{19}{\coeffexp}{\f}{25}}} -\oodef\z{\xintIrr {\xintPowerSeries {0}{19}{\coeffexp}{\f}}} +\fdef\z{\xintIrr {\xintPowerSeries {0}{19}{\coeffexp}{\f}}} % \texttt{\hyphenchar\font45 }% @@ -12593,7 +12860,7 @@ You want more digits and have some time? compile this copy of the {\xintMul {4/239}{\xintFxPtPowerSeries {0}{#2}{\coeffarctg}{\xb}{#3}}}% }}% \pdfresettimer -\oodef\Z {\Machin {1000}} +\fdef\Z {\Machin {1000}} \odef\W {\the\pdfelapsedtime} \message{\Z} \message{computed in \xintRound {2}{\W/65536} seconds.} @@ -12601,12 +12868,13 @@ You want more digits and have some time? compile this copy of the | This will log the first 1000 digits of $\pi$ after the decimal point. On my -laptop (a 2012 model) this took about $16$ seconds last time I tried.% +laptop (a 2012 model) this took about $5.6$ seconds last time I tried.% % -\footnote{With \texttt{1.09i} and earlier \xintname releases, this used - to be \dtt{42} seconds; the \texttt{1.09j} division is much faster - with small denominators as occurs here with \dtt{\char92xa=1/25}, and - I believe this to be the main explanation for the speed gain.} +\footnote{With \texttt{v1.09i} and earlier \xintname, this used to be \dtt{42} + seconds; starting with \texttt{v1.09j}, and prior to \texttt{v1.2}, it was + \dtt{16} seconds (this was probably due to a more efficient division with + denominators at most $9999$). The |v1.2| \xintcorename achieves a further + gain.} % As mentioned in the introduction, the file \href{http://www.ctan.org/pkg/pi}{pi.tex} by \textsc{D. @@ -12951,7 +13219,7 @@ $+$ or $-$. \csa{xintGGCFrac}|{a+b/c+d/e+f/g+h/...+x/y}|\ntype{f} is a clone of \csbxint{GCFrac}, hence again \LaTeX{} specific with package -|amsmath|.\NewWith {1.09m} +|amsmath|. It does not assume the coefficients to be numbers as understood by \xintfracname. The macro can be used for displaying arbitrary content as a continued fraction with |\cfrac|, using only plus signs though. Note @@ -12986,10 +13254,10 @@ $$\xintGCtoGCx {+\cfrac\xintFwOver}{\\\xintFwOver}{a+b/...}\endcfrac$$ \csa{xintFtoC}|{f}|\etype{\Ff} computes the coefficients of the simple continued fraction of |f| and returns them as a list -(sequence) of braced items.\NewWith {1.09m} +(sequence) of braced items. \begin{everbatim*} -\oodef\test{\xintFtoC{-5262046/89233}}\texttt{\meaning\test} +\fdef\test{\xintFtoC{-5262046/89233}}\texttt{\meaning\test} \end{everbatim*} \subsection{\csbh{xintFtoCs}}\label{xintFtoCs} @@ -13049,20 +13317,20 @@ format'. \csa{xintFGtoC}|{f}{g}|\etype{\Ff\Ff} computes the common initial coefficients to -two given fractions |f| and |g|. Notice\NewWith {1.09m} that any real number |fx>g| +two given fractions |f| and |g|. Notice that any real number |fx>g| will then necessarily share with |f| and |g| these common initial coefficients for its regular continued fraction. The coefficients are output as a sequence of braced numbers. This list can then be manipulated via macros from \xinttoolsname, or other macros of \xintcfracname. \begin{everbatim*} -\oodef\test{\xintFGtoC{-5262046/89233}{-5314647/90125}}\texttt{\meaning\test} +\fdef\test{\xintFGtoC{-5262046/89233}{-5314647/90125}}\texttt{\meaning\test} \end{everbatim*} \begin{everbatim*} -\oodef\test{\xintFGtoC{3.141592653}{3.141592654}}\texttt{\meaning\test} +\fdef\test{\xintFGtoC{3.141592653}{3.141592654}}\texttt{\meaning\test} \end{everbatim*} \begin{everbatim*} -\oodef\test{\xintFGtoC{3.1415926535897932384}{3.1415926535897932385}}\meaning\test +\fdef\test{\xintFGtoC{3.1415926535897932384}{3.1415926535897932385}}\meaning\test \end{everbatim*} \begin{everbatim*} \xintRound {30}{\xintCstoF{\xintListWithSep{,}{\test}}} @@ -13071,7 +13339,7 @@ braced numbers. This list can then be manipulated via macros from \xintRound {30}{\xintCtoF{\test}} \end{everbatim*} \begin{everbatim*} -\oodef\test{\xintFGtoC{1.41421356237309}{1.4142135623731}}\meaning\test +\fdef\test{\xintFGtoC{1.41421356237309}{1.4142135623731}}\meaning\test \end{everbatim*} \subsection{\csbh{xintFtoCC}}\label{xintFtoCC} @@ -13109,7 +13377,7 @@ simplification by 3 in the result above). \subsection{\csbh{xintCtoF}}\label{xintCtoF} \csa{xintCtoF}|{{a}{b}{c}...{z}}|\etype{f} computes the fraction corresponding -to the coefficients, which may be fractions or even macros.\NewWith {1.09m} +to the coefficients, which may be fractions or even macros. \begin{everbatim*} \xintCtoF {\xintApply {\xintiiPow 3}{\xintSeq {1}{5}}} \end{everbatim*} @@ -13166,9 +13434,9 @@ fractions, but otherwise it is not necessarily the case. \subsection{\csbh{xintCtoCv}}\label{xintCtoCv} \csa{xintCtoCv}|{{a}{b}{c}...{z}}|\etype{f} returns the sequence of the -corresponding convergents, each one within braces.\NewWith {1.09m} +corresponding convergents, each one within braces. \begin{everbatim*} -\oodef\test{\xintCtoCv {11111111111}}\texttt{\meaning\test} +\fdef\test{\xintCtoCv {11111111111}}\texttt{\meaning\test} \end{everbatim*} \subsection{\csbh{xintGCtoCv}}\label{xintGCtoCv} @@ -13263,7 +13531,7 @@ The coefficients, after expansion, are, as shown, being enclosed in an added pair of braces, they may thus be fractions. \begin{everbatim*} \def\macro #1{\the\numexpr\ifodd#1 -1-#1\else1+#1\fi\relax/\the\numexpr 1+#1*#1\relax} -\oodef\x{\xintCntoGC {5}{\macro}}\meaning\x +\fdef\x{\xintCntoGC {5}{\macro}}\meaning\x \[\xintGCFrac{\xintCntoGC {5}{\macro}}\] \end{everbatim*} @@ -13309,7 +13577,7 @@ fraction of the same type, each expanded coefficient being enclosed within braces. % \begin{everbatim*} -\oodef\x {\xintGCtoGC {1+\xintPow{1.5}{3}/{1/7}+{-3/5}/% +\fdef\x {\xintGCtoGC {1+\xintPow{1.5}{3}/{1/7}+{-3/5}/% \xintFac {6}+\xintCstoF {2,-7,-5}/16}} \meaning\x \end{everbatim*} @@ -13374,7 +13642,7 @@ convergent. % (getting the 500th took about 1.2s on my laptop last time I tried, % and the 200th convergent is obtained ten times faster). \begin{everbatim*} -\oodef\z {\xintCntoF {199}{\cn}}% +\fdef\z {\xintCntoF {199}{\cn}}% \begingroup\parindent 0pt \leftskip 2.5cm \indent\llap {Numerator = }\printnumber{\xintNumerator\z}\par \indent\llap {Denominator = }\printnumber{\xintDenominator\z}\par @@ -13463,15 +13731,29 @@ $1$ or $-1$. % \bigskip % This is \expandafter|\xintbndlversion| of \expandafter|\xintbndldate|. % -% Extensive changes in release |1.1| of |2014/10/28| were located in -% \xintexprnameimp. Also with that release, -% packages \xintkernelnameimp and \xintcorenameimp were extracted from -% \xinttoolsnameimp and \xintnameimp, and |\xintAdd| was modified to not -% multiply denominators blindly. -% -% \smallskip -% \noindent\fbox{\xinttoolsnameimp is not loaded anymore by -% \xintnameimp, nor by \xintfracnameimp. It is loaded by \xintexprnameimp.} +% \begin{itemize} +% \item Release |1.2| of |2015/10/10| has entirely rewritten the core +% arithmetic routines in \xintcorenameimp. Many macros benefit indirectly +% from the faster core routines. The new model is yet to be extended to +% other portions of the code: for example the routines of \xintbinhexnameimp +% could be made faster for very big inputs if they adopted some of the style +% used now for the basic arithmetic routines. +% +% The parser of \xintexprnameimp is also faster at gathering digits and does +% not have a limit at |5000| digits per number anymore. +% +% \item Extensive changes in release |1.1| of |2014/10/28| were located in +% \xintexprnameimp. Also with that release, packages \xintkernelnameimp and +% \xintcorenameimp were extracted from \xinttoolsnameimp and \xintnameimp, +% and |\xintAdd| was modified to not multiply denominators blindly. +% +% \xinttoolsnameimp is not loaded anymore by \xintnameimp, nor by +% \xintfracnameimp. It is loaded by \xintexprnameimp. +% \end{itemize} +% +% Large portions of the code date back to the initial release, and at that +% time I was learning my trade in expandable TeX macro programming. At some +% point in the future, I will have to re-examine the older parts of the code. % % \section {Package \xintkernelnameimp implementation} % \label{sec:kernelimp} @@ -13479,8 +13761,10 @@ $1$ or $-1$. % \localtableofcontents % % This package provides the common minimal code base for loading management -% and catcode control and also a few programming utilities. It is loaded by both -% |xintcore.sty| and |xinttools.sty| hence by all other packages. +% and catcode control and also a few programming utilities. With |1.2| a few +% more helper macros and all |\chardef|'s have been moved here. The package is +% loaded by both |xintcore.sty| and |xinttools.sty| hence by all other +% packages. % % First appeared as a separate package with release |1.1|. % @@ -13524,19 +13808,36 @@ $1$ or $-1$. \else \def\y#1#2{\PackageInfo{#1}{#2}}% \fi + \let\z\relax \expandafter \ifx\csname numexpr\endcsname\relax \y{xintkernel}{\numexpr not available, aborting input}% - \aftergroup\endinput + \def\z{\endgroup\endinput}% \else \expandafter \ifx\csname XINTsetupcatcodes\endcsname\relax \else \y{xintkernel}{I was already loaded, aborting input}% - \aftergroup\endinput + \def\z{\endgroup\endinput}% \fi \fi - \def\SetCatcodesIfInputNotAborted + \ifx\z\relax\else\expandafter\z\fi% +% \end{macrocode} +% |1.2| corrects a long-standing somewhat subtle bug, of which the author +% became aware only on |15/09/13|: earlier releases had |\aftergroup\endinput| +% above, rather than |\def\z{\endgroup\endinput}| and the |\ifx| test. The +% |\endinput| token was indeed inserted after the |\endgroup| from +% |\PrepareCatcodes|, but all material and in particular |\XINT_setupcatcodes| +% from the macro now called |\PrepareCatcodes| was expanded before the +% |\endinput| had come into effect ! as a result the catcodes would be +% modified in unwanted ways, in Plain \TeX, if the source had for example +% |\input xint.sty| followed by |\input xintkernel.sty|: the catcode changes +% would be done before the second input of |xintkernel.sty| had been aborted. +% One didn't see the situation under \LaTeX{} (in normal circumstances), +% because a second |\usepackage{xintkernel}| would not do any input of +% |xintkernel.sty| to start with. +% \begin{macrocode} + \def\PrepareCatcodes {% \endgroup \def\XINT_restorecatcodes @@ -13605,19 +13906,19 @@ $1$ or $-1$. \catcode36=3 % $ \catcode91=12 % [ \catcode93=12 % ] - \catcode33=11 % ! LETTER + \catcode33=12 % ! \catcode64=11 % @ LETTER \catcode38=12 % & \catcode124=12 % | \catcode63=11 % ? LETTER \catcode34=12 % " \catcode39=12 % ' - \catcode126=3 % ~ + \catcode126=3 % ~ MATH \catcode59=12 % ; }% \XINT_setcatcodes }% -\SetCatcodesIfInputNotAborted +\PrepareCatcodes % \end{macrocode} % Other modules could possibly be loaded under a different catcode regime. % \begin{macrocode} @@ -13648,10 +13949,55 @@ $1$ or $-1$. \fi \XINT_providespackage \ProvidesPackage {xintkernel}% - [2015/09/12 v1.1c Paraphernalia for the xint packages (jfB)]% + [2015/10/10 v1.2 Paraphernalia for the xint packages (jfB)]% +% \end{macrocode} +% \subsection{Constants} +% |v1.2| decides to move them to \xintkernelnameimp from \xintcorenameimp and +% \xintnameimp. The |\count|'s are left in their respective packages. +% \begin{macrocode} +\chardef\xint_c_ 0 +\chardef\xint_c_i 1 +\chardef\xint_c_ii 2 +\chardef\xint_c_iii 3 +\chardef\xint_c_iv 4 +\chardef\xint_c_v 5 +\chardef\xint_c_vi 6 +\chardef\xint_c_vii 7 +\chardef\xint_c_viii 8 +\chardef\xint_c_ix 9 +\chardef\xint_c_x 10 +\chardef\xint_c_xiv 14 +\chardef\xint_c_xvi 16 +\chardef\xint_c_xviii 18 +\chardef\xint_c_xxii 22 +\chardef\xint_c_ii^v 32 +\chardef\xint_c_ii^vi 64 +\chardef\xint_c_ii^vii 128 +\mathchardef\xint_c_ii^viii 256 +\mathchardef\xint_c_ii^xii 4096 +\mathchardef\xint_c_x^iv 10000 % \end{macrocode} % \subsection{Token management utilities} % \begin{macrocode} +\def\XINT_tmpa { }% +\ifx\XINT_tmpa\space\else + \immediate\write-1{Package xintkernel Warning: ATTENTION!}% + \immediate\write-1{\string\space\XINT_tmpa macro does not have its normal + meaning.}% + \immediate\write-1{\XINT_tmpa\XINT_tmpa\XINT_tmpa\XINT_tmpa + All kinds of catastrophes will ensue!!!!}% +\fi +\def\XINT_tmpb {}% +\ifx\XINT_tmpb\empty\else + \immediate\write-1{Package xintkernel Warning: ATTENTION!}% + \immediate\write-1{\string\empty\XINT_tmpa macro does not have its normal + meaning.}% + \immediate\write-1{\XINT_tmpa\XINT_tmpa\XINT_tmpa\XINT_tmpa + All kinds of catastrophes will ensue!!!!}% +\fi +\let\XINT_tmpa\relax \let\XINT_tmpb\relax +\ifdefined\space\else\def\space { }\fi +\ifdefined\empty\else\def\empty {}\fi \long\def\xint_gobble_ {}% \long\def\xint_gobble_i #1{}% \long\def\xint_gobble_ii #1#2{}% @@ -13667,14 +14013,33 @@ $1$ or $-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} -% \subsection{gob til macros and UD style fork} +% \subsection{``gob til'' macros and UD style fork} +% Some moved here from \xintcorenameimp by release |1.2|. % \begin{macrocode} -\def\xint_gob_til_zero #10{}% -\def\xint_UDzerominusfork #10-#2#3\krof {#2}% \long\def\xint_gob_til_R #1\R {}% \long\def\xint_gob_til_W #1\W {}% \long\def\xint_gob_til_Z #1\Z {}% +\def\xint_gob_til_zero #10{}% +\def\xint_gob_til_one #11{}% +\def\xint_gob_til_zeros_iii #1000{}% +\def\xint_gob_til_zeros_iv #10000{}% +\def\xint_gob_til_eightzeroes #100000000{}% +\def\xint_gob_til_exclam #1!{}% catcode 12 exclam +\def\xint_gob_til_dot #1.{}% +\def\xint_gob_til_G #1G{}% +\def\xint_gob_til_minus #1-{}% +\def\xint_gob_til_relax #1\relax {}% +\def\xint_UDzerominusfork #10-#2#3\krof {#2}% +\def\xint_UDzerofork #10#2#3\krof {#2}% +\def\xint_UDsignfork #1-#2#3\krof {#2}% +\def\xint_UDwfork #1\W#2#3\krof {#2}% +\def\xint_UDXINTWfork #1\XINT_W#2#3\krof {#2}% +\def\xint_UDzerosfork #100#2#3\krof {#2}% +\def\xint_UDonezerofork #110#2#3\krof {#2}% +\def\xint_UDsignsfork #1--#2#3\krof {#2}% \let\xint_relax\relax \def\xint_brelax {\xint_relax }% \long\def\xint_gob_til_xint_relax #1\xint_relax {}% @@ -13687,19 +14052,20 @@ $1$ or $-1$. % \begin{macrocode} \long\def\xint_bye #1\xint_bye {}% % \end{macrocode} -% \subsection{\csh{xint_dothis}, \csh{xint_orthat}} -% \lverb|New with 1.1. Used as \if..\xint_dothis{..}\fi -% followed by \xint_orthat{...}. To be used with less probable things first.| +% \subsection{\csh{xintdothis}, \csh{xintorthat}} +% \lverb|New with 1.1. Public names without underscores with 1.2. Used as +% \if..\xint_dothis{..}\fi followed by \xint_orthat{...}. To +% be used with less probable things first.| % \begin{macrocode} \long\def\xint_dothis #1#2\xint_orthat #3{\fi #1}% v1.1 \let\xint_orthat \xint_firstofone +\long\def\xintdothis #1#2\xintorthat #3{\fi #1}% +\let\xintorthat \xint_firstofone % \end{macrocode} % \subsection{\csh{xint_zapspaces}} -% \lverb|& -% 1.1. Zaps leading, intermediate, trailing, spaces in completely -% expanding context -% (\edef, \csname . . . \endcsname). To be used as:$\ -% $null$ $ $ $ \xint_zapspaces foo \xint_gobble_i $% notice the mandatory space after foo +% \lverb|1.1. This little utility zaps leading, intermediate, trailing, +% spaces in completely expanding context (\edef, \csname . . . \endcsname). +% $centeredline$bgroup\xint_zapspaces foo\xint_gobble_i$egroup % % Will remove some brace pairs (but not spaces inside them). By the way the % \zap@spaces of LaTeX2e handles unexpectedly things such as \zap@spaces 1 @@ -13712,28 +14078,25 @@ $1$ or $-1$. % brace-stripping may occur. And this iterates: each time a #2 is removed, % either we then have spaces and next #1 will be empty, or we have no spaces % and #1 will end at the first space. Ultimately #2 will be \xint_gobble_i. -% -% Code comment from 1.1 release said to do: % -% \xint_zapspaces foo \xint_bye\xint_bye -% -% perhaps because it was pretty. It works also, but \xint_gobble_i is one -% token less. Compatible with an empty foo.| +% This is not really robust as it may switch the expansion order of macros, +% and the \xint_zapspaces token might end up being fetched up by a macro. But +% it is enough for our purposes, for example: +% $centeredline +% $bgroup\the\numexpr \xint_zapspaces 1 2 \xint_gobble_i\relax$egroup +% expands to 12, and not 12\relax. Imagine also: +% $centeredline +% $bgroup\the\numexpr 1 2\expandafter.\the\numexpr ...$egroup +% +% The space will delay the \expandafter. Thus we have to get rid of spaces in +% contexts where arguments are fetched by delimited macros and fed to +% \numexpr (or for any reason can contain spaces). I apply this corrective +% treatment so far only in $xintexprnameimp but perhaps I should in +% $xintfracnameimp too. As said above, perhaps the zapspaces should force +% expansion too, but I leave it standing.| % \begin{macrocode} \def\xint_zapspaces #1 #2{#1#2\xint_zapspaces }% v1.1 % \end{macrocode} -% \subsection{Constants} -% \begin{macrocode} -\chardef\xint_c_ 0 -\chardef\xint_c_i 1 -\chardef\xint_c_ii 2 -\chardef\xint_c_iii 3 -\chardef\xint_c_iv 4 -\chardef\xint_c_v 5 -\chardef\xint_c_vi 6 -\chardef\xint_c_vii 7 -\chardef\xint_c_viii 8 -% \end{macrocode} % \subsection{\csh{odef}, \csh{oodef}, \csh{fdef}} % \lverb|May be prefixed with \global. No parameter text.| % \begin{macrocode} @@ -13748,7 +14111,10 @@ $1$ or $-1$. \ifdefined\fdef\else\let\fdef\xintfdef\fi % \end{macrocode} % \subsection{\csh{xintReverseOrder}} -% \lverb|\xintReverseOrder: does NOT expand its argument.| +% \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.| % \begin{macrocode} \def\xintReverseOrder {\romannumeral0\xintreverseorder }% \long\def\xintreverseorder #1% @@ -13879,7 +14245,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xinttools}% - [2015/09/12 v1.1c Expandable and non-expandable utilities (jfB)]% + [2015/10/10 v1.2 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.| @@ -14072,2999 +14438,2382 @@ $1$ or $-1$. \def\xintCSVtoListNonStripped {\romannumeral0\xintcsvtolistnonstripped }% \def\xintCSVtoListNonStrippedNoExpand {\romannumeral0\xintcsvtolistnonstrippednoexpand }% -\long\def\xintcsvtolistnonstripped #1% -{% - \expandafter\XINT_csvtol_loop_a\expandafter - {\expandafter}\romannumeral-`0#1% - ,\xint_bye,\xint_bye,\xint_bye,\xint_bye - ,\xint_bye,\xint_bye,\xint_bye,\xint_bye,\Z -}% -\long\def\xintcsvtolistnonstrippednoexpand #1% -{% - \XINT_csvtol_loop_a - {}#1,\xint_bye,\xint_bye,\xint_bye,\xint_bye - ,\xint_bye,\xint_bye,\xint_bye,\xint_bye,\Z -}% -\long\def\XINT_csvtol_loop_a #1#2,#3,#4,#5,#6,#7,#8,#9,% -{% - \xint_bye #9\XINT_csvtol_finish_a\xint_bye - \XINT_csvtol_loop_b {#1}{{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}}% -}% -\long\def\XINT_csvtol_loop_b #1#2{\XINT_csvtol_loop_a {#1#2}}% -\long\def\XINT_csvtol_finish_a\xint_bye\XINT_csvtol_loop_b #1#2#3\Z -{% - \XINT_csvtol_finish_b #3\R,\R,\R,\R,\R,\R,\R,\Z #2{#1}% -}% -% \end{macrocode} -% \lverb|1.1c revisits this old code and improves upon the earlier endings. -% But as the _d.. macros have already nine parameters, I needed the -% \expandafter and \xint_gob_til_Z in finish_b (compare \XINT_keep_endb, or -% also \XINT_RQ_end_b).| -% \begin{macrocode} -\def\XINT_csvtol_finish_b #1,#2,#3,#4,#5,#6,#7,#8\Z -{% - \xint_gob_til_R - #1\expandafter\XINT_csvtol_finish_dviii\xint_gob_til_Z - #2\expandafter\XINT_csvtol_finish_dvii \xint_gob_til_Z - #3\expandafter\XINT_csvtol_finish_dvi \xint_gob_til_Z - #4\expandafter\XINT_csvtol_finish_dv \xint_gob_til_Z - #5\expandafter\XINT_csvtol_finish_div \xint_gob_til_Z - #6\expandafter\XINT_csvtol_finish_diii \xint_gob_til_Z - #7\expandafter\XINT_csvtol_finish_dii \xint_gob_til_Z - \R\XINT_csvtol_finish_di \Z -}% -\long\def\XINT_csvtol_finish_dviii #1#2#3#4#5#6#7#8#9{ #9}% -\long\def\XINT_csvtol_finish_dvii #1#2#3#4#5#6#7#8#9{ #9{#1}}% -\long\def\XINT_csvtol_finish_dvi #1#2#3#4#5#6#7#8#9{ #9{#1}{#2}}% -\long\def\XINT_csvtol_finish_dv #1#2#3#4#5#6#7#8#9{ #9{#1}{#2}{#3}}% -\long\def\XINT_csvtol_finish_div #1#2#3#4#5#6#7#8#9{ #9{#1}{#2}{#3}{#4}}% -\long\def\XINT_csvtol_finish_diii #1#2#3#4#5#6#7#8#9{ #9{#1}{#2}{#3}{#4}{#5}}% -\long\def\XINT_csvtol_finish_dii #1#2#3#4#5#6#7#8#9% - { #9{#1}{#2}{#3}{#4}{#5}{#6}}% -\long\def\XINT_csvtol_finish_di\Z #1#2#3#4#5#6#7#8#9% - { #9{#1}{#2}{#3}{#4}{#5}{#6}{#7}}% -% \end{macrocode} -% \subsection{\csh{xintListWithSep}} -% \lverb|1.04. -% \xintListWithSep {\sep}{{a}{b}...{z}} returns a \sep b \sep ....\sep z. It -% f-expands its second argument. The 'sep' may be \par's: the macro -% \xintlistwithsep etc... are all declared long. 'sep' does not have to be a -% single token. It is not expanded.| -% \begin{macrocode} -\def\xintListWithSep {\romannumeral0\xintlistwithsep }% -\def\xintListWithSepNoExpand {\romannumeral0\xintlistwithsepnoexpand }% -\long\def\xintlistwithsep #1#2% - {\expandafter\XINT_lws\expandafter {\romannumeral-`0#2}{#1}}% -\long\def\XINT_lws #1#2{\XINT_lws_start {#2}#1\xint_bye }% -\long\def\xintlistwithsepnoexpand #1#2{\XINT_lws_start {#1}#2\xint_bye }% -\long\def\XINT_lws_start #1#2% -{% - \xint_bye #2\XINT_lws_dont\xint_bye - \XINT_lws_loop_a {#2}{#1}% -}% -\long\def\XINT_lws_dont\xint_bye\XINT_lws_loop_a #1#2{ }% -\long\def\XINT_lws_loop_a #1#2#3% -{% - \xint_bye #3\XINT_lws_end\xint_bye - \XINT_lws_loop_b {#1}{#2#3}{#2}% -}% -\long\def\XINT_lws_loop_b #1#2{\XINT_lws_loop_a {#1#2}}% -\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. -% -% \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 -% first f-expanded. The \xintNthEltNoExpand does no expansion of its second -% argument. Both variants expand the first argument inside \numexpr. -% -% With i = 0, the number of items is returned. This is different from \xintLen -% 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.+ -% \begin{macrocode} -\def\xintNthElt {\romannumeral0\xintnthelt }% -\def\xintNthEltNoExpand {\romannumeral0\xintntheltnoexpand }% -\def\xintnthelt #1#2% -{% - \expandafter\XINT_nthelt_a\the\numexpr #1\expandafter.% - \expandafter{\romannumeral-`0#2}% -}% -\def\xintntheltnoexpand #1% -{% - \expandafter\XINT_nthelt_a\the\numexpr #1.% -}% -\def\XINT_nthelt_a #1#2.% -{% - \xint_UDzerominusfork - #1-{\XINT_nthelt_bzero}% - 0#1{\XINT_nthelt_bneg {#2}}% - 0-{\XINT_nthelt_bpos {#1#2}}% - \krof -}% -\long\def\XINT_nthelt_bzero #1% -{% - \XINT_length_loop 0.#1\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% -{% - \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 -}% -\long\def\XINT_nthelt_bpos #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 -}% -\def\XINT_nthelt_loop_a #1% -{% - \ifnum #1>\xint_c_viii - \expandafter\XINT_nthelt_loop_b - \else - \XINT_nthelt_getit - \fi - {#1}% -}% -\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}% -}% -\def\XINT_nthelt_silentend #1\xint_bye { }% -\def\XINT_nthelt_getit\fi #1% -{% - \fi\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 - {\noexpand\xint_gob_til_xint_relax #1\noexpand\expandafter\space - \noexpand\xint_gobble_ii\xint_relax\space #1}% -% \end{macrocode} -% \subsection{\csh{xintKeep}} -% \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) returns (in two -% expansion steps) the first i elements from the list, which 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 i<0, the last |i| elements are returned (in the same order as in -% the original list). -% -% With |i| equal to or bigger than the length of the (f-expanded) list, -% the full list is returned.+ -% \begin{macrocode} -\def\xintKeep {\romannumeral0\xintkeep }% -\def\xintKeepNoExpand {\romannumeral0\xintkeepnoexpand }% -\def\xintkeep #1#2% -{% - \expandafter\XINT_keep_a\the\numexpr #1\expandafter.% - \expandafter{\romannumeral-`0#2}% -}% -\def\xintkeepnoexpand #1% -{% - \expandafter\XINT_keep_a\the\numexpr #1.% -}% -\def\XINT_keep_a #1#2.% -{% - \xint_UDzerominusfork - #1-{\expandafter\space\xint_gobble_i }% - 0#1{\XINT_keep_bneg_a {#2}}% - 0-{\XINT_keep_bpos {#1#2}}% - \krof -}% -\long\def\XINT_keep_bneg_a #1#2% -{% - \expandafter\XINT_keep_bneg_b \the\numexpr \xintLength{#2}-#1.{#2}% -}% -\def\XINT_keep_bneg_b #1#2.% -{% - \xint_UDzerominusfork - #1-{\xint_firstofone_thenstop }% - 0#1{\xint_firstofone_thenstop }% - 0-{\XINT_trim_bpos {#1#2}}% - \krof -}% -\long\def\XINT_keep_bpos #1#2% -{% - \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% -{% - \ifnum #1>\xint_c_vi - \expandafter\XINT_keep_loop_b - \else - \XINT_keep_finish - \fi - {#1}% -}% -\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}% - {{#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 -{% - \XINT_keep_endb #4\W\W\W\W\W\W\Z #2{#3}% -}% -\def\XINT_keep_endb #1#2#3#4#5#6#7\Z -{% - \xint_gob_til_W - #1\XINT_keep_endc_ - #2\XINT_keep_endc_i - #3\XINT_keep_endc_ii - #4\XINT_keep_endc_iii - #5\XINT_keep_endc_iv - #6\XINT_keep_endc_v - \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}}}% -% \end{macrocode} -% \subsection{\csh{xintTrim}} -% \lverb+First included in release 1.09m. -% -% \xintTrim {i}{stuff f-expanding to {a}{b}...{z}} (or `tokens' abcd...z, -% but each naked token ends up braced in the output) returns (in two -% expansion steps) the sequence with the first i elements omitted. The -% list is first f-expanded. The i is expanded inside \numexpr. Variant -% \xintTrimNoExpand does not expand the list argument. -% -% With i = 0, the original (expanded) list is returned. -% -% With i<0, the last |i| elements from the tail are suppressed. -% -% With |i| equal to or bigger than the length of the (f-expanded) list, -% the empty list is returned.+ -% \begin{macrocode} -\def\xintTrim {\romannumeral0\xinttrim }% -\def\xintTrimNoExpand {\romannumeral0\xinttrimnoexpand }% -\def\xinttrim #1#2% -{% - \expandafter\XINT_trim_a\the\numexpr #1\expandafter.% - \expandafter{\romannumeral-`0#2}% -}% -\def\xinttrimnoexpand #1% -{% - \expandafter\XINT_trim_a\the\numexpr #1.% -}% -\def\XINT_trim_a #1#2.% -{% - \xint_UDzerominusfork - #1-{\xint_firstofone_thenstop }% - 0#1{\XINT_trim_bneg_a {#2}}% - 0-{\XINT_trim_bpos {#1#2}}% - \krof -}% -\long\def\XINT_trim_bneg_a #1#2% -{% - \expandafter\XINT_trim_bneg_b \the\numexpr \xintLength{#2}-#1.{#2}% -}% -\def\XINT_trim_bneg_b #1#2.% -{% - \xint_UDzerominusfork - #1-{\expandafter\space\xint_gobble_i }% - 0#1{\expandafter\space\xint_gobble_i }% - 0-{\XINT_keep_bpos {#1#2}}% - \krof -}% -\long\def\XINT_trim_bpos #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 -}% -\def\XINT_trim_loop_a #1% -{% - \ifnum #1>\xint_c_vii - \expandafter\XINT_trim_loop_b - \else - \XINT_trim_finish - \fi - {#1}% -}% -\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}% -}% -\def\XINT_trim_silentend #1\xint_bye { }% -\def\XINT_trim_finish\fi #1% -{% - \fi\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{xintApply}} -% \lverb|\xintApply {\macro}{{a}{b}...{z}} returns {\macro{a}}...{\macro{b}} -% where each instance of \macro is f-expanded. The list itself is first -% f-expanded and may thus be a macro. Introduced with release 1.04.| -% \begin{macrocode} -\def\xintApply {\romannumeral0\xintapply }% -\def\xintApplyNoExpand {\romannumeral0\xintapplynoexpand }% -\long\def\xintapply #1#2% -{% - \expandafter\XINT_apply\expandafter {\romannumeral-`0#2}% - {#1}% -}% -\long\def\XINT_apply #1#2{\XINT_apply_loop_a {}{#2}#1\xint_bye }% -\long\def\xintapplynoexpand #1#2{\XINT_apply_loop_a {}{#1}#2\xint_bye }% -\long\def\XINT_apply_loop_a #1#2#3% -{% - \xint_bye #3\XINT_apply_end\xint_bye - \expandafter - \XINT_apply_loop_b - \expandafter {\romannumeral-`0#2{#3}}{#1}{#2}% -}% -\long\def\XINT_apply_loop_b #1#2{\XINT_apply_loop_a {#2{#1}}}% -\long\def\XINT_apply_end\xint_bye\expandafter\XINT_apply_loop_b - \expandafter #1#2#3{ #2}% -% \end{macrocode} -% \subsection{\csh{xintApplyUnbraced}} -% \lverb|\xintApplyUnbraced {\macro}{{a}{b}...{z}} returns \macro{a}...\macro{z} -% where each instance of \macro is f-expanded using \romannumeral-`0. The second -% argument may be a macro as it is itself also f-expanded. No braces -% are added: this allows for example a non-expandable \def in \macro, without -% having to do \gdef. Introduced with release 1.06b.| -% \begin{macrocode} -\def\xintApplyUnbraced {\romannumeral0\xintapplyunbraced }% -\def\xintApplyUnbracedNoExpand {\romannumeral0\xintapplyunbracednoexpand }% -\long\def\xintapplyunbraced #1#2% -{% - \expandafter\XINT_applyunbr\expandafter {\romannumeral-`0#2}% - {#1}% -}% -\long\def\XINT_applyunbr #1#2{\XINT_applyunbr_loop_a {}{#2}#1\xint_bye }% -\long\def\xintapplyunbracednoexpand #1#2% - {\XINT_applyunbr_loop_a {}{#1}#2\xint_bye }% -\long\def\XINT_applyunbr_loop_a #1#2#3% -{% - \xint_bye #3\XINT_applyunbr_end\xint_bye - \expandafter\XINT_applyunbr_loop_b - \expandafter {\romannumeral-`0#2{#3}}{#1}{#2}% -}% -\long\def\XINT_applyunbr_loop_b #1#2{\XINT_applyunbr_loop_a {#2#1}}% -\long\def\XINT_applyunbr_end\xint_bye\expandafter\XINT_applyunbr_loop_b - \expandafter #1#2#3{ #2}% -% \end{macrocode} -% \subsection{\csh{xintSeq}} -% \lverb|1.09c. Without the optional argument puts stress on the input stack, -% should not be used to generated thousands of terms then.| -% \begin{macrocode} -\def\xintSeq {\romannumeral0\xintseq }% -\def\xintseq #1{\XINT_seq_chkopt #1\xint_bye }% -\def\XINT_seq_chkopt #1% -{% - \ifx [#1\expandafter\XINT_seq_opt - \else\expandafter\XINT_seq_noopt - \fi #1% -}% -\def\XINT_seq_noopt #1\xint_bye #2% -{% - \expandafter\XINT_seq\expandafter - {\the\numexpr#1\expandafter}\expandafter{\the\numexpr #2}% -}% -\def\XINT_seq #1#2% -{% - \ifcase\ifnum #1=#2 0\else\ifnum #2>#1 1\else -1\fi\fi\space - \expandafter\xint_firstoftwo_thenstop - \or - \expandafter\XINT_seq_p - \else - \expandafter\XINT_seq_n - \fi - {#2}{#1}% -}% -\def\XINT_seq_p #1#2% -{% - \ifnum #1>#2 - \expandafter\expandafter\expandafter\XINT_seq_p - \else - \expandafter\XINT_seq_e - \fi - \expandafter{\the\numexpr #1-\xint_c_i}{#2}{#1}% -}% -\def\XINT_seq_n #1#2% -{% - \ifnum #1<#2 - \expandafter\expandafter\expandafter\XINT_seq_n - \else - \expandafter\XINT_seq_e - \fi - \expandafter{\the\numexpr #1+\xint_c_i}{#2}{#1}% -}% -\def\XINT_seq_e #1#2#3{ }% -\def\XINT_seq_opt [\xint_bye #1]#2#3% -{% - \expandafter\XINT_seqo\expandafter - {\the\numexpr #2\expandafter}\expandafter - {\the\numexpr #3\expandafter}\expandafter - {\the\numexpr #1}% -}% -\def\XINT_seqo #1#2% -{% - \ifcase\ifnum #1=#2 0\else\ifnum #2>#1 1\else -1\fi\fi\space - \expandafter\XINT_seqo_a - \or - \expandafter\XINT_seqo_pa - \else - \expandafter\XINT_seqo_na - \fi - {#1}{#2}% -}% -\def\XINT_seqo_a #1#2#3{ {#1}}% -\def\XINT_seqo_o #1#2#3#4{ #4}% -\def\XINT_seqo_pa #1#2#3% -{% - \ifcase\ifnum #3=\xint_c_ 0\else\ifnum #3>\xint_c_ 1\else -1\fi\fi\space - \expandafter\XINT_seqo_o - \or - \expandafter\XINT_seqo_pb - \else - \xint_afterfi{\expandafter\space\xint_gobble_iv}% - \fi - {#1}{#2}{#3}{{#1}}% -}% -\def\XINT_seqo_pb #1#2#3% -{% - \expandafter\XINT_seqo_pc\expandafter{\the\numexpr #1+#3}{#2}{#3}% -}% -\def\XINT_seqo_pc #1#2% -{% - \ifnum #1>#2 - \expandafter\XINT_seqo_o - \else - \expandafter\XINT_seqo_pd - \fi - {#1}{#2}% -}% -\def\XINT_seqo_pd #1#2#3#4{\XINT_seqo_pb {#1}{#2}{#3}{#4{#1}}}% -\def\XINT_seqo_na #1#2#3% -{% - \ifcase\ifnum #3=\xint_c_ 0\else\ifnum #3>\xint_c_ 1\else -1\fi\fi\space - \expandafter\XINT_seqo_o - \or - \xint_afterfi{\expandafter\space\xint_gobble_iv}% - \else - \expandafter\XINT_seqo_nb - \fi - {#1}{#2}{#3}{{#1}}% -}% -\def\XINT_seqo_nb #1#2#3% -{% - \expandafter\XINT_seqo_nc\expandafter{\the\numexpr #1+#3}{#2}{#3}% -}% -\def\XINT_seqo_nc #1#2% -{% - \ifnum #1<#2 - \expandafter\XINT_seqo_o - \else - \expandafter\XINT_seqo_nd - \fi - {#1}{#2}% -}% -\def\XINT_seqo_nd #1#2#3#4{\XINT_seqo_nb {#1}{#2}{#3}{#4{#1}}}% -% \end{macrocode} -%\subsection{\csh{xintloop}, \csh{xintbreakloop}, \csh{xintbreakloopanddo}, -% \csh{xintloopskiptonext}} -% \lverb|1.09g [2013/11/22]. Made long with 1.09h.| -% \begin{macrocode} -\long\def\xintloop #1#2\repeat {#1#2\xintloop_again\fi\xint_gobble_i {#1#2}}% -\long\def\xintloop_again\fi\xint_gobble_i #1{\fi - #1\xintloop_again\fi\xint_gobble_i {#1}}% -\long\def\xintbreakloop #1\xintloop_again\fi\xint_gobble_i #2{}% -\long\def\xintbreakloopanddo #1#2\xintloop_again\fi\xint_gobble_i #3{#1}% -\long\def\xintloopskiptonext #1\xintloop_again\fi\xint_gobble_i #2{% - #2\xintloop_again\fi\xint_gobble_i {#2}}% -% \end{macrocode} -% \subsection{\csh{xintiloop}, \csh{xintiloopindex}, \csh{xintouteriloopindex}, -% \csh{xintbreakiloop}, \csh{xintbreakiloopanddo}, \csh{xintiloopskiptonext}, -% \csh{xintiloopskipandredo}} -% \lverb|1.09g [2013/11/22]. Made long with 1.09h.| -% \begin{macrocode} -\def\xintiloop [#1+#2]{% - \expandafter\xintiloop_a\the\numexpr #1\expandafter.\the\numexpr #2.}% -\long\def\xintiloop_a #1.#2.#3#4\repeat{% - #3#4\xintiloop_again\fi\xint_gobble_iii {#1}{#2}{#3#4}}% -\def\xintiloop_again\fi\xint_gobble_iii #1#2{% - \fi\expandafter\xintiloop_again_b\the\numexpr#1+#2.#2.}% -\long\def\xintiloop_again_b #1.#2.#3{% - #3\xintiloop_again\fi\xint_gobble_iii {#1}{#2}{#3}}% -\long\def\xintbreakiloop #1\xintiloop_again\fi\xint_gobble_iii #2#3#4{}% -\long\def\xintbreakiloopanddo - #1.#2\xintiloop_again\fi\xint_gobble_iii #3#4#5{#1}% -\long\def\xintiloopindex #1\xintiloop_again\fi\xint_gobble_iii #2% - {#2#1\xintiloop_again\fi\xint_gobble_iii {#2}}% -\long\def\xintouteriloopindex #1\xintiloop_again - #2\xintiloop_again\fi\xint_gobble_iii #3% - {#3#1\xintiloop_again #2\xintiloop_again\fi\xint_gobble_iii {#3}}% -\long\def\xintiloopskiptonext #1\xintiloop_again\fi\xint_gobble_iii #2#3{% - \expandafter\xintiloop_again_b \the\numexpr#2+#3.#3.}% -\long\def\xintiloopskipandredo #1\xintiloop_again\fi\xint_gobble_iii #2#3#4{% - #4\xintiloop_again\fi\xint_gobble_iii {#2}{#3}{#4}}% -% \end{macrocode} -% \subsection{\csh{XINT_xflet}} -% \lverb|1.09e [2013/10/29]: we f-expand unbraced tokens and swallow arising -% space tokens until the dust settles.| -% \begin{macrocode} -\def\XINT_xflet #1% -{% - \def\XINT_xflet_macro {#1}\XINT_xflet_zapsp -}% -\def\XINT_xflet_zapsp -{% - \expandafter\futurelet\expandafter\XINT_token - \expandafter\XINT_xflet_sp?\romannumeral-`0% -}% -\def\XINT_xflet_sp? -{% - \ifx\XINT_token\XINT_sptoken - \expandafter\XINT_xflet_zapsp - \else\expandafter\XINT_xflet_zapspB - \fi -}% -\def\XINT_xflet_zapspB -{% - \expandafter\futurelet\expandafter\XINT_tokenB - \expandafter\XINT_xflet_spB?\romannumeral-`0% -}% -\def\XINT_xflet_spB? -{% - \ifx\XINT_tokenB\XINT_sptoken - \expandafter\XINT_xflet_zapspB - \else\expandafter\XINT_xflet_eq? - \fi -}% -\def\XINT_xflet_eq? -{% - \ifx\XINT_token\XINT_tokenB - \expandafter\XINT_xflet_macro - \else\expandafter\XINT_xflet_zapsp - \fi -}% -% \end{macrocode} -% \subsection{\csh{xintApplyInline}} -% \lverb|1.09a: \xintApplyInline\macro{{a}{b}...{z}} has the same effect as -% executing \macro{a} and then applying again \xintApplyInline to the shortened -% list {{b}...{z}} until nothing is left. This is a non-expandable command -% which will result in quicker code than using \xintApplyUnbraced. It f-expands -% its second (list) argument first, which may thus be encapsulated in a macro. -% -% Rewritten in 1.09c. Nota bene: uses catcode 3 Z as privated list terminator.| -% \begin{macrocode} -\catcode`Z 3 -\long\def\xintApplyInline #1#2% -{% - \long\expandafter\def\expandafter\XINT_inline_macro - \expandafter ##\expandafter 1\expandafter {#1{##1}}% - \XINT_xflet\XINT_inline_b #2Z% this Z has catcode 3 -}% -\def\XINT_inline_b -{% - \ifx\XINT_token Z\expandafter\xint_gobble_i - \else\expandafter\XINT_inline_d\fi -}% -\long\def\XINT_inline_d #1% -{% - \long\def\XINT_item{{#1}}\XINT_xflet\XINT_inline_e -}% -\def\XINT_inline_e -{% - \ifx\XINT_token Z\expandafter\XINT_inline_w - \else\expandafter\XINT_inline_f\fi -}% -\def\XINT_inline_f -{% - \expandafter\XINT_inline_g\expandafter{\XINT_inline_macro {##1}}% -}% -\long\def\XINT_inline_g #1% -{% - \expandafter\XINT_inline_macro\XINT_item - \long\def\XINT_inline_macro ##1{#1}\XINT_inline_d -}% -\def\XINT_inline_w #1% -{% - \expandafter\XINT_inline_macro\XINT_item -}% -% \end{macrocode} -% \subsection{\csh{xintFor}, \csh{xintFor*}, \csh{xintBreakFor}, \csh{xintBreakForAndDo}} -% \lverb|1.09c [2013/10/09]: a new kind of loop which uses macro parameters -% #1, #2, #3, #4 rather than macros; while not expandable it survives executing -% code closing groups, like what happens in an alignment with the $& character. -% When inserted in a macro for later use, the # character must be doubled. -% -% The non-star variant works on a csv list, which it expands once, the -% star variant works on a token list, which it (repeatedly) f-expands. -% -% 1.09e adds \XINT_forever with \xintintegers, \xintdimensions, \xintrationals -% and \xintBreakFor, \xintBreakForAndDo, \xintifForFirst, \xintifForLast. On -% this occasion \xint_firstoftwo and \xint_secondoftwo are made long. -% -% 1.09f: rewrites large parts of \xintFor code in order to filter the comma -% separated list via \xintCSVtoList which gets rid of spaces. The #1 in -% \XINT_for_forever? has an initial space token which serves two purposes: -% preventing brace stripping, and stopping the expansion made by \xintcsvtolist. -% If the \XINT_forever branch is taken, the added space will not be a problem -% there. -% -% 1.09f rewrites (2013/11/03) the code which now allows all macro parameters -% from #1 to #9 in \xintFor, \xintFor*, and \XINT_forever.| -% \begin{macrocode} -\def\XINT_tmpa #1#2{\ifnum #2<#1 \xint_afterfi {{#########2}}\fi}% -\def\XINT_tmpb #1#2{\ifnum #1<#2 \xint_afterfi {{#########2}}\fi}% -\def\XINT_tmpc #1% -{% - \expandafter\edef \csname XINT_for_left#1\endcsname - {\xintApplyUnbraced {\XINT_tmpa #1}{123456789}}% - \expandafter\edef \csname XINT_for_right#1\endcsname - {\xintApplyUnbraced {\XINT_tmpb #1}{123456789}}% -}% -\xintApplyInline \XINT_tmpc {123456789}% -\long\def\xintBreakFor #1Z{}% -\long\def\xintBreakForAndDo #1#2Z{#1}% -\def\xintFor {\let\xintifForFirst\xint_firstoftwo - \futurelet\XINT_token\XINT_for_ifstar }% -\def\XINT_for_ifstar {\ifx\XINT_token*\expandafter\XINT_forx - \else\expandafter\XINT_for \fi }% -\catcode`U 3 % with numexpr -\catcode`V 3 % with xintfrac.sty (xint.sty not enough) -\catcode`D 3 % with dimexpr -\def\XINT_flet_zapsp -{% - \futurelet\XINT_token\XINT_flet_sp? -}% -\def\XINT_flet_sp? -{% - \ifx\XINT_token\XINT_sptoken - \xint_afterfi{\expandafter\XINT_flet_zapsp\romannumeral0}% - \else\expandafter\XINT_flet_macro - \fi -}% -\long\def\XINT_for #1#2in#3#4#5% -{% - \expandafter\XINT_toks\expandafter - {\expandafter\XINT_for_d\the\numexpr #2\relax {#5}}% - \def\XINT_flet_macro {\expandafter\XINT_for_forever?\space}% - \expandafter\XINT_flet_zapsp #3Z% -}% -\def\XINT_for_forever? #1Z% -{% - \ifx\XINT_token U\XINT_to_forever\fi - \ifx\XINT_token V\XINT_to_forever\fi - \ifx\XINT_token D\XINT_to_forever\fi - \expandafter\the\expandafter\XINT_toks\romannumeral0\xintcsvtolist {#1}Z% -}% -\def\XINT_to_forever\fi #1\xintcsvtolist #2{\fi \XINT_forever #2}% -\long\def\XINT_forx *#1#2in#3#4#5% -{% - \expandafter\XINT_toks\expandafter - {\expandafter\XINT_forx_d\the\numexpr #2\relax {#5}}% - \XINT_xflet\XINT_forx_forever? #3Z% -}% -\def\XINT_forx_forever? -{% - \ifx\XINT_token U\XINT_to_forxever\fi - \ifx\XINT_token V\XINT_to_forxever\fi - \ifx\XINT_token D\XINT_to_forxever\fi - \XINT_forx_empty? -}% -\def\XINT_to_forxever\fi #1\XINT_forx_empty? {\fi \XINT_forever }% -\catcode`U 11 -\catcode`D 11 -\catcode`V 11 -\def\XINT_forx_empty? -{% - \ifx\XINT_token Z\expandafter\xintBreakFor\fi - \the\XINT_toks -}% -\long\def\XINT_for_d #1#2#3% -{% - \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#2}% - \XINT_toks {{#3}}% - \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname - \the\XINT_toks \csname XINT_for_right#1\endcsname }% - \XINT_toks {\XINT_x\let\xintifForFirst\xint_secondoftwo\XINT_for_d #1{#2}}% - \futurelet\XINT_token\XINT_for_last? -}% -\long\def\XINT_forx_d #1#2#3% -{% - \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#2}% - \XINT_toks {{#3}}% - \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname - \the\XINT_toks \csname XINT_for_right#1\endcsname }% - \XINT_toks {\XINT_x\let\xintifForFirst\xint_secondoftwo\XINT_forx_d #1{#2}}% - \XINT_xflet\XINT_for_last? -}% -\def\XINT_for_last? -{% - \let\xintifForLast\xint_secondoftwo - \ifx\XINT_token Z\let\xintifForLast\xint_firstoftwo - \xint_afterfi{\xintBreakForAndDo{\XINT_x\xint_gobble_i Z}}\fi - \the\XINT_toks -}% -% \end{macrocode} -% \subsection{\csh{XINT_forever}, \csh{xintintegers}, \csh{xintdimensions}, \csh{xintrationals}} -% \lverb|New with 1.09e. But this used inadvertently \xintiadd/\xintimul which -% have the unnecessary \xintnum overhead. Changed in 1.09f to use -% \xintiiadd/\xintiimul which do not have this overhead. Also 1.09f uses -% \xintZapSpacesB for the \xintrationals case to get rid of leading and ending -% spaces in the #4 and #5 delimited parameters of \XINT_forever_opt_a -% (for \xintintegers and \xintdimensions this is not necessary, due to the use -% of \numexpr resp. \dimexpr in \XINT_?expr_Ua, resp.\XINT_?expr_Da).| -% \begin{macrocode} -\catcode`U 3 -\catcode`D 3 -\catcode`V 3 -\let\xintegers U% -\let\xintintegers U% -\let\xintdimensions D% -\let\xintrationals V% -\def\XINT_forever #1% -{% - \expandafter\XINT_forever_a - \csname XINT_?expr_\ifx#1UU\else\ifx#1DD\else V\fi\fi a\expandafter\endcsname - \csname XINT_?expr_\ifx#1UU\else\ifx#1DD\else V\fi\fi i\expandafter\endcsname - \csname XINT_?expr_\ifx#1UU\else\ifx#1DD\else V\fi\fi \endcsname -}% -\catcode`U 11 -\catcode`D 11 -\catcode`V 11 -\def\XINT_?expr_Ua #1#2% - {\expandafter{\expandafter\numexpr\the\numexpr #1\expandafter\relax - \expandafter\relax\expandafter}% - \expandafter{\the\numexpr #2}}% -\def\XINT_?expr_Da #1#2% - {\expandafter{\expandafter\dimexpr\number\dimexpr #1\expandafter\relax - \expandafter s\expandafter p\expandafter\relax\expandafter}% - \expandafter{\number\dimexpr #2}}% -\catcode`Z 11 -\def\XINT_?expr_Va #1#2% +\long\def\xintcsvtolistnonstripped #1% {% - \expandafter\XINT_?expr_Vb\expandafter - {\romannumeral-`0\xintrawwithzeros{\xintZapSpacesB{#2}}}% - {\romannumeral-`0\xintrawwithzeros{\xintZapSpacesB{#1}}}% + \expandafter\XINT_csvtol_loop_a\expandafter + {\expandafter}\romannumeral-`0#1% + ,\xint_bye,\xint_bye,\xint_bye,\xint_bye + ,\xint_bye,\xint_bye,\xint_bye,\xint_bye,\Z }% -\catcode`Z 3 -\def\XINT_?expr_Vb #1#2{\expandafter\XINT_?expr_Vc #2.#1.}% -\def\XINT_?expr_Vc #1/#2.#3/#4.% +\long\def\xintcsvtolistnonstrippednoexpand #1% {% - \xintifEq {#2}{#4}% - {\XINT_?expr_Vf {#3}{#1}{#2}}% - {\expandafter\XINT_?expr_Vd\expandafter - {\romannumeral0\xintiimul {#2}{#4}}% - {\romannumeral0\xintiimul {#1}{#4}}% - {\romannumeral0\xintiimul {#2}{#3}}% - }% + \XINT_csvtol_loop_a + {}#1,\xint_bye,\xint_bye,\xint_bye,\xint_bye + ,\xint_bye,\xint_bye,\xint_bye,\xint_bye,\Z }% -\def\XINT_?expr_Vd #1#2#3{\expandafter\XINT_?expr_Ve\expandafter {#2}{#3}{#1}}% -\def\XINT_?expr_Ve #1#2{\expandafter\XINT_?expr_Vf\expandafter {#2}{#1}}% -\def\XINT_?expr_Vf #1#2#3{{#2/#3}{{0}{#1}{#2}{#3}}}% -\def\XINT_?expr_Ui {{\numexpr 1\relax}{1}}% -\def\XINT_?expr_Di {{\dimexpr 0pt\relax}{65536}}% -\def\XINT_?expr_Vi {{1/1}{0111}}% -\def\XINT_?expr_U #1#2% - {\expandafter{\expandafter\numexpr\the\numexpr #1+#2\relax\relax}{#2}}% -\def\XINT_?expr_D #1#2% - {\expandafter{\expandafter\dimexpr\the\numexpr #1+#2\relax sp\relax}{#2}}% -\def\XINT_?expr_V #1#2{\XINT_?expr_Vx #2}% -\def\XINT_?expr_Vx #1#2% +\long\def\XINT_csvtol_loop_a #1#2,#3,#4,#5,#6,#7,#8,#9,% {% - \expandafter\XINT_?expr_Vy\expandafter - {\romannumeral0\xintiiadd {#1}{#2}}{#2}% + \xint_bye #9\XINT_csvtol_finish_a\xint_bye + \XINT_csvtol_loop_b {#1}{{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}}% }% -\def\XINT_?expr_Vy #1#2#3#4% +\long\def\XINT_csvtol_loop_b #1#2{\XINT_csvtol_loop_a {#1#2}}% +\long\def\XINT_csvtol_finish_a\xint_bye\XINT_csvtol_loop_b #1#2#3\Z {% - \expandafter{\romannumeral0\xintiiadd {#3}{#1}/#4}{{#1}{#2}{#3}{#4}}% + \XINT_csvtol_finish_b #3\R,\R,\R,\R,\R,\R,\R,\Z #2{#1}% }% -\def\XINT_forever_a #1#2#3#4% +% \end{macrocode} +% \lverb|1.1c revisits this old code and improves upon the earlier endings. +% But as the _d.. macros have already nine parameters, I needed the +% \expandafter and \xint_gob_til_Z in finish_b (compare \XINT_keep_endb, or +% also \XINT_RQ_end_b).| +% \begin{macrocode} +\def\XINT_csvtol_finish_b #1,#2,#3,#4,#5,#6,#7,#8\Z {% - \ifx #4[\expandafter\XINT_forever_opt_a - \else\expandafter\XINT_forever_b - \fi #1#2#3#4% + \xint_gob_til_R + #1\expandafter\XINT_csvtol_finish_dviii\xint_gob_til_Z + #2\expandafter\XINT_csvtol_finish_dvii \xint_gob_til_Z + #3\expandafter\XINT_csvtol_finish_dvi \xint_gob_til_Z + #4\expandafter\XINT_csvtol_finish_dv \xint_gob_til_Z + #5\expandafter\XINT_csvtol_finish_div \xint_gob_til_Z + #6\expandafter\XINT_csvtol_finish_diii \xint_gob_til_Z + #7\expandafter\XINT_csvtol_finish_dii \xint_gob_til_Z + \R\XINT_csvtol_finish_di \Z }% -\def\XINT_forever_b #1#2#3Z{\expandafter\XINT_forever_c\the\XINT_toks #2#3}% -\long\def\XINT_forever_c #1#2#3#4#5% - {\expandafter\XINT_forever_d\expandafter #2#4#5{#3}Z}% -\def\XINT_forever_opt_a #1#2#3[#4+#5]#6Z% +\long\def\XINT_csvtol_finish_dviii #1#2#3#4#5#6#7#8#9{ #9}% +\long\def\XINT_csvtol_finish_dvii #1#2#3#4#5#6#7#8#9{ #9{#1}}% +\long\def\XINT_csvtol_finish_dvi #1#2#3#4#5#6#7#8#9{ #9{#1}{#2}}% +\long\def\XINT_csvtol_finish_dv #1#2#3#4#5#6#7#8#9{ #9{#1}{#2}{#3}}% +\long\def\XINT_csvtol_finish_div #1#2#3#4#5#6#7#8#9{ #9{#1}{#2}{#3}{#4}}% +\long\def\XINT_csvtol_finish_diii #1#2#3#4#5#6#7#8#9{ #9{#1}{#2}{#3}{#4}{#5}}% +\long\def\XINT_csvtol_finish_dii #1#2#3#4#5#6#7#8#9% + { #9{#1}{#2}{#3}{#4}{#5}{#6}}% +\long\def\XINT_csvtol_finish_di\Z #1#2#3#4#5#6#7#8#9% + { #9{#1}{#2}{#3}{#4}{#5}{#6}{#7}}% +% \end{macrocode} +% \subsection{\csh{xintListWithSep}} +% \lverb|1.04. +% \xintListWithSep {\sep}{{a}{b}...{z}} returns a \sep b \sep ....\sep z. It +% f-expands its second argument. The 'sep' may be \par's: the macro +% \xintlistwithsep etc... are all declared long. 'sep' does not have to be a +% single token. It is not expanded.| +% \begin{macrocode} +\def\xintListWithSep {\romannumeral0\xintlistwithsep }% +\def\xintListWithSepNoExpand {\romannumeral0\xintlistwithsepnoexpand }% +\long\def\xintlistwithsep #1#2% + {\expandafter\XINT_lws\expandafter {\romannumeral-`0#2}{#1}}% +\long\def\XINT_lws #1#2{\XINT_lws_start {#2}#1\xint_bye }% +\long\def\xintlistwithsepnoexpand #1#2{\XINT_lws_start {#1}#2\xint_bye }% +\long\def\XINT_lws_start #1#2% {% - \expandafter\expandafter\expandafter - \XINT_forever_opt_c\expandafter\the\expandafter\XINT_toks - \romannumeral-`0#1{#4}{#5}#3% + \xint_bye #2\XINT_lws_dont\xint_bye + \XINT_lws_loop_a {#2}{#1}% }% -\long\def\XINT_forever_opt_c #1#2#3#4#5#6{\XINT_forever_d #2{#4}{#5}#6{#3}Z}% -\long\def\XINT_forever_d #1#2#3#4#5% +\long\def\XINT_lws_dont\xint_bye\XINT_lws_loop_a #1#2{ }% +\long\def\XINT_lws_loop_a #1#2#3% {% - \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#5}% - \XINT_toks {{#2}}% - \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname - \the\XINT_toks \csname XINT_for_right#1\endcsname }% - \XINT_x - \let\xintifForFirst\xint_secondoftwo - \expandafter\XINT_forever_d\expandafter #1\romannumeral-`0#4{#2}{#3}#4{#5}% + \xint_bye #3\XINT_lws_end\xint_bye + \XINT_lws_loop_b {#1}{#2#3}{#2}% }% +\long\def\XINT_lws_loop_b #1#2{\XINT_lws_loop_a {#1#2}}% +\long\def\XINT_lws_end\xint_bye\XINT_lws_loop_b #1#2#3{ #1}% % \end{macrocode} -% \subsection{\csh{xintForpair}, \csh{xintForthree}, \csh{xintForfour}} -% \lverb|1.09c. -% -% [2013/11/02] 1.09f \xintForpair delegate to \xintCSVtoList and its -% \xintZapSpacesB the handling of spaces. Does not share code with \xintFor -% anymore. +% \subsection{\csh{xintNthElt}} +% \lverb+First included in release 1.06. % -% [2013/11/03] 1.09f: \xintForpair extended to accept #1#2, #2#3 etc... up to -% #8#9, \xintForthree, #1#2#3 up to #7#8#9, \xintForfour id. | +% \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 +% first f-expanded. The \xintNthEltNoExpand does no expansion of its second +% argument. Both variants expand the first argument inside \numexpr. +% +% With i = 0, the number of items is returned. This is different from \xintLen +% 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.+ % \begin{macrocode} -\catcode`j 3 -\long\def\xintForpair #1#2#3in#4#5#6% +\def\xintNthElt {\romannumeral0\xintnthelt }% +\def\xintNthEltNoExpand {\romannumeral0\xintntheltnoexpand }% +\def\xintnthelt #1#2% {% - \let\xintifForFirst\xint_firstoftwo - \XINT_toks {\XINT_forpair_d #2{#6}}% - \expandafter\the\expandafter\XINT_toks #4jZ% + \expandafter\XINT_nthelt_a\the\numexpr #1\expandafter.% + \expandafter{\romannumeral-`0#2}% }% -\long\def\XINT_forpair_d #1#2#3(#4)#5% +\def\xintntheltnoexpand #1% {% - \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#2}% - \XINT_toks \expandafter{\romannumeral0\xintcsvtolist{ #4}}% - \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname - \the\XINT_toks \csname XINT_for_right\the\numexpr#1+\xint_c_i\endcsname}% - \let\xintifForLast\xint_secondoftwo - \ifx #5j\expandafter\xint_firstoftwo - \else\expandafter\xint_secondoftwo - \fi - {\let\xintifForLast\xint_firstoftwo - \xintBreakForAndDo {\XINT_x \xint_gobble_i Z}}% - \XINT_x - \let\xintifForFirst\xint_secondoftwo\XINT_forpair_d #1{#2}% + \expandafter\XINT_nthelt_a\the\numexpr #1.% }% -\long\def\xintForthree #1#2#3in#4#5#6% +\def\XINT_nthelt_a #1#2.% {% - \let\xintifForFirst\xint_firstoftwo - \XINT_toks {\XINT_forthree_d #2{#6}}% - \expandafter\the\expandafter\XINT_toks #4jZ% + \xint_UDzerominusfork + #1-{\XINT_nthelt_bzero}% + 0#1{\XINT_nthelt_bneg {#2}}% + 0-{\XINT_nthelt_bpos {#1#2}}% + \krof }% -\long\def\XINT_forthree_d #1#2#3(#4)#5% +\long\def\XINT_nthelt_bzero #1% {% - \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#2}% - \XINT_toks \expandafter{\romannumeral0\xintcsvtolist{ #4}}% - \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname - \the\XINT_toks \csname XINT_for_right\the\numexpr#1+\xint_c_ii\endcsname}% - \let\xintifForLast\xint_secondoftwo - \ifx #5j\expandafter\xint_firstoftwo - \else\expandafter\xint_secondoftwo - \fi - {\let\xintifForLast\xint_firstoftwo - \xintBreakForAndDo {\XINT_x \xint_gobble_i Z}}% - \XINT_x - \let\xintifForFirst\xint_secondoftwo\XINT_forthree_d #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 }% -\long\def\xintForfour #1#2#3in#4#5#6% +\long\def\XINT_nthelt_bneg #1#2% {% - \let\xintifForFirst\xint_firstoftwo - \XINT_toks {\XINT_forfour_d #2{#6}}% - \expandafter\the\expandafter\XINT_toks #4jZ% + \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 }% -\long\def\XINT_forfour_d #1#2#3(#4)#5% +\long\def\XINT_nthelt_bpos #1#2% {% - \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#2}% - \XINT_toks \expandafter{\romannumeral0\xintcsvtolist{ #4}}% - \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname - \the\XINT_toks \csname XINT_for_right\the\numexpr#1+\xint_c_iii\endcsname}% - \let\xintifForLast\xint_secondoftwo - \ifx #5j\expandafter\xint_firstoftwo - \else\expandafter\xint_secondoftwo - \fi - {\let\xintifForLast\xint_firstoftwo - \xintBreakForAndDo {\XINT_x \xint_gobble_i Z}}% - \XINT_x - \let\xintifForFirst\xint_secondoftwo\XINT_forfour_d #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 }% -\catcode`Z 11 -\catcode`j 11 +\def\XINT_nthelt_loop_a #1% +{% + \ifnum #1>\xint_c_viii + \expandafter\XINT_nthelt_loop_b + \else + \XINT_nthelt_getit + \fi + {#1}% +}% +\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}% +}% +\def\XINT_nthelt_silentend #1\xint_bye { }% +\def\XINT_nthelt_getit\fi #1% +{% + \fi\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 + {\noexpand\xint_gob_til_xint_relax #1\noexpand\expandafter\space + \noexpand\xint_gobble_ii\xint_relax\space #1}% % \end{macrocode} -% \subsection{\csh{xintAssign}, \csh{xintAssignArray}, \csh{xintDigitsOf}} -% \lverb|\xintAssign {a}{b}..{z}\to\A\B...\Z resp. \xintAssignArray -% {a}{b}..{z}\to\U. +% \subsection{\csh{xintKeep}} +% \lverb+First included in release 1.09m. % -% \xintDigitsOf=\xintAssignArray. +% \xintKeep {i}{stuff f-expanding to {a}{b}...{z}} (or `tokens' abcd...z, +% but each naked token ends up braced in the output) returns (in two +% expansion steps) the first i elements from the list, which is first +% f-expanded. The i is expanded inside \numexpr. The variant +% \xintKeepNoExpand does not expand the list argument. % -% 1.1c 2015/09/12 has (belatedly) corrected some "features" of -% \xintAssign which didn't like the case of a space right before the "\to", or -% the case with the first token not an opening brace and the subsequent -% material containing brace groups. The new code handles gracefully these -% situations.| +% With i = 0, the empty sequence is returned. +% +% With i<0, the last |i| elements are returned (in the same order as in +% the original list). +% +% With |i| equal to or bigger than the length of the (f-expanded) list, +% the full list is returned.+ % \begin{macrocode} -\def\xintAssign{\def\XINT_flet_macro {\XINT_assign_fork}\XINT_flet_zapsp }% -\def\XINT_assign_fork +\def\xintKeep {\romannumeral0\xintkeep }% +\def\xintKeepNoExpand {\romannumeral0\xintkeepnoexpand }% +\def\xintkeep #1#2% {% - \let\XINT_assign_def\def - \ifx\XINT_token[\expandafter\XINT_assign_opt - \else\expandafter\XINT_assign_a - \fi + \expandafter\XINT_keep_a\the\numexpr #1\expandafter.% + \expandafter{\romannumeral-`0#2}% }% -\def\XINT_assign_opt [#1]% +\def\xintkeepnoexpand #1% {% - \ifcsname #1def\endcsname - \expandafter\let\expandafter\XINT_assign_def \csname #1def\endcsname - \else - \expandafter\let\expandafter\XINT_assign_def \csname xint#1def\endcsname - \fi - \XINT_assign_a + \expandafter\XINT_keep_a\the\numexpr #1.% }% -\long\def\XINT_assign_a #1\to +\def\XINT_keep_a #1#2.% {% - \def\XINT_flet_macro{\XINT_assign_b}% - \expandafter\XINT_flet_zapsp\romannumeral-`0#1\xint_relax\to + \xint_UDzerominusfork + #1-{\expandafter\space\xint_gobble_i }% + 0#1{\XINT_keep_bneg_a {#2}}% + 0-{\XINT_keep_bpos {#1#2}}% + \krof }% -\long\def\XINT_assign_b +\long\def\XINT_keep_bneg_a #1#2% {% - \ifx\XINT_token\bgroup - \expandafter\XINT_assign_c - \else\expandafter\XINT_assign_f - \fi + \expandafter\XINT_keep_bneg_b \the\numexpr \xintLength{#2}-#1.{#2}% }% -\long\def\XINT_assign_f #1\xint_relax\to #2% +\def\XINT_keep_bneg_b #1#2.% {% - \XINT_assign_def #2{#1}% + \xint_UDzerominusfork + #1-{\xint_firstofone_thenstop }% + 0#1{\xint_firstofone_thenstop }% + 0-{\XINT_trim_bpos {#1#2}}% + \krof }% -\long\def\XINT_assign_c #1% +\long\def\XINT_keep_bpos #1#2% {% - \def\xint_temp {#1}% - \ifx\xint_temp\xint_brelax - \expandafter\XINT_assign_e - \else - \expandafter\XINT_assign_d - \fi + \XINT_keep_loop_a {#1}{}#2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_bye }% -\long\def\XINT_assign_d #1\to #2% +\def\XINT_keep_loop_a #1% {% - \expandafter\XINT_assign_def\expandafter #2\expandafter{\xint_temp}% - \XINT_assign_c #1\to + \ifnum #1>\xint_c_vi + \expandafter\XINT_keep_loop_b + \else + \XINT_keep_finish + \fi + {#1}% }% -\def\XINT_assign_e #1\to {}% -\def\xintRelaxArray #1% +\long\def\XINT_keep_loop_b #1#2#3#4#5#6#7#8#9% {% - \edef\XINT_restoreescapechar {\escapechar\the\escapechar\relax}% - \escapechar -1 - \expandafter\def\expandafter\xint_arrayname\expandafter {\string #1}% - \XINT_restoreescapechar - \xintiloop [\csname\xint_arrayname 0\endcsname+-1] - \global - \expandafter\let\csname\xint_arrayname\xintiloopindex\endcsname\relax - \ifnum \xintiloopindex > \xint_c_ - \repeat - \global\expandafter\let\csname\xint_arrayname 00\endcsname\relax - \global\let #1\relax + \xint_gob_til_xint_relax #9\XINT_keep_enda\xint_relax + \expandafter\XINT_keep_loop_c\expandafter{\the\numexpr #1-\xint_c_vii}% + {{#3}{#4}{#5}{#6}{#7}{#8}{#9}}{#2}% }% -\def\xintAssignArray{\def\XINT_flet_macro {\XINT_assignarray_fork}% - \XINT_flet_zapsp }% -\def\XINT_assignarray_fork +\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 {% - \let\XINT_assignarray_def\def - \ifx\XINT_token[\expandafter\XINT_assignarray_opt - \else\expandafter\XINT_assignarray - \fi + \XINT_keep_endb #4\W\W\W\W\W\W\Z #2{#3}% }% -\def\XINT_assignarray_opt [#1]% +\def\XINT_keep_endb #1#2#3#4#5#6#7\Z {% - \ifcsname #1def\endcsname - \expandafter\let\expandafter\XINT_assignarray_def \csname #1def\endcsname - \else - \expandafter\let\expandafter\XINT_assignarray_def - \csname xint#1def\endcsname - \fi - \XINT_assignarray + \xint_gob_til_W + #1\XINT_keep_endc_ + #2\XINT_keep_endc_i + #3\XINT_keep_endc_ii + #4\XINT_keep_endc_iii + #5\XINT_keep_endc_iv + #6\XINT_keep_endc_v + \W\XINT_keep_endc_vi\Z }% -\long\def\XINT_assignarray #1\to #2% +\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 {% - \edef\XINT_restoreescapechar {\escapechar\the\escapechar\relax }% - \escapechar -1 - \expandafter\def\expandafter\xint_arrayname\expandafter {\string #2}% - \XINT_restoreescapechar - \def\xint_itemcount {0}% - \expandafter\XINT_assignarray_loop \romannumeral-`0#1\xint_relax - \csname\xint_arrayname 00\expandafter\endcsname - \csname\xint_arrayname 0\expandafter\endcsname - \expandafter {\xint_arrayname}#2% + \fi\XINT_keep_finish_loop_a {#1}{}{#3}{#4}{#5}{#6}{#7}{#8}\Z {#2}% }% -\long\def\XINT_assignarray_loop #1% +\def\XINT_keep_finish_loop_a #1% {% - \def\xint_temp {#1}% - \ifx\xint_brelax\xint_temp - \expandafter\def\csname\xint_arrayname 0\expandafter\endcsname - \expandafter{\the\numexpr\xint_itemcount}% - \expandafter\expandafter\expandafter\XINT_assignarray_end - \else - \expandafter\def\expandafter\xint_itemcount\expandafter - {\the\numexpr\xint_itemcount+\xint_c_i}% - \expandafter\XINT_assignarray_def - \csname\xint_arrayname\xint_itemcount\expandafter\endcsname - \expandafter{\xint_temp }% - \expandafter\XINT_assignarray_loop - \fi + \xint_gob_til_zero #1\XINT_keep_finish_z0% + \expandafter\XINT_keep_finish_loop_b\expandafter + {\the\numexpr #1-\xint_c_i}% }% -\def\XINT_assignarray_end #1#2#3#4% +\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% {% - \def #4##1% - {% - \romannumeral0\expandafter #1\expandafter{\the\numexpr ##1}% - }% - \def #1##1% - {% - \ifnum ##1<\xint_c_ - \xint_afterfi {\xintError:ArrayIndexIsNegative\space }% - \else - \xint_afterfi {% - \ifnum ##1>#2 - \xint_afterfi {\xintError:ArrayIndexBeyondLimit\space }% - \else\xint_afterfi - {\expandafter\expandafter\expandafter\space\csname #3##1\endcsname}% - \fi}% - \fi - }% + \xint_gob_til_xint_relax #3\XINT_keep_finish_exit\xint_relax + \XINT_keep_finish_loop_c {#1}{#2}{#3}% }% -\let\xintDigitsOf\xintAssignArray -\let\XINT_tmpa\relax \let\XINT_tmpb\relax \let\XINT_tmpc\relax -\XINT_restorecatcodes_endinput% +\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}}}% % \end{macrocode} -%\catcode`\<=0 \catcode`\>=11 \catcode`\*=11 \catcode`\/=11 -%\let\relax -%\def<*xintcore>{\catcode`\<=12 \catcode`\>=12 \catcode`\*=12 \catcode`\/=12 } -% -%<*xintcore> -% -% \StoreCodelineNo {xinttools} -% -% \section{Package \xintcorenameimp implementation} -% \label{sec:coreimp} -% -% \localtableofcontents -% -% Got split off from \xintnameimp with release |1.1| (macros |\XINT_SQ|, -% |\xintLDg|, |\xintHalf| which are dependencies of |\XINT_div_prepare| were -% forgotten and they were added to the package only later with |1.1b|). -% Release |1.1| also added the new macro |\xintiiDivRound|. The package does -% not load \xinttoolsnameimp. -% -% Since release |xint 1.09a| the macros doing arithmetic operations -% apply systematically |\xintnum| to their arguments; this adds a little -% overhead but this is more convenient for using count registers even -% with infix notation; also this is what |xintfrac.sty| did all along. -% It simplifies the discussion in the documentation too. +% \subsection{\csh{xintTrim}} +% \lverb+First included in release 1.09m. % -% \subsection{Catcodes, \protect\eTeX{} and reload detection} +% \xintTrim {i}{stuff f-expanding to {a}{b}...{z}} (or `tokens' abcd...z, +% but each naked token ends up braced in the output) returns (in two +% expansion steps) the sequence with the first i elements omitted. The +% list is first f-expanded. The i is expanded inside \numexpr. Variant +% \xintTrimNoExpand does not expand the list argument. % -% The code for reload detection was initially copied from \textsc{Heiko -% Oberdiek}'s packages, then modified. +% With i = 0, the original (expanded) list is returned. % -% The method for catcodes was also initially directly inspired by these -% packages. +% With i<0, the last |i| elements from the tail are suppressed. % +% With |i| equal to or bigger than the length of the (f-expanded) list, +% the empty list is returned.+ % \begin{macrocode} -\begingroup\catcode61\catcode48\catcode32=10\relax% - \catcode13=5 % ^^M - \endlinechar=13 % - \catcode123=1 % { - \catcode125=2 % } - \catcode64=11 % @ - \catcode35=6 % # - \catcode44=12 % , - \catcode45=12 % - - \catcode46=12 % . - \catcode58=12 % : - \let\z\endgroup - \expandafter\let\expandafter\x\csname ver@xintcore.sty\endcsname - \expandafter\let\expandafter\w\csname ver@xintkernel.sty\endcsname - \expandafter - \ifx\csname PackageInfo\endcsname\relax - \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% - \else - \def\y#1#2{\PackageInfo{#1}{#2}}% - \fi - \expandafter - \ifx\csname numexpr\endcsname\relax - \y{xintcore}{\numexpr not available, aborting input}% - \aftergroup\endinput - \else - \ifx\x\relax % plain-TeX, first loading of xintcore.sty - \ifx\w\relax % but xintkernel.sty not yet loaded. - \def\z{\endgroup\input xintkernel.sty\relax}% - \fi +\def\xintTrim {\romannumeral0\xinttrim }% +\def\xintTrimNoExpand {\romannumeral0\xinttrimnoexpand }% +\def\xinttrim #1#2% +{% + \expandafter\XINT_trim_a\the\numexpr #1\expandafter.% + \expandafter{\romannumeral-`0#2}% +}% +\def\xinttrimnoexpand #1% +{% + \expandafter\XINT_trim_a\the\numexpr #1.% +}% +\def\XINT_trim_a #1#2.% +{% + \xint_UDzerominusfork + #1-{\xint_firstofone_thenstop }% + 0#1{\XINT_trim_bneg_a {#2}}% + 0-{\XINT_trim_bpos {#1#2}}% + \krof +}% +\long\def\XINT_trim_bneg_a #1#2% +{% + \expandafter\XINT_trim_bneg_b \the\numexpr \xintLength{#2}-#1.{#2}% +}% +\def\XINT_trim_bneg_b #1#2.% +{% + \xint_UDzerominusfork + #1-{\expandafter\space\xint_gobble_i }% + 0#1{\expandafter\space\xint_gobble_i }% + 0-{\XINT_keep_bpos {#1#2}}% + \krof +}% +\long\def\XINT_trim_bpos #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 +}% +\def\XINT_trim_loop_a #1% +{% + \ifnum #1>\xint_c_vii + \expandafter\XINT_trim_loop_b \else - \def\empty {}% - \ifx\x\empty % LaTeX, first loading, - % variable is initialized, but \ProvidesPackage not yet seen - \ifx\w\relax % xintkernel.sty not yet loaded. - \def\z{\endgroup\RequirePackage{xintkernel}}% - \fi - \else - \aftergroup\endinput % xintkernel already loaded. - \fi + \XINT_trim_finish \fi - \fi -\z% -\XINTsetupcatcodes% defined in xintkernel.sty + {#1}% +}% +\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}% +}% +\def\XINT_trim_silentend #1\xint_bye { }% +\def\XINT_trim_finish\fi #1% +{% + \fi\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{Package identification} +% \subsection{\csh{xintApply}} +% \lverb|\xintApply {\macro}{{a}{b}...{z}} returns {\macro{a}}...{\macro{b}} +% where each instance of \macro is f-expanded. The list itself is first +% f-expanded and may thus be a macro. Introduced with release 1.04.| % \begin{macrocode} -\XINT_providespackage -\ProvidesPackage{xintcore}% - [2015/09/12 v1.1c Expandable arithmetic on big integers (jfB)]% +\def\xintApply {\romannumeral0\xintapply }% +\def\xintApplyNoExpand {\romannumeral0\xintapplynoexpand }% +\long\def\xintapply #1#2% +{% + \expandafter\XINT_apply\expandafter {\romannumeral-`0#2}% + {#1}% +}% +\long\def\XINT_apply #1#2{\XINT_apply_loop_a {}{#2}#1\xint_bye }% +\long\def\xintapplynoexpand #1#2{\XINT_apply_loop_a {}{#1}#2\xint_bye }% +\long\def\XINT_apply_loop_a #1#2#3% +{% + \xint_bye #3\XINT_apply_end\xint_bye + \expandafter + \XINT_apply_loop_b + \expandafter {\romannumeral-`0#2{#3}}{#1}{#2}% +}% +\long\def\XINT_apply_loop_b #1#2{\XINT_apply_loop_a {#2{#1}}}% +\long\def\XINT_apply_end\xint_bye\expandafter\XINT_apply_loop_b + \expandafter #1#2#3{ #2}% % \end{macrocode} -% \subsection{More token management, constants} +% \subsection{\csh{xintApplyUnbraced}} +% \lverb|\xintApplyUnbraced {\macro}{{a}{b}...{z}} returns \macro{a}...\macro{z} +% where each instance of \macro is f-expanded using \romannumeral-`0. The second +% argument may be a macro as it is itself also f-expanded. No braces +% are added: this allows for example a non-expandable \def in \macro, without +% having to do \gdef. Introduced with release 1.06b.| % \begin{macrocode} -\def\xint_minus_thenstop { -}% -\def\xint_gob_til_zeros_iii #1000{}% -\def\xint_gob_til_zeros_iv #10000{}% -\def\xint_gob_til_one #11{}% -\def\xint_gob_til_G #1G{}% -\def\xint_gob_til_minus #1-{}% -\def\xint_gob_til_relax #1\relax {}% -\def\xint_exchangetwo_keepbraces #1#2{{#2}{#1}}% -\def\xint_exchangetwo_keepbraces_thenstop #1#2{ {#2}{#1}}% -\def\xint_UDzerofork #10#2#3\krof {#2}% -\def\xint_UDsignfork #1-#2#3\krof {#2}% -\def\xint_UDwfork #1\W#2#3\krof {#2}% -\def\xint_UDzerosfork #100#2#3\krof {#2}% -\def\xint_UDonezerofork #110#2#3\krof {#2}% -\def\xint_UDsignsfork #1--#2#3\krof {#2}% -\chardef\xint_c_ix 9 -\chardef\xint_c_x 10 -\chardef\xint_c_ii^v 32 % not used in xint, common to xintfrac and xintbinhex -\chardef\xint_c_ii^vi 64 -\mathchardef\xint_c_ixixixix 9999 -\mathchardef\xint_c_x^iv 10000 -\newcount\xint_c_x^viii \xint_c_x^viii 100000000 +\def\xintApplyUnbraced {\romannumeral0\xintapplyunbraced }% +\def\xintApplyUnbracedNoExpand {\romannumeral0\xintapplyunbracednoexpand }% +\long\def\xintapplyunbraced #1#2% +{% + \expandafter\XINT_applyunbr\expandafter {\romannumeral-`0#2}% + {#1}% +}% +\long\def\XINT_applyunbr #1#2{\XINT_applyunbr_loop_a {}{#2}#1\xint_bye }% +\long\def\xintapplyunbracednoexpand #1#2% + {\XINT_applyunbr_loop_a {}{#1}#2\xint_bye }% +\long\def\XINT_applyunbr_loop_a #1#2#3% +{% + \xint_bye #3\XINT_applyunbr_end\xint_bye + \expandafter\XINT_applyunbr_loop_b + \expandafter {\romannumeral-`0#2{#3}}{#1}{#2}% +}% +\long\def\XINT_applyunbr_loop_b #1#2{\XINT_applyunbr_loop_a {#2#1}}% +\long\def\XINT_applyunbr_end\xint_bye\expandafter\XINT_applyunbr_loop_b + \expandafter #1#2#3{ #2}% % \end{macrocode} -% \subsection{\csh{XINT_RQ}} -% \lverb|Cette macro renverse et ajoute le nombre minimal de zéros à -% la fin pour que la longueur soit alors multiple de 4$\ -% \romannumeral0\XINT_RQ {}\R\R\R\R\R\R\R\R\Z$\ -% Attention, ceci n'est utilisé que pour des chaînes de chiffres, et donc le -% comportement avec des {..} ou autres espaces n'a fait l'objet d'aucune -% attention.| +% \subsection{\csh{xintSeq}} +% \lverb|1.09c. Without the optional argument puts stress on the input stack, +% should not be used to generated thousands of terms then.| % \begin{macrocode} -\def\XINT_RQ #1#2#3#4#5#6#7#8#9% +\def\xintSeq {\romannumeral0\xintseq }% +\def\xintseq #1{\XINT_seq_chkopt #1\xint_bye }% +\def\XINT_seq_chkopt #1% +{% + \ifx [#1\expandafter\XINT_seq_opt + \else\expandafter\XINT_seq_noopt + \fi #1% +}% +\def\XINT_seq_noopt #1\xint_bye #2% {% - \xint_gob_til_R #9\XINT_RQ_end_a\R\XINT_RQ {#9#8#7#6#5#4#3#2#1}% + \expandafter\XINT_seq\expandafter + {\the\numexpr#1\expandafter}\expandafter{\the\numexpr #2}% }% -\def\XINT_RQ_end_a\R\XINT_RQ #1#2\Z +\def\XINT_seq #1#2% {% - \XINT_RQ_end_b #1\Z + \ifcase\ifnum #1=#2 0\else\ifnum #2>#1 1\else -1\fi\fi\space + \expandafter\xint_firstoftwo_thenstop + \or + \expandafter\XINT_seq_p + \else + \expandafter\XINT_seq_n + \fi + {#2}{#1}% }% -\def\XINT_RQ_end_b #1#2#3#4#5#6#7#8% +\def\XINT_seq_p #1#2% {% - \xint_gob_til_R - #8\XINT_RQ_end_viii - #7\XINT_RQ_end_vii - #6\XINT_RQ_end_vi - #5\XINT_RQ_end_v - #4\XINT_RQ_end_iv - #3\XINT_RQ_end_iii - #2\XINT_RQ_end_ii - \R\XINT_RQ_end_i - \Z #2#3#4#5#6#7#8% + \ifnum #1>#2 + \expandafter\expandafter\expandafter\XINT_seq_p + \else + \expandafter\XINT_seq_e + \fi + \expandafter{\the\numexpr #1-\xint_c_i}{#2}{#1}% }% -\def\XINT_RQ_end_viii #1\Z #2#3#4#5#6#7#8#9\Z { #9}% -\def\XINT_RQ_end_vii #1\Z #2#3#4#5#6#7#8#9\Z { #8#9000}% -\def\XINT_RQ_end_vi #1\Z #2#3#4#5#6#7#8#9\Z { #7#8#900}% -\def\XINT_RQ_end_v #1\Z #2#3#4#5#6#7#8#9\Z { #6#7#8#90}% -\def\XINT_RQ_end_iv #1\Z #2#3#4#5#6#7#8#9\Z { #5#6#7#8#9}% -\def\XINT_RQ_end_iii #1\Z #2#3#4#5#6#7#8#9\Z { #4#5#6#7#8#9000}% -\def\XINT_RQ_end_ii #1\Z #2#3#4#5#6#7#8#9\Z { #3#4#5#6#7#8#900}% -\def\XINT_RQ_end_i \Z #1#2#3#4#5#6#7#8\Z { #1#2#3#4#5#6#7#80}% -% \end{macrocode} -% \subsection{\csh{XINT_OQ}} -% \begin{macrocode} -\def\XINT_OQ #1#2#3#4#5#6#7#8#9% +\def\XINT_seq_n #1#2% {% - \xint_gob_til_R #9\XINT_OQ_end_a\R\XINT_OQ {#9#8#7#6#5#4#3#2#1}% + \ifnum #1<#2 + \expandafter\expandafter\expandafter\XINT_seq_n + \else + \expandafter\XINT_seq_e + \fi + \expandafter{\the\numexpr #1+\xint_c_i}{#2}{#1}% }% -\def\XINT_OQ_end_a\R\XINT_OQ #1#2\Z +\def\XINT_seq_e #1#2#3{ }% +\def\XINT_seq_opt [\xint_bye #1]#2#3% {% - \XINT_OQ_end_b #1\Z + \expandafter\XINT_seqo\expandafter + {\the\numexpr #2\expandafter}\expandafter + {\the\numexpr #3\expandafter}\expandafter + {\the\numexpr #1}% }% -\def\XINT_OQ_end_b #1#2#3#4#5#6#7#8% +\def\XINT_seqo #1#2% {% - \xint_gob_til_R - #8\XINT_OQ_end_viii - #7\XINT_OQ_end_vii - #6\XINT_OQ_end_vi - #5\XINT_OQ_end_v - #4\XINT_OQ_end_iv - #3\XINT_OQ_end_iii - #2\XINT_OQ_end_ii - \R\XINT_OQ_end_i - \Z #2#3#4#5#6#7#8% + \ifcase\ifnum #1=#2 0\else\ifnum #2>#1 1\else -1\fi\fi\space + \expandafter\XINT_seqo_a + \or + \expandafter\XINT_seqo_pa + \else + \expandafter\XINT_seqo_na + \fi + {#1}{#2}% }% -\def\XINT_OQ_end_viii #1\Z #2#3#4#5#6#7#8#9\Z { #9}% -\def\XINT_OQ_end_vii #1\Z #2#3#4#5#6#7#8#9\Z { #8#90000000}% -\def\XINT_OQ_end_vi #1\Z #2#3#4#5#6#7#8#9\Z { #7#8#9000000}% -\def\XINT_OQ_end_v #1\Z #2#3#4#5#6#7#8#9\Z { #6#7#8#900000}% -\def\XINT_OQ_end_iv #1\Z #2#3#4#5#6#7#8#9\Z { #5#6#7#8#90000}% -\def\XINT_OQ_end_iii #1\Z #2#3#4#5#6#7#8#9\Z { #4#5#6#7#8#9000}% -\def\XINT_OQ_end_ii #1\Z #2#3#4#5#6#7#8#9\Z { #3#4#5#6#7#8#900}% -\def\XINT_OQ_end_i \Z #1#2#3#4#5#6#7#8\Z { #1#2#3#4#5#6#7#80}% -% \end{macrocode} -% \subsection{\csh{XINT_SQ}} -% \begin{macrocode} -\def\XINT_SQ #1#2#3#4#5#6#7#8% +\def\XINT_seqo_a #1#2#3{ {#1}}% +\def\XINT_seqo_o #1#2#3#4{ #4}% +\def\XINT_seqo_pa #1#2#3% {% - \xint_gob_til_R #8\XINT_SQ_end_a\R\XINT_SQ {#8#7#6#5#4#3#2#1}% + \ifcase\ifnum #3=\xint_c_ 0\else\ifnum #3>\xint_c_ 1\else -1\fi\fi\space + \expandafter\XINT_seqo_o + \or + \expandafter\XINT_seqo_pb + \else + \xint_afterfi{\expandafter\space\xint_gobble_iv}% + \fi + {#1}{#2}{#3}{{#1}}% }% -\def\XINT_SQ_end_a\R\XINT_SQ #1#2\Z +\def\XINT_seqo_pb #1#2#3% {% - \XINT_SQ_end_b #1\Z + \expandafter\XINT_seqo_pc\expandafter{\the\numexpr #1+#3}{#2}{#3}% }% -\def\XINT_SQ_end_b #1#2#3#4#5#6#7% +\def\XINT_seqo_pc #1#2% {% - \xint_gob_til_R - #7\XINT_SQ_end_vii - #6\XINT_SQ_end_vi - #5\XINT_SQ_end_v - #4\XINT_SQ_end_iv - #3\XINT_SQ_end_iii - #2\XINT_SQ_end_ii - \R\XINT_SQ_end_i - \Z #2#3#4#5#6#7% -}% -\def\XINT_SQ_end_vii #1\Z #2#3#4#5#6#7#8\Z { #8}% -\def\XINT_SQ_end_vi #1\Z #2#3#4#5#6#7#8\Z { #7#8000000}% -\def\XINT_SQ_end_v #1\Z #2#3#4#5#6#7#8\Z { #6#7#800000}% -\def\XINT_SQ_end_iv #1\Z #2#3#4#5#6#7#8\Z { #5#6#7#80000}% -\def\XINT_SQ_end_iii #1\Z #2#3#4#5#6#7#8\Z { #4#5#6#7#8000}% -\def\XINT_SQ_end_ii #1\Z #2#3#4#5#6#7#8\Z { #3#4#5#6#7#800}% -\def\XINT_SQ_end_i \Z #1#2#3#4#5#6#7\Z { #1#2#3#4#5#6#70}% -% \end{macrocode} -% \subsection{\csh{XINT_cuz}} -% \begin{macrocode} -\edef\xint_cleanupzeros_andstop #1#2#3#4% + \ifnum #1>#2 + \expandafter\XINT_seqo_o + \else + \expandafter\XINT_seqo_pd + \fi + {#1}{#2}% +}% +\def\XINT_seqo_pd #1#2#3#4{\XINT_seqo_pb {#1}{#2}{#3}{#4{#1}}}% +\def\XINT_seqo_na #1#2#3% {% - \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4\relax + \ifcase\ifnum #3=\xint_c_ 0\else\ifnum #3>\xint_c_ 1\else -1\fi\fi\space + \expandafter\XINT_seqo_o + \or + \xint_afterfi{\expandafter\space\xint_gobble_iv}% + \else + \expandafter\XINT_seqo_nb + \fi + {#1}{#2}{#3}{{#1}}% }% -\def\xint_cleanupzeros_nostop #1#2#3#4% +\def\XINT_seqo_nb #1#2#3% {% - \the\numexpr #1#2#3#4\relax + \expandafter\XINT_seqo_nc\expandafter{\the\numexpr #1+#3}{#2}{#3}% }% -\def\XINT_rev_andcuz #1% +\def\XINT_seqo_nc #1#2% {% - \expandafter\xint_cleanupzeros_andstop - \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 + \ifnum #1<#2 + \expandafter\XINT_seqo_o + \else + \expandafter\XINT_seqo_nd + \fi + {#1}{#2}% }% +\def\XINT_seqo_nd #1#2#3#4{\XINT_seqo_nb {#1}{#2}{#3}{#4{#1}}}% +% \end{macrocode} +%\subsection{\csh{xintloop}, \csh{xintbreakloop}, \csh{xintbreakloopanddo}, +% \csh{xintloopskiptonext}} +% \lverb|1.09g [2013/11/22]. Made long with 1.09h.| +% \begin{macrocode} +\long\def\xintloop #1#2\repeat {#1#2\xintloop_again\fi\xint_gobble_i {#1#2}}% +\long\def\xintloop_again\fi\xint_gobble_i #1{\fi + #1\xintloop_again\fi\xint_gobble_i {#1}}% +\long\def\xintbreakloop #1\xintloop_again\fi\xint_gobble_i #2{}% +\long\def\xintbreakloopanddo #1#2\xintloop_again\fi\xint_gobble_i #3{#1}% +\long\def\xintloopskiptonext #1\xintloop_again\fi\xint_gobble_i #2{% + #2\xintloop_again\fi\xint_gobble_i {#2}}% % \end{macrocode} -% \lverb|& -% routine CleanUpZeros. Utilisée en particulier par la -% soustraction.$\ -% INPUT: longueur **multiple de 4** (<-- ATTENTION)$\ -% OUTPUT: on a retiré tous les leading zéros, on n'est **plus* -% nécessairement de longueur 4n$\ -% Délimiteur pour _main: \W\W\W\W\W\W\W\Z avec SEPT \W| +% \subsection{\csh{xintiloop}, \csh{xintiloopindex}, \csh{xintouteriloopindex}, +% \csh{xintbreakiloop}, \csh{xintbreakiloopanddo}, \csh{xintiloopskiptonext}, +% \csh{xintiloopskipandredo}} +% \lverb|1.09g [2013/11/22]. Made long with 1.09h.| +% \begin{macrocode} +\def\xintiloop [#1+#2]{% + \expandafter\xintiloop_a\the\numexpr #1\expandafter.\the\numexpr #2.}% +\long\def\xintiloop_a #1.#2.#3#4\repeat{% + #3#4\xintiloop_again\fi\xint_gobble_iii {#1}{#2}{#3#4}}% +\def\xintiloop_again\fi\xint_gobble_iii #1#2{% + \fi\expandafter\xintiloop_again_b\the\numexpr#1+#2.#2.}% +\long\def\xintiloop_again_b #1.#2.#3{% + #3\xintiloop_again\fi\xint_gobble_iii {#1}{#2}{#3}}% +\long\def\xintbreakiloop #1\xintiloop_again\fi\xint_gobble_iii #2#3#4{}% +\long\def\xintbreakiloopanddo + #1.#2\xintiloop_again\fi\xint_gobble_iii #3#4#5{#1}% +\long\def\xintiloopindex #1\xintiloop_again\fi\xint_gobble_iii #2% + {#2#1\xintiloop_again\fi\xint_gobble_iii {#2}}% +\long\def\xintouteriloopindex #1\xintiloop_again + #2\xintiloop_again\fi\xint_gobble_iii #3% + {#3#1\xintiloop_again #2\xintiloop_again\fi\xint_gobble_iii {#3}}% +\long\def\xintiloopskiptonext #1\xintiloop_again\fi\xint_gobble_iii #2#3{% + \expandafter\xintiloop_again_b \the\numexpr#2+#3.#3.}% +\long\def\xintiloopskipandredo #1\xintiloop_again\fi\xint_gobble_iii #2#3#4{% + #4\xintiloop_again\fi\xint_gobble_iii {#2}{#3}{#4}}% +% \end{macrocode} +% \subsection{\csh{XINT_xflet}} +% \lverb|1.09e [2013/10/29]: we f-expand unbraced tokens and swallow arising +% space tokens until the dust settles.| % \begin{macrocode} -\def\XINT_cuz #1% +\def\XINT_xflet #1% {% - \XINT_cuz_loop #1\W\W\W\W\W\W\W\Z% + \def\XINT_xflet_macro {#1}\XINT_xflet_zapsp }% -\def\XINT_cuz_loop #1#2#3#4#5#6#7#8% +\def\XINT_xflet_zapsp {% - \xint_gob_til_W #8\xint_cuz_end_a\W - \xint_gob_til_Z #8\xint_cuz_end_A\Z - \XINT_cuz_check_a {#1#2#3#4#5#6#7#8}% + \expandafter\futurelet\expandafter\XINT_token + \expandafter\XINT_xflet_sp?\romannumeral-`0% }% -\def\xint_cuz_end_a #1\XINT_cuz_check_a #2% +\def\XINT_xflet_sp? {% - \xint_cuz_end_b #2% + \ifx\XINT_token\XINT_sptoken + \expandafter\XINT_xflet_zapsp + \else\expandafter\XINT_xflet_zapspB + \fi }% -\edef\xint_cuz_end_b #1#2#3#4#5\Z +\def\XINT_xflet_zapspB {% - \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4\relax + \expandafter\futurelet\expandafter\XINT_tokenB + \expandafter\XINT_xflet_spB?\romannumeral-`0% }% -\def\xint_cuz_end_A \Z\XINT_cuz_check_a #1{ 0}% -\def\XINT_cuz_check_a #1% +\def\XINT_xflet_spB? {% - \expandafter\XINT_cuz_check_b\the\numexpr #1\relax + \ifx\XINT_tokenB\XINT_sptoken + \expandafter\XINT_xflet_zapspB + \else\expandafter\XINT_xflet_eq? + \fi }% -\def\XINT_cuz_check_b #1% +\def\XINT_xflet_eq? {% - \xint_gob_til_zero #1\xint_cuz_backtoloop 0\XINT_cuz_stop #1% + \ifx\XINT_token\XINT_tokenB + \expandafter\XINT_xflet_macro + \else\expandafter\XINT_xflet_zapsp + \fi }% -\def\XINT_cuz_stop #1\W #2\Z{ #1}% -\def\xint_cuz_backtoloop 0\XINT_cuz_stop 0{\XINT_cuz_loop }% % \end{macrocode} -% \subsection{\csh{xintNum}} -% \lverb|& -% For example \xintNum {----+-+++---+----000000000000003}$\ -% 1.05 defines \xintiNum, which allows redefinition of \xintNum by xintfrac.sty -% Slightly modified in 1.06b (\R->\xint_relax) to avoid initial re-scan of -% input stack (while still allowing empty #1). In versions earlier than 1.09a -% it was entirely up to the user to apply \xintnum; starting with 1.09a -% arithmetic -% macros of xint.sty (like earlier already xintfrac.sty with its own \xintnum) -% make use of \xintnum. This allows arguments to -% be count registers, or even \numexpr arbitrary long expressions (with the -% trick of braces, see the user documentation). +% \subsection{\csh{xintApplyInline}} +% \lverb|1.09a: \xintApplyInline\macro{{a}{b}...{z}} has the same effect as +% executing \macro{a} and then applying again \xintApplyInline to the shortened +% list {{b}...{z}} until nothing is left. This is a non-expandable command +% which will result in quicker code than using \xintApplyUnbraced. It f-expands +% its second (list) argument first, which may thus be encapsulated in a macro. % -% Note (22/06/14): \xintiNum jamais utilisé sous ce nom, le supprimer? -% \XINT_num maintenant utilisé par le parseur de xintexpr.| +% Rewritten in 1.09c. Nota bene: uses catcode 3 Z as privated list terminator.| % \begin{macrocode} -\def\xintiNum {\romannumeral0\xintinum }% -\def\xintinum #1% -{% - \expandafter\XINT_num_loop - \romannumeral-`0#1\xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_relax\Z -}% -\let\xintNum\xintiNum \let\xintnum\xintinum -\def\XINT_num #1% -{% - \XINT_num_loop #1\xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_relax\Z -}% -\def\XINT_num_loop #1#2#3#4#5#6#7#8% -{% - \xint_gob_til_xint_relax #8\XINT_num_end\xint_relax - \XINT_num_NumEight #1#2#3#4#5#6#7#8% -}% -\edef\XINT_num_end\xint_relax\XINT_num_NumEight #1\xint_relax #2\Z -{% - \noexpand\expandafter\space\noexpand\the\numexpr #1+\xint_c_\relax -}% -\def\XINT_num_NumEight #1#2#3#4#5#6#7#8% +\catcode`Z 3 +\long\def\xintApplyInline #1#2% {% - \ifnum \numexpr #1#2#3#4#5#6#7#8+\xint_c_= \xint_c_ - \xint_afterfi {\expandafter\XINT_num_keepsign_a - \the\numexpr #1#2#3#4#5#6#7#81\relax}% - \else - \xint_afterfi {\expandafter\XINT_num_finish - \the\numexpr #1#2#3#4#5#6#7#8\relax}% - \fi + \long\expandafter\def\expandafter\XINT_inline_macro + \expandafter ##\expandafter 1\expandafter {#1{##1}}% + \XINT_xflet\XINT_inline_b #2Z% this Z has catcode 3 }% -\def\XINT_num_keepsign_a #1% +\def\XINT_inline_b {% - \xint_gob_til_one#1\XINT_num_gobacktoloop 1\XINT_num_keepsign_b + \ifx\XINT_token Z\expandafter\xint_gobble_i + \else\expandafter\XINT_inline_d\fi }% -\def\XINT_num_gobacktoloop 1\XINT_num_keepsign_b {\XINT_num_loop }% -\def\XINT_num_keepsign_b #1{\XINT_num_loop -}% -\def\XINT_num_finish #1\xint_relax #2\Z { #1}% -% \end{macrocode} -% \subsection{\csh{xintSgn}, \csh{xintiiSgn}, \csh{XINT_Sgn}, \csh{XINT_cntSgn}} -% \lverb|& -% Changed in 1.05. Earlier code was unnecessarily strange. 1.09a with \xintnum -% -% 1.09i defines \XINT_Sgn and \XINT_cntSgn (was \XINT__Sgn in 1.09i) for reasons -% of internal optimizations. -% -% xintfrac.sty will overwrite \xintsgn with use of \xintraw rather than -% \xintnum, naturally.| -% \begin{macrocode} -\def\xintiiSgn {\romannumeral0\xintiisgn }% -\def\xintiisgn #1% +\long\def\XINT_inline_d #1% {% - \expandafter\XINT_sgn \romannumeral-`0#1\Z% + \long\def\XINT_item{{#1}}\XINT_xflet\XINT_inline_e }% -\def\xintSgn {\romannumeral0\xintsgn }% -\def\xintsgn #1% +\def\XINT_inline_e {% - \expandafter\XINT_sgn \romannumeral0\xintnum{#1}\Z% + \ifx\XINT_token Z\expandafter\XINT_inline_w + \else\expandafter\XINT_inline_f\fi }% -\def\XINT_sgn #1#2\Z +\def\XINT_inline_f {% - \xint_UDzerominusfork - #1-{ 0}% - 0#1{ -1}% - 0-{ 1}% - \krof + \expandafter\XINT_inline_g\expandafter{\XINT_inline_macro {##1}}% }% -\def\XINT_Sgn #1#2\Z +\long\def\XINT_inline_g #1% {% - \xint_UDzerominusfork - #1-{0}% - 0#1{-1}% - 0-{1}% - \krof + \expandafter\XINT_inline_macro\XINT_item + \long\def\XINT_inline_macro ##1{#1}\XINT_inline_d }% -\def\XINT_cntSgn #1#2\Z +\def\XINT_inline_w #1% {% - \xint_UDzerominusfork - #1-\xint_c_ - 0#1\m@ne % I will not allocate a count only for -1? - 0-\xint_c_i - \krof + \expandafter\XINT_inline_macro\XINT_item }% % \end{macrocode} -% \subsection{\csh{xintiOpp}} -% \lverb|\xintnum added in 1.09a| +% \subsection{\csh{xintFor}, \csh{xintFor*}, \csh{xintBreakFor}, \csh{xintBreakForAndDo}} +% \lverb|1.09c [2013/10/09]: a new kind of loop which uses macro parameters +% #1, #2, #3, #4 rather than macros; while not expandable it survives executing +% code closing groups, like what happens in an alignment with the $& character. +% When inserted in a macro for later use, the # character must be doubled. +% +% The non-star variant works on a csv list, which it expands once, the +% star variant works on a token list, which it (repeatedly) f-expands. +% +% 1.09e adds \XINT_forever with \xintintegers, \xintdimensions, \xintrationals +% and \xintBreakFor, \xintBreakForAndDo, \xintifForFirst, \xintifForLast. On +% this occasion \xint_firstoftwo and \xint_secondoftwo are made long. +% +% 1.09f: rewrites large parts of \xintFor code in order to filter the comma +% separated list via \xintCSVtoList which gets rid of spaces. The #1 in +% \XINT_for_forever? has an initial space token which serves two purposes: +% preventing brace stripping, and stopping the expansion made by \xintcsvtolist. +% If the \XINT_forever branch is taken, the added space will not be a problem +% there. +% +% 1.09f rewrites (2013/11/03) the code which now allows all macro parameters +% from #1 to #9 in \xintFor, \xintFor*, and \XINT_forever.| % \begin{macrocode} -\def\xintiiOpp {\romannumeral0\xintiiopp }% -\def\xintiiopp #1% -{% - \expandafter\XINT_opp \romannumeral-`0#1% -}% -\def\xintiOpp {\romannumeral0\xintiopp }% -\def\xintiopp #1% +\def\XINT_tmpa #1#2{\ifnum #2<#1 \xint_afterfi {{#########2}}\fi}% +\def\XINT_tmpb #1#2{\ifnum #1<#2 \xint_afterfi {{#########2}}\fi}% +\def\XINT_tmpc #1% {% - \expandafter\XINT_opp \romannumeral0\xintnum{#1}% + \expandafter\edef \csname XINT_for_left#1\endcsname + {\xintApplyUnbraced {\XINT_tmpa #1}{123456789}}% + \expandafter\edef \csname XINT_for_right#1\endcsname + {\xintApplyUnbraced {\XINT_tmpb #1}{123456789}}% }% -\let\xintOpp\xintiOpp \let\xintopp\xintiopp -\def\XINT_Opp #1{\romannumeral0\XINT_opp #1}% -\def\XINT_opp #1% +\xintApplyInline \XINT_tmpc {123456789}% +\long\def\xintBreakFor #1Z{}% +\long\def\xintBreakForAndDo #1#2Z{#1}% +\def\xintFor {\let\xintifForFirst\xint_firstoftwo + \futurelet\XINT_token\XINT_for_ifstar }% +\def\XINT_for_ifstar {\ifx\XINT_token*\expandafter\XINT_forx + \else\expandafter\XINT_for \fi }% +\catcode`U 3 % with numexpr +\catcode`V 3 % with xintfrac.sty (xint.sty not enough) +\catcode`D 3 % with dimexpr +\def\XINT_flet_zapsp {% - \xint_UDzerominusfork - #1-{ 0}% zero - 0#1{ }% negative - 0-{ -#1}% positive - \krof + \futurelet\XINT_token\XINT_flet_sp? }% -% \end{macrocode} -% \subsection{\csh{xintiAbs}, \csh{xintiiAbs}} -% \lverb|Release 1.09a has now \xintiabs which does \xintnum and this is -% inherited by DecSplit, by Sqr, and macros of xintgcd.sty. Attention, car ces -% macros de toute façon doivent passer à la valeur absolue et donc en profite -% pour faire le \xintnum, mais pour optimisation sans overhead il vaut mieux -% utiliser \xintiiAbs ou autre point d'accès.| -% \begin{macrocode} -\def\xintiiAbs {\romannumeral0\xintiiabs }% -\def\xintiiabs #1% +\def\XINT_flet_sp? {% - \expandafter\XINT_abs \romannumeral-`0#1% + \ifx\XINT_token\XINT_sptoken + \xint_afterfi{\expandafter\XINT_flet_zapsp\romannumeral0}% + \else\expandafter\XINT_flet_macro + \fi }% -\def\xintiAbs {\romannumeral0\xintiabs }% -\def\xintiabs #1% +\long\def\XINT_for #1#2in#3#4#5% {% - \expandafter\XINT_abs \romannumeral0\xintnum{#1}% + \expandafter\XINT_toks\expandafter + {\expandafter\XINT_for_d\the\numexpr #2\relax {#5}}% + \def\XINT_flet_macro {\expandafter\XINT_for_forever?\space}% + \expandafter\XINT_flet_zapsp #3Z% }% -\let\xintAbs\xintiAbs \let\xintabs\xintiabs -\def\XINT_Abs #1{\romannumeral0\XINT_abs #1}% -\def\XINT_abs #1% +\def\XINT_for_forever? #1Z% {% - \xint_UDsignfork - #1{ }% - -{ #1}% - \krof + \ifx\XINT_token U\XINT_to_forever\fi + \ifx\XINT_token V\XINT_to_forever\fi + \ifx\XINT_token D\XINT_to_forever\fi + \expandafter\the\expandafter\XINT_toks\romannumeral0\xintcsvtolist {#1}Z% }% -% \end{macrocode} -% \subsection{\csh{xintFDg}, \csh{xintiiFDg}} -% \lverb|& -% FIRST DIGIT. Code simplified in 1.05. -% And prepared for redefinition by xintfrac to parse through \xintNum. Version -% 1.09a inserts the \xintnum already here.| -% \begin{macrocode} -\def\xintiiFDg {\romannumeral0\xintiifdg }% -\def\xintiifdg #1% +\def\XINT_to_forever\fi #1\xintcsvtolist #2{\fi \XINT_forever #2}% +\long\def\XINT_forx *#1#2in#3#4#5% {% - \expandafter\XINT_fdg \romannumeral-`0#1\W\Z + \expandafter\XINT_toks\expandafter + {\expandafter\XINT_forx_d\the\numexpr #2\relax {#5}}% + \XINT_xflet\XINT_forx_forever? #3Z% }% -\def\xintFDg {\romannumeral0\xintfdg }% -\def\xintfdg #1% +\def\XINT_forx_forever? {% - \expandafter\XINT_fdg \romannumeral0\xintnum{#1}\W\Z + \ifx\XINT_token U\XINT_to_forxever\fi + \ifx\XINT_token V\XINT_to_forxever\fi + \ifx\XINT_token D\XINT_to_forxever\fi + \XINT_forx_empty? }% -\def\XINT_FDg #1{\romannumeral0\XINT_fdg #1\W\Z }% -\def\XINT_fdg #1#2#3\Z +\def\XINT_to_forxever\fi #1\XINT_forx_empty? {\fi \XINT_forever }% +\catcode`U 11 +\catcode`D 11 +\catcode`V 11 +\def\XINT_forx_empty? {% - \xint_UDzerominusfork - #1-{ 0}% zero - 0#1{ #2}% negative - 0-{ #1}% positive - \krof + \ifx\XINT_token Z\expandafter\xintBreakFor\fi + \the\XINT_toks }% -% \end{macrocode} -% \subsection{\csh{xintLDg}, \csh{xintiiLDg}} -% \lverb|& -% LAST DIGIT. Simplified in 1.05. And prepared for extension by xintfrac -% to parse through \xintNum. Release 1.09a adds the \xintnum already here, -% and this propagates to \xintOdd, etc... 1.09e The \xintiiLDg is for -% defining \xintiiOdd which is used once (currently) elsewhere . -% -% bug fix (1.1b): \xintiiLDg is needed by the division macros next, thus -% it needs to be in the xintcore.sty| -% \begin{macrocode} -\def\xintiiLDg {\romannumeral0\xintiildg }% -\def\xintiildg #1% +\long\def\XINT_for_d #1#2#3% {% - \expandafter\XINT_ldg\expandafter {\romannumeral-`0#1}% + \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#2}% + \XINT_toks {{#3}}% + \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname + \the\XINT_toks \csname XINT_for_right#1\endcsname }% + \XINT_toks {\XINT_x\let\xintifForFirst\xint_secondoftwo\XINT_for_d #1{#2}}% + \futurelet\XINT_token\XINT_for_last? }% -\def\xintLDg {\romannumeral0\xintldg }% -\def\xintldg #1% +\long\def\XINT_forx_d #1#2#3% {% - \expandafter\XINT_ldg\expandafter {\romannumeral0\xintnum{#1}}% + \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#2}% + \XINT_toks {{#3}}% + \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname + \the\XINT_toks \csname XINT_for_right#1\endcsname }% + \XINT_toks {\XINT_x\let\xintifForFirst\xint_secondoftwo\XINT_forx_d #1{#2}}% + \XINT_xflet\XINT_for_last? }% -\def\XINT_LDg #1{\romannumeral0\XINT_ldg {#1}}% -\def\XINT_ldg #1% +\def\XINT_for_last? {% - \expandafter\XINT_ldg_\romannumeral0\xintreverseorder {#1}\Z + \let\xintifForLast\xint_secondoftwo + \ifx\XINT_token Z\let\xintifForLast\xint_firstoftwo + \xint_afterfi{\xintBreakForAndDo{\XINT_x\xint_gobble_i Z}}\fi + \the\XINT_toks }% -\def\XINT_ldg_ #1#2\Z{ #1}% % \end{macrocode} -% \subsection{\csh{xintDouble}} -% \lverb|v1.08| +% \subsection{\csh{XINT_forever}, \csh{xintintegers}, \csh{xintdimensions}, \csh{xintrationals}} +% \lverb|New with 1.09e. But this used inadvertently \xintiadd/\xintimul which +% have the unnecessary \xintnum overhead. Changed in 1.09f to use +% \xintiiadd/\xintiimul which do not have this overhead. Also 1.09f uses +% \xintZapSpacesB for the \xintrationals case to get rid of leading and ending +% spaces in the #4 and #5 delimited parameters of \XINT_forever_opt_a +% (for \xintintegers and \xintdimensions this is not necessary, due to the use +% of \numexpr resp. \dimexpr in \XINT_?expr_Ua, resp.\XINT_?expr_Da).| % \begin{macrocode} -\def\xintDouble {\romannumeral0\xintdouble }% -\def\xintdouble #1% +\catcode`U 3 +\catcode`D 3 +\catcode`V 3 +\let\xintegers U% +\let\xintintegers U% +\let\xintdimensions D% +\let\xintrationals V% +\def\XINT_forever #1% {% - \expandafter\XINT_dbl\romannumeral-`0#1% - \R\R\R\R\R\R\R\Z \W\W\W\W\W\W\W + \expandafter\XINT_forever_a + \csname XINT_?expr_\ifx#1UU\else\ifx#1DD\else V\fi\fi a\expandafter\endcsname + \csname XINT_?expr_\ifx#1UU\else\ifx#1DD\else V\fi\fi i\expandafter\endcsname + \csname XINT_?expr_\ifx#1UU\else\ifx#1DD\else V\fi\fi \endcsname }% -\def\XINT_dbl #1% +\catcode`U 11 +\catcode`D 11 +\catcode`V 11 +\def\XINT_?expr_Ua #1#2% + {\expandafter{\expandafter\numexpr\the\numexpr #1\expandafter\relax + \expandafter\relax\expandafter}% + \expandafter{\the\numexpr #2}}% +\def\XINT_?expr_Da #1#2% + {\expandafter{\expandafter\dimexpr\number\dimexpr #1\expandafter\relax + \expandafter s\expandafter p\expandafter\relax\expandafter}% + \expandafter{\number\dimexpr #2}}% +\catcode`Z 11 +\def\XINT_?expr_Va #1#2% {% - \xint_UDzerominusfork - #1-\XINT_dbl_zero - 0#1\XINT_dbl_neg - 0-{\XINT_dbl_pos #1}% - \krof + \expandafter\XINT_?expr_Vb\expandafter + {\romannumeral-`0\xintrawwithzeros{\xintZapSpacesB{#2}}}% + {\romannumeral-`0\xintrawwithzeros{\xintZapSpacesB{#1}}}% }% -\def\XINT_dbl_zero #1\Z \W\W\W\W\W\W\W { 0}% -\def\XINT_dbl_neg - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_dbl_pos }% -\def\XINT_dbl_pos +\catcode`Z 3 +\def\XINT_?expr_Vb #1#2{\expandafter\XINT_?expr_Vc #2.#1.}% +\def\XINT_?expr_Vc #1/#2.#3/#4.% +{% + \xintifEq {#2}{#4}% + {\XINT_?expr_Vf {#3}{#1}{#2}}% + {\expandafter\XINT_?expr_Vd\expandafter + {\romannumeral0\xintiimul {#2}{#4}}% + {\romannumeral0\xintiimul {#1}{#4}}% + {\romannumeral0\xintiimul {#2}{#3}}% + }% +}% +\def\XINT_?expr_Vd #1#2#3{\expandafter\XINT_?expr_Ve\expandafter {#2}{#3}{#1}}% +\def\XINT_?expr_Ve #1#2{\expandafter\XINT_?expr_Vf\expandafter {#2}{#1}}% +\def\XINT_?expr_Vf #1#2#3{{#2/#3}{{0}{#1}{#2}{#3}}}% +\def\XINT_?expr_Ui {{\numexpr 1\relax}{1}}% +\def\XINT_?expr_Di {{\dimexpr 0pt\relax}{65536}}% +\def\XINT_?expr_Vi {{1/1}{0111}}% +\def\XINT_?expr_U #1#2% + {\expandafter{\expandafter\numexpr\the\numexpr #1+#2\relax\relax}{#2}}% +\def\XINT_?expr_D #1#2% + {\expandafter{\expandafter\dimexpr\the\numexpr #1+#2\relax sp\relax}{#2}}% +\def\XINT_?expr_V #1#2{\XINT_?expr_Vx #2}% +\def\XINT_?expr_Vx #1#2% {% - \expandafter\XINT_dbl_a \expandafter{\expandafter}\expandafter 0% - \romannumeral0\XINT_SQ {}% + \expandafter\XINT_?expr_Vy\expandafter + {\romannumeral0\xintiiadd {#1}{#2}}{#2}% }% -\def\XINT_dbl_a #1#2#3#4#5#6#7#8#9% +\def\XINT_?expr_Vy #1#2#3#4% {% - \xint_gob_til_W #9\XINT_dbl_end_a\W - \expandafter\XINT_dbl_b - \the\numexpr \xint_c_x^viii+#2+\xint_c_ii*#9#8#7#6#5#4#3\relax {#1}% + \expandafter{\romannumeral0\xintiiadd {#3}{#1}/#4}{{#1}{#2}{#3}{#4}}% }% -\def\XINT_dbl_b 1#1#2#3#4#5#6#7#8#9% +\def\XINT_forever_a #1#2#3#4% {% - \XINT_dbl_a {#2#3#4#5#6#7#8#9}{#1}% + \ifx #4[\expandafter\XINT_forever_opt_a + \else\expandafter\XINT_forever_b + \fi #1#2#3#4% }% -\def\XINT_dbl_end_a #1+#2+#3\relax #4% +\def\XINT_forever_b #1#2#3Z{\expandafter\XINT_forever_c\the\XINT_toks #2#3}% +\long\def\XINT_forever_c #1#2#3#4#5% + {\expandafter\XINT_forever_d\expandafter #2#4#5{#3}Z}% +\def\XINT_forever_opt_a #1#2#3[#4+#5]#6Z% {% - \expandafter\XINT_dbl_end_b #2#4% + \expandafter\expandafter\expandafter + \XINT_forever_opt_c\expandafter\the\expandafter\XINT_toks + \romannumeral-`0#1{#4}{#5}#3% }% -\edef\XINT_dbl_end_b #1#2#3#4#5#6#7#8% +\long\def\XINT_forever_opt_c #1#2#3#4#5#6{\XINT_forever_d #2{#4}{#5}#6{#3}Z}% +\long\def\XINT_forever_d #1#2#3#4#5% {% - \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5#6#7#8\relax + \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#5}% + \XINT_toks {{#2}}% + \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname + \the\XINT_toks \csname XINT_for_right#1\endcsname }% + \XINT_x + \let\xintifForFirst\xint_secondoftwo + \expandafter\XINT_forever_d\expandafter #1\romannumeral-`0#4{#2}{#3}#4{#5}% }% % \end{macrocode} -% \subsection{\csh{xintHalf}} -% \lverb|v1.08. Relase 1.1 left it in xint.sty, but it is needed by the -% division routines included in xintcore.sty. Thus moved here for bugfix -% release 1.1c. -% Also \XINT_SQ which it uses. Moved here \xintDouble as well by sympathy.| +% \subsection{\csh{xintForpair}, \csh{xintForthree}, \csh{xintForfour}} +% \lverb|1.09c. +% +% [2013/11/02] 1.09f \xintForpair delegate to \xintCSVtoList and its +% \xintZapSpacesB the handling of spaces. Does not share code with \xintFor +% anymore. +% +% [2013/11/03] 1.09f: \xintForpair extended to accept #1#2, #2#3 etc... up to +% #8#9, \xintForthree, #1#2#3 up to #7#8#9, \xintForfour id. | % \begin{macrocode} -\def\xintHalf {\romannumeral0\xinthalf }% -\def\xinthalf #1% -{% - \expandafter\XINT_half\romannumeral-`0#1% - \R\R\R\R\R\R\R\Z \W\W\W\W\W\W\W -}% -\def\XINT_half #1% +\catcode`j 3 +\long\def\xintForpair #1#2#3in#4#5#6% {% - \xint_UDzerominusfork - #1-\XINT_half_zero - 0#1\XINT_half_neg - 0-{\XINT_half_pos #1}% - \krof + \let\xintifForFirst\xint_firstoftwo + \XINT_toks {\XINT_forpair_d #2{#6}}% + \expandafter\the\expandafter\XINT_toks #4jZ% }% -\def\XINT_half_zero #1\Z \W\W\W\W\W\W\W { 0}% -\def\XINT_half_neg {\expandafter\XINT_opp\romannumeral0\XINT_half_pos }% -\def\XINT_half_pos {\expandafter\XINT_half_a\romannumeral0\XINT_SQ {}}% -\def\XINT_half_a #1#2#3#4#5#6#7#8% +\long\def\XINT_forpair_d #1#2#3(#4)#5% {% - \xint_gob_til_W #8\XINT_half_dont\W - \expandafter\XINT_half_b - \the\numexpr \xint_c_x^viii+\xint_c_v*#7#6#5#4#3#2#1\relax #8% + \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#2}% + \XINT_toks \expandafter{\romannumeral0\xintcsvtolist{ #4}}% + \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname + \the\XINT_toks \csname XINT_for_right\the\numexpr#1+\xint_c_i\endcsname}% + \let\xintifForLast\xint_secondoftwo + \ifx #5j\expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo + \fi + {\let\xintifForLast\xint_firstoftwo + \xintBreakForAndDo {\XINT_x \xint_gobble_i Z}}% + \XINT_x + \let\xintifForFirst\xint_secondoftwo\XINT_forpair_d #1{#2}% }% -\edef\XINT_half_dont\W\expandafter\XINT_half_b - \the\numexpr \xint_c_x^viii+\xint_c_v*#1#2#3#4#5#6#7\relax \W\W\W\W\W\W\W +\long\def\xintForthree #1#2#3in#4#5#6% {% - \noexpand\expandafter\space - \noexpand\the\numexpr (#1#2#3#4#5#6#7+\xint_c_i)/\xint_c_ii-\xint_c_i \relax + \let\xintifForFirst\xint_firstoftwo + \XINT_toks {\XINT_forthree_d #2{#6}}% + \expandafter\the\expandafter\XINT_toks #4jZ% }% -\def\XINT_half_b 1#1#2#3#4#5#6#7#8% +\long\def\XINT_forthree_d #1#2#3(#4)#5% {% - \XINT_half_c {#2#3#4#5#6#7}{#1}% + \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#2}% + \XINT_toks \expandafter{\romannumeral0\xintcsvtolist{ #4}}% + \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname + \the\XINT_toks \csname XINT_for_right\the\numexpr#1+\xint_c_ii\endcsname}% + \let\xintifForLast\xint_secondoftwo + \ifx #5j\expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo + \fi + {\let\xintifForLast\xint_firstoftwo + \xintBreakForAndDo {\XINT_x \xint_gobble_i Z}}% + \XINT_x + \let\xintifForFirst\xint_secondoftwo\XINT_forthree_d #1{#2}% }% -\def\XINT_half_c #1#2#3#4#5#6#7#8#9% +\long\def\xintForfour #1#2#3in#4#5#6% {% - \xint_gob_til_W #3\XINT_half_end_a #2\W - \expandafter\XINT_half_d - \the\numexpr \xint_c_x^viii+\xint_c_v*#9#8#7#6#5#4#3+#2\relax {#1}% + \let\xintifForFirst\xint_firstoftwo + \XINT_toks {\XINT_forfour_d #2{#6}}% + \expandafter\the\expandafter\XINT_toks #4jZ% }% -\def\XINT_half_d 1#1#2#3#4#5#6#7#8#9% +\long\def\XINT_forfour_d #1#2#3(#4)#5% {% - \XINT_half_c {#2#3#4#5#6#7#8#9}{#1}% + \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#2}% + \XINT_toks \expandafter{\romannumeral0\xintcsvtolist{ #4}}% + \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname + \the\XINT_toks \csname XINT_for_right\the\numexpr#1+\xint_c_iii\endcsname}% + \let\xintifForLast\xint_secondoftwo + \ifx #5j\expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo + \fi + {\let\xintifForLast\xint_firstoftwo + \xintBreakForAndDo {\XINT_x \xint_gobble_i Z}}% + \XINT_x + \let\xintifForFirst\xint_secondoftwo\XINT_forfour_d #1{#2}% }% -\def\XINT_half_end_a #1\W #2\relax #3% +\catcode`Z 11 +\catcode`j 11 +% \end{macrocode} +% \subsection{\csh{xintAssign}, \csh{xintAssignArray}, \csh{xintDigitsOf}} +% \lverb|\xintAssign {a}{b}..{z}\to\A\B...\Z resp. \xintAssignArray +% {a}{b}..{z}\to\U. +% +% \xintDigitsOf=\xintAssignArray. +% +% 1.1c 2015/09/12 has (belatedly) corrected some "features" of +% \xintAssign which didn't like the case of a space right before the "\to", or +% the case with the first token not an opening brace and the subsequent +% material containing brace groups. The new code handles gracefully these +% situations.| +% \begin{macrocode} +\def\xintAssign{\def\XINT_flet_macro {\XINT_assign_fork}\XINT_flet_zapsp }% +\def\XINT_assign_fork {% - \xint_gob_til_zero #1\XINT_half_end_b 0\space #1#3% + \let\XINT_assign_def\def + \ifx\XINT_token[\expandafter\XINT_assign_opt + \else\expandafter\XINT_assign_a + \fi }% -\edef\XINT_half_end_b 0\space 0#1#2#3#4#5#6#7% +\def\XINT_assign_opt [#1]% {% - \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5#6#7\relax + \ifcsname #1def\endcsname + \expandafter\let\expandafter\XINT_assign_def \csname #1def\endcsname + \else + \expandafter\let\expandafter\XINT_assign_def \csname xint#1def\endcsname + \fi + \XINT_assign_a }% -% \end{macrocode} -% \subsection{\csh{xintDec}} -% \lverb!v1.08! -% \begin{macrocode} -\def\xintDec {\romannumeral0\xintdec }% -\def\xintdec #1% +\long\def\XINT_assign_a #1\to {% - \expandafter\XINT_dec\romannumeral-`0#1% - \R\R\R\R\R\R\R\R\Z \W\W\W\W\W\W\W\W + \def\XINT_flet_macro{\XINT_assign_b}% + \expandafter\XINT_flet_zapsp\romannumeral-`0#1\xint_relax\to }% -\def\XINT_dec #1% +\long\def\XINT_assign_b {% - \xint_UDzerominusfork - #1-\XINT_dec_zero - 0#1\XINT_dec_neg - 0-{\XINT_dec_pos #1}% - \krof + \ifx\XINT_token\bgroup + \expandafter\XINT_assign_c + \else\expandafter\XINT_assign_f + \fi }% -\def\XINT_dec_zero #1\W\W\W\W\W\W\W\W { -1}% -\def\XINT_dec_neg - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_inc_pos }% -\def\XINT_dec_pos +\long\def\XINT_assign_f #1\xint_relax\to #2% {% - \expandafter\XINT_dec_a \expandafter{\expandafter}% - \romannumeral0\XINT_OQ {}% + \XINT_assign_def #2{#1}% }% -\def\XINT_dec_a #1#2#3#4#5#6#7#8#9% +\long\def\XINT_assign_c #1% {% - \expandafter\XINT_dec_b - \the\numexpr 11#9#8#7#6#5#4#3#2-\xint_c_i\relax {#1}% + \def\xint_temp {#1}% + \ifx\xint_temp\xint_brelax + \expandafter\XINT_assign_e + \else + \expandafter\XINT_assign_d + \fi }% -\def\XINT_dec_b 1#1% +\long\def\XINT_assign_d #1\to #2% {% - \xint_gob_til_one #1\XINT_dec_A 1\XINT_dec_c + \expandafter\XINT_assign_def\expandafter #2\expandafter{\xint_temp}% + \XINT_assign_c #1\to }% -\def\XINT_dec_c #1#2#3#4#5#6#7#8#9{\XINT_dec_a {#1#2#3#4#5#6#7#8#9}}% -\def\XINT_dec_A 1\XINT_dec_c #1#2#3#4#5#6#7#8#9% - {\XINT_dec_B {#1#2#3#4#5#6#7#8#9}}% -\def\XINT_dec_B #1#2\W\W\W\W\W\W\W\W +\def\XINT_assign_e #1\to {}% +\def\xintRelaxArray #1% {% - \expandafter\XINT_dec_cleanup - \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% + \edef\XINT_restoreescapechar {\escapechar\the\escapechar\relax}% + \escapechar -1 + \expandafter\def\expandafter\xint_arrayname\expandafter {\string #1}% + \XINT_restoreescapechar + \xintiloop [\csname\xint_arrayname 0\endcsname+-1] + \global + \expandafter\let\csname\xint_arrayname\xintiloopindex\endcsname\relax + \ifnum \xintiloopindex > \xint_c_ + \repeat + \global\expandafter\let\csname\xint_arrayname 00\endcsname\relax + \global\let #1\relax }% -\edef\XINT_dec_cleanup #1#2#3#4#5#6#7#8% - {\noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5#6#7#8\relax }% -% \end{macrocode} -% \subsection{\csh{xintInc}} -% \lverb!v1.08! -% \begin{macrocode} -\def\xintInc {\romannumeral0\xintinc }% -\def\xintinc #1% +\def\xintAssignArray{\def\XINT_flet_macro {\XINT_assignarray_fork}% + \XINT_flet_zapsp }% +\def\XINT_assignarray_fork {% - \expandafter\XINT_inc\romannumeral-`0#1% - \R\R\R\R\R\R\R\R\Z \W\W\W\W\W\W\W\W + \let\XINT_assignarray_def\def + \ifx\XINT_token[\expandafter\XINT_assignarray_opt + \else\expandafter\XINT_assignarray + \fi }% -\def\XINT_inc #1% +\def\XINT_assignarray_opt [#1]% {% - \xint_UDzerominusfork - #1-\XINT_inc_zero - 0#1\XINT_inc_neg - 0-{\XINT_inc_pos #1}% - \krof + \ifcsname #1def\endcsname + \expandafter\let\expandafter\XINT_assignarray_def \csname #1def\endcsname + \else + \expandafter\let\expandafter\XINT_assignarray_def + \csname xint#1def\endcsname + \fi + \XINT_assignarray }% -\def\XINT_inc_zero #1\W\W\W\W\W\W\W\W { 1}% -\def\XINT_inc_neg {\expandafter\XINT_opp\romannumeral0\XINT_dec_pos }% -\def\XINT_inc_pos +\long\def\XINT_assignarray #1\to #2% {% - \expandafter\XINT_inc_a \expandafter{\expandafter}% - \romannumeral0\XINT_OQ {}% + \edef\XINT_restoreescapechar {\escapechar\the\escapechar\relax }% + \escapechar -1 + \expandafter\def\expandafter\xint_arrayname\expandafter {\string #2}% + \XINT_restoreescapechar + \def\xint_itemcount {0}% + \expandafter\XINT_assignarray_loop \romannumeral-`0#1\xint_relax + \csname\xint_arrayname 00\expandafter\endcsname + \csname\xint_arrayname 0\expandafter\endcsname + \expandafter {\xint_arrayname}#2% }% -\def\XINT_inc_a #1#2#3#4#5#6#7#8#9% +\long\def\XINT_assignarray_loop #1% {% - \xint_gob_til_W #9\XINT_inc_end\W - \expandafter\XINT_inc_b - \the\numexpr 10#9#8#7#6#5#4#3#2+\xint_c_i\relax {#1}% + \def\xint_temp {#1}% + \ifx\xint_brelax\xint_temp + \expandafter\def\csname\xint_arrayname 0\expandafter\endcsname + \expandafter{\the\numexpr\xint_itemcount}% + \expandafter\expandafter\expandafter\XINT_assignarray_end + \else + \expandafter\def\expandafter\xint_itemcount\expandafter + {\the\numexpr\xint_itemcount+\xint_c_i}% + \expandafter\XINT_assignarray_def + \csname\xint_arrayname\xint_itemcount\expandafter\endcsname + \expandafter{\xint_temp }% + \expandafter\XINT_assignarray_loop + \fi }% -\def\XINT_inc_b 1#1% +\def\XINT_assignarray_end #1#2#3#4% {% - \xint_gob_til_zero #1\XINT_inc_A 0\XINT_inc_c + \def #4##1% + {% + \romannumeral0\expandafter #1\expandafter{\the\numexpr ##1}% + }% + \def #1##1% + {% + \ifnum ##1<\xint_c_ + \xint_afterfi {\xintError:ArrayIndexIsNegative\space }% + \else + \xint_afterfi {% + \ifnum ##1>#2 + \xint_afterfi {\xintError:ArrayIndexBeyondLimit\space }% + \else\xint_afterfi + {\expandafter\expandafter\expandafter\space\csname #3##1\endcsname}% + \fi}% + \fi + }% }% -\def\XINT_inc_c #1#2#3#4#5#6#7#8#9{\XINT_inc_a {#1#2#3#4#5#6#7#8#9}}% -\def\XINT_inc_A 0\XINT_inc_c #1#2#3#4#5#6#7#8#9% - {\XINT_dec_B {#1#2#3#4#5#6#7#8#9}}% -\def\XINT_inc_end\W #1\relax #2{ 1#2}% +\let\xintDigitsOf\xintAssignArray +\let\XINT_tmpa\relax \let\XINT_tmpb\relax \let\XINT_tmpc\relax +\XINT_restorecatcodes_endinput% % \end{macrocode} -% \subsection{Variants for addition sub-routines} -% \lverb|& -% Release 1.03 re-organizes sub-routines to facilitate future developments: the -% diverse variants of addition, with diverse conditions on inputs and output are -% first listed; they will be used in multiplication, or in the summation, or in -% the power routines. I am aware that the commenting is close to non-existent, -% sorry about that. +%\catcode`\<=0 \catcode`\>=11 \catcode`\*=11 \catcode`\/=11 +%\let\relax +%\def<*xintcore>{\catcode`\<=12 \catcode`\>=12 \catcode`\*=12 \catcode`\/=12 } +% +%<*xintcore> +% +% \StoreCodelineNo {xinttools} % -% Addition and multiplication each have multiple implementations corresponding -% to slightly differing formats on input and on output.| +% \section{Package \xintcorenameimp implementation} +% \label{sec:coreimp} % -% \subsubsection{Addition vI: \csh{XINT_add_A}} -% \lverb|& -% INPUT:$\ -% \romannumeral0\XINT_add_A 0{}\W\X\Y\Z \W\X\Y\Z$\ -% 1. et renversés $\ -% 2. de longueur 4n (avec des leading zéros éventuels)$\ -% 3. l'un des deux ne doit pas se terminer par 0000$\$relax -% [Donc on peut avoir 0000 comme input si l'autre est >0 et ne se termine pas en -% 0000 bien sûr]. On peut avoir l'un des deux vides. Mais alors l'autre ne doit -% être ni vide ni 0000. +% \localtableofcontents +% +% Got split off from \xintnameimp with release |1.1|. Release |1.1| also added +% the new macro |\xintiiDivRound|. The package does not load +% \xinttoolsnameimp. +% +% \begin{framed} +% The core arithmetic routines have been entirely rewritten for release +% |1.2|. +% +% The commenting continues (\xintdocdate) to be very sparse: actually it got +% worse than ever with release |1.2|. I will possibly add comments at a +% later date, but for the time being the new routines are not commented at +% all. +% \end{framed} +% +% Also, with |1.2|, |\xintAdd| etc... have been left undefined control +% sequences: only |\xintiAdd| and |\xintiiAdd| (etc...) are provided via +% \xintcorenameimp. It was announced a long time ago that |\xintAdd| etc... +% were to be removed from \xintnameimp and only defined by \xintfracnameimp. +% +% \subsection{Catcodes, \protect\eTeX{} and reload detection} +% +% The code for reload detection was initially copied from \textsc{Heiko +% Oberdiek}'s packages, then modified. +% +% The method for catcodes was also initially directly inspired by these +% packages. % -% OUTPUT: la somme +, ordre normal, plus sur 4n, pas de leading zeros -% La procédure est plus rapide lorsque est le plus court des deux.$\ -% Nota bene: (30 avril 2013). J'ai une version qui est deux fois plus rapide sur -% des nombres d'environ 1000 chiffres chacun, et qui commence à être avantageuse -% pour des nombres d'au moins 200 chiffres. Cependant il serait vraiment -% compliqué d'en étendre l'utilisation aux emplois de l'addition dans les -% autres routines, comme celle de multiplication ou celle de division; et son -% implémentation ajouterait au minimum la mesure de la longueur des summands.| -% \begin{macrocode} -\def\XINT_add_A #1#2#3#4#5#6% -{% - \xint_gob_til_W #3\xint_add_az\W - \XINT_add_AB #1{#3#4#5#6}{#2}% -}% -\def\xint_add_az\W\XINT_add_AB #1#2% -{% - \XINT_add_AC_checkcarry #1% -}% -% \end{macrocode} -% \lverb|& -% ici #2 est prévu pour l'addition, mais attention il devra être renversé -% pour \numexpr. #3 = résultat partiel. #4 = chiffres qui restent. On vérifie si -% le deuxième nombre s'arrête.| % \begin{macrocode} -\def\XINT_add_AB #1#2#3#4\W\X\Y\Z #5#6#7#8% -{% - \xint_gob_til_W #5\xint_add_bz\W - \XINT_add_ABE #1#2{#8#7#6#5}{#3}#4\W\X\Y\Z -}% -\def\XINT_add_ABE #1#2#3#4#5#6% -{% - \expandafter\XINT_add_ABEA\the\numexpr #1+10#5#4#3#2+#6.% -}% -\def\XINT_add_ABEA #1#2#3.#4% -{% - \XINT_add_A #2{#3#4}% -}% +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \let\z\endgroup + \expandafter\let\expandafter\x\csname ver@xintcore.sty\endcsname + \expandafter\let\expandafter\w\csname ver@xintkernel.sty\endcsname + \expandafter + \ifx\csname PackageInfo\endcsname\relax + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \else + \def\y#1#2{\PackageInfo{#1}{#2}}% + \fi + \expandafter + \ifx\csname numexpr\endcsname\relax + \y{xintcore}{\numexpr not available, aborting input}% + \aftergroup\endinput + \else + \ifx\x\relax % plain-TeX, first loading of xintcore.sty + \ifx\w\relax % but xintkernel.sty not yet loaded. + \def\z{\endgroup\input xintkernel.sty\relax}% + \fi + \else + \def\empty {}% + \ifx\x\empty % LaTeX, first loading, + % variable is initialized, but \ProvidesPackage not yet seen + \ifx\w\relax % xintkernel.sty not yet loaded. + \def\z{\endgroup\RequirePackage{xintkernel}}% + \fi + \else + \aftergroup\endinput % xintkernel already loaded. + \fi + \fi + \fi +\z% +\XINTsetupcatcodes% defined in xintkernel.sty % \end{macrocode} -% \lverb|& -% ici le deuxième nombre est fini -% #6 part à la poubelle, #2#3#4#5 est le #2 dans \XINT_add_AB -% on ne vérifie pas la retenue cette fois, mais les fois suivantes| +% \subsection{Package identification} % \begin{macrocode} -\def\xint_add_bz\W\XINT_add_ABE #1#2#3#4#5#6% -{% - \expandafter\XINT_add_CC\the\numexpr #1+10#5#4#3#2.% -}% -\def\XINT_add_CC #1#2#3.#4% -{% - \XINT_add_AC_checkcarry #2{#3#4}% on va examiner et \'eliminer #2 -}% +\XINT_providespackage +\ProvidesPackage{xintcore}% + [2015/10/10 v1.2 Expandable arithmetic on big integers (jfB)]% % \end{macrocode} -% \lverb|& -% retenue plus chiffres qui restent de l'un des deux nombres. -% #2 = résultat partiel -% #3#4#5#6 = summand, avec plus significatif à droite| +% \subsection{Counts for holding needed constants} % \begin{macrocode} -\def\XINT_add_AC_checkcarry #1% -{% - \xint_gob_til_zero #1\xint_add_AC_nocarry 0\XINT_add_C -}% -\def\xint_add_AC_nocarry 0\XINT_add_C #1#2\W\X\Y\Z -{% - \expandafter - \xint_cleanupzeros_andstop - \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_add_C #1#2#3#4#5% -{% - \xint_gob_til_W #2\xint_add_cz\W - \XINT_add_CD {#5#4#3#2}{#1}% -}% -\def\XINT_add_CD #1% -{% - \expandafter\XINT_add_CC\the\numexpr 1+10#1.% -}% -\def\xint_add_cz\W\XINT_add_CD #1#2{ 1#2}% +\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 +\newcount\xint_c_x^ix \xint_c_x^ix 1000000000 +\newcount\xint_c_x^viii_mone \xint_c_x^viii_mone 99999999 +\newcount\xint_c_xii_e_viii \xint_c_xii_e_viii 1200000000 +\newcount\xint_c_xi_e_viii_mone \xint_c_xi_e_viii_mone 1099999999 +\newcount\xint_c_xii_e_viii_mone\xint_c_xii_e_viii_mone 1199999999 % \end{macrocode} -% \subsubsection{Addition vII: \csh{XINT_addr_A}} +% \subsection{\csh{xintNum}} % \lverb|& -% INPUT: \romannumeral0\XINT_addr_A 0{}\W\X\Y\Z \W\X\Y\Z +% For example \xintNum {----+-+++---+----000000000000003}$\ +% 1.05 defines \xintiNum, which allows redefinition of \xintNum by xintfrac.sty +% Slightly modified in 1.06b (\R->\xint_relax) to avoid initial re-scan of +% input stack (while still allowing empty #1). In versions earlier than 1.09a +% it was entirely up to the user to apply \xintnum; starting with 1.09a +% arithmetic +% macros of xint.sty (like earlier already xintfrac.sty with its own \xintnum) +% make use of \xintnum. This allows arguments to +% be count registers, or even \numexpr arbitrary long expressions (with the +% trick of braces, see the user documentation). % -% Comme \XINT_add_A, la différence principale c'est qu'elle donne son résultat -% aussi *sur 4n*, renversé. De plus cette variante accepte que l'un ou même les -% deux inputs soient vides. Utilisé par la sommation et par la division (pour -% les quotients). Et aussi par la multiplication d'ailleurs.$\ -% INPUT: comme pour \XINT_add_A$\ -% 1. et renversés $\ -% 2. de longueur 4n (avec des leading zéros éventuels)$\ -% 3. l'un des deux ne doit pas se terminer par 0000$\ -% OUTPUT: la somme +, *aussi renversée* et *sur 4n*| +% Note (10/2015): I should take time to revisit this.| % \begin{macrocode} -\def\XINT_addr_A #1#2#3#4#5#6% -{% - \xint_gob_til_W #3\xint_addr_az\W - \XINT_addr_B #1{#3#4#5#6}{#2}% -}% -\def\xint_addr_az\W\XINT_addr_B #1#2% -{% - \XINT_addr_AC_checkcarry #1% -}% -\def\XINT_addr_B #1#2#3#4\W\X\Y\Z #5#6#7#8% -{% - \xint_gob_til_W #5\xint_addr_bz\W - \XINT_addr_E #1#2{#8#7#6#5}{#3}#4\W\X\Y\Z -}% -\def\XINT_addr_E #1#2#3#4#5#6% -{% - \expandafter\XINT_addr_ABEA\the\numexpr #1+10#5#4#3#2+#6\relax -}% -\def\XINT_addr_ABEA #1#2#3#4#5#6#7% +\def\xintiNum {\romannumeral0\xintinum }% +\def\xintinum #1% {% - \XINT_addr_A #2{#7#6#5#4#3}% + \expandafter\XINT_num_loop + \romannumeral-`0#1\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\Z }% -\def\xint_addr_bz\W\XINT_addr_E #1#2#3#4#5#6% +\let\xintNum\xintiNum \let\xintnum\xintinum +\def\XINT_num #1% {% - \expandafter\XINT_addr_CC\the\numexpr #1+10#5#4#3#2\relax + \XINT_num_loop #1\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\Z }% -\def\XINT_addr_CC #1#2#3#4#5#6#7% +\def\XINT_num_loop #1#2#3#4#5#6#7#8% {% - \XINT_addr_AC_checkcarry #2{#7#6#5#4#3}% + \xint_gob_til_xint_relax #8\XINT_num_end\xint_relax + \XINT_num_NumEight #1#2#3#4#5#6#7#8% }% -\def\XINT_addr_AC_checkcarry #1% +\edef\XINT_num_end\xint_relax\XINT_num_NumEight #1\xint_relax #2\Z {% - \xint_gob_til_zero #1\xint_addr_AC_nocarry 0\XINT_addr_C + \noexpand\expandafter\space\noexpand\the\numexpr #1+\xint_c_\relax }% -\def\xint_addr_AC_nocarry 0\XINT_addr_C #1#2\W\X\Y\Z { #1#2}% -\def\XINT_addr_C #1#2#3#4#5% +\def\XINT_num_NumEight #1#2#3#4#5#6#7#8% {% - \xint_gob_til_W #2\xint_addr_cz\W - \XINT_addr_D {#5#4#3#2}{#1}% + \ifnum \numexpr #1#2#3#4#5#6#7#8+\xint_c_= \xint_c_ + \xint_afterfi {\expandafter\XINT_num_keepsign_a + \the\numexpr #1#2#3#4#5#6#7#81\relax}% + \else + \xint_afterfi {\expandafter\XINT_num_finish + \the\numexpr #1#2#3#4#5#6#7#8\relax}% + \fi }% -\def\XINT_addr_D #1% +\def\XINT_num_keepsign_a #1% {% - \expandafter\XINT_addr_CC\the\numexpr 1+10#1\relax + \xint_gob_til_one#1\XINT_num_gobacktoloop 1\XINT_num_keepsign_b }% -\def\xint_addr_cz\W\XINT_addr_D #1#2{ #21000}% +\def\XINT_num_gobacktoloop 1\XINT_num_keepsign_b {\XINT_num_loop }% +\def\XINT_num_keepsign_b #1{\XINT_num_loop -}% +\def\XINT_num_finish #1\xint_relax #2\Z { #1}% % \end{macrocode} -% \subsubsection{Addition vIII: \csh{XINT_addm_A}} -% \lverb|& -% INPUT:\romannumeral0\XINT_addm_A 0{}\W\X\Y\Z \W\X\Y\Z$\ -% 1. et renversés$\ -% 2. de longueur 4n ; non$\ -% 3. est *garanti au moins aussi long* que $\ -% OUTPUT: la somme +, ordre normal, pas sur 4n, leading zeros retirés. -% Utilisé par la multiplication.| +% \subsection{Zeroes} +% \lverb|Changed for 1.2 which has a base model of eight digits rather than +% four for the basic operations.| % \begin{macrocode} -\def\XINT_addm_A #1#2#3#4#5#6% -{% - \xint_gob_til_W #3\xint_addm_az\W - \XINT_addm_AB #1{#3#4#5#6}{#2}% -}% -\def\xint_addm_az\W\XINT_addm_AB #1#2% -{% - \XINT_addm_AC_checkcarry #1% -}% -\def\XINT_addm_AB #1#2#3#4\W\X\Y\Z #5#6#7#8% -{% - \XINT_addm_ABE #1#2{#8#7#6#5}{#3}#4\W\X\Y\Z -}% -\def\XINT_addm_ABE #1#2#3#4#5#6% -{% - \expandafter\XINT_addm_ABEA\the\numexpr #1+10#5#4#3#2+#6.% -}% -\def\XINT_addm_ABEA #1#2#3.#4% -{% - \XINT_addm_A #2{#3#4}% -}% -\def\XINT_addm_AC_checkcarry #1% +\edef\XINT_cuz_small #1#2#3#4#5#6#7#8% {% - \xint_gob_til_zero #1\xint_addm_AC_nocarry 0\XINT_addm_C + \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5#6#7#8\relax }% -\def\xint_addm_AC_nocarry 0\XINT_addm_C #1#2\W\X\Y\Z +%%%%%%%%%%%% +\def\XINT_cuz #1#2#3#4#5#6#7#8#9% {% - \expandafter - \xint_cleanupzeros_andstop - \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% + \xint_gob_til_R #9\XINT_cuz_e \R + \xint_gob_til_eightzeroes #1#2#3#4#5#6#7#8\XINT_cuz_z 00000000% + \XINT_cuz_clean #1#2#3#4#5#6#7#8#9% }% -\def\XINT_addm_C #1#2#3#4#5% +\edef\XINT_cuz_clean #1#2#3#4#5#6#7#8#9\R + {\noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5#6#7#8\relax #9}% +\edef\XINT_cuz_e\R #1\XINT_cuz_clean #2\R + {\noexpand\expandafter\space\noexpand\the\numexpr #2\relax }% +\def\XINT_cuz_z 00000000\XINT_cuz_clean 00000000{\XINT_cuz }% +%%%%%%%%%%%% +\def\XINT_cuz_byviii #1#2#3#4#5#6#7#8#9% {% - \xint_gob_til_W - #5\xint_addm_cw - #4\xint_addm_cx - #3\xint_addm_cy - #2\xint_addm_cz - \W\XINT_addm_CD {#5#4#3#2}{#1}% + \xint_gob_til_R #9\XINT_cuz_byviii_e \R + \xint_gob_til_eightzeroes #1#2#3#4#5#6#7#8\XINT_cuz_byviii_z 00000000% + \XINT_cuz_byviii_clean #1#2#3#4#5#6#7#8#9% }% -\def\XINT_addm_CD #1% +\def\XINT_cuz_byviii_clean #1\R { #1}% +\def\XINT_cuz_byviii_e\R #1\XINT_cuz_byviii_clean #2\R{ #2}% +\def\XINT_cuz_byviii_z 00000000\XINT_cuz_byviii_clean 00000000{\XINT_cuz_byviii}% +% \end{macrocode} +% \subsection{Blocks of eight digits} +% \lverb|Lingua of release 1.2.| +% \begin{macrocode} +\def\XINT_zeroes_forviii #1#2#3#4#5#6#7#8% {% - \expandafter\XINT_addm_CC\the\numexpr 1+10#1.% + \xint_gob_til_R #8\XINT_zeroes_forviii_end\R\XINT_zeroes_forviii }% -\def\XINT_addm_CC #1#2#3.#4% +\edef\XINT_zeroes_forviii_end\R\XINT_zeroes_forviii #1#2#3#4#5#6#7#8#9\W {% - \XINT_addm_AC_checkcarry #2{#3#4}% + \noexpand\expandafter\space\noexpand\xint_gob_til_one #2#3#4#5#6#7#8% }% -\def\xint_addm_cw - #1\xint_addm_cx - #2\xint_addm_cy - #3\xint_addm_cz - \W\XINT_addm_CD +%%%%%%%%%%%% +\def\XINT_rsepbyviii #1#2#3#4#5#6#7#8% {% - \expandafter\XINT_addm_CDw\the\numexpr 1+#1#2#3.% + \XINT_rsepbyviii_b {#1#2#3#4#5#6#7#8}% }% -\def\XINT_addm_CDw #1.#2#3\X\Y\Z +\def\XINT_rsepbyviii_b #1#2#3#4#5#6#7#8#9% {% - \XINT_addm_end #1#3% + #2#3#4#5#6#7#8#9\expandafter!\the\numexpr + 1#1\expandafter.\the\numexpr 1\XINT_rsepbyviii }% -\def\xint_addm_cx - #1\xint_addm_cy - #2\xint_addm_cz - \W\XINT_addm_CD +\def\XINT_rsepbyviii_end_B #1\relax #2#3{#2.}% +\def\XINT_rsepbyviii_end_A #11#2\expandafter #3\relax #4#5{#2.1#5.}% +%%%%%%%%%%%% +\def\XINT_sepandrev {% - \expandafter\XINT_addm_CDx\the\numexpr 1+#1#2.% + \expandafter\XINT_sepandrev_a\the\numexpr 1\XINT_rsepbyviii }% -\def\XINT_addm_CDx #1.#2#3\Y\Z +\def\XINT_sepandrev_a {\XINT_sepandrev_b {}}% +\def\XINT_sepandrev_b #1#2.#3.#4.#5.#6.#7.#8.#9.% {% - \XINT_addm_end #1#3% + \xint_gob_til_R #9\XINT_sepandrev_end\R + \XINT_sepandrev_b {#9!#8!#7!#6!#5!#4!#3!#2!#1}% }% -\def\xint_addm_cy - #1\xint_addm_cz - \W\XINT_addm_CD +\def\XINT_sepandrev_end\R\XINT_sepandrev_b #1#2\W {\XINT_sepandrev_done #1}% +\def\XINT_sepandrev_done #11#2!{ }% +%%%%%%%%%%%% +\def\XINT_sepandrev_andcount {% - \expandafter\XINT_addm_CDy\the\numexpr 1+#1.% + \expandafter\XINT_sepandrev_andcount_a\the\numexpr 1\XINT_rsepbyviii }% -\def\XINT_addm_CDy #1.#2#3\Z +\def\XINT_sepandrev_andcount_a {\XINT_sepandrev_andcount_b 0.{}}% +\def\XINT_sepandrev_andcount_b #1.#2#3.#4.#5.#6.#7.#8.#9.% {% - \XINT_addm_end #1#3% + \xint_gob_til_R #9\XINT_sepandrev_andcount_end\R + \expandafter\XINT_sepandrev_andcount_b \the\numexpr #1+\xint_c_xiv.% + {#9!#8!#7!#6!#5!#4!#3!#2}% }% -\def\xint_addm_cz\W\XINT_addm_CD #1#2#3{\XINT_addm_end #1#3}% -\edef\XINT_addm_end #1#2#3#4#5% - {\noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5\relax}% +\def\XINT_sepandrev_andcount_end\R + \expandafter\XINT_sepandrev_andcount_b\the\numexpr #1+\xint_c_xiv.#2#3#4\W +{\expandafter\XINT_sepandrev_andcount_done\the\numexpr \xint_c_ii*#3+#1.#2}% +\edef\XINT_sepandrev_andcount_done #1.#21#3!% + {\noexpand\expandafter\space\noexpand\the\numexpr #1-#3.}% % \end{macrocode} -% \subsubsection{Addition vIV: \csh{XINT_addp_A}} -% \lverb|& -% INPUT: -% \romannumeral0\XINT_addp_A 0{}\W\X\Y\Z \W\X\Y\Z$\ -% 1. et renversés$\ -% 2. de longueur 4n ; non$\ -% 3. est *garanti au moins aussi long* que $\ -% OUTPUT: la somme +, dans l'ordre renversé, sur 4n, et en faisant -% attention de ne pas terminer en 0000. -% Utilisé par la multiplication servant pour le calcul des puissances.| +% \subsection{Blocks of eight, for needs of v1.2 \csh{xintiiDivision}.} % \begin{macrocode} -\def\XINT_addp_A #1#2#3#4#5#6% -{% - \xint_gob_til_W #3\xint_addp_az\W - \XINT_addp_AB #1{#3#4#5#6}{#2}% -}% -\def\xint_addp_az\W\XINT_addp_AB #1#2% -{% - \XINT_addp_AC_checkcarry #1% -}% -\def\XINT_addp_AC_checkcarry #1% +\def\XINT_sepbyviii_andcount {% - \xint_gob_til_zero #1\xint_addp_AC_nocarry 0\XINT_addp_C + \expandafter\XINT_sepbyviii_andcount_a\the\numexpr\XINT_sepbyviii }% -\def\xint_addp_AC_nocarry 0\XINT_addp_C +\def\XINT_sepbyviii #1#2#3#4#5#6#7#8% {% - \XINT_addp_F + 1#1#2#3#4#5#6#7#8\expandafter!\the\numexpr\XINT_sepbyviii }% -\def\XINT_addp_AB #1#2#3#4\W\X\Y\Z #5#6#7#8% +\def\XINT_sepbyviii_end #1\relax {\relax\XINT_sepbyviii_andcount_end!}% +\def\XINT_sepbyviii_andcount_a {\XINT_sepbyviii_andcount_b \xint_c_.}% +\def\XINT_sepbyviii_andcount_b #1.#2!#3!#4!#5!#6!#7!#8!#9!% {% - \XINT_addp_ABE #1#2{#8#7#6#5}{#3}#4\W\X\Y\Z + #2\expandafter!\the\numexpr#3\expandafter!\the\numexpr#4\expandafter + !\the\numexpr#5\expandafter!\the\numexpr#6\expandafter!\the\numexpr + #7\expandafter + !\the\numexpr#8\expandafter!\the\numexpr#9\expandafter!\the\numexpr + \expandafter\XINT_sepbyviii_andcount_b\the\numexpr #1+\xint_c_viii.% }% -\def\XINT_addp_ABE #1#2#3#4#5#6% +\def\XINT_sepbyviii_andcount_end #1\XINT_sepbyviii_andcount_b\the\numexpr + #2+\xint_c_viii.#3#4\W {\expandafter.\the\numexpr #2+#3.}% +%%%%%%%%%%%% +\def\XINT_rev_nounsep #1#2!#3!#4!#5!#6!#7!#8!#9!% {% - \expandafter\XINT_addp_ABEA\the\numexpr #1+10#5#4#3#2+#6\relax + \xint_gob_til_R #9\XINT_rev_nounsep_end\R + \XINT_rev_nounsep {#9!#8!#7!#6!#5!#4!#3!#2!#1}% }% -\def\XINT_addp_ABEA #1#2#3#4#5#6#7% +\def\XINT_rev_nounsep_end\R\XINT_rev_nounsep #1#2\W {\XINT_rev_nounsep_done #1}% +\def\XINT_rev_nounsep_done #11{ 1}% +%%%%%%%%%%%% +\def\XINT_sepbyviii_Z #1#2#3#4#5#6#7#8% {% - \XINT_addp_A #2{#7#6#5#4#3}%<-- attention on met donc \`a droite + 1#1#2#3#4#5#6#7#8\expandafter!\the\numexpr\XINT_sepbyviii_Z }% -\def\XINT_addp_C #1#2#3#4#5% +\def\XINT_sepbyviii_Z_end #1\relax {\relax\Z!}% +%%%%%%%%%%%% +\def\XINT_unsep_cuzsmall #11#2!1#3!1#4!1#5!1#6!1#7!1#8!1#9!% {% - \xint_gob_til_W - #5\xint_addp_cw - #4\xint_addp_cx - #3\xint_addp_cy - #2\xint_addp_cz - \W\XINT_addp_CD {#5#4#3#2}{#1}% -}% -\def\XINT_addp_CD #1% -{% - \expandafter\XINT_addp_CC\the\numexpr 1+10#1\relax -}% -\def\XINT_addp_CC #1#2#3#4#5#6#7% -{% - \XINT_addp_AC_checkcarry #2{#7#6#5#4#3}% -}% -\def\xint_addp_cw - #1\xint_addp_cx - #2\xint_addp_cy - #3\xint_addp_cz - \W\XINT_addp_CD -{% - \expandafter\XINT_addp_CDw\the\numexpr \xint_c_i+10#1#2#3\relax -}% -\def\XINT_addp_CDw #1#2#3#4#5#6% -{% - \xint_gob_til_zeros_iv #2#3#4#5\XINT_addp_endDw_zeros - 0000\XINT_addp_endDw #2#3#4#5% + \xint_gob_til_R #9\XINT_unsep_cuzsmall_end\R + \XINT_unsep_cuzsmall {#1#2#3#4#5#6#7#8#9}% }% -\def\XINT_addp_endDw_zeros 0000\XINT_addp_endDw 0000#1\X\Y\Z{ #1}% -\def\XINT_addp_endDw #1#2#3#4#5\X\Y\Z{ #5#4#3#2#1}% -\def\xint_addp_cx - #1\xint_addp_cy - #2\xint_addp_cz - \W\XINT_addp_CD +\def\XINT_unsep_cuzsmall_end\R + \XINT_unsep_cuzsmall #1{\XINT_unsep_cuzsmall_done #1}% +\def\XINT_unsep_cuzsmall_done #1\R #2\W{\XINT_cuz_small #1}% +\def\XINT_unsep_delim {1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W}% +%%%%%%%%%%%% +\def\XINT_div_unsepQ #11#2!1#3!1#4!1#5!1#6!1#7!1#8!1#9!% {% - \expandafter\XINT_addp_CDx\the\numexpr \xint_c_i+100#1#2\relax + \xint_gob_til_R #9\XINT_div_unsepQ_end\R + \XINT_div_unsepQ {#1#2#3#4#5#6#7#8#9}% }% -\def\XINT_addp_CDx #1#2#3#4#5#6% +\def\XINT_div_unsepQ_end\R\XINT_div_unsepQ #1{\XINT_div_unsepQ_x #1}% +\def\XINT_div_unsepQ_x #1#2#3#4#5#6#7#8#9% {% - \xint_gob_til_zeros_iv #2#3#4#5\XINT_addp_endDx_zeros - 0000\XINT_addp_endDx #2#3#4#5% + \xint_gob_til_R #9\XINT_div_unsepQ_e \R + \xint_gob_til_eightzeroes #1#2#3#4#5#6#7#8\XINT_div_unsepQ_y 00000000% + \expandafter\XINT_div_unsepQ_done \the\numexpr #1#2#3#4#5#6#7#8.#9% }% -\def\XINT_addp_endDx_zeros 0000\XINT_addp_endDx 0000#1\Y\Z{ #1}% -\def\XINT_addp_endDx #1#2#3#4#5\Y\Z{ #5#4#3#2#1}% -\def\xint_addp_cy #1\xint_addp_cz\W\XINT_addp_CD +\def\XINT_div_unsepQ_e\R\xint_gob_til_eightzeroes #1\XINT_div_unsepQ_y #2\W + {\the\numexpr #1\relax \Z}% +\def\XINT_div_unsepQ_y #1.#2\R #3\W{\XINT_cuz_small #2\Z}% +\def\XINT_div_unsepQ_done #1.#2\R #3\W { #1#2\Z}% +%%%%%%%%%%%% +\def\XINT_div_unsepR #11#2!1#3!1#4!1#5!1#6!1#7!1#8!1#9!% {% - \expandafter\XINT_addp_CDy\the\numexpr \xint_c_i+1000#1\relax + \xint_gob_til_R #9\XINT_div_unsepR_end\R + \XINT_div_unsepR {#1#2#3#4#5#6#7#8#9}% }% -\def\XINT_addp_CDy #1#2#3#4#5#6% +\def\XINT_div_unsepR_end\R\XINT_div_unsepR #1{\XINT_div_unsepR_done #1}% +\def\XINT_div_unsepR_done #1\R #2\W {\XINT_cuz #1\R}% +%%%%%%%%%%%% +\def\XINT_unrevbyviii #11#2!1#3!1#4!1#5!1#6!1#7!1#8!1#9!% {% - \xint_gob_til_zeros_iv #2#3#4#5\XINT_addp_endDy_zeros - 0000\XINT_addp_endDy #2#3#4#5% + \xint_gob_til_R #9\XINT_unrevbyviii_a\R + \XINT_unrevbyviii {#9#8#7#6#5#4#3#2#1}% }% -\def\XINT_addp_endDy_zeros 0000\XINT_addp_endDy 0000#1\Z{ #1}% -\def\XINT_addp_endDy #1#2#3#4#5\Z{ #5#4#3#2#1}% -\def\xint_addp_cz\W\XINT_addp_CD #1#2{ #21000}% -\def\XINT_addp_F #1#2#3#4#5% +\edef\XINT_unrevbyviii_a\R\XINT_unrevbyviii #1#2\W + {\noexpand\expandafter\space + \noexpand\romannumeral-`0\noexpand\xint_gob_til_Z #1}% +\def\XINT_smallunrevbyviii 1#1!1#2!1#3!1#4!1#5!1#6!1#7!1#8!#9\W% {% - \xint_gob_til_W - #5\xint_addp_Gw - #4\xint_addp_Gx - #3\xint_addp_Gy - #2\xint_addp_Gz - \W\XINT_addp_G {#2#3#4#5}{#1}% + \expandafter\XINT_cuz_small\xint_gob_til_Z #8#7#6#5#4#3#2#1% }% -\def\XINT_addp_G #1#2% +% \end{macrocode} +% \subsection{\csh{xintReverseDigits}} +% \lverb|v1.2. Needed now by \xintLDg.| +% \begin{macrocode} +\def\XINT_microrevsep #1#2#3#4#5#6#7#8% {% - \XINT_addp_F {#2#1}% + 1#8#7#6#5#4#3#2#1\expandafter!\the\numexpr\XINT_microrevsep }% -\def\xint_addp_Gw - #1\xint_addp_Gx - #2\xint_addp_Gy - #3\xint_addp_Gz - \W\XINT_addp_G #4% +\def\XINT_microrevsep_end #1\W #2\expandafter #3\Z{#2!}% +\def\xintReverseDigits {\romannumeral0\xintreversedigits }% +\def\xintreversedigits #1{\expandafter\XINT_reversedigits\romannumeral-`0#1\Z}% +\def\XINT_reversedigits #1% {% - \xint_gob_til_zeros_iv #3#2#10\XINT_addp_endGw_zeros - 0000\XINT_addp_endGw #3#2#10% + \xint_UDsignfork + #1{\expandafter\xint_minus_thenstop\romannumeral0\XINT_reversedigits_a}% + -{\XINT_reversedigits_a #1}% + \krof }% -\def\XINT_addp_endGw_zeros 0000\XINT_addp_endGw 0000#1\X\Y\Z{ #1}% -\def\XINT_addp_endGw #1#2#3#4#5\X\Y\Z{ #5#1#2#3#4}% -\def\xint_addp_Gx - #1\xint_addp_Gy - #2\xint_addp_Gz - \W\XINT_addp_G #3% -{% - \xint_gob_til_zeros_iv #2#100\XINT_addp_endGx_zeros - 0000\XINT_addp_endGx #2#100% +\def\XINT_reversedigits_a #1\Z +{% + \expandafter\XINT_revdigits_a\the\numexpr\expandafter\XINT_microrevsep + \romannumeral-`0#1{\XINT_microrevsep_end\W}\XINT_microrevsep_end + \XINT_microrevsep_end\XINT_microrevsep_end + \XINT_microrevsep_end\XINT_microrevsep_end + \XINT_microrevsep_end\XINT_microrevsep_end\Z + 1\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% -\def\XINT_addp_endGx_zeros 0000\XINT_addp_endGx 0000#1\Y\Z{ #1}% -\def\XINT_addp_endGx #1#2#3#4#5\Y\Z{ #5#1#2#3#4}% -\def\xint_addp_Gy - #1\xint_addp_Gz - \W\XINT_addp_G #2% +\def\XINT_revdigits_a {\XINT_revdigits_b {}}% +\def\XINT_revdigits_b #11#2!1#3!1#4!1#5!1#6!1#7!1#8!1#9!% {% - \xint_gob_til_zeros_iv #1000\XINT_addp_endGy_zeros - 0000\XINT_addp_endGy #1000% + \xint_gob_til_R #9\XINT_revdigits_end\R + \XINT_revdigits_b {#9#8#7#6#5#4#3#2#1}% }% -\def\XINT_addp_endGy_zeros 0000\XINT_addp_endGy 0000#1\Z{ #1}% -\def\XINT_addp_endGy #1#2#3#4#5\Z{ #5#1#2#3#4}% -\def\xint_addp_Gz\W\XINT_addp_G #1#2{ #2}% +\edef\XINT_revdigits_end\R\XINT_revdigits_b #1#2\W + {\noexpand\expandafter\space\noexpand\xint_gob_til_Z #1}% % \end{macrocode} -% \subsection{\csh{xintiAdd}, \csh{xintiiAdd}} -% \lverb|ADDITION -% [algo plus efficace lorsque le premier argument plus long que le second] +% \subsection{\csh{xintSgn}, \csh{xintiiSgn}, \csh{XINT_Sgn}, \csh{XINT_cntSgn}} +% \lverb|& +% Changed in 1.05. Earlier code was unnecessarily strange. 1.09a with \xintnum % -% Note (octobre 2014, pendant la préparation de la sortie de 1.1) +% 1.09i defines \XINT_Sgn and \XINT_cntSgn (was \XINT__Sgn in 1.09i) for reasons +% of internal optimizations. % -% Je n'aurais pas dû l'appeler \xintAdd, mais seulement \xintiAdd. Le format -% de sortie de \xintAdd est modifié par xintfrac.sty, celui de \xintiAdd ne -% bouge pas, et \xintiiAdd reste la version stricte.| +% xintfrac.sty will overwrite \xintsgn with use of \xintraw rather than +% \xintnum, naturally.| % \begin{macrocode} -\def\xintiiAdd {\romannumeral0\xintiiadd }% -\def\xintiiadd #1{\expandafter\xint_iiadd\romannumeral-`0#1\Z }% -\def\xint_iiadd #1#2\Z #3% -{% - \expandafter\XINT_add_fork\expandafter #1\romannumeral-`0#3\Z #2\Z -}% -\def\xintiAdd {\romannumeral0\xintiadd }% -\def\xintiadd #1% +\def\xintiiSgn {\romannumeral0\xintiisgn }% +\def\xintiisgn #1% {% - \expandafter\xint_add\romannumeral0\xintnum{#1}\Z + \expandafter\XINT_sgn \romannumeral-`0#1\Z% }% -\def\xint_add #1#2\Z #3% +\def\xintSgn {\romannumeral0\xintsgn }% +\def\xintsgn #1% {% - \expandafter\XINT_add_fork\expandafter #1\romannumeral0\xintnum{#3}\Z #2\Z + \expandafter\XINT_sgn \romannumeral0\xintnum{#1}\Z% }% -\let\xintAdd\xintiAdd \let\xintadd\xintiadd -\def\XINT_add_fork #1#2% +\def\XINT_sgn #1#2\Z {% - \xint_UDzerofork - #1\XINT_add_firstiszero - #2\XINT_add_secondiszero - 0{}% + \xint_UDzerominusfork + #1-{ 0}% + 0#1{ -1}% + 0-{ 1}% \krof - \xint_UDsignsfork - #1#2\XINT_add_minusminus - #1-\XINT_add_minusplus - #2-\XINT_add_plusminus - --\XINT_add_plusplus - \krof #1#2% }% -\def\XINT_add_firstiszero #1\krof #2#3\Z #4\Z { #3}% -\def\XINT_add_secondiszero #1\krof #2#3\Z #4\Z { #2#4}% -\def\XINT_add_plusplus #1#2#3\Z #4\Z {\XINT_add_pre {#1#4}{#2#3}}% -\def\XINT_add_minusminus #1#2#3\Z #4\Z - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_add_pre {#4}{#3}}% -\def\XINT_add_minusplus #1#2#3\Z #4\Z {\XINT_sub_pre {#2#3}{#4}}% -\def\XINT_add_plusminus #1#2#3\Z #4\Z {\XINT_sub_pre {#1#4}{#3}}% -% \end{macrocode} -% \lverb|positive summands| -% \begin{macrocode} -\def\XINT_add_pre #1% +\def\XINT_Sgn #1#2\Z {% - \expandafter\XINT_add_pre_b\expandafter - {\romannumeral0\XINT_RQ {}#1\R\R\R\R\R\R\R\R\Z }% + \xint_UDzerominusfork + #1-{0}% + 0#1{-1}% + 0-{1}% + \krof }% -\def\XINT_add_pre_b #1#2% +\def\XINT_cntSgn #1#2\Z {% - \expandafter\XINT_add_A - \expandafter0\expandafter{\expandafter}% - \romannumeral0\XINT_RQ {}#2\R\R\R\R\R\R\R\R\Z - \W\X\Y\Z #1\W\X\Y\Z + \xint_UDzerominusfork + #1-\xint_c_ + 0#1\xint_c_mone + 0-\xint_c_i + \krof }% % \end{macrocode} -% \subsection{\csh{xintiSub}, \csh{xintiiSub}} -% \lverb|Release 1.09a has \xintnum added into \xintiSub.| +% \subsection{\csh{xintiOpp}, \csh{xintiiOpp}} % \begin{macrocode} -\def\xintiiSub {\romannumeral0\xintiisub }% -\def\xintiisub #1{\expandafter\xint_iisub\romannumeral-`0#1\Z }% -\def\xint_iisub #1#2\Z #3% -{% - \expandafter\XINT_sub_fork\expandafter #1\romannumeral-`0#3\Z #2\Z -}% -\def\xintiSub {\romannumeral0\xintisub }% -\def\xintisub #1% +\def\xintiiOpp {\romannumeral0\xintiiopp }% +\def\xintiiopp #1% {% - \expandafter\xint_sub\romannumeral0\xintnum{#1}\Z + \expandafter\XINT_opp \romannumeral-`0#1% }% -\def\xint_sub #1#2\Z #3% +\def\xintiOpp {\romannumeral0\xintiopp }% +\def\xintiopp #1% {% - \expandafter\XINT_sub_fork\expandafter #1\romannumeral0\xintnum{#3}\Z #2\Z + \expandafter\XINT_opp \romannumeral0\xintnum{#1}% }% -\let\xintSub\xintiSub \let\xintsub\xintisub -\def\XINT_sub_fork #1#2% +\def\XINT_Opp #1{\romannumeral0\XINT_opp #1}% +\def\XINT_opp #1% {% - \xint_UDzerofork - #1\XINT_sub_firstiszero - #2\XINT_sub_secondiszero - 0{}% + \xint_UDzerominusfork + #1-{ 0}% zero + 0#1{ }% negative + 0-{ -#1}% positive \krof - \xint_UDsignsfork - #1#2\XINT_sub_minusminus - #1-\XINT_sub_minusplus - #2-\XINT_sub_plusminus - --\XINT_sub_plusplus - \krof #1#2% }% -\def\XINT_sub_firstiszero #1\krof #2#3\Z #4\Z {\XINT_opp #3}% -\def\XINT_sub_secondiszero #1\krof #2#3\Z #4\Z { #2#4}% -\def\XINT_sub_plusplus #1#2#3\Z #4\Z {\XINT_sub_pre {#1#4}{#2#3}}% -\def\XINT_sub_minusminus #1#2#3\Z #4\Z {\XINT_sub_pre {#3}{#4}}% -\def\XINT_sub_minusplus #1#2#3\Z #4\Z - {\expandafter\xint_minus_thenstop\romannumeral0\XINT_add_pre {#4}{#2#3}}% -\def\XINT_sub_plusminus #1#2#3\Z #4\Z {\XINT_add_pre {#1#4}{#3}}% % \end{macrocode} -% \lverb|SOUSTRACTION A-B avec A premier argument, B second argument de -% \xintSub et ensuite \XINT_sub_pre ici| +% \subsection{\csh{xintiAbs}, \csh{xintiiAbs}} +% \lverb|Release 1.09a has now \xintiabs which does \xintnum and this is +% inherited by DecSplit, by Sqr, and macros of xintgcd.sty. Attention, car ces +% macros de toute façon doivent passer à la valeur absolue et donc en profite +% pour faire le \xintnum, mais pour optimisation sans overhead il vaut mieux +% utiliser \xintiiAbs ou autre point d'accès.| % \begin{macrocode} -\def\XINT_sub_pre #1% -{% - \expandafter\XINT_sub_pre_b\expandafter - {\romannumeral0\XINT_RQ {}#1\R\R\R\R\R\R\R\R\Z }% -}% -\def\XINT_sub_pre_b #1#2% +\def\xintiiAbs {\romannumeral0\xintiiabs }% +\def\xintiiabs #1% {% - \expandafter\XINT_sub_A - \expandafter1\expandafter{\expandafter}% - \romannumeral0\XINT_RQ {}#2\R\R\R\R\R\R\R\R\Z - \W\X\Y\Z #1 \W\X\Y\Z + \expandafter\XINT_abs \romannumeral-`0#1% }% -% \end{macrocode} -% \lverb|& -% \romannumeral0\XINT_sub_A 1{}\W\X\Y\Z\W\X\Y\Z$\ -% N1 et N2 sont présentés à l'envers ET ON A RAJOUTÉ DES ZÉROS -% POUR QUE LEURS LONGUEURS À CHACUN SOIENT MULTIPLES DE 4, MAIS -% AUCUN NE SE TERMINE EN 0000.$\ output: N2 - N1$\ -% Elle donne le résultat dans le **bon ordre**, avec le bon signe, -% et sans zéros superflus.| -% \begin{macrocode} -\def\XINT_sub_A #1#2#3\W\X\Y\Z #4#5#6#7% +\def\xintiAbs {\romannumeral0\xintiabs }% +\def\xintiabs #1% {% - \xint_gob_til_W - #4\xint_sub_az - \W\XINT_sub_B #1{#4#5#6#7}{#2}#3\W\X\Y\Z + \expandafter\XINT_abs \romannumeral0\xintnum{#1}% }% -\def\XINT_sub_B #1#2#3#4#5#6#7% +\def\XINT_Abs #1{\romannumeral0\XINT_abs #1}% +\def\XINT_abs #1% {% - \xint_gob_til_W - #4\xint_sub_bz - \W\XINT_sub_onestep #1#2{#7#6#5#4}{#3}% + \xint_UDsignfork + #1{ }% + -{ #1}% + \krof }% % \end{macrocode} +% \subsection{\csh{xintFDg}, \csh{xintiiFDg}} % \lverb|& -% d'abord la branche principale -% #6 = 4 chiffres de N1, plus significatif en *premier*, -% #2#3#4#5 chiffres de N2, plus significatif en *dernier* -% On veut N2 - N1.| +% FIRST DIGIT. Code simplified in 1.05. +% And prepared for redefinition by xintfrac to parse through \xintNum. Version +% 1.09a inserts the \xintnum already here.| % \begin{macrocode} -\def\XINT_sub_onestep #1#2#3#4#5#6% +\def\xintiiFDg {\romannumeral0\xintiifdg }% +\def\xintiifdg #1% {% - \expandafter\XINT_sub_backtoA\the\numexpr 11#5#4#3#2-#6+#1-\xint_c_i.% + \expandafter\XINT_fdg \romannumeral-`0#1\W\Z }% -% \end{macrocode} -% \lverb|ON PRODUIT LE RÉSULTAT DANS LE BON ORDRE| -% \begin{macrocode} -\def\XINT_sub_backtoA #1#2#3.#4% +\def\xintFDg {\romannumeral0\xintfdg }% +\def\xintfdg #1% {% - \XINT_sub_A #2{#3#4}% + \expandafter\XINT_fdg \romannumeral0\xintnum{#1}\W\Z }% -\def\xint_sub_bz - \W\XINT_sub_onestep #1#2#3#4#5#6#7% +\def\XINT_FDg #1{\romannumeral0\XINT_fdg #1\W\Z }% +\def\XINT_fdg #1#2#3\Z {% - \xint_UDzerofork - #1\XINT_sub_C % une retenue - 0\XINT_sub_D % pas de retenue + \xint_UDzerominusfork + #1-{ 0}% zero + 0#1{ #2}% negative + 0-{ #1}% positive \krof - {#7}#2#3#4#5% -}% -\def\XINT_sub_D #1#2\W\X\Y\Z -{% - \expandafter - \xint_cleanupzeros_andstop - \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_sub_C #1#2#3#4#5% -{% - \xint_gob_til_W - #2\xint_sub_cz - \W\XINT_sub_AC_onestep {#5#4#3#2}{#1}% -}% -\def\XINT_sub_AC_onestep #1% -{% - \expandafter\XINT_sub_backtoC\the\numexpr 11#1-\xint_c_i.% }% -\def\XINT_sub_backtoC #1#2#3.#4% +% \end{macrocode} +% \subsection{\csh{xintLDg}, \csh{xintiiLDg}} +% \lverb|& +% LAST DIGIT. Simplified in 1.05. And prepared for extension by xintfrac +% to parse through \xintNum. Release 1.09a adds the \xintnum already here, +% and this propagates to \xintOdd, etc... 1.09e The \xintiiLDg is for +% defining \xintiiOdd which is used once (currently) elsewhere . +% +% bug fix (1.1b): \xintiiLDg is needed by the division macros next, thus +% it needs to be in the xintcore.sty. +% +% Rewritten for 1.2.| +% \begin{macrocode} +\def\xintLDg {\romannumeral0\xintldg }% +\def\xintldg #1{\xintiildg {\xintNum{#1}}}% +\def\xintiiLDg {\romannumeral0\xintiildg }% +\def\xintiildg #1% {% - \XINT_sub_AC_checkcarry #2{#3#4}% la retenue va \^etre examin\'ee + \expandafter\XINT_ldg_done\romannumeral0% + \expandafter\XINT_revdigits_a\the\numexpr\expandafter\XINT_microrevsep + \romannumeral0\expandafter\XINT_abs + \romannumeral-`0#1{\XINT_microrevsep_end\W}\XINT_microrevsep_end + \XINT_microrevsep_end\XINT_microrevsep_end + \XINT_microrevsep_end\XINT_microrevsep_end + \XINT_microrevsep_end\XINT_microrevsep_end\Z + 1\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W + \Z }% -\def\XINT_sub_AC_checkcarry #1% +\def\XINT_ldg_done #1#2\Z { #1}% +% \end{macrocode} +% \subsection{\csh{xintDouble}} +% \lverb|v1.08. Rewritten for v1.2.| +% \begin{macrocode} +\def\xintDouble {\romannumeral0\xintdouble }% +\def\xintdouble #1% {% - \xint_gob_til_one #1\xint_sub_AC_nocarry 1\XINT_sub_C + \expandafter\XINT_dbl\romannumeral-`0#1\Z }% -\def\xint_sub_AC_nocarry 1\XINT_sub_C #1#2\W\X\Y\Z +\def\XINT_dbl #1% {% - \expandafter - \XINT_cuz_loop - \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\W\W\W\W\W\W\W\Z + \xint_UDzerominusfork + #1-\XINT_dbl_zero + 0#1\XINT_dbl_neg + 0-{\XINT_dbl_pos #1}% + \krof }% -\def\xint_sub_cz\W\XINT_sub_AC_onestep #1% +\def\XINT_dbl_zero #1\Z { 0}% +\def\XINT_dbl_neg + {\expandafter\xint_minus_thenstop\romannumeral0\XINT_dbl_pos }% +\def\XINT_dbl_pos #1\Z {% - \XINT_cuz + \expandafter\XINT_dbl_pos_aa + \romannumeral0\expandafter\XINT_sepandrev + \romannumeral0\XINT_zeroes_forviii #1\R\R\R\R\R\R\R\R{10}0000001\W + #1\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax XX% + \R.\R.\R.\R.\R.\R.\R.\R.\W 1\Z!% + 1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% -\def\xint_sub_az\W\XINT_sub_B #1#2#3#4#5#6#7% +\def\XINT_dbl_pos_aa {% - \xint_gob_til_W - #4\xint_sub_ez - \W\XINT_sub_Eenter #1{#3}#4#5#6#7% + \expandafter\XINT_mul_out\the\numexpr\XINT_verysmallmul 0.2!% }% % \end{macrocode} -% \lverb|le premier nombre continue, le résultat sera < 0.| +% \subsection{\csh{xintHalf}} +% \lverb|v1.08. Rewritten for v1.2.| % \begin{macrocode} -\def\XINT_sub_Eenter #1#2% -{% - \expandafter - \XINT_sub_E\expandafter1\expandafter{\expandafter}% - \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 - \W\X\Y\Z #1% -}% -\def\XINT_sub_E #1#2#3#4#5#6% +\def\xintHalf {\romannumeral0\xinthalf }% +\def\xinthalf #1% {% - \xint_gob_til_W #3\xint_sub_F\W - \XINT_sub_Eonestep #1{#6#5#4#3}{#2}% + \expandafter\XINT_half\romannumeral-`0#1\Z }% -\def\XINT_sub_Eonestep #1#2% +\def\XINT_half #1% {% - \expandafter\XINT_sub_backtoE\the\numexpr 109999-#2+#1.% + \xint_UDzerominusfork + #1-\XINT_half_zero + 0#1\XINT_half_neg + 0-{\XINT_half_pos #1}% + \krof }% -\def\XINT_sub_backtoE #1#2#3.#4% +\def\XINT_half_zero #1\Z { 0}% +\def\XINT_half_neg {\expandafter\XINT_opp\romannumeral0\XINT_half_pos }% +\def\XINT_half_pos #1\Z {% - \XINT_sub_E #2{#3#4}% + \expandafter\XINT_half_pos_a + \romannumeral0\expandafter\XINT_sepandrev + \romannumeral0\XINT_zeroes_forviii #1\R\R\R\R\R\R\R\R{10}0000001\W + #1\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax XX% + \R.\R.\R.\R.\R.\R.\R.\R.\W + 1\Z!% + 1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% -\def\xint_sub_F\W\XINT_sub_Eonestep #1#2#3#4% +\def\XINT_half_pos_a + {\expandafter\XINT_half_pos_b\the\numexpr\XINT_verysmallmul 0.5!}% +\def\XINT_half_pos_b 1#1#2#3#4#5#6#7#8!1#9% {% - \xint_UDonezerofork - #4#1{\XINT_sub_Fdec 0}% soustraire 1. Et faire signe - - #1#4{\XINT_sub_Finc 1}% additionner 1. Et faire signe - - 10\XINT_sub_DD % terminer. Mais avec signe - - \krof - {#3}% + \xint_gob_til_Z #9\XINT_half_small \Z + \XINT_mul_out 1#1#2#3#4#5#6#7!1#9% }% -\def\XINT_sub_DD {\expandafter\xint_minus_thenstop\romannumeral0\XINT_sub_D }% -\def\XINT_sub_Fdec #1#2#3#4#5#6% +\edef\XINT_half_small \Z\XINT_mul_out 1#1!#2\W {% - \xint_gob_til_W #3\xint_sub_Fdec_finish\W - \XINT_sub_Fdec_onestep #1{#6#5#4#3}{#2}% + \noexpand\expandafter\space\noexpand\the\numexpr #1\relax }% -\def\XINT_sub_Fdec_onestep #1#2% +% \end{macrocode} +% \subsection{\csh{xintDec}} +% \lverb|v1.08. Rewritten for v1.2.| +% \begin{macrocode} +\def\xintDec {\romannumeral0\xintdec }% +\def\xintdec #1% {% - \expandafter\XINT_sub_backtoFdec\the\numexpr 11#2+#1-\xint_c_i.% + \expandafter\XINT_dec\romannumeral-`0#1\Z }% -\def\XINT_sub_backtoFdec #1#2#3.#4% +\def\XINT_dec #1% {% - \XINT_sub_Fdec #2{#3#4}% + \xint_UDzerominusfork + #1-\XINT_dec_zero + 0#1\XINT_dec_neg + 0-{\XINT_dec_pos #1}% + \krof }% -\def\xint_sub_Fdec_finish\W\XINT_sub_Fdec_onestep #1#2% +\def\XINT_dec_zero #1\Z { -1}% +\def\XINT_dec_neg + {\expandafter\xint_minus_thenstop\romannumeral0\XINT_inc_pos }% +\def\XINT_dec_pos #1\Z {% - \expandafter\xint_minus_thenstop\romannumeral0\XINT_cuz + \expandafter\XINT_dec_pos_aa + \romannumeral0\expandafter\XINT_sepandrev + \romannumeral0\XINT_zeroes_forviii #1\R\R\R\R\R\R\R\R{10}0000001\W + #1\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax XX% + \R.\R.\R.\R.\R.\R.\R.\R.\W + \Z!\Z!\Z!\Z!\Z!\W }% -\def\XINT_sub_Finc #1#2#3#4#5#6% +\def\XINT_dec_pos_aa {\XINT_sub_aa 100000001!\Z!\Z!\Z!\Z!\Z!\W }% +% \end{macrocode} +% \subsection{\csh{xintInc}} +% \lverb!v1.08. Rewritten for v1.2.! +% \begin{macrocode} +\def\xintInc {\romannumeral0\xintinc }% +\def\xintinc #1% {% - \xint_gob_til_W #3\xint_sub_Finc_finish\W - \XINT_sub_Finc_onestep #1{#6#5#4#3}{#2}% + \expandafter\XINT_inc\romannumeral-`0#1\Z }% -\def\XINT_sub_Finc_onestep #1#2% +\def\XINT_inc #1% {% - \expandafter\XINT_sub_backtoFinc\the\numexpr 10#2+#1.% + \xint_UDzerominusfork + #1-\XINT_inc_zero + 0#1\XINT_inc_neg + 0-{\XINT_inc_pos #1}% + \krof }% -\def\XINT_sub_backtoFinc #1#2#3.#4% +\def\XINT_inc_zero #1\Z { 1}% +\def\XINT_inc_neg {\expandafter\XINT_opp\romannumeral0\XINT_dec_pos }% +\def\XINT_inc_pos #1\Z +{% + \expandafter\XINT_inc_pos_aa + \romannumeral0\expandafter\XINT_sepandrev + \romannumeral0\XINT_zeroes_forviii #1\R\R\R\R\R\R\R\R{10}0000001\W + #1\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax XX% + \R.\R.\R.\R.\R.\R.\R.\R.\W + \Z!\Z!\Z!\Z!\Z!\W +}% +\def\XINT_inc_pos_aa {\XINT_add_aa 100000001!\Z!\Z!\Z!\Z!\Z!\W }% +% \end{macrocode} +% \subsection{Core arithmetic} +% \lverb|The four operations have been rewritten entirely for release v1.2. +% The new routines works with separated blocks of eight digits. They all measure +% first the lengths of the arguments, even addition and subtraction (this was +% not the case with xintcore.sty 1.1 or earlier.) +% +% The technique of chaining \the\numexpr induces a limitation on the +% maximal size depending on the size of the input save stack and the maximum +% expansion depth. For the current (TL2015) settings (5000, resp. 10000), the +% induced limit for addition of numbers is at 19968 and for multiplication +% it is observed to be 19959 (valid as of 2015/10/07). +% +% Side remark: I tested that \the\numexpr was more efficient than \number. But +% it reduced the allowable numbers for addition from 19976 digits to 19968 +% digits.| +% +% \subsection{\csbh{xintiAdd}, \csbh{xintiiAdd}} +% \begin{macrocode} +\def\xintiAdd {\romannumeral0\xintiadd }% +\def\xintiadd #1{\expandafter\XINT_iadd\romannumeral0\xintnum{#1}\Z }% +\def\xintiiAdd {\romannumeral0\xintiiadd }% +\def\xintiiadd #1{\expandafter\XINT_iiadd\romannumeral-`0#1\Z }% +\def\XINT_iiadd #1#2\Z #3% {% - \XINT_sub_Finc #2{#3#4}% + \expandafter\XINT_add_nfork\expandafter #1\romannumeral-`0#3\Z #2\Z }% -\def\xint_sub_Finc_finish\W\XINT_sub_Finc_onestep #1#2#3% +\def\XINT_iadd #1#2\Z #3% {% - \xint_UDzerofork - #1{\expandafter\expandafter\expandafter - \xint_minus_thenstop\xint_cleanupzeros_nostop}% - 0{ -1}% - \krof - #3% + \expandafter\XINT_add_nfork\expandafter #1\romannumeral0\xintnum{#3}\Z #2\Z }% -\def\xint_sub_ez\W\XINT_sub_Eenter #1% +\def\XINT_add_fork #1#2\Z #3\Z {\XINT_add_nfork #1#3\Z #2\Z}% +\def\XINT_add_nfork #1#2% {% \xint_UDzerofork - #1\XINT_sub_K % il y a une retenue - 0\XINT_sub_L % pas de retenue + #1\XINT_add_firstiszero + #2\XINT_add_secondiszero + 0{}% \krof + \xint_UDsignsfork + #1#2\XINT_add_minusminus + #1-\XINT_add_minusplus + #2-\XINT_add_plusminus + --\XINT_add_plusplus + \krof #1#2% }% -\def\XINT_sub_L #1\W\X\Y\Z {\XINT_cuz_loop #1\W\W\W\W\W\W\W\Z }% -\def\XINT_sub_K #1% -{% - \expandafter - \XINT_sub_KK\expandafter1\expandafter{\expandafter}% - \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 -}% -\def\XINT_sub_KK #1#2#3#4#5#6% -{% - \xint_gob_til_W #3\xint_sub_KK_finish\W - \XINT_sub_KK_onestep #1{#6#5#4#3}{#2}% +\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 {}{}}% +\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{}}% +\def\XINT_add_pp_a #1#2#3\Z +{% + \expandafter\XINT_add_pp_b + \romannumeral0\expandafter\XINT_sepandrev_andcount + \romannumeral0\XINT_zeroes_forviii #2#3\R\R\R\R\R\R\R\R{10}0000001\W + #2#3\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax\xint_c_ii\xint_c_iii + \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii + \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W + \X #1% +}% +\let\XINT_add_plusplus \XINT_add_pp_a +\def\XINT_add_pp_b #1.#2\X #3\Z +{% + \expandafter\XINT_add_checklengths + \the\numexpr #1\expandafter.% + \romannumeral0\expandafter\XINT_sepandrev_andcount + \romannumeral0\XINT_zeroes_forviii #3\R\R\R\R\R\R\R\R{10}0000001\W + #3\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax\xint_c_ii\xint_c_iii + \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii + \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W + \Z!\Z!\Z!\Z!\Z!\W #2\Z!\Z!\Z!\Z!\Z!\W +}% +\def\XINT_add_checklengths #1.#2.% +{% + \ifnum #2>#1 + \expandafter\XINT_add_exchange + \else + \expandafter\XINT_add_A + \fi + #1.#2.% }% -\def\XINT_sub_KK_onestep #1#2% +\def\XINT_add_exchange #1.#2.#3\Z!\Z!\Z!\Z!\Z!\W #4\Z {% - \expandafter\XINT_sub_backtoKK\the\numexpr 109999-#2+#1.% + \XINT_add_A #2.#1.#4\Z!\Z!\Z!\Z!\Z!\W #3\Z }% -\def\XINT_sub_backtoKK #1#2#3.#4% +\def\XINT_add_A #1.#2.% {% - \XINT_sub_KK #2{#3#4}% + \ifnum #1>\xint_c_vi % + \expandafter\XINT_add_aa + \else \expandafter\XINT_add_aa_small + \fi }% -\def\xint_sub_KK_finish\W\XINT_sub_KK_onestep #1#2#3% +%%%%%%%%%%%% +\def\XINT_add_out #1\Z #2\W% {% - \expandafter\xint_minus_thenstop - \romannumeral0\XINT_cuz_loop #3\W\W\W\W\W\W\W\Z + \expandafter\XINT_cuz_small\romannumeral0\XINT_unrevbyviii {}% + #11\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% -% \end{macrocode} -% \subsection{\csh{xintiMul}, \csh{xintiiMul}} -% \lverb|1.09a adds \xintnum| -% \begin{macrocode} -\def\xintiiMul {\romannumeral0\xintiimul }% -\def\xintiimul #1% +\def\XINT_add_out_small #1\Z #2\W% {% - \expandafter\xint_iimul\expandafter {\romannumeral-`0#1}% + \XINT_smallunrevbyviii #11\Z!1\R!1\R!1\R!1\R!1\R!1\R!\W }% -\def\xint_iimul #1#2% +%%%%%%%%%%%% +\def\XINT_add_aa {\expandafter\XINT_add_out\the\numexpr\XINT_add_a \xint_c_ii}% +\def\XINT_add_aa_small + {\expandafter\XINT_add_out_small\the\numexpr\XINT_add_a \xint_c_ii}% +\def\XINT_add_a #1!#2!#3!#4!#5\W #6!#7!#8!#9!% {% - \expandafter\XINT_mul_fork \romannumeral-`0#2\Z #1\Z + \XINT_add_b #1!#6!#2!#7!#3!#8!#4!#9!#5\W }% -\def\xintiMul {\romannumeral0\xintimul }% -\def\xintimul #1% +\def\XINT_add_b #1#2!#3!% {% - \expandafter\xint_mul\expandafter {\romannumeral0\xintnum{#1}}% + \xint_gob_til_Z #2\XINT_add_bi \Z + \expandafter\XINT_add_c\the\numexpr#1+#2+#3-\xint_c_ii.% }% -\def\xint_mul #1#2% +\def\XINT_add_bi\Z + \expandafter\XINT_add_c + \the\numexpr#1+#2+#3-\xint_c_ii.#4!#5!#6!#7!#8!#9!\Z !\W {% - \expandafter\XINT_mul_fork \romannumeral0\xintnum{#2}\Z #1\Z + \XINT_add_k #1#3!#5!#7!#9!% }% -\let\xintMul\xintiMul \let\xintmul\xintimul -\def\XINT_Mul #1#2{\romannumeral0\XINT_mul_fork #2\Z #1\Z }% -% \end{macrocode} -% \lverb|& -% MULTIPLICATION$\ -% Ici #1#2 = 2e input et #3#4 = 1er input $\ -% Release 1.03 adds some overhead to first compute and compare the -% lengths of the two inputs. The algorithm is asymmetrical and whether -% the first input is the longest or the shortest sometimes has a strong -% impact. 50 digits times 1000 digits used to be 5 times faster -% than 1000 digits times 50 digits. With the new code, the user input -% order does not matter as it is decided by the routine what is best. -% This is important for the extension to fractions, as there is no way -% then to generally control or guess the most frequent sizes of the -% inputs besides actually computing their lengths. | -% \begin{macrocode} -\def\XINT_mul_fork #1#2\Z #3#4\Z +\def\XINT_add_c #1#2.% {% - \xint_UDzerofork - #1\XINT_mul_zero - #3\XINT_mul_zero - 0{}% - \krof - \xint_UDsignsfork - #1#3\XINT_mul_minusminus % #1 = #3 = - - #1-{\XINT_mul_minusplus #3}% % #1 = - - #3-{\XINT_mul_plusminus #1}% % #3 = - - --{\XINT_mul_plusplus #1#3}% - \krof - {#2}{#4}% + 1#2\expandafter!\the\numexpr\XINT_add_d #1% }% -\def\XINT_mul_zero #1\krof #2#3{ 0}% -\def\XINT_mul_minusminus #1#2% +\def\XINT_add_d #1#2!#3!% {% - \expandafter\XINT_mul_choice_a - \expandafter{\romannumeral0\xintlength {#2}}% - {\romannumeral0\xintlength {#1}}{#1}{#2}% + \xint_gob_til_Z #2\XINT_add_di \Z + \expandafter\XINT_add_e\the\numexpr#1+#2+#3-\xint_c_ii.% }% -\def\XINT_mul_minusplus #1#2#3% +\def\XINT_add_di\Z\expandafter\XINT_add_e + \the\numexpr#1+#2+#3-\xint_c_ii.#4!#5!#6!#7!#8\W {% - \expandafter\xint_minus_thenstop\romannumeral0\expandafter - \XINT_mul_choice_a - \expandafter{\romannumeral0\xintlength {#1#3}}% - {\romannumeral0\xintlength {#2}}{#2}{#1#3}% + \XINT_add_k #1#3!#5!#7!% }% -\def\XINT_mul_plusminus #1#2#3% +\def\XINT_add_e #1#2.% {% - \expandafter\xint_minus_thenstop\romannumeral0\expandafter - \XINT_mul_choice_a - \expandafter{\romannumeral0\xintlength {#3}}% - {\romannumeral0\xintlength {#1#2}}{#1#2}{#3}% + 1#2\expandafter!\the\numexpr\XINT_add_f #1% }% -\def\XINT_mul_plusplus #1#2#3#4% +\def\XINT_add_f #1#2!#3!% {% - \expandafter\XINT_mul_choice_a - \expandafter{\romannumeral0\xintlength {#2#4}}% - {\romannumeral0\xintlength {#1#3}}{#1#3}{#2#4}% + \xint_gob_til_Z #2\XINT_add_fi \Z + \expandafter\XINT_add_g\the\numexpr#1+#2+#3-\xint_c_ii.% }% -\def\XINT_mul_choice_a #1#2% +\def\XINT_add_fi\Z\expandafter\XINT_add_g + \the\numexpr#1+#2+#3-\xint_c_ii.#4!#5!#6\W {% - \expandafter\XINT_mul_choice_b\expandafter{#2}{#1}% + \XINT_add_k #1#3!#5!% }% -\def\XINT_mul_choice_b #1#2% +\def\XINT_add_g #1#2.% {% - \ifnum #1<\xint_c_v - \expandafter\XINT_mul_choice_littlebyfirst - \else - \ifnum #2<\xint_c_v - \expandafter\expandafter\expandafter\XINT_mul_choice_littlebysecond - \else - \expandafter\expandafter\expandafter\XINT_mul_choice_compare - \fi - \fi - {#1}{#2}% + 1#2\expandafter!\the\numexpr\XINT_add_h #1% }% -\def\XINT_mul_choice_littlebyfirst #1#2#3#4% +\def\XINT_add_h #1#2!#3!% {% - \expandafter\XINT_mul_M - \expandafter{\the\numexpr #3\expandafter}% - \romannumeral0\XINT_RQ {}#4\R\R\R\R\R\R\R\R\Z \Z\Z\Z\Z + \xint_gob_til_Z #2\XINT_add_hi \Z + \expandafter\XINT_add_i\the\numexpr#1+#2+#3-\xint_c_ii.% }% -\def\XINT_mul_choice_littlebysecond #1#2#3#4% +\def\XINT_add_hi\Z + \expandafter\XINT_add_i\the\numexpr#1+#2+#3-\xint_c_ii.#4\W {% - \expandafter\XINT_mul_M - \expandafter{\the\numexpr #4\expandafter}% - \romannumeral0\XINT_RQ {}#3\R\R\R\R\R\R\R\R\Z \Z\Z\Z\Z + \XINT_add_k #1#3!% }% -\def\XINT_mul_choice_compare #1#2% +\def\XINT_add_i #1#2.% {% - \ifnum #1>#2 - \expandafter \XINT_mul_choice_i - \else - \expandafter \XINT_mul_choice_ii - \fi - {#1}{#2}% + 1#2\expandafter!\the\numexpr\XINT_add_a #1% }% -\def\XINT_mul_choice_i #1#2% +%%%%%%%%%%%% +\def\XINT_add_k #1% + {\if #12\expandafter\XINT_add_ke\else\expandafter\XINT_add_l \fi}% +\def\XINT_add_ke #1% {% - \ifnum #1<\numexpr\ifcase \numexpr (#2-\xint_c_iii)/\xint_c_iv\relax - \or 330\or 168\or 109\or 80\or 66\or 52\else 0\fi\relax - \expandafter\XINT_mul_choice_same - \else - \expandafter\XINT_mul_choice_permute - \fi + \xint_gob_til_Z #1\XINT_add_kf\Z 1% }% -\def\XINT_mul_choice_ii #1#2% +\def\XINT_add_kf\Z 1{1}% +\def\XINT_add_l #1% {% - \ifnum #2<\numexpr\ifcase \numexpr (#1-\xint_c_iii)/\xint_c_iv\relax - \or 330\or 168\or 109\or 80\or 66\or 52\else 0\fi\relax - \expandafter\XINT_mul_choice_permute - \else - \expandafter\XINT_mul_choice_same - \fi + \xint_gob_til_Z #1\XINT_add_lf\Z \XINT_add_m 1% }% -\def\XINT_mul_choice_same #1#2% +\def\XINT_add_lf\Z\XINT_add_m 1{100000001}% +\def\XINT_add_m #1!% {% - \expandafter\XINT_mul_enter - \romannumeral0\XINT_RQ {}#1\R\R\R\R\R\R\R\R\Z - \Z\Z\Z\Z #2\W\W\W\W + \expandafter\XINT_add_n\the\numexpr\xint_c_i+#1.% }% -\def\XINT_mul_choice_permute #1#2% +\def\XINT_add_n #1#2.% {% - \expandafter\XINT_mul_enter - \romannumeral0\XINT_RQ {}#2\R\R\R\R\R\R\R\R\Z - \Z\Z\Z\Z #1\W\W\W\W + 1#2\expandafter!\the\numexpr\XINT_add_o #1% }% +\def\XINT_add_o #1% + {\if #12\expandafter\XINT_add_l\else\expandafter\XINT_add_ke \fi}% % \end{macrocode} -% \lverb|& -% Cette portion de routine d'addition se branche directement sur _addr_ -% lorsque -% le premier nombre est épuisé, ce qui est garanti arriver avant le second -% nombre. Elle produit son résultat toujours sur 4n, renversé. Ses deux inputs -% sont garantis sur 4n.| +% \subsection{\csh{xintiSub}, \csh{xintiiSub}} +% \lverb|Entirely rewritten for v1.2.| % \begin{macrocode} -\def\XINT_mul_Ar #1#2#3#4#5#6% -{% - \xint_gob_til_Z #6\xint_mul_br\Z\XINT_mul_Br #1{#6#5#4#3}{#2}% -}% -\def\xint_mul_br\Z\XINT_mul_Br #1#2% -{% - \XINT_addr_AC_checkcarry #1% -}% -\def\XINT_mul_Br #1#2#3#4\W\X\Y\Z #5#6#7#8% +\def\xintiiSub {\romannumeral0\xintiisub }% +\def\xintiisub #1{\expandafter\XINT_iisub\romannumeral-`0#1\Z }% +\def\XINT_iisub #1#2\Z #3% {% - \expandafter\XINT_mul_ABEAr - \the\numexpr #1+10#2+#8#7#6#5.{#3}#4\W\X\Y\Z + \expandafter\XINT_sub_nfork\expandafter #1\romannumeral-`0#3\Z #2\Z }% -\def\XINT_mul_ABEAr #1#2#3#4#5#6.#7% +\def\xintiSub {\romannumeral0\xintisub }% +\def\xintisub #1{\expandafter\XINT_isub\romannumeral0\xintnum{#1}\Z }% +\def\XINT_isub #1#2\Z #3% {% - \XINT_mul_Ar #2{#7#6#5#4#3}% + \expandafter\XINT_sub_nfork\expandafter #1\romannumeral0\xintnum{#3}\Z #2\Z }% -% \end{macrocode} -% \subsubsection{``Small'' multiplication: \csh{XINT_mul_Mr}} -% \lverb|& -% << Petite >> multiplication. -% mul_Mr renvoie le résultat *à l'envers*, sur *4n*$\ -% \romannumeral0\XINT_mul_Mr {}\Z\Z\Z\Z$\ -% Fait la multiplication de par , qui est < 10000. -% est présenté *à l'envers*, sur *4n*. Lorsque vaut 0, donne 0000.| -% \begin{macrocode} -\def\XINT_mul_Mr #1% +\def\XINT_sub_nfork #1#2% {% - \expandafter\XINT_mul_Mr_checkifzeroorone\expandafter{\the\numexpr #1}% + \xint_UDzerofork + #1\XINT_sub_firstiszero + #2\XINT_sub_secondiszero + 0{}% + \krof + \xint_UDsignsfork + #1#2\XINT_sub_minusminus + #1-\XINT_sub_minusplus + #2-\XINT_sub_plusminus + --\XINT_sub_plusplus + \krof #1#2% }% -\def\XINT_mul_Mr_checkifzeroorone #1% +\def\XINT_sub_firstiszero #1\krof 0#2#3\Z #4\Z {\XINT_opp #2#3}% +\def\XINT_sub_secondiszero #1\krof #20#3\Z #4\Z { #2#4}% +\def\XINT_sub_plusminus #1#2{\XINT_add_pp_a #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}% +\def\XINT_sub_minusminus #1#2{\XINT_sub_mm_a {}{}}% +\def\XINT_sub_mm_a #1#2#3\Z +{% + \expandafter\XINT_sub_mm_b + \romannumeral0\expandafter\XINT_sepandrev_andcount + \romannumeral0\XINT_zeroes_forviii #2#3\R\R\R\R\R\R\R\R{10}0000001\W + #2#3\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax\xint_c_ii\xint_c_iii + \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii + \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W + \X #1% +}% +\def\XINT_sub_mm_b #1.#2\X #3\Z +{% + \expandafter\XINT_sub_checklengths + \the\numexpr #1\expandafter.% + \romannumeral0\expandafter\XINT_sepandrev_andcount + \romannumeral0\XINT_zeroes_forviii #3\R\R\R\R\R\R\R\R{10}0000001\W + #3\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax \xint_c_ii\xint_c_iii + \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii + \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W + \Z!\Z!\Z!\Z!\Z!\W #2\Z!\Z!\Z!\Z!\Z!\W +}% +\def\XINT_sub_checklengths #1.#2.% {% - \ifcase #1 - \expandafter\XINT_mul_Mr_zero - \or - \expandafter\XINT_mul_Mr_one + \ifnum #2>#1 + \expandafter\XINT_sub_exchange \else - \expandafter\XINT_mul_Nr + \expandafter\XINT_sub_aa \fi - {0000}{}{#1}% }% -\def\XINT_mul_Mr_zero #1\Z\Z\Z\Z { 0000}% -\def\XINT_mul_Mr_one #1#2#3#4\Z\Z\Z\Z { #4}% -\def\XINT_mul_Nr #1#2#3#4#5#6#7% +\def\XINT_sub_exchange #1\Z!\Z!\Z!\Z!\Z!\W #2\Z {% - \xint_gob_til_Z #4\xint_mul_pr\Z\XINT_mul_Pr {#1}{#3}{#7#6#5#4}{#2}{#3}% + \expandafter\XINT_opp\romannumeral0\XINT_sub_aa + #2\Z!\Z!\Z!\Z!\Z!\W #1\Z }% -\def\XINT_mul_Pr #1#2#3% +%%%%%%%%%%%% +\def\XINT_sub_prepare_rescue #1\W {\relax\Z-\W}% +\def\XINT_sub_prepare_cuz #1\W {\relax\XINT_cuz_byviii!\Z 0\W\R}% +%%%%%%%%%%%% +\def\XINT_sub_aa {\expandafter\XINT_sub_out\the\numexpr\XINT_sub_a \xint_c_i }% +\def\XINT_sub_out #1\Z #2#3\W {% - \expandafter\XINT_mul_Lr\the\numexpr \xint_c_x^viii+#1+#2*#3\relax + \if-#2\expandafter\XINT_sub_startrescue\fi + \expandafter\XINT_cuz_small + \romannumeral0\XINT_unrevbyviii {}#11\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% -\def\XINT_mul_Lr 1#1#2#3#4#5#6#7#8#9% +\def\XINT_sub_startrescue\expandafter\XINT_cuz_small + \romannumeral0\XINT_unrevbyviii #1#2\Z!#3\W {% - \XINT_mul_Nr {#1#2#3#4}{#9#8#7#6#5}% + \expandafter\XINT_sub_rescue_finish + \the\numexpr\XINT_sub_rescue_a #2!% + 1\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W \R }% -\def\xint_mul_pr\Z\XINT_mul_Pr #1#2#3#4#5% +\def\XINT_sub_rescue_finish + {\expandafter-\romannumeral0\expandafter\XINT_cuz + \romannumeral0\XINT_unrevbyviii {}}% +\def\XINT_sub_rescue_a #1!% {% - \xint_gob_til_zeros_iv #1\XINT_mul_Mr_end_nocarry 0000% - \XINT_mul_Mr_end_carry #1{#4}% + \expandafter\XINT_sub_rescue_c\the\numexpr \xint_c_xii_e_viii-#1.% }% -\def\XINT_mul_Mr_end_nocarry 0000\XINT_mul_Mr_end_carry 0000#1{ #1}% -\def\XINT_mul_Mr_end_carry #1#2#3#4#5{ #5#4#3#2#1}% -% \end{macrocode} -% \subsubsection{``Small'' multiplication variant: \csh{XINT_mul_M}} -% \lverb|& -% << Petite >> multiplication. -% renvoie le résultat *à l'endroit*, avec *nettoyage des leading zéros*.$\ -% \romannumeral0\XINT_mul_M {}\Z\Z\Z\Z$\ -% Fait la multiplication de par , qui est < 10000. -% est présenté *à l'envers*, sur *4n*. | -% \begin{macrocode} -\def\XINT_mul_M #1% +\def\XINT_sub_rescue_c 1#1#2.% {% - \expandafter\XINT_mul_M_checkifzeroorone\expandafter{\the\numexpr #1}% + 1#2\expandafter!\the\numexpr\XINT_sub_rescue_d #1% }% -\def\XINT_mul_M_checkifzeroorone #1% +\def\XINT_sub_rescue_d #1#2#3!% {% - \ifcase #1 - \expandafter\XINT_mul_M_zero - \or - \expandafter\XINT_mul_M_one - \else - \expandafter\XINT_mul_N - \fi - {0000}{}{#1}% + \xint_gob_til_minus #2\XINT_sub_rescue_z -% + \expandafter\XINT_sub_rescue_c\the\numexpr \xint_c_xii_e_viii_mone-#2#3+#1.% }% -\def\XINT_mul_M_zero #1\Z\Z\Z\Z { 0}% -\def\XINT_mul_M_one #1#2#3#4\Z\Z\Z\Z +\def\XINT_sub_rescue_z #1.{1!}% +%%%%%%%%%%%% +\def\XINT_sub_a #1!#2!#3!#4!#5\W #6!#7!#8!#9!% {% - \expandafter\xint_cleanupzeros_andstop\romannumeral0\xintreverseorder{#4}% + \XINT_sub_b #1!#6!#2!#7!#3!#8!#4!#9!#5\W }% -\def\XINT_mul_N #1#2#3#4#5#6#7% +\def\XINT_sub_b #1#2#3!#4!% {% - \xint_gob_til_Z #4\xint_mul_p\Z\XINT_mul_P {#1}{#3}{#7#6#5#4}{#2}{#3}% + \xint_gob_til_Z #2\XINT_sub_bi \Z + \expandafter\XINT_sub_c\the\numexpr#1+1#4-#3-\xint_c_i.% }% -\def\XINT_mul_P #1#2#3% +\def\XINT_sub_c 1#1#2.% {% - \expandafter\XINT_mul_L\the\numexpr \xint_c_x^viii+#1+#2*#3\relax + 1#2\expandafter!\the\numexpr\XINT_sub_d #1% }% -\def\XINT_mul_L 1#1#2#3#4#5#6#7#8#9% +\def\XINT_sub_d #1#2#3!#4!% {% - \XINT_mul_N {#1#2#3#4}{#5#6#7#8#9}% + \xint_gob_til_Z #2\XINT_sub_di \Z + \expandafter\XINT_sub_e\the\numexpr#1+1#4-#3-\xint_c_i.% }% -\def\xint_mul_p\Z\XINT_mul_P #1#2#3#4#5% +\def\XINT_sub_e 1#1#2.% {% - \XINT_mul_M_end #1#4% + 1#2\expandafter!\the\numexpr\XINT_sub_f #1% }% -\edef\XINT_mul_M_end #1#2#3#4#5#6#7#8% +\def\XINT_sub_f #1#2#3!#4!% {% - \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5#6#7#8\relax + \xint_gob_til_Z #2\XINT_sub_fi \Z + \expandafter\XINT_sub_g\the\numexpr#1+1#4-#3-\xint_c_i.% }% -% \end{macrocode} -% \subsubsection{Main routine: \csh{XINT_mul_enter}} -% \lverb|& -% Routine de multiplication principale -% (attention délimiteurs modifiés pour 1.08)$\ -% Le résultat partiel est toujours maintenu avec significatif à -% droite et il a un nombre multiple de 4 de chiffres$\ -% \romannumeral0\XINT_mul_enter \Z\Z\Z\Z \W\W\W\W$\ -% avec *renversé*, *longueur 4n* (zéros éventuellement ajoutés -% au-delà du chiffre le plus significatif) -% et dans l'ordre *normal*, et pas forcément longueur 4n. -% pas de signes.$\ -% Pour 1.08: dans \XINT_mul_enter et les modifs de 1.03 -% qui filtrent les courts, on pourrait croire que le -% second opérande a au moins quatre chiffres; mais le problème c'est que -% ceci est appelé par \XINT_sqr. Et de plus \XINT_sqr est utilisé dans -% la nouvelle routine d'extraction de racine carrée: je ne veux pas -% rajouter l'overhead à \XINT_sqr de voir si a longueur est au moins 4. -% Dilemme donc. Il ne semble pas y avoir d'autres accès -% directs (celui de big fac n'est pas un problème). J'ai presque été -% tenté de faire du 5x4, mais si on veut maintenir les résultats -% intermédiaires sur 4n, il y a des complications. Par ailleurs, -% je modifie aussi un petit peu la façon de coder la suite, compte tenu -% du style que j'ai développé ultérieurement. Attention terminaison -% modifiée pour le deuxième opérande.| -% \begin{macrocode} -\def\XINT_mul_enter #1\Z\Z\Z\Z #2#3#4#5% -{% - \xint_gob_til_W #5\XINT_mul_exit_a\W - \XINT_mul_start {#2#3#4#5}#1\Z\Z\Z\Z -}% -\def\XINT_mul_exit_a\W\XINT_mul_start #1% -{% - \XINT_mul_exit_b #1% -}% -\def\XINT_mul_exit_b #1#2#3#4% +\def\XINT_sub_g 1#1#2.% {% - \xint_gob_til_W - #2\XINT_mul_exit_ci - #3\XINT_mul_exit_cii - \W\XINT_mul_exit_ciii #1#2#3#4% + 1#2\expandafter!\the\numexpr\XINT_sub_h #1% }% -\def\XINT_mul_exit_ciii #1\W #2\Z\Z\Z\Z \W\W\W +\def\XINT_sub_h #1#2#3!#4!% {% - \XINT_mul_M {#1}#2\Z\Z\Z\Z + \xint_gob_til_Z #2\XINT_sub_hi \Z + \expandafter\XINT_sub_i\the\numexpr#1+1#4-#3-\xint_c_i.% }% -\def\XINT_mul_exit_cii\W\XINT_mul_exit_ciii #1\W\W #2\Z\Z\Z\Z \W\W +\def\XINT_sub_i 1#1#2.% {% - \XINT_mul_M {#1}#2\Z\Z\Z\Z + 1#2\expandafter!\the\numexpr\XINT_sub_a #1% }% -\def\XINT_mul_exit_ci\W\XINT_mul_exit_cii - \W\XINT_mul_exit_ciii #1\W\W\W #2\Z\Z\Z\Z \W +\def\XINT_sub_bi\Z + \expandafter\XINT_sub_c\the\numexpr#1+1#2-#3.#4!#5!#6!#7!#8!#9!\Z !\W {% - \XINT_mul_M {#1}#2\Z\Z\Z\Z + \XINT_sub_k #1#2!#5!#7!#9!% }% -\def\XINT_mul_start #1#2\Z\Z\Z\Z +\def\XINT_sub_di\Z + \expandafter\XINT_sub_e\the\numexpr#1+1#2-#3.#4!#5!#6!#7!#8\W {% - \expandafter\XINT_mul_main\expandafter - {\romannumeral0\XINT_mul_Mr {#1}#2\Z\Z\Z\Z}#2\Z\Z\Z\Z + \XINT_sub_k #1#2!#5!#7!% }% -\def\XINT_mul_main #1#2\Z\Z\Z\Z #3#4#5#6% +\def\XINT_sub_fi\Z + \expandafter\XINT_sub_g\the\numexpr#1+1#2-#3.#4!#5!#6\W {% - \xint_gob_til_W #6\XINT_mul_finish_a\W - \XINT_mul_compute {#3#4#5#6}{#1}#2\Z\Z\Z\Z + \XINT_sub_k #1#2!#5!% }% -\def\XINT_mul_compute #1#2#3\Z\Z\Z\Z +\def\XINT_sub_hi\Z + \expandafter\XINT_sub_i\the\numexpr#1+1#2-#3.#4\W {% - \expandafter\XINT_mul_main\expandafter - {\romannumeral0\expandafter - \XINT_mul_Ar\expandafter0\expandafter{\expandafter}% - \romannumeral0\XINT_mul_Mr {#1}#3\Z\Z\Z\Z - \W\X\Y\Z 0000#2\W\X\Y\Z }#3\Z\Z\Z\Z + \XINT_sub_k #1#2!% }% -% \end{macrocode} -% \lverb|& -% Ici, le deuxième nombre se termine. Fin du calcul. On utilise la variante -% \XINT_addm_A de l'addition car on sait que le deuxième terme est au moins -% aussi long que le premier. Lorsque le multiplicateur avait longueur 4n, la -% dernière addition a fourni le résultat à l'envers, il faut donc encore le -% renverser. | -% \begin{macrocode} -\def\XINT_mul_finish_a\W\XINT_mul_compute #1% +%%%%%%%%%%%% +\def\XINT_sub_k #1#2% {% - \XINT_mul_finish_b #1% + \xint_gob_til_Z #2\XINT_sub_p\Z \XINT_sub_l #1#2% }% -\def\XINT_mul_finish_b #1#2#3#4% +\def\XINT_sub_l #1% {% - \xint_gob_til_W - #1\XINT_mul_finish_c - #2\XINT_mul_finish_ci - #3\XINT_mul_finish_cii - \W\XINT_mul_finish_ciii #1#2#3#4% + \xint_UDzerofork + #1\XINT_sub_m + 0{}% + \krof }% -\def\XINT_mul_finish_ciii #1\W #2#3\Z\Z\Z\Z \W\W\W +\def\XINT_sub_m #1!% {% - \expandafter\XINT_addm_A\expandafter0\expandafter{\expandafter}% - \romannumeral0\XINT_mul_Mr {#1}#3\Z\Z\Z\Z \W\X\Y\Z 000#2\W\X\Y\Z + \expandafter\XINT_sub_n\the\numexpr 1#1-\xint_c_i!% }% -\def\XINT_mul_finish_cii - \W\XINT_mul_finish_ciii #1\W\W #2#3\Z\Z\Z\Z \W\W +\def\XINT_sub_n 1#1% {% - \expandafter\XINT_addm_A\expandafter0\expandafter{\expandafter}% - \romannumeral0\XINT_mul_Mr {#1}#3\Z\Z\Z\Z \W\X\Y\Z 00#2\W\X\Y\Z + \xint_UDzerofork + #1{\XINT_sub_o}% + 0{\XINT_sub_n_checkzero}% + \krof }% -\def\XINT_mul_finish_ci #1\XINT_mul_finish_ciii #2\W\W\W #3#4\Z\Z\Z\Z \W +\def\XINT_sub_o #1!{1#1\expandafter!\the\numexpr\XINT_sub_m }% +\def\XINT_sub_n_checkzero #1!% {% - \expandafter\XINT_addm_A\expandafter0\expandafter{\expandafter}% - \romannumeral0\XINT_mul_Mr {#2}#4\Z\Z\Z\Z \W\X\Y\Z 0#3\W\X\Y\Z + \xint_gob_til_eightzeroes #1\XINT_sub_n_prepare_cuz 00000000% + 1#1!% }% -\def\XINT_mul_finish_c #1\XINT_mul_finish_ciii \W\W\W\W #2#3\Z\Z\Z\Z +\def\XINT_sub_n_prepare_cuz 00000000100000000{1\XINT_sub_prepare_cuz}% +\def\XINT_sub_p\Z\XINT_sub_l #1\Z!% {% - \expandafter\xint_cleanupzeros_andstop\romannumeral0\xintreverseorder{#2}% + \xint_UDzerofork + #1{-1\XINT_sub_prepare_rescue}% + 0{1\XINT_sub_prepare_cuz }% + \krof }% % \end{macrocode} -% \subsubsection{Variant: \csh{XINT_mulr_enter}} -% \lverb|& -% \romannumeral0\XINT_mulr_enter \Z\Z\Z\Z \W\W\W\W $\ -% Ici est à l'envers sur 4n, et est à l'endroit, pas sur 4n, comme -% dans \XINT_mul_enter, mais le résultat est lui-même fourni *à l'envers*, sur -% *4n* (en faisant attention de ne pas avoir 0000 à la fin).$\ -% Utilisé par le calcul des puissances. J'ai modifié dans 1.08 sur le -% modèle de la nouvelle version de \XINT_mul_enter. Je pourrais économiser des -% macros et fusionner \XINT_mul_enter et \XINT_mulr_enter. Une autre fois.| +% \subsection{\csh{xintiMul}, \csh{xintiiMul}} +% \lverb|Completely rewritten for v1.2.| % \begin{macrocode} -\def\XINT_mulr_enter #1\Z\Z\Z\Z #2#3#4#5% +\def\xintiMul {\romannumeral0\xintimul }% +\def\xintimul #1% {% - \xint_gob_til_W #5\XINT_mulr_exit_a\W - \XINT_mulr_start {#2#3#4#5}#1\Z\Z\Z\Z + \expandafter\XINT_imul\romannumeral0\xintnum{#1}\Z }% -\def\XINT_mulr_exit_a\W\XINT_mulr_start #1% +\def\XINT_imul #1#2\Z #3% {% - \XINT_mulr_exit_b #1% + \expandafter\XINT_mul_nfork\expandafter #1\romannumeral0\xintnum{#3}\Z #2\Z }% -\def\XINT_mulr_exit_b #1#2#3#4% +\def\xintiiMul {\romannumeral0\xintiimul }% +\def\xintiimul #1% {% - \xint_gob_til_W - #2\XINT_mulr_exit_ci - #3\XINT_mulr_exit_cii - \W\XINT_mulr_exit_ciii #1#2#3#4% + \expandafter\XINT_iimul\romannumeral-`0#1\Z }% -\def\XINT_mulr_exit_ciii #1\W #2\Z\Z\Z\Z \W\W\W +\def\XINT_iimul #1#2\Z #3% {% - \XINT_mul_Mr {#1}#2\Z\Z\Z\Z + \expandafter\XINT_mul_nfork\expandafter #1\romannumeral-`0#3\Z #2\Z }% -\def\XINT_mulr_exit_cii\W\XINT_mulr_exit_ciii #1\W\W #2\Z\Z\Z\Z \W\W +% \end{macrocode} +% \lverb|I have changed the fork, and it complicates matters elsewhere.| +% \begin{macrocode} +\def\XINT_mul_fork #1#2\Z #3\Z{\XINT_mul_nfork #1#3\Z #2\Z}% +\def\XINT_mul_nfork #1#2% {% - \XINT_mul_Mr {#1}#2\Z\Z\Z\Z + \xint_UDzerofork + #1\XINT_mul_zero + #2\XINT_mul_zero + 0{}% + \krof + \xint_UDsignsfork + #1#2\XINT_mul_minusminus + #1-\XINT_mul_minusplus + #2-\XINT_mul_plusminus + --\XINT_mul_plusplus + \krof #1#2% }% -\def\XINT_mulr_exit_ci\W\XINT_mulr_exit_cii - \W\XINT_mulr_exit_ciii #1\W\W\W #2\Z\Z\Z\Z \W +\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}% +\def\XINT_mul_plusminus #1#2% + {\expandafter\xint_minus_thenstop\romannumeral0\XINT_mul_plusplus #1{}}% +\def\XINT_mul_plusplus #1#2#3\Z +{% + \expandafter\XINT_mul_pre_b + \romannumeral0\expandafter\XINT_sepandrev_andcount + \romannumeral0\XINT_zeroes_forviii #2#3\R\R\R\R\R\R\R\R{10}0000001\W + #2#3\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax\xint_c_ii\xint_c_iii + \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii + \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W + \W #1% +}% +\def\XINT_mul_pre_b #1.#2\W #3\Z +{% + \expandafter\XINT_mul_checklengths + \the\numexpr #1\expandafter.% + \romannumeral0\expandafter\XINT_sepandrev_andcount + \romannumeral0\XINT_zeroes_forviii #3\R\R\R\R\R\R\R\R{10}0000001\W + #3\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax\xint_c_ii\xint_c_iii + \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii + \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W + 1\Z!\W #21\Z!% + 1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W +}% +% \end{macrocode} +% \lverb|Cooking recipee, 2015/10/05.| +% \begin{macrocode} +\def\XINT_mul_checklengths #1.#2.% +{% + \ifnum #2=\xint_c_i\expandafter\XINT_mul_smallbyfirst\fi + \ifnum #1=\xint_c_i\expandafter\XINT_mul_smallbysecond\fi + \ifnum #2<#1 + \ifnum \numexpr (#2-\xint_c_i)*(#1-#2)<383 + \XINT_mul_exchange + \fi + \else + \ifnum \numexpr (#1-\xint_c_i)*(#2-#1)>383 + \XINT_mul_exchange + \fi + \fi + \XINT_mul_start +}% +\def\XINT_mul_smallbyfirst #1\XINT_mul_start 1#2!1\Z!\W +{% + \ifnum#2=\xint_c_i\expandafter\XINT_mul_oneisone\fi + \ifnum#2<\xint_c_xxii\expandafter\XINT_mul_verysmall\fi + \expandafter\XINT_mul_out\the\numexpr\XINT_smallmul 1#2!% +}% +\def\XINT_mul_smallbysecond #1\XINT_mul_start #2\W 1#3!1\Z!% +{% + \ifnum#3=\xint_c_i\expandafter\XINT_mul_oneisone\fi + \ifnum#3<\xint_c_xxii\expandafter\XINT_mul_verysmall\fi + \expandafter\XINT_mul_out\the\numexpr\XINT_smallmul 1#3!#2% +}% +\def\XINT_mul_oneisone #1!{\XINT_mul_out }% +\def\XINT_mul_verysmall\expandafter\XINT_mul_out + \the\numexpr\XINT_smallmul 1#1!% + {\expandafter\XINT_mul_out\the\numexpr\XINT_verysmallmul 0.#1!}% +\def\XINT_mul_exchange #1\XINT_mul_start #2\W #31\Z!% + {\fi\fi\XINT_mul_start #31\Z!\W #2}% +\def\XINT_mul_start + {\expandafter\XINT_mul_out\the\numexpr\XINT_mul_loop 100000000!\Z\W}% +\def\XINT_mul_out + {\expandafter\XINT_cuz_small\romannumeral0\XINT_unrevbyviii {}}% +\def\XINT_mul_loop #1\Z #2\W #3\W 1#4!% +{% + \xint_gob_til_Z #4\XINT_mul_e \Z + \expandafter\XINT_mul_a\the\numexpr \XINT_smallmul 1#4!#3\W + #11!\W #3\W +}% +\def\XINT_mul_a #11\Z!\W #2!1!#3\W +{% + \expandafter\XINT_mul_b\the\numexpr + \XINT_add_a \xint_c_ii #2!\Z!\Z!\Z!\Z!\Z!\W #1\Z!\Z!\Z!\Z!\Z!\W +}% +\def\XINT_mul_b 1#1!{1#1\expandafter!\the\numexpr\XINT_mul_loop }% +\def\XINT_mul_e\Z #1\W #2!1!#3\W #4\W {#2!1\Z!}% +% \end{macrocode} +% \lverb|1.2 small and mini multiplication in base 10^8 with carry. On output +% the small multiplication suppresses ending zeroes. The situation is +% different with addition which may end up inserting a final 1!, thus +% multiplication is « cleaner » in that aspect. Used by the main +% multiplication routines. But division, float factorial, etc.. have their +% own variants as they need output with specific constraints. +% | +% \begin{macrocode} +\def\XINT_minimulwc_a 1#1.#2.#3!#4#5#6#7#8.% {% - \XINT_mul_Mr {#1}#2\Z\Z\Z\Z + \expandafter\XINT_minimulwc_b + \the\numexpr \xint_c_x^ix+#1+#3*#8.#3*#4#5#6#7+#2*#8.#2*#4#5#6#7.% }% -\def\XINT_mulr_start #1#2\Z\Z\Z\Z +\def\XINT_minimulwc_b 1#1#2#3#4#5#6.#7.% {% - \expandafter\XINT_mulr_main\expandafter - {\romannumeral0\XINT_mul_Mr {#1}#2\Z\Z\Z\Z}#2\Z\Z\Z\Z + \expandafter\XINT_minimulwc_c + \the\numexpr \xint_c_x^ix+#1#2#3#4#5+#7.#6.% }% -\def\XINT_mulr_main #1#2\Z\Z\Z\Z #3#4#5#6% +\def\XINT_minimulwc_c 1#1#2#3#4#5#6.#7.#8.% {% - \xint_gob_til_W #6\XINT_mulr_finish_a\W - \XINT_mulr_compute {#3#4#5#6}{#1}#2\Z\Z\Z\Z + 1#6#7\expandafter!% + \the\numexpr\expandafter\XINT_smallmul_a + \the\numexpr \xint_c_x^viii+#1#2#3#4#5+#8.% }% -\def\XINT_mulr_compute #1#2#3\Z\Z\Z\Z +\def\XINT_smallmul 1#1#2#3#4#5!{\XINT_smallmul_a 100000000.#1#2#3#4.#5!}% +\def\XINT_smallmul_a #1.#2.#3!1#4!% {% - \expandafter\XINT_mulr_main\expandafter - {\romannumeral0\expandafter - \XINT_mul_Ar\expandafter0\expandafter{\expandafter}% - \romannumeral0\XINT_mul_Mr {#1}#3\Z\Z\Z\Z - \W\X\Y\Z 0000#2\W\X\Y\Z }#3\Z\Z\Z\Z + \xint_gob_til_Z #4\XINT_smallmul_e\Z + \XINT_minimulwc_a #1.#2.#3!#4.#2.#3!% }% -\def\XINT_mulr_finish_a\W\XINT_mulr_compute #1% +\def\XINT_smallmul_e\Z\XINT_minimulwc_a 1#1.#2\Z #3!% + {\xint_gob_til_eightzeroes #1\XINT_smallmul_f 000000001\relax #1!1\Z!}% +\def\XINT_smallmul_f 000000001\relax 00000000!1{1\relax}% +% \end{macrocode} +% \lverb|This is multiplication by 1 up to 21. Last time I checked it is never +% called with a wasteful multiplicand of 1.| +% \begin{macrocode} +\def\XINT_verysmallmul #1.#2!1#3!% {% - \XINT_mulr_finish_b #1% + \xint_gob_til_Z #3\XINT_verysmallmul_e\Z + \expandafter\XINT_verysmallmul_a + \the\numexpr #2*#3+#1.#2!% }% -\def\XINT_mulr_finish_b #1#2#3#4% +\def\XINT_verysmallmul_e\Z\expandafter\XINT_verysmallmul_a\the\numexpr + #1+#2#3.#4!% +{\xint_gob_til_zero #2\XINT_verysmallmul_f 0\xint_c_x^viii+#2#3!1\Z!}% +\def\XINT_verysmallmul_f #1!1{1\relax}% +\def\XINT_verysmallmul_a #1#2.% {% - \xint_gob_til_W - #1\XINT_mulr_finish_c - #2\XINT_mulr_finish_ci - #3\XINT_mulr_finish_cii - \W\XINT_mulr_finish_ciii #1#2#3#4% + \unless\ifnum #1#2<\xint_c_x^ix + \expandafter\XINT_verysmallmul_bi\else + \expandafter\XINT_verysmallmul_bj\fi + \the\numexpr \xint_c_x^ix+#1#2.% }% -\def\XINT_mulr_finish_ciii #1\W #2#3\Z\Z\Z\Z \W\W\W +\def\XINT_verysmallmul_bj{\expandafter\XINT_verysmallmul_cj }% +\def\XINT_verysmallmul_cj 1#1#2.% + {1#2\expandafter!\the\numexpr\XINT_verysmallmul #1.}% +\def\XINT_verysmallmul_bi\the\numexpr\xint_c_x^ix+#1#2#3.% + {1#3\expandafter!\the\numexpr\XINT_verysmallmul #1#2.}% +% \end{macrocode} +% \lverb|Used by division and by squaring, not by multiplication itself.| +% \begin{macrocode} +\def\XINT_minimul_a #1.#2!#3#4#5#6#7!% {% - \expandafter\XINT_addp_A\expandafter0\expandafter{\expandafter}% - \romannumeral0\XINT_mul_Mr {#1}#3\Z\Z\Z\Z \W\X\Y\Z 000#2\W\X\Y\Z + \expandafter\XINT_minimul_b + \the\numexpr \xint_c_x^viii+#2*#7.#2*#3#4#5#6+#1*#7.#1*#3#4#5#6.% }% -\def\XINT_mulr_finish_cii - \W\XINT_mulr_finish_ciii #1\W\W #2#3\Z\Z\Z\Z \W\W +\def\XINT_minimul_b 1#1#2#3#4#5.#6.% {% - \expandafter\XINT_addp_A\expandafter0\expandafter{\expandafter}% - \romannumeral0\XINT_mul_Mr {#1}#3\Z\Z\Z\Z \W\X\Y\Z 00#2\W\X\Y\Z + \expandafter\XINT_minimul_c + \the\numexpr \xint_c_x^ix+#1#2#3#4+#6.#5.% }% -\def\XINT_mulr_finish_ci #1\XINT_mulr_finish_ciii #2\W\W\W #3#4\Z\Z\Z\Z \W +\def\XINT_minimul_c 1#1#2#3#4#5#6.#7.#8.% {% - \expandafter\XINT_addp_A\expandafter0\expandafter{\expandafter}% - \romannumeral0\XINT_mul_Mr {#2}#4\Z\Z\Z\Z \W\X\Y\Z 0#3\W\X\Y\Z + 1#6#7\expandafter!\the\numexpr \xint_c_x^viii+#1#2#3#4#5+#8!% }% -\def\XINT_mulr_finish_c #1\XINT_mulr_finish_ciii \W\W\W\W #2#3\Z\Z\Z\Z { #2}% % \end{macrocode} % \subsection{\csh{xintiSqr}, \csh{xintiiSqr}} +% \lverb|Rewritten for v1.2.| % \begin{macrocode} \def\xintiiSqr {\romannumeral0\xintiisqr }% \def\xintiisqr #1% {% - \expandafter\XINT_sqr\expandafter {\romannumeral0\xintiiabs{#1}}% + \expandafter\XINT_sqr\romannumeral0\xintiiabs{#1}\Z }% \def\xintiSqr {\romannumeral0\xintisqr }% \def\xintisqr #1% {% - \expandafter\XINT_sqr\expandafter {\romannumeral0\xintiabs{#1}}% + \expandafter\XINT_sqr\romannumeral0\xintiabs{#1}\Z +}% +\def\XINT_sqr #1\Z +{% + \expandafter\XINT_sqr_a + \romannumeral0\expandafter\XINT_sepandrev_andcount + \romannumeral0\XINT_zeroes_forviii #1\R\R\R\R\R\R\R\R{10}0000001\W + #1\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax\xint_c_ii\xint_c_iii + \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii + \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W + \Z +}% +\def\XINT_sqr_a #1.% +{% + \ifnum #1=\xint_c_i \expandafter\XINT_sqr_small + \else\expandafter\XINT_sqr_start\fi +}% +\def\XINT_sqr_small 1#1#2#3#4#5!\Z +{% + \ifnum #1#2#3#4#5<46341 \expandafter\XINT_sqr_verysmall\fi + \expandafter\XINT_sqr_small_out + \the\numexpr\XINT_minimul_a #1#2#3#4.#5!#1#2#3#4#5!% +}% +\edef\XINT_sqr_verysmall + \expandafter\XINT_sqr_small_out\the\numexpr\XINT_minimul_a #1!#2!% + {\noexpand\expandafter\space\noexpand\the\numexpr #2*#2\relax}% +\def\XINT_sqr_small_out 1#1!1#2!% +{% + \XINT_cuz #2#1\R }% -\let\xintSqr\xintiSqr \let\xintsqr\xintisqr -\def\XINT_sqr #1% +\def\XINT_sqr_start #1\Z {% - \expandafter\XINT_mul_enter - \romannumeral0% - \XINT_RQ {}#1\R\R\R\R\R\R\R\R\Z - \Z\Z\Z\Z #1\W\W\W\W + \expandafter\XINT_mul_out + \the\numexpr\XINT_mul_loop 100000000!\Z\W #11\Z!\W #11\Z!% + 1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% % \end{macrocode} % \subsection{\csh{xintiPow}, \csh{xintiiPow}} -% \lverb|1.02 modified the \XINT_posprod routine, the was renamed -% \XINT_pow_posprod and moved here, as it was well adapted for computing powers. -% Then 1.03 moved the special variants of multiplication (hence of addition) -% which were needed to earlier in this style file. -% -% Modified in 1.06, the exponent is given to a \numexpr rather than twice -% expanded. \xintnum added in 1.09a. -% -% \XINT_pow_posprod: Routine de produit servant pour le calcul des -% puissances. Chaque nouveau terme est plus grand que ce qui a déjà été calculé. -% Par conséquent on a intérêt à le conserver en second dans la routine de -% multiplication, donc le précédent calcul a intérêt à avoir été donné sur 4n, à -% l'envers. Il faut donc modifier la multiplication pour qu'elle fasse cela. Ce -% qui oblige à utiliser une version spéciale de l'addition également. -% -% 1.09j has reorganized the main loop, the described above \XINT_pow_posprod -% routine has been removed, intermediate multiplications are done -% immediately. Also, the maximal accepted exponent is now 100000 (no such -% restriction in \xintFloatPow, which accepts any exponent less than 2^31, and -% in \xintFloatPower which accepts long integers as exponent). -% -% 2^100000=9.990020930143845e30102 and multiplication of two numbers -% with 30000 digits would take hours on my laptop (seconds for 1000 digits).| +% \lverb|& +% The exponent is not limited but with current default settings of tex memory, +% with xint 1.2, the maximal exponent for 2^N is N = 2^17 = 131072.| % \begin{macrocode} \def\xintiiPow {\romannumeral0\xintiipow }% \def\xintiipow #1% @@ -17076,7 +16825,6 @@ $1$ or $-1$. {% \expandafter\xint_pow\romannumeral0\xintnum{#1}\Z% }% -\let\xintPow\xintiPow \let\xintpow\xintipow \def\xint_pow #1#2\Z {% \xint_UDsignfork @@ -17135,132 +16883,248 @@ $1$ or $-1$. \xint_afterfi {\xintError:DivisionByZero\space 0}% \fi }% -\def\XINT_pow_AatleastTwo #1% +\def\XINT_pow_AatleastTwo #1% +{% + \ifcase\XINT_cntSgn #1\Z + \expandafter\XINT_pow_BisZero + \or + \expandafter\XINT_pow_I_in + \else + \expandafter\XINT_pow_BisNegative + \fi + {#1}% +}% +\edef\XINT_pow_BisNegative #1#2% + {\noexpand\xintError:FractionRoundedToZero\space 0}% +\def\XINT_pow_BisZero #1#2{ 1}% +% \end{macrocode} +% \lverb|B = #1 > 0, A = #2 > 1.| +% \begin{macrocode} +% \def\XINT_pow_checkBsize #1% +% {% +% \ifnum #1>131000 +% \expandafter\XINT_pow_BtooBig +% \else +% \expandafter\XINT_pow_I_in +% \fi +% {#1}% +% }% +% \edef\XINT_pow_BtooBig #1#2{\noexpand\xintError:ExponentTooBig\space 0}% +%%%%%%%%%%%% +\def\XINT_pow_I_in #1#2% +{% + \expandafter\XINT_pow_I_loop + \the\numexpr #1\expandafter.% + \romannumeral0\expandafter\XINT_sepandrev + \romannumeral0\XINT_zeroes_forviii #2\R\R\R\R\R\R\R\R{10}0000001\W + #2\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax XX% + \R.\R.\R.\R.\R.\R.\R.\R.\W 1\Z!\W + 1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W +}% +\def\XINT_pow_I_loop #1.% +{% + \ifnum #1 = \xint_c_i\expandafter\XINT_pow_I_exit\fi + \ifodd #1 + \expandafter\XINT_pow_II_in + \else + \expandafter\XINT_pow_I_squareit + \fi #1.% +}% +\def\XINT_pow_I_exit \ifodd #1\fi #2.#3\W {\XINT_mul_out #3}% +\def\XINT_pow_I_squareit #1.#2\W% +{% + \expandafter\XINT_pow_I_loop + \the\numexpr #1/\xint_c_ii\expandafter.% + \the\numexpr\XINT_pow_mulbutcheckifsmall #2\W #2\W +}% +%%%%%%%%%%%% +\def\XINT_pow_mulbutcheckifsmall #1!1#2% +{% + \xint_gob_til_Z #2\XINT_pow_mul_small\Z + \XINT_mul_loop 100000000!\Z\W #1!1#2% +}% +\def\XINT_pow_mul_small\Z\XINT_mul_loop 100000000!\Z\W 1#1!1\Z!\W +{% + \XINT_smallmul 1#1!% +}% +%%%%%%%%%%%% +\def\XINT_pow_II_in #1.#2\W +{% + \expandafter\XINT_pow_II_loop + \the\numexpr #1/\xint_c_ii-\xint_c_i\expandafter.% + \the\numexpr\XINT_pow_mulbutcheckifsmall #2\W #2\W #2\W +}% +\def\XINT_pow_II_loop #1.% +{% + \ifnum #1 = \xint_c_i\expandafter\XINT_pow_II_exit\fi + \ifodd #1 + \expandafter\XINT_pow_II_odda + \else + \expandafter\XINT_pow_II_even + \fi #1.% +}% +\def\XINT_pow_II_exit\ifodd #1\fi #2.#3\W #4\W +{% + \expandafter\XINT_mul_out + \the\numexpr\XINT_pow_mulbutcheckifsmall #4\W #3% +}% +\def\XINT_pow_II_even #1.#2\W +{% + \expandafter\XINT_pow_II_loop + \the\numexpr #1/\xint_c_ii\expandafter.% + \the\numexpr\XINT_pow_mulbutcheckifsmall #2\W #2\W +}% +\def\XINT_pow_II_odda #1.#2\W #3\W +{% + \expandafter\XINT_pow_II_oddb + \the\numexpr #1/\xint_c_ii-\xint_c_i\expandafter.% + \the\numexpr\XINT_pow_mulbutcheckifsmall #3\W #2\W #2\W +}% +\def\XINT_pow_II_oddb #1.#2\W #3\W +{% + \expandafter\XINT_pow_II_loop + \the\numexpr #1\expandafter.% + \the\numexpr\XINT_pow_mulbutcheckifsmall #3\W #3\W #2\W +}% +% \end{macrocode} +% \subsection{\csh{xintiFac}, \csh{xintiiFac}} +% \lverb|Moved to xintcore.sty with release 1.2 (to be usable by \bnumexpr). +% The routine has been partially rewritten and there is an intrinsic limit at +% 9999. Anyhow with current default settings of the etex memory and the +% current 1.2 routine (last commit: eada1b1), the maximal possible computation +% is 5971! (which has 19956 digits). Also, I add \xintiiFac which does only +% \romannumeral-`0 and not \numexpr on its argument. This is for a silly +% slight optimization of the \xintiiexpr (and \bnumexpr) parsers. If the +% argument is >=2^31 an arithmetic overflow will occur in the \ifnum. This is +% not as good as in the \numexpr, but well.| +% \begin{macrocode} +\def\xintiFac {\romannumeral0\xintifac }% +\def\xintifac #1% +{% + \expandafter\XINT_fac_fork\expandafter {\the\numexpr#1}% +}% +\def\xintiiFac {\romannumeral0\xintiifac }% +\def\xintiifac #1% +{% + \expandafter\XINT_fac_fork\expandafter {\romannumeral-`0#1}% +}% +\let\xintFac\xintiFac \let\xintfac\xintifac +\def\XINT_fac_fork #1% {% \ifcase\XINT_cntSgn #1\Z - \expandafter\XINT_pow_BisZero + \xint_afterfi{\expandafter\space\expandafter 1\xint_gobble_i }% \or - \expandafter\XINT_pow_checkBsize + \expandafter\XINT_fac_checksize \else - \expandafter\XINT_pow_BisNegative + \xint_afterfi{\expandafter\xintError:FactorialOfNegativeNumber + \expandafter\space\expandafter 1\xint_gobble_i }% \fi {#1}% }% -\edef\XINT_pow_BisNegative #1#2% - {\noexpand\xintError:FractionRoundedToZero\space 0}% -\def\XINT_pow_BisZero #1#2{ 1}% -% \end{macrocode} -% \lverb|B = #1 > 0, A = #2 > 1. With 1.05, I replace \xintiLen{#1}>9 by -% direct use of \numexpr [to generate an error message if the exponent is too -% large] 1.06: \numexpr was already used above.| -% \begin{macrocode} -\def\XINT_pow_checkBsize #1% +\def\XINT_fac_checksize #1% {% - \ifnum #1>100000 - \expandafter\XINT_pow_BtooBig - \else - \expandafter\XINT_pow_loopI - \fi - {#1}% + \ifnum #1>9999 + \xint_dothis{\expandafter\xintError:FactorialOfTooBigNumber + \expandafter\space\expandafter 1\xint_gob_til_W }\fi + \ifnum #1>465 \xint_dothis{\XINT_fac_bigloop_a #1.}\fi + \ifnum #1>101 \xint_dothis{\XINT_fac_medloop_a #1.\XINT_mul_out}\fi + \xint_orthat{\XINT_fac_smallloop_a #1.\XINT_mul_out}% + 1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W }% -\edef\XINT_pow_BtooBig #1#2{\noexpand\xintError:ExponentTooBig\space 0}% -\def\XINT_pow_loopI #1% +\def\XINT_fac_bigloop_a #1.% {% - \ifnum #1=\xint_c_i\XINT_pow_Iend\fi - \ifodd #1 - \expandafter\XINT_pow_loopI_odd - \else - \expandafter\XINT_pow_loopI_even - \fi - {#1}% + \expandafter\XINT_fac_bigloop_b \the\numexpr + #1+\xint_c_i-\xint_c_ii*((#1-464)/\xint_c_ii).#1.% }% -\edef\XINT_pow_Iend\fi #1\fi #2#3{\noexpand\fi\space #3}% -\def\XINT_pow_loopI_even #1#2% +\def\XINT_fac_bigloop_b #1.#2.% {% - \expandafter\XINT_pow_loopI\expandafter - {\the\numexpr #1/\xint_c_ii\expandafter}\expandafter - {\romannumeral0\xintiisqr {#2}}% + \expandafter\XINT_fac_medloop_a + \the\numexpr #1-\xint_c_i.{\XINT_fac_bigloop_loop #1.#2.}% }% -\def\XINT_pow_loopI_odd #1#2% +\def\XINT_fac_bigloop_loop #1.#2.% {% - \expandafter\XINT_pow_loopI_odda\expandafter - {\romannumeral0\XINT_RQ {}#2\R\R\R\R\R\R\R\R\Z }{#1}{#2}% + \ifnum #1>#2 \expandafter\XINT_fac_bigloop_exit\fi + \expandafter\XINT_fac_bigloop_loop + \the\numexpr #1+\xint_c_ii\expandafter.% + \the\numexpr #2\expandafter.\the\numexpr\XINT_fac_bigloop_mul #1!% }% -\def\XINT_pow_loopI_odda #1#2#3% +\def\XINT_fac_bigloop_exit #1!{\XINT_mul_out}% +\def\XINT_fac_bigloop_mul #1!% {% - \expandafter\XINT_pow_loopII\expandafter - {\the\numexpr #2/\xint_c_ii-\xint_c_i\expandafter}\expandafter - {\romannumeral0\xintiisqr {#3}}{#1}% + \expandafter\XINT_smallmul + \the\numexpr \xint_c_x^viii+#1*(#1+\xint_c_i)!% }% -\def\XINT_pow_loopII #1% +\def\XINT_fac_medloop_a #1.% {% - \ifnum #1 = \xint_c_i\XINT_pow_IIend\fi - \ifodd #1 - \expandafter\XINT_pow_loopII_odd - \else - \expandafter\XINT_pow_loopII_even - \fi - {#1}% + \expandafter\XINT_fac_medloop_b + \the\numexpr #1+\xint_c_i-\xint_c_iii*((#1-100)/\xint_c_iii).#1.% }% -\def\XINT_pow_loopII_even #1#2% +\def\XINT_fac_medloop_b #1.#2.% {% - \expandafter\XINT_pow_loopII\expandafter - {\the\numexpr #1/\xint_c_ii\expandafter}\expandafter - {\romannumeral0\xintiisqr {#2}}% + \expandafter\XINT_fac_smallloop_a + \the\numexpr #1-\xint_c_i.{\XINT_fac_medloop_loop #1.#2.}% }% -\def\XINT_pow_loopII_odd #1#2#3% +\def\XINT_fac_medloop_loop #1.#2.% {% - \expandafter\XINT_pow_loopII_odda\expandafter - {\romannumeral0\XINT_mulr_enter #3\Z\Z\Z\Z #2\W\W\W\W}{#1}{#2}% + \ifnum #1>#2 \expandafter\XINT_fac_loop_exit\fi + \expandafter\XINT_fac_medloop_loop + \the\numexpr #1+\xint_c_iii\expandafter.% + \the\numexpr #2\expandafter.\the\numexpr\XINT_fac_medloop_mul #1!% }% -\def\XINT_pow_loopII_odda #1#2#3% +\def\XINT_fac_medloop_mul #1!% {% - \expandafter\XINT_pow_loopII\expandafter - {\the\numexpr #2/\xint_c_ii-\xint_c_i\expandafter}\expandafter - {\romannumeral0\xintiisqr {#3}}{#1}% + \expandafter\XINT_smallmul + \the\numexpr + \xint_c_x^viii+#1*(#1+\xint_c_i)*(#1+\xint_c_ii)!% +}% +\def\XINT_fac_smallloop_a #1.% +{% + \csname + XINT_fac_smallloop_\the\numexpr #1-\xint_c_iv*(#1/\xint_c_iv)\relax + \endcsname #1.% +}% +\expandafter\def\csname XINT_fac_smallloop_1\endcsname #1.% +{% + \XINT_fac_smallloop_loop 2.#1.100000001!1\Z!% +}% +\expandafter\def\csname XINT_fac_smallloop_-2\endcsname #1.% +{% + \XINT_fac_smallloop_loop 3.#1.100000002!1\Z!% +}% +\expandafter\def\csname XINT_fac_smallloop_-1\endcsname #1.% +{% + \XINT_fac_smallloop_loop 4.#1.100000006!1\Z!% +}% +\expandafter\def\csname XINT_fac_smallloop_0\endcsname #1.% +{% + \XINT_fac_smallloop_loop 5.#1.1000000024!1\Z!% +}% +\def\XINT_fac_smallloop_loop #1.#2.% +{% + \ifnum #1>#2 \expandafter\XINT_fac_loop_exit\fi + \expandafter\XINT_fac_smallloop_loop + \the\numexpr #1+\xint_c_iv\expandafter.% + \the\numexpr #2\expandafter.\the\numexpr\XINT_fac_smallloop_mul #1!% }% -\def\XINT_pow_IIend\fi #1\fi #2#3#4% +\def\XINT_fac_smallloop_mul #1!% {% - \fi\XINT_mul_enter #4\Z\Z\Z\Z #3\W\W\W\W + \expandafter\XINT_smallmul + \the\numexpr + \xint_c_x^viii+#1*(#1+\xint_c_i)*(#1+\xint_c_ii)*(#1+\xint_c_iii)!% }% +\def\XINT_fac_loop_exit #1!#2\Z!#3{#3#2\Z!}% % \end{macrocode} % \subsection{\csh{xintiDivision}, \csh{xintiQuo}, \csh{xintiRem}, % \csh{xintiiDivision}, \csh{xintiiQuo}, \csh{xintiiRem}} -% \lverb|The 1.09a release inserted the use of \xintnum. The \xintiiDivision -% etc... are the ones which do only \romannumeral-`0. -% -% January 5, 2014: Naturally, addition, subtraction, multiplication and division -% are the first things I did and since then I had left the division -% untouched. So in preparation of release 1.09j, I started revisiting the -% division, I did various minor improvements obtaining roughly -% 10$% efficiency gain. Then I decided I -% should deliberately impact the input save stack, with the hope to gain more -% speed from removing tokens and leaving them upstream. -% -% For this however I had to modify the underlying mathematical algorithm. The -% initial one is a bit unusual I guess, and, I trust, rather efficient, but it -% does not produce the quotient digits (in base 10000) one by one; at any given -% time it is possible that some correction will be made, which means it is not -% an appropriate algorithm for a TeX implementation which will abandon the -% quotient upstream. Thus I now have with 1.09j a new underlying mathematical -% algorithm, presumably much more standard. It is a bit complicated to implement -% expandably these things, but in the end I had regained the already mentioned -% 10$% efficiency and even more for -% small to medium sized inputs (up to 30$% perhaps). And in passing I did a -% special routine for divisors < 10000, which is 5 to 10 times faster still. -% -% But, I then tested a variant of my new implementation which again did -% not impact the input save stack and, for sizes of up to 200 digits, it -% is not much worse, indeed it is perhaps actually better than the one -% abandoning the quotient digits upstream (and in the end putting them -% in the correct order). So, finally, I re-incorporated the produced -% quotient digits within a tail recursion. Hence \xintiDivision, like all -% other routines in xint (except \xintSeq without optional parameter) -% does not impact the input save stack. One can have a produced -% quotient longer than 4x5000=20000 digits, and no need to worry about -% consequences propagating to \xintTrunc, \xintRound, \xintFloat, -% \xintFloatSqrt, etc... and all other places using the division. See -% also \xintXTrunc in this context.| +% \lverb|Completely rewritten for v1.2. +% WARNING: some comments below try to describe the flow of tokens but they +% date back from xint 1.09j and I updated them on the fly while doing the 1.2 +% version. As the new works in base 10^8, not 10^4 and "drops" the quotient +% digits,rather than store them upfront as the earlier code, I may well have +% not correctly converted all such comments. At the last minute some +% previously #1 became stuff like #1#2#3#4, then of course the old comments +% describing what the macro parameters stand for are necessarily wrong.| % \begin{macrocode} \def\xintiiQuo {\romannumeral0\xintiiquo }% \def\xintiiRem {\romannumeral0\xintiirem }% @@ -17270,16 +17134,15 @@ $1$ or $-1$. \def\xintiRem {\romannumeral0\xintirem }% \def\xintiquo {\expandafter\xint_firstoftwo_thenstop\romannumeral0\xintidivision }% \def\xintirem {\expandafter\xint_secondoftwo_thenstop\romannumeral0\xintidivision }% -\let\xintQuo\xintiQuo\let\xintquo\xintiquo % deprecated (1.1) -\let\xintRem\xintiRem\let\xintrem\xintirem % deprecated (1.1) +\let\xintQuo\xintiQuo\let\xintquo\xintiquo % deprecated +\let\xintRem\xintiRem\let\xintrem\xintirem % deprecated % \end{macrocode} % \lverb-#1 = A, #2 = B. On calcule le quotient et le reste dans la division % euclidienne de A par B: A=BQ+R, 0<= R < |B|.- % \begin{macrocode} \def\xintiDivision {\romannumeral0\xintidivision }% -\def\xintidivision #1{\expandafter\XINT_division\romannumeral0\xintnum{#1}\Z }% -\let\xintDivision\xintiDivision \let\xintdivision\xintidivision % deprecated -\def\XINT_division #1#2\Z #3{\expandafter\XINT_iidivision_a\expandafter #1% +\def\xintidivision #1{\expandafter\XINT_idivision\romannumeral0\xintnum{#1}\Z }% +\def\XINT_idivision #1#2\Z #3{\expandafter\XINT_iidivision_a\expandafter #1% \romannumeral0\xintnum{#3}\Z #2\Z }% \def\xintiiDivision {\romannumeral0\xintiidivision }% \def\xintiidivision #1{\expandafter\XINT_iidivision \romannumeral-`0#1\Z }% @@ -17293,10 +17156,10 @@ $1$ or $-1$. \romannumeral0\XINT_iidivision_bpos #1}\fi \xint_orthat{\XINT_iidivision_bpos #1#2}% }% -\def\XINT_iidivision_divbyzero #1\Z #2\Z {\xintError:DivisionByZero\space {0}{0}}% -\def\XINT_iidivision_aiszero #1\Z #2\Z { {0}{0}}% +\def\XINT_iidivision_divbyzero #1\Z #2\Z {\xintError:DivisionByZero{0}{0}}% +\def\XINT_iidivision_aiszero #1\Z #2\Z {{0}{0}}% \def\XINT_iidivision_bneg #1% q->-q, r unchanged - {\expandafter\space\expandafter{\romannumeral0\XINT_opp #1}}% + {\expandafter{\romannumeral0\XINT_opp #1}}% \def\XINT_iidivision_bpos #1% {% \xint_UDsignfork @@ -17313,7 +17176,7 @@ $1$ or $-1$. \else \expandafter\XINT_iidivision_aneg_rpos \fi {#1}{#2}}% -\def\XINT_iidivision_aneg_rzero #1#2#3{ {-#1}{0}}% necessarily q was >0 +\def\XINT_iidivision_aneg_rzero #1#2#3{{-#1}{0}}% necessarily q was >0 \def\XINT_iidivision_aneg_rpos #1% {% \expandafter\XINT_iidivision_aneg_end\expandafter @@ -17321,229 +17184,211 @@ $1$ or $-1$. }% \def\XINT_iidivision_aneg_end #1#2#3% {% - \expandafter\xint_exchangetwo_keepbraces_thenstop - \expandafter{\romannumeral0\XINT_sub_pre {#3}{#2}}{#1}% r-> b-r + \expandafter\xint_exchangetwo_keepbraces + \expandafter{\romannumeral0\XINT_sub_mm_a {}{}#3\Z #2\Z}{#1}% r-> b-r }% -% \end{macrocode} -% \lverb|& -% Pour la suite A et B sont > 0. -% #1 = B. Pour le moment à l'endroit. -% Calcul du plus petit K = 4n >= longueur de B| -% \begin{macrocode} +%%%%%%%%%%%% \def\XINT_div_prepare #1% {% - \expandafter \XINT_div_prepareB_aa \expandafter - {\romannumeral0\xintlength {#1}}{#1}% B > 0 ici + \XINT_div_prepare_a #1\R\R\R\R\R\R\R\R {10}0000001\W !{#1}% }% -\def\XINT_div_prepareB_aa #1% +\def\XINT_div_prepare_a #1#2#3#4#5#6#7#8#9% {% - \ifnum #1=\xint_c_i - \expandafter\XINT_div_prepareB_onedigit - \else - \expandafter\XINT_div_prepareB_a - \fi - {#1}% -}% -\def\XINT_div_prepareB_a #1% -{% - \expandafter\XINT_div_prepareB_c\expandafter - {\the\numexpr \xint_c_iv*((#1+\xint_c_i)/\xint_c_iv)}{#1}% + \xint_gob_til_R #9\XINT_div_prepare_small\R + \XINT_div_prepare_b #9% }% -% \end{macrocode} -% \lverb|B=1 and B=2 treated specially.| -% \begin{macrocode} -\def\XINT_div_prepareB_onedigit #1#2% +%%%%%%%%%%%% +\def\XINT_div_prepare_small\R #1!#2% {% - \ifcase#2 + \ifcase #2 \or\expandafter\XINT_div_BisOne \or\expandafter\XINT_div_BisTwo - \else\expandafter\XINT_div_prepareB_e - \fi {000}{0}{4}{#2}% + \else\expandafter\XINT_div_small_a + \fi {#2}% }% -\def\XINT_div_BisOne #1#2#3#4#5{ {#5}{0}}% -\def\XINT_div_BisTwo #1#2#3#4#5% +\def\XINT_div_BisOne #1#2{{#2}{0}}% +\def\XINT_div_BisTwo #1#2% {% \expandafter\expandafter\expandafter\XINT_div_BisTwo_a - \ifodd\xintiiLDg{#5} \expandafter1\else \expandafter0\fi {#5}% + \ifodd\xintLDg{#2} \expandafter1\else \expandafter0\fi {#2}% }% -\edef\XINT_div_BisTwo_a #1#2% +\def\XINT_div_BisTwo_a #1#2% {% - \noexpand\expandafter\space\noexpand\expandafter - {\noexpand\romannumeral0\noexpand\xinthalf {#2}}{#1}% + \expandafter{\romannumeral0\xinthalf {#2}}{#1}% }% -% \end{macrocode} -% \lverb|#1 = K. 1.09j uses \csname, earlier versions did it with -% \ifcase.| -% \begin{macrocode} -\def\XINT_div_prepareB_c #1#2% +\def\XINT_div_small_a #1#2% {% - \csname XINT_div_prepareB_d\romannumeral\numexpr#1-#2\endcsname - {#1}% + \expandafter\XINT_div_small_b + \the\numexpr #1/\xint_c_ii\expandafter + .\the\numexpr \xint_c_x^viii+#1\expandafter!% + \romannumeral0% + \XINT_div_small_ba #2\R\R\R\R\R\R\R\R{10}0000001\W + #2\XINT_sepbyviii_Z_end 2345678\relax }% -\def\XINT_div_prepareB_d {\XINT_div_prepareB_e {}{0000}}% -\def\XINT_div_prepareB_di {\XINT_div_prepareB_e {0}{000}}% -\def\XINT_div_prepareB_dii {\XINT_div_prepareB_e {00}{00}}% -\def\XINT_div_prepareB_diii {\XINT_div_prepareB_e {000}{0}}% -\def\XINT_div_cleanR #10000.{{#1}}% -% \end{macrocode} -% \lverb|#1 = zéros à rajouter à B, #2=c [modifié dans 1.09j, ce sont maintenant -% des zéros explicites en nombre 4 - ancien c, et on utilisera -% \XINT_div_cleanR et non plus \XINT_dsh_checksignx pour nettoyer à la fin -% des zéros en excès dans le Reste; in all comments next, «c» stands now {0} or -% {00} or {000} or {0000} rather than a digit as in earlier versions], #3=K, #4 -% = B| -% \begin{macrocode} -\def\XINT_div_prepareB_e #1#2#3#4% +\def\XINT_div_small_b #1!#2{#2#1!}% +\def\XINT_div_small_ba #1#2#3#4#5#6#7#8#9% {% - \ifnum#3=\xint_c_iv\expandafter\XINT_div_prepareLittleB_f - \else\expandafter\XINT_div_prepareB_f - \fi - #4#1{#3}{#2}{#1}% + \xint_gob_til_R #9\XINT_div_smallsmall\R + \expandafter\XINT_div_dosmalldiv + \the\numexpr\expandafter\XINT_sepbyviii_Z + \romannumeral0\XINT_zeroes_forviii + #1#2#3#4#5#6#7#8#9% }% -% \end{macrocode} -% \lverb|x = #1#2#3#4 = 4 premiers chiffres de B. #1 est non nul. B is reversed. -% With 1.09j or latter x+1 and (x+1)/2 are pre-computed. Si K=4 on ne renverse -% pas B, et donc B=x dans la suite. De plus pour K=4 on ne travaille pas avec -% x+1 et (x+1)/2 mais avec x et x/2.| -% \begin{macrocode} -\def\XINT_div_prepareB_f #1#2#3#4#5#{% - \expandafter\XINT_div_prepareB_g - \the\numexpr #1#2#3#4+\xint_c_i\expandafter - .\the\numexpr (#1#2#3#4+\xint_c_i)/\xint_c_ii\expandafter - .\romannumeral0\xintreverseorder {#1#2#3#4#5}.{#1#2#3#4}% +\def\XINT_div_smallsmall\R + \expandafter\XINT_div_dosmalldiv + \the\numexpr\expandafter\XINT_sepbyviii_Z + \romannumeral0\XINT_zeroes_forviii #1\R #2\relax + {{\XINT_div_dosmallsmall}{#1}}% +\def\XINT_div_dosmallsmall #1.1#2!#3% +{% + \expandafter\XINT_div_smallsmallend + \the\numexpr (#3+#1)/#2-\xint_c_i.#2.#3.% }% -\def\XINT_div_prepareLittleB_f #1#{% - \expandafter\XINT_div_prepareB_g \the\numexpr #1/\xint_c_ii.{}.{}.{#1}% +\def\XINT_div_smallsmallend #1.#2.#3.{\expandafter + {\the\numexpr #1\expandafter}\expandafter{\the\numexpr #3-#1*#2}}% +\def\XINT_div_dosmalldiv + {{\expandafter\XINT_sdiv_out\the\numexpr\XINT_smalldivx_a}}% +%%%%%%%%%%%% +\def\XINT_div_prepare_b + {\expandafter\XINT_div_prepare_c\romannumeral0\XINT_zeroes_forviii }% +\def\XINT_div_prepare_c #1!% +{% + \XINT_div_prepare_d #1.00000000!{#1}% }% -% \end{macrocode} -% \lverb|& -% #1 = x' = x+1= 1+quatre premiers chiffres de B, #2 = y = (x+1)/2 précalculé -% #3 = B préparé et maintenant renversé, #4=x, -% #5 = K, #6 = «c», #7= {} ou {0} ou {00} ou {000}, #8 = A initial -% On multiplie aussi A par 10^c. -> AK{x'yx}B«c». Par contre dans le -% cas little on a #1=y=(x/2), #2={}, #3={}, #4=x, donc cela donne -% ->AK{y{}x}{}«c», il n'y a pas de B.| -% \begin{macrocode} -\def\XINT_div_prepareB_g #1.#2.#3.#4#5#6#7#8% +\def\XINT_div_prepare_d #1#2#3#4#5#6#7#8#9% {% - \XINT_div_prepareA_a {#8#7}{#5}{{#1}{#2}{#4}}{#3}{#6}% + \expandafter\XINT_div_prepare_e\xint_gob_til_dot #1#2#3#4#5#6#7#8#9!% }% -% \end{macrocode} -% \lverb|A, K, {x'yx}, B«c» | -% \begin{macrocode} -\def\XINT_div_prepareA_a #1% +\def\XINT_div_prepare_e #1!#2!#3#4% {% - \expandafter\XINT_div_prepareA_b\expandafter - {\romannumeral0\xintlength {#1}}{#1}% + \XINT_div_prepare_f #4#3\X {#1}{#3}% }% -% \end{macrocode} -% \lverb|L0, A, K, {x'yx}, B«c»| -% \begin{macrocode} -\def\XINT_div_prepareA_b #1% +\def\XINT_div_prepare_f #1#2#3#4#5#6#7#8#9\X {% - \expandafter\XINT_div_prepareA_c\expandafter - {\the\numexpr \xint_c_iv*((#1+\xint_c_i)/\xint_c_iv)}{#1}% + \expandafter\XINT_div_prepare_g + \the\numexpr #1#2#3#4#5#6#7#8+\xint_c_i\expandafter + .\the\numexpr (#1#2#3#4#5#6#7#8+\xint_c_i)/\xint_c_ii\expandafter + .\the\numexpr #1#2#3#4#5#6#7#8\expandafter + .\romannumeral0\XINT_sepandrev_andcount + #1#2#3#4#5#6#7#8#9\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678% + \relax\xint_c_ii\xint_c_iii + \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii + \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W + \X }% -% \end{macrocode} -% \lverb|L, L0, A, K, {x'yx}, B, «c»| -% \begin{macrocode} -\def\XINT_div_prepareA_c #1#2% +\def\XINT_div_prepare_g #1.#2.#3.#4.#5\X #6#7#8% {% - \csname XINT_div_prepareA_d\romannumeral\numexpr #1-#2\endcsname - {#1}% + \expandafter\XINT_div_prepare_h + \the\numexpr\expandafter\XINT_sepbyviii_andcount + \romannumeral0\XINT_zeroes_forviii #8#7\R\R\R\R\R\R\R\R{10}0000001\W + #8#7\XINT_sepbyviii_end 2345678\relax + \xint_c_vii!\xint_c_vi!\xint_c_v!\xint_c_iv!% + \xint_c_iii!\xint_c_ii!\xint_c_i!\xint_c_\W + {#1}{#2}{#3}{#4}{#5}{#6}% }% -\def\XINT_div_prepareA_d {\XINT_div_prepareA_e {}}% -\def\XINT_div_prepareA_di {\XINT_div_prepareA_e {0}}% -\def\XINT_div_prepareA_dii {\XINT_div_prepareA_e {00}}% -\def\XINT_div_prepareA_diii {\XINT_div_prepareA_e {000}}% -% \end{macrocode} -% \lverb|#1#3 = A préparé, #2 = longueur de ce A préparé, #4=K, #5={x'yx}-> -% LKAx'yxB«c»| -% \begin{macrocode} -\def\XINT_div_prepareA_e #1#2#3#4#5% +\def\XINT_div_prepare_h #11.#2.#3#4#5#6%#7#8% {% - \XINT_div_start_a {#2}{#4}{#1#3}#5% + \XINT_div_start_a {#2}{#6}{#1}{#3}{#4}{#5}%{#7}{#8}% }% % \end{macrocode} -% \lverb|L, K, A, x',y,x, B, «c» (avec y{}x{} au lieu de x'yxB dans la -% variante little)| +% \lverb|L, K, A, x',y,x, B, «c». Attention que K est diminué de 1 plus loin. +% Comme xint 1.2 a déjà repéré K=1, on a ici au minimum K=2. Attention B est à +% l'envers, A est à l'endroit et les deux avec séparateurs. Attention que ce +% n'est pas ici qu'on boucle mais en \XINT_div_I_a.| % \begin{macrocode} \def\XINT_div_start_a #1#2% {% - \ifnum #2=\xint_c_iv \expandafter\XINT_div_little_b + \ifnum #1 < #2 + \expandafter\XINT_div_zeroQ \else - \ifnum #1 < #2 - \expandafter\expandafter\expandafter\XINT_div_III_aa - \else - \expandafter\expandafter\expandafter\XINT_div_start_b - \fi + \expandafter\XINT_div_start_b \fi {#1}{#2}% }% +\def\XINT_div_zeroQ #1#2#3#4#5#6#7% +{% + \expandafter\XINT_div_zeroQ_end + \romannumeral0\XINT_unsep_cuzsmall + #31\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W .% +}% +\def\XINT_div_zeroQ_end #1.#2% + {\expandafter{\expandafter0\expandafter}\XINT_div_cleanR #1#2.}% % \end{macrocode} -% \lverb|L, K, A, x',y,x, B, «c».| +% \lverb|L, K, A, x',y,x, B, «c»->K.A.x{LK{x'y}x}B«c»| % \begin{macrocode} -\def\XINT_div_III_aa #1#2#3#4#5#6#7% +\def\XINT_div_start_b #1#2#3#4#5#6% {% - \expandafter\expandafter\expandafter - \XINT_div_III_b\xint_cleanupzeros_nostop #3.{0000}% + \expandafter\XINT_div_finish\the\numexpr + \XINT_div_start_c {#2}.#3.{#6}{{#1}{#2}{{#4}{#5}}{#6}}% }% +\def\XINT_div_finish +{% + \expandafter\XINT_div_finish_a \romannumeral-`0\XINT_div_unsepQ +}% +\def\XINT_div_finish_a #1\Z #2.{\XINT_div_finish_b #2.{#1}}% % \end{macrocode} -% \lverb|R.Q«c».| +% \lverb|Ici ce sont routines de fin. Le reste déjà nettoyé. R.Q«c».| % \begin{macrocode} -\def\XINT_div_III_b #1% +\def\XINT_div_finish_b #1% {% \if0#1% - \expandafter\XINT_div_III_bRzero + \expandafter\XINT_div_finish_bRzero \else - \expandafter\XINT_div_III_bRpos + \expandafter\XINT_div_finish_bRpos \fi #1% }% -\def\XINT_div_III_bRzero 0.#1#2% -{% - \expandafter\space\expandafter - {\romannumeral0\XINT_cuz_loop #1\W\W\W\W\W\W\W\Z}{0}% -}% -\def\XINT_div_III_bRpos #1.#2#3% -{% - \expandafter\XINT_div_III_c \XINT_div_cleanR #1#3.{#2}% -}% -\def\XINT_div_III_c #1#2% -{% - \expandafter\space\expandafter - {\romannumeral0\XINT_cuz_loop #2\W\W\W\W\W\W\W\Z}{#1}% +\def\XINT_div_finish_bRzero 0.#1#2{{#1}{0}}% +\def\XINT_div_finish_bRpos #1.#2#3% +{% + \expandafter\xint_exchangetwo_keepbraces\XINT_div_cleanR #1#3.{#2}% }% +\def\XINT_div_cleanR #100000000.{{#1}}% % \end{macrocode} -% \lverb|L, K, A, x',y,x, B, «c»->K.A.x{LK{x'y}x}B«c»| +% \lverb|Kalpha.A.x{LK{x'y}x}, B, «c», au début #2=alpha est vide. On fait une +% boucle pour prendre K unités de A (on a au moins L égal à K) et les mettre +% dans alpha.| % \begin{macrocode} -\def\XINT_div_start_b #1#2#3#4#5#6% +\def\XINT_div_start_c #1% {% - \XINT_div_start_c {#2}.#3.{#6}{{#1}{#2}{{#4}{#5}}{#6}}% + \ifnum #1>\xint_c_vi + \expandafter\XINT_div_start_ca + \else + \expandafter\XINT_div_start_cb + \fi {#1}% }% -% \end{macrocode} -% \lverb|Kalpha.A.x{LK{x'y}x}, B, «c», au début #2=alpha est vide| -% \begin{macrocode} -\def\XINT_div_start_c #1#2.#3#4#5#6% +\def\XINT_div_start_ca #1#2.#3!#4!#5!#6!#7!#8!#9!% {% - \ifnum #1=\xint_c_iv\XINT_div_start_ca\fi \expandafter\XINT_div_start_c\expandafter - {\the\numexpr #1-\xint_c_iv}#2#3#4#5#6.% -}% -\def\XINT_div_start_ca\fi\expandafter\XINT_div_start_c\expandafter - #1#2#3#4#5{\fi\XINT_div_start_d {#2#3#4#5}#2#3#4#5}% + {\the\numexpr #1-\xint_c_vii}#2#3!#4!#5!#6!#7!#8!#9!.% +}% +\def\XINT_div_start_cb #1% + {\csname XINT_div_start_c_\romannumeral\numexpr#1\endcsname}% +\def\XINT_div_start_c_i #1.#2!% + {\XINT_div_start_c_ #1#2!.}% +\def\XINT_div_start_c_ii #1.#2!#3!% + {\XINT_div_start_c_ #1#2!#3!.}% +\def\XINT_div_start_c_iii #1.#2!#3!#4!% + {\XINT_div_start_c_ #1#2!#3!#4!.}% +\def\XINT_div_start_c_iv #1.#2!#3!#4!#5!% + {\XINT_div_start_c_ #1#2!#3!#4!#5!.}% +\def\XINT_div_start_c_v #1.#2!#3!#4!#5!#6!% + {\XINT_div_start_c_ #1#2!#3!#4!#5!#6!.}% +\def\XINT_div_start_c_vi #1.#2!#3!#4!#5!#6!#7!% + {\XINT_div_start_c_ #1#2!#3!#4!#5!#6!#7!.}% % \end{macrocode} % \lverb|#1=a, #2=alpha (de longueur K, à l'endroit).#3=reste de A.#4=x, -% #5={LK{x'y}x},#6=B,«c» -> a, x, alpha, B, {0000}, L, K, {x'y},x, -% alpha'=reste de A, B{}«c». Pour K=4 on a en fait B=x, faudra revoir après.| +% #5={LK{x'y}x},#6=B,«c» -> a, x, alpha, B, {00000000}, L, K, {x'y},x, +% alpha'=reste de A, B«c».| % \begin{macrocode} -\def\XINT_div_start_d #1#2.#3.#4#5#6% +\def\XINT_div_start_c_ 1#1!#2.#3.#4#5#6% {% - \XINT_div_I_a {#1}{#4}{#2}{#6}{0000}#5{#3}{#6}{}% + \XINT_div_I_a {#1}{#4}{1#1!#2}{#6}{00000000}#5{#3}{#6}% }% % \end{macrocode} % \lverb|Ceci est le point de retour de la boucle principale. a, x, alpha, B, -% q0, L, K, {x'y}, x, alpha', BQ«c» | +% q0, L, K, {x'y}, x, alpha', B«c» | % \begin{macrocode} \def\XINT_div_I_a #1#2% {% @@ -17554,17 +17399,17 @@ $1$ or $-1$. \xint_gob_til_zero #1\XINT_div_I_czero 0\XINT_div_I_c #1% }% % \end{macrocode} -% \lverb|On intercepte quotient nul: #1=a, x, alpha, B, #5=q0, L, K, {x'y}, x, -% alpha', BQ«c» -> q{alpha} L, K, {x'y}, x, alpha', BQ«c»| +% \lverb|On intercepte petit quotient nul: #1=a, x, alpha, B, #5=q0, L, K, +% {x'y}, x, alpha', B«c» -> on lâche un q puis {alpha} L, K, {x'y}, x, +% alpha', B«c».| % \begin{macrocode} -\def\XINT_div_I_czero 0% - \XINT_div_I_c 0.#1#2#3#4#5{\XINT_div_I_g {#5}{#3}}% +\def\XINT_div_I_czero 0\XINT_div_I_c 0.#1#2#3#4#5{1#5\XINT_div_I_g {#3}}% \def\XINT_div_I_c #1.#2#3% {% - \expandafter\XINT_div_I_da\the\numexpr #2-#1*#3.#1.% + \expandafter\XINT_div_I_da\the\numexpr #2-#1*#3.#1.{#2}{#3}% }% % \end{macrocode} -% \lverb|r.q.alpha, B, q0, L, K, {x'y}, x, alpha', BQ«c»| +% \lverb|r.q.alpha, B, q0, L, K, {x'y}, x, alpha', B«c»| % \begin{macrocode} \def\XINT_div_I_da #1.% {% @@ -17578,413 +17423,451 @@ $1$ or $-1$. \fi \fi }% +% \end{macrocode} +% \lverb|attention très mauvaises notations avec _b et _db.| +% \begin{macrocode} \def\XINT_div_I_dN #1.% {% - \expandafter\XINT_div_I_dP\the\numexpr #1-\xint_c_i.% + \expandafter\XINT_div_I_b\the\numexpr #1-\xint_c_i.% }% -\def\XINT_div_I_db #1.#2#3% #1=q=un chiffre, #2=alpha, #3=B +\def\XINT_div_I_db #1.#2#3#4#5% {% - \expandafter\XINT_div_I_dc\expandafter - {\romannumeral0\expandafter\XINT_div_sub_xpxp\expandafter - {\romannumeral0\xintreverseorder{#2}}% - {\romannumeral0\XINT_mul_Mr {#1}#3\Z\Z\Z\Z }}% - #1{#2}{#3}% + \expandafter\XINT_div_I_dc\expandafter #1% + \romannumeral0\expandafter\XINT_div_sub\expandafter + {\romannumeral0\XINT_rev_nounsep {}#4\R!\R!\R!\R!\R!\R!\R!\R!\W}% + {\the\numexpr\XINT_div_verysmallmul #1!#51\Z!}% + \Z {#4}{#5}% }% +% \end{macrocode} +% \lverb|La soustraction spéciale renvoie simplement - si le chiffre q est +% trop grand. On invoque dans ce cas I_dP.| +% \begin{macrocode} \def\XINT_div_I_dc #1#2% {% - \if-#1% s'arranger pour que si n\'egatif on ait renvoy\'e alpha=-. - \expandafter\xint_firstoftwo - \else\expandafter\xint_secondoftwo\fi - {\expandafter\XINT_div_I_dP\the\numexpr #2-\xint_c_i.}% - {\XINT_div_I_e {#1}#2}% + \if-#2\expandafter\XINT_div_I_dd\else\expandafter\XINT_div_I_de\fi + #1#2% }% -% \end{macrocode} -% \lverb|alpha,q,ancien alpha,B, q0->1nouveauq.alpha, L, K, {x'y},x, alpha', -% BQ«c»| -% \begin{macrocode} -\def\XINT_div_I_e #1#2#3#4#5% +\def\XINT_div_I_dd #1-\Z +{% + \if #11\expandafter\XINT_div_I_dz\fi + \expandafter\XINT_div_I_dP\the\numexpr #1-\xint_c_i.XX% +}% +\def\XINT_div_I_dz #1XX#2#3#4% {% - \expandafter\XINT_div_I_f \the\numexpr \xint_c_x^iv+#2+#5{#1}% + 1#4\XINT_div_I_g {#2}% }% +\def\XINT_div_I_de #1#2\Z #3#4#5{1#5+#1\XINT_div_I_g {#2}}% % \end{macrocode} -% \lverb|q.alpha, B, q0, L, K, {x'y},x, alpha'BQ«c» (intercepter q=0?) -% -> 1nouveauq.nouvel alpha, L, K, {x'y}, x, alpha',BQ«c»| +% \lverb|q.alpha, B, q0, L, K, {x'y},x, alpha'B«c» (q=0 has been intercepted) +% -> 1nouveauq.nouvel alpha, L, K, {x'y}, x, alpha',B«c»| % \begin{macrocode} -\def\XINT_div_I_dP #1.#2#3#4% +\def\XINT_div_I_dP #1.#2#3#4#5#6% {% - \expandafter \XINT_div_I_f \the\numexpr \xint_c_x^iv+#1+#4\expandafter - {\romannumeral0\expandafter\XINT_div_sub_xpxp\expandafter - {\romannumeral0\xintreverseorder{#2}}% - {\romannumeral0\XINT_mul_Mr {#1}#3\Z\Z\Z\Z }}% + 1#6+#1\expandafter\XINT_div_I_g\expandafter + {\romannumeral0\expandafter\XINT_div_sub\expandafter + {\romannumeral0\XINT_rev_nounsep {}#4\R!\R!\R!\R!\R!\R!\R!\R!\W}% + {\the\numexpr\XINT_div_verysmallmul #1!#51\Z!}% + }% }% % \end{macrocode} -% \lverb|1#1#2#3#4=nouveau q, nouvel alpha, L, K, {x'y},x,alpha', BQ«c»| +% \lverb|1#1=nouveau q. nouvel alpha, L, K, {x'y},x,alpha', BQ«c»| % \begin{macrocode} -\def\XINT_div_I_f 1#1#2#3#4{\XINT_div_I_g {#1#2#3#4}}% % \end{macrocode} % \lverb|#1=q,#2=nouvel alpha,#3=L, #4=K, #5={x'y}, #6=x, #7= alpha',#8=B, -% #9=Q«c» -> {x'y}alpha.alpha'.{{x'y}xKL}B{Qq}«c»| +% «c» -> on laisse q puis {x'y}alpha.alpha'.{{x'y}xKL}B«c»| % \begin{macrocode} -\def\XINT_div_I_g #1#2#3#4#5#6#7#8#9% +\def\XINT_div_I_g #1#2#3#4#5#6#7% {% - \ifnum#3=#4 - \expandafter\XINT_div_III_ab + \expandafter !\the\numexpr + \ifnum#2=#3 + \expandafter\XINT_div_exittofinish \else \expandafter\XINT_div_I_h \fi - {#5}#2.#7.{{#5}{#6}{#4}{#3}}{#8}{#9#1}% + {#4}#1.#6.{{#4}{#5}{#3}{#2}}{#7}% }% % \end{macrocode} -% \lverb|{x'y}alpha.alpha'.{{x'y}xKL}B{Qq}«c» -> R sans leading zeros.{Qq}«c»| +% \lverb|{x'y}alpha.alpha'.{{x'y}xKL}B«c» -> Attention retour à l'envoyeur ici +% par terminaison des \the\numexpr. On doit reprendre le Q déjà sorti, qui n'a +% plus de séparateurs, ni de leading 1. Ensuite R sans leading zeros.«c»| % \begin{macrocode} -\def\XINT_div_III_ab #1#2.#3.#4#5% +\def\XINT_div_exittofinish #1#2.#3.#4#5% {% - \expandafter\XINT_div_III_b - \romannumeral0\XINT_cuz_loop #2#3\W\W\W\W\W\W\W\Z.% + 1\expandafter\expandafter\expandafter!\expandafter\XINT_unsep_delim + \romannumeral0\XINT_div_unsepR #2#31\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W.% }% % \end{macrocode} -% \lverb|#1={x'y}alpha.#2#3#4#5#6=reste de A. -% #7={{x'y},x,K,L},#8=B,nouveauQ«c» devient {x'y},alpha sur K+4 chiffres.B, -% {{x'y},x,K,L}, #6= nouvel alpha',B,nouveauQ«c»| +% \lverb|#1={x'y}alpha.#2!#3=reste de A. +% #4={{x'y},x,K,L},#5=B,«c» devient {x'y},alpha sur K+4 chiffres.B, +% {{x'y},x,K,L}, #6= nouvel alpha',B,«c»| % \begin{macrocode} -\def\XINT_div_I_h #1.#2#3#4#5#6.#7#8% +\def\XINT_div_I_h #1.#2!#3.#4#5% {% - \XINT_div_II_b #1#2#3#4#5.{#8}{#7}{#6}{#8}% + \XINT_div_II_b #1#2!.{#5}{#4}{#3}{#5}% }% % \end{macrocode} -% \lverb|{x'y}alpha.B, {{x'y},x,K,L}, nouveau alpha',B, Q«c» On -% intercepte la situation avec alpha débutant par 0000 qui est la seule qui -% pourrait donner un q1 nul. Donc q1 est non nul et la soustraction spéciale -% recevra un q1*B de longueur K ou K+4 et jamais 0000. Ensuite un q2 éventuel -% s'il est calculé est nécessairement non nul lui aussi. Comme dans la phase I -% on a aussi intercepté un q nul, la soustraction spéciale ne reçoit donc jamais -% un qB nul. Note: j'ai testé plusieurs fois que ma technique de gob_til_zeros -% est plus rapide que d'utiliser un \ifnum | +% \lverb|{x'y}alpha.B, {{x'y},x,K,L}, nouveau alpha',B,«c»| % \begin{macrocode} -\def\XINT_div_II_b #1#2#3#4#5#6#7#8#9% +\def\XINT_div_II_b #11#2!#3!% {% - \xint_gob_til_zeros_iv #2#3#4#5\XINT_div_II_skipc 0000% - \XINT_div_II_c #1{#2#3#4#5}{#6#7#8#9}% + \xint_gob_til_eightzeroes #2\XINT_div_II_skipc 00000000% + \XINT_div_II_c #1{1#2}{#3}% }% % \end{macrocode} -% \lverb|x'y{0000}{4chiffres}reste de alpha.#6=B,#7={{x'y},x,K,L}, alpha',B, -% Q«c» -> {x'y}x,K,L (à diminuer de 4), {alpha sur -% K}B{q1=0000}{alpha'}B,Q«c»| +% \lverb|x'y{100000000}{1<8>}reste de alpha.#6=B,#7={{x'y},x,K,L}, alpha',B, +% «c» -> {x'y}x,K,L (à diminuer de 4), {alpha sur +% K}B{q1=00000000}{alpha'}B,«c»| % \begin{macrocode} -\def\XINT_div_II_skipc 0000\XINT_div_II_c #1#2#3#4#5.#6#7% +\def\XINT_div_II_skipc 00000000\XINT_div_II_c #1#2#3#4#5.#6#7% {% - \XINT_div_II_k #7{#4#5}{#6}{0000}% + \XINT_div_II_k #7{#4!#5}{#6}{00000000}% }% % \end{macrocode} -% \lverb|x'ya->1qx'yalpha.B, {{x'y},x,K,L}, nouveau alpha',B, Q«c»| +% \lverb|x'ya->1qx'yalpha.B, {{x'y},x,K,L}, nouveau alpha',B, «c».| % \begin{macrocode} \def\XINT_div_II_c #1#2#3#4% {% - \expandafter\XINT_div_II_d\the\numexpr (#3#4+#2)/#1+\xint_c_ixixixix\relax - {#1}{#2}#3#4% + \expandafter\XINT_div_II_d\the\numexpr\XINT_div_mini + #1.#2!#3!#4!{#1}{#2}#3!#4!% }% % \end{macrocode} -% \lverb|1 suivi de q1 sur quatre chiffres, #5=x', #6=y, #7=alpha.#8=B, -% {{x'y},x,K,L}, alpha', B, Q«c» --> nouvel alpha.x',y,B,q1,{{x'y},x,K,L}, -% alpha', B, Q«c» | +% \lverb|1 suivi de q1 sur huit chiffres! #2=x', #3=y, #4=alpha.#5=B, +% {{x'y},x,K,L}, alpha', B, «c» --> nouvel alpha.x',y,B,q1,{{x'y},x,K,L}, +% alpha', B, «c» | % \begin{macrocode} -\def\XINT_div_II_d 1#1#2#3#4#5#6#7.#8% +\def\XINT_div_II_d 1#1#2#3#4#5!#6#7#8.#9% {% \expandafter\XINT_div_II_e - \romannumeral0\expandafter\XINT_div_sub_xpxp\expandafter - {\romannumeral0\xintreverseorder{#7}}% - {\romannumeral0\XINT_mul_Mr {#1#2#3#4}#8\Z\Z\Z\Z }.% - {#5}{#6}{#8}{#1#2#3#4}% + \romannumeral0\expandafter\XINT_div_sub\expandafter + {\romannumeral0\XINT_rev_nounsep {}#8\R!\R!\R!\R!\R!\R!\R!\R!\W}% + {\the\numexpr\XINT_div_smallmul_a 100000000.#1#2#3#4.#5!#91\Z!}% + .{#6}{#7}{#9}{#1#2#3#4#5}% }% % \end{macrocode} -% \lverb|alpha.x',y,B,q1, {{x'y},x,K,L}, alpha', B, Q«c»| +% \lverb|alpha.x',y,B,q1, {{x'y},x,K,L}, alpha', B, «c». Attention la +% soustraction spéciale doit maintenir les blocs 1<8>!| % \begin{macrocode} -\def\XINT_div_II_e #1#2#3#4% +\def\XINT_div_II_e 1#1!% {% - \xint_gob_til_zeros_iv #1#2#3#4\XINT_div_II_skipf 0000% - \XINT_div_II_f #1#2#3#4% + \xint_gob_til_eightzeroes #1\XINT_div_II_skipf 00000000% + \XINT_div_II_f 1#1!% }% % \end{macrocode} -% \lverb|0000alpha sur K chiffres.#2=x',#3=y,#4=B,#5=q1, #6={{x'y},x,K,L}, -% #7=alpha',BQ«c» -> {x'y}x,K,L (à diminuer de 4), -% {alpha sur K}B{q1}{alpha'}BQ«c»| +% \lverb|100000000!alpha sur K chiffres.#2=x',#3=y,#4=B,#5=q1, #6={{x'y},x,K,L}, +% #7=alpha',B«c» -> {x'y}x,K,L (à diminuer de 1), +% {alpha sur K}B{q1}{alpha'}B«c»| % \begin{macrocode} -\def\XINT_div_II_skipf 0000\XINT_div_II_f 0000#1.#2#3#4#5#6% +\def\XINT_div_II_skipf 00000000\XINT_div_II_f 100000000!#1.#2#3#4#5#6% {% \XINT_div_II_k #6{#1}{#4}{#5}% }% % \end{macrocode} -% \lverb|a1 (huit chiffres), alpha (sur K+4), x', y, B, q1, {{x'y},x,K,L}, -% alpha', B,Q«c»| +% \lverb|1!1!, alpha (sur K+1 blocs de 8). x', y, B, q1, {{x'y},x,K,L}, +% alpha', B,«c».| % \begin{macrocode} -\def\XINT_div_II_f #1#2#3#4#5#6#7#8#9.% +\def\XINT_div_II_f #1!#2!#3.% {% - \XINT_div_II_fa {#1#2#3#4#5#6#7#8}{#1#2#3#4#5#6#7#8#9}% + \XINT_div_II_fa {#1!#2!}{#1!#2!#3}% }% \def\XINT_div_II_fa #1#2#3#4% {% - \expandafter\XINT_div_II_g\expandafter - {\the\numexpr (#1+#4)/#3-\xint_c_i}{#2}% + \expandafter\XINT_div_II_g \the\numexpr\XINT_div_mini #3.#4!#1{#2}% }% % \end{macrocode} % \lverb|#1=q, #2=alpha (K+4), #3=B, #4=q1, {{x'y},x,K,L}, alpha', BQ«c» -% -> 1 puis nouveau q sur 4 chiffres, nouvel alpha sur K chiffres, -% B, {{x'y},x,K,L}, alpha',BQ«c» | +% -> 1 puis nouveau q sur 8 chiffres. nouvel alpha sur K blocs, +% B, {{x'y},x,K,L}, alpha',B«c» | % \begin{macrocode} -\def\XINT_div_II_g #1#2#3#4% +\def\XINT_div_II_g 1#1#2#3#4#5!#6#7#8% {% \expandafter \XINT_div_II_h - \the\numexpr #4+#1+\xint_c_x^iv\expandafter\expandafter\expandafter - {\expandafter\xint_gobble_iv - \romannumeral0\expandafter\XINT_div_sub_xpxp\expandafter - {\romannumeral0\xintreverseorder{#2}}% - {\romannumeral0\XINT_mul_Mr {#1}#3\Z\Z\Z\Z }}{#3}% + \the\numexpr 1#1#2#3#4#5+#8\expandafter\expandafter\expandafter + .\expandafter\expandafter\expandafter + {\expandafter\xint_gob_til_exclam + \romannumeral0\expandafter\XINT_div_sub\expandafter + {\romannumeral0\XINT_rev_nounsep {}#6\R!\R!\R!\R!\R!\R!\R!\R!\W}% + {\the\numexpr\XINT_div_smallmul_a 100000000.#1#2#3#4.#5!#71\Z!}}% + {#7}% }% % \end{macrocode} -% \lverb|1 puis nouveau q sur 4 chiffres, #5=nouvel alpha sur K chiffres, -% #6=B, #7={{x'y},x,K,L} avec L à ajuster, alpha', BQ«c» -% -> {x'y}x,K,L à diminuer de 4, {alpha}B{q}, alpha', BQ«c»| +% \lverb|1 puis nouveau q sur 8 chiffres, #2=nouvel alpha sur K blocs, +% #3=B, #4={{x'y},x,K,L} avec L à ajuster, alpha', BQ«c» +% -> {x'y}x,K,L à diminuer de 1, {alpha}B{q}, alpha', BQ«c»| % \begin{macrocode} -\def\XINT_div_II_h 1#1#2#3#4#5#6#7% +\def\XINT_div_II_h 1#1.#2#3#4% {% - \XINT_div_II_k #7{#5}{#6}{#1#2#3#4}% + \XINT_div_II_k #4{#2}{#3}{#1}% }% % \end{macrocode} -% \lverb|{x'y}x,K,L à diminuer de 4, alpha, B{q}alpha',BQ«c» -% ->nouveau L.K,x',y,x,alpha.B,q,alpha',B,Q«c» -% ->{LK{x'y}x},x,a,alpha.B,q,alpha',B,Q«c»| +% \lverb|{x'y}x,K,L à diminuer de 1, alpha, B{q}alpha',B«c» +% ->nouveau L.K,x',y,x,alpha.B,q,alpha',B,«c» +% ->{LK{x'y}x},x,a,alpha.B,q,alpha',B,«c»| % \begin{macrocode} \def\XINT_div_II_k #1#2#3#4#5% {% - \expandafter\XINT_div_II_l \the\numexpr #4-\xint_c_iv.{#3}#1{#2}#5.% + \expandafter\XINT_div_II_l \the\numexpr #4-\xint_c_i.{#3}#1{#2}#5.% }% -\def\XINT_div_II_l #1.#2#3#4#5#6#7#8#9% +\def\XINT_div_II_l #1.#2#3#4#51#6!% {% - \XINT_div_II_m {{#1}{#2}{{#3}{#4}}{#5}}{#5}{#6#7#8#9}#6#7#8#9% + \XINT_div_II_m {{#1}{#2}{{#3}{#4}}{#5}}{#5}{#6}1#6!% }% % \end{macrocode} -% \lverb|{LK{x'y}x},x,a,alpha.B{q}alpha'BQ -> a, x, alpha, B, q, -% L, K, {x'y}, x, alpha', BQ«c» | +% \lverb|{LK{x'y}x},x,a,alpha.B{q}alpha'B -> a, x, alpha, B, q, +% L, K, {x'y}, x, alpha', B«c» | % \begin{macrocode} \def\XINT_div_II_m #1#2#3#4.#5#6% {% \XINT_div_I_a {#3}{#2}{#4}{#5}{#6}#1% }% % \end{macrocode} -% \lverb|L, K, A, y,{},x, {},«c»->A.{yx}L{}«c» Comme ici K=4, dans -% la phase I on n'a pas besoin de alpha, car a = alpha. De plus on a maintenu B -% dans l'ordre qui est donc la même chose que x. Par ailleurs la phase I est -% simplifiée, il s'agit simplement de la division euclidienne de a par x, et de -% plus on n'a à la faire qu'une unique fois et ensuite la phase II peut boucler -% sur elle-même au lieu de revenir en phase I, par conséquent il n'y a pas non -% plus de q0 ici. Enfin, le y est (x/2) pas ((x+1)/2) il n'y a pas de x'=x+1| +% \lverb|This multiplication is exactly like \XINT_smallmul, but it always +% keeps the ending carry. For optimization I duplicated the whole code.| % \begin{macrocode} -\def\XINT_div_little_b #1#2#3#4#5#6#7% +\def\XINT_div_minimulwc_a 1#1.#2.#3!#4#5#6#7#8.% {% - \XINT_div_little_c #3.{{#4}{#6}}{#1}% + \expandafter\XINT_div_minimulwc_b + \the\numexpr \xint_c_x^ix+#1+#3*#8.#3*#4#5#6#7+#2*#8.#2*#4#5#6#7.% }% -% \end{macrocode} -% \lverb|#1#2#3#4=a, #5=alpha'=reste de A.#6={yx}, #7=L, «c» -> a, -% y, x, L, alpha'=reste de A, «c».| -% \begin{macrocode} -\def\XINT_div_little_c #1#2#3#4#5.#6#7% +\def\XINT_div_minimulwc_b 1#1#2#3#4#5#6.#7.% +{% + \expandafter\XINT_div_minimulwc_c + \the\numexpr \xint_c_x^ix+#1#2#3#4#5+#7.#6.% +}% +\def\XINT_div_minimulwc_c 1#1#2#3#4#5#6.#7.#8.% {% - \XINT_div_littleI_a {#1#2#3#4}#6{#7}{#5}% + 1#6#7\expandafter!% + \the\numexpr\expandafter\XINT_div_smallmul_a + \the\numexpr \xint_c_x^viii+#1#2#3#4#5+#8.% }% +\def\XINT_div_smallmul_a #1.#2.#3!1#4!% +{% + \xint_gob_til_Z #4\XINT_div_smallmul_e\Z + \XINT_div_minimulwc_a #1.#2.#3!#4.#2.#3!% +}% +\def\XINT_div_smallmul_e\Z\XINT_div_minimulwc_a 1#1.#2\Z #3!{1\relax #1!}% % \end{macrocode} -% \lverb|a, y, x, L, alpha',«c» On calcule ici (contrairement à la -% phase I générale) le vrai quotient euclidien de a par x=B, c'est donc un -% chiffre de 0 à 9. De plus on n'a à faire cela qu'une unique fois.| +% \lverb|Special very small multiplication for division. We only need to cater +% for multiplicands from 1 to 9. The ending is different from standard +% verysmallmul, a zero carry is not suppressed. And no final 1\Z! is added. If +% #1=1 let's not forget to add the 100000000! at the end.| % \begin{macrocode} -\def\XINT_div_littleI_a #1#2#3% +\def\XINT_div_verysmallmul #1% + {\xint_gob_til_one #1\XINT_div_verysmallisone 1\XINT_div_verysmallmul_a 0.#1}% +\def\XINT_div_verysmallisone 1\XINT_div_verysmallmul_a 0.1!1#11\Z!% + {1\relax #1100000000!}% +\def\XINT_div_verysmallmul_a #1.#2!1#3!% {% - \expandafter\XINT_div_littleI_b - \the\numexpr (#1+#2)/#3-\xint_c_i{#1}{#2}{#3}% + \xint_gob_til_Z #3\XINT_div_verysmallmul_e\Z + \expandafter\XINT_div_verysmallmul_b + \the\numexpr \xint_c_x^ix+#2*#3+#1.#2!% }% +\def\XINT_div_verysmallmul_b 1#1#2.% + {1#2\expandafter!\the\numexpr\XINT_div_verysmallmul_a #1.}% +\def\XINT_div_verysmallmul_e\Z #1\Z +#2#3!{1\relax 0000000#2!}% % \end{macrocode} -% \lverb|On intercepte quotient nul: [est-ce vraiment utile? ou n'est-ce pas -% plutôt une perte de temps en moyenne? il faudrait tester] q=0#1=a, -% #2=y, x, L, alpha', «c» -> -% II_a avec L{alpha}alpha'.{yx}{0000}«c». Et en cas de quotient non nul on -% procède avec littleI_c avec #1=q, #2=a, #3=y, #4=x -> {nouvel alpha sur 4 -% chiffres}q{yx},L,alpha',«c».| +% \lverb|Special subtraction for division purposes.| % \begin{macrocode} -\def\XINT_div_littleI_b #1% +\def\XINT_div_sub #1#2% {% - \xint_gob_til_zero #1\XINT_div_littleI_skip 0\XINT_div_littleI_c #1% + \expandafter\XINT_div_sub_clean + \the\numexpr\expandafter\XINT_div_sub_a\expandafter + 1#2\Z!\Z!\Z!\Z!\Z!\W #1\Z!\Z!\Z!\Z!\Z!\W }% -\def\XINT_div_littleI_skip 0\XINT_div_littleI_c 0#1#2#3#4#5% - {\XINT_div_littleII_a {#4}{#1}#5.{{#2}{#3}}{0000}}% -\def\XINT_div_littleI_c #1#2#3#4% +\def\XINT_div_sub_clean #1-#2#3\W {% - \expandafter\expandafter\expandafter\XINT_div_littleI_e - \expandafter\expandafter\expandafter - {\expandafter\xint_gobble_i\the\numexpr \xint_c_x^iv+#2-#1*#4}#1{{#3}{#4}}% + \if1#2\expandafter\XINT_rev_nounsep\else\expandafter\XINT_div_sub_neg\fi + {}#1\R!\R!\R!\R!\R!\R!\R!\R!\W }% -% \end{macrocode} -% \lverb|#1=nouvel alpha sur 4 chiffres#2=q,#3={yx}, #4=L, #5=alpha',«c» -> -% L{alpha}alpha'.{yx}{000q}«c» point d'entrée de la boucle principale| -% \begin{macrocode} -\def\XINT_div_littleI_e #1#2#3#4#5% - {\XINT_div_littleII_a {#4}{#1}#5.{#3}{000#2}}% -% \end{macrocode} -% \lverb|L{alpha}alpha'.{yx}Q«c» et c'est là qu'on boucle| -% \begin{macrocode} -\def\XINT_div_littleII_a #1% +\def\XINT_div_sub_neg #1\W { -}% +\def\XINT_div_sub_a #1!#2!#3!#4!#5\W #6!#7!#8!#9!% {% - \ifnum#1=\xint_c_iv - \expandafter\XINT_div_littleIII_ab - \else - \expandafter\XINT_div_littleII_b - \fi {#1}% + \XINT_div_sub_b #1!#6!#2!#7!#3!#8!#4!#9!#5\W }% -% \end{macrocode} -% \lverb|L{alpha}alpha'.{yx}Q«c» -> (en fait #3 est vide normalement ici) R -% sans leading zeros.Q«c»| -% \begin{macrocode} -\def\XINT_div_littleIII_ab #1#2#3.#4% +\def\XINT_div_sub_b #1#2#3!#4!% {% - \expandafter\XINT_div_III_b\the\numexpr #2#3.% + \xint_gob_til_Z #4\XINT_div_sub_bi \Z + \expandafter\XINT_div_sub_c\the\numexpr#1-#3+1#4-\xint_c_i.% }% -% \end{macrocode} -% \lverb|L{alpha}alpha'.{yx}Q«c». On diminue L de quatre, comme cela c'est -% fait.| -% \begin{macrocode} -\def\XINT_div_littleII_b #1% +\def\XINT_div_sub_c 1#1#2.% {% - \expandafter\XINT_div_littleII_c\expandafter {\the\numexpr #1-\xint_c_iv}% + 1#2\expandafter!\the\numexpr\XINT_div_sub_d #1% }% -% \end{macrocode} -% \lverb|{nouveauL}{alpha}alpha'.{yx}Q«c». On prélève 4 chiffres de alpha' -> -% {nouvel alpha sur huit chiffres}yx{nouveau L}{nouvel alpha'}Q«c». Regarder -% si l'ancien alpha était 0000 n'avancerait à rien car obligerait à refaire une -% chose comme la phase I, donc on ne perd pas de temps avec ça, on reste en -% permanence en phase II.| -% \begin{macrocode} -\def\XINT_div_littleII_c #1#2#3#4#5#6#7.#8% +\def\XINT_div_sub_d #1#2#3!#4!% {% - \XINT_div_littleII_d {#2#3#4#5#6}#8{#1}{#7}% + \xint_gob_til_Z #4\XINT_div_sub_di \Z + \expandafter\XINT_div_sub_e\the\numexpr#1-#3+1#4-\xint_c_i.% }% -\def\XINT_div_littleII_d #1#2#3% +\def\XINT_div_sub_e 1#1#2.% {% - \expandafter\XINT_div_littleII_e\the\numexpr (#1+#2)/#3+\xint_c_ixixixix.% - {#1}{#2}{#3}% + 1#2\expandafter!\the\numexpr\XINT_div_sub_f #1% }% -% \end{macrocode} -% \lverb|1 suivi de #1=q1 sur quatre chiffres.#2=alpha, #3=y, #4=x, -% L, alpha', Q«c» --> nouvel alpha sur 4.{q1}{yx},L,alpha', Q«c» | -% \begin{macrocode} -\def\XINT_div_littleII_e 1#1.#2#3#4% +\def\XINT_div_sub_f #1#2#3!#4!% {% - \expandafter\expandafter\expandafter\XINT_div_littleII_f - \expandafter\xint_gobble_i\the\numexpr \xint_c_x^iv+#2-#1*#4.% - {#1}{{#3}{#4}}% + \xint_gob_til_Z #4\XINT_div_sub_fi \Z + \expandafter\XINT_div_sub_g\the\numexpr#1-#3+1#4-\xint_c_i.% }% -% \end{macrocode} -% \lverb|alpha.q,{yx},L,alpha',Q«c»->L{alpha}alpha'.{yx}{Qq}«c»| -% \begin{macrocode} -\def\XINT_div_littleII_f #1.#2#3#4#5#6% +\def\XINT_div_sub_g 1#1#2.% {% - \XINT_div_littleII_a {#4}{#1}#5.{#3}{#6#2}% + 1#2\expandafter!\the\numexpr\XINT_div_sub_h #1% }% -% \end{macrocode} -% \lverb|La soustraction spéciale. Dans 1.09j, elle fait A-qB, pour A (en fait -% alpha dans mes dénominations des commentaires du code) et qB chacun de -% longueur K ou K+4, avec K au moins huit multiple de quatre, qB a ses quatre -% chiffres significatifs (qui sont à droite) non nuls. Si A-qB<0 il suffit de -% renvoyer -, le résultat n'importe pas. On est sûr que qB est non nul. On le -% met dans cette version en premier pour tester plus facilement le cas avec qB -% de longueur K+4 et A de longueur seulement K. Lorsque la longueur de qB est -% inférieure ou égale à celle de A, on va jusqu'à la fin de A et donc c'est la -% retenue finale qui décide du cas négatif éventuel. Le résultat non négatif est -% toujours donc renvoyé avec la même longueur que A, et il est dans l'ordre. -% J'ai fait une implémentation des phases I et II en maintenant alpha toujours à -% l'envers afin d'éviter le reverse order systématique fait sur A (ou plutôt -% alpha), mais alors il fallait que la soustraction ici s'arrange pour repérer -% les huit chiffres les plus significatifs, au final ce n'était pas plus rapide, -% et même pénalisant pour de gros inputs. Dans les versions 1.09i et antérieures -% (en fait je pense qu'ici rien quasiment n'avait bougé depuis la première -% implémentation), la soustraction spéciale n'était pratiquée que dans des cas -% avec certainement A-qB positif ou nul. De plus on n'excluait pas q=0, donc il -% fallait aussi faire un éventuel reverseorder sur ce qui était encore non -% traité. Les cas avec q=0 sont maintenant interceptés en amont et comme A et qB -% ont toujours quasiment la même longueur on ne s'embarrasse pas de -% complications pour la fin.| -% \begin{macrocode} -\def\XINT_div_sub_xpxp #1#2% #1=alpha d\'ej\`a renvers\'e, #2 se d\'eveloppe en qB +\def\XINT_div_sub_h #1#2#3!#4!% {% - \expandafter\XINT_div_sub_xpxp_b #2\W\X\Y\Z #1\W\X\Y\Z + \xint_gob_til_Z #4\XINT_div_sub_hi \Z + \expandafter\XINT_div_sub_i\the\numexpr#1-#3+1#4-\xint_c_i.% }% -\def\XINT_div_sub_xpxp_b +\def\XINT_div_sub_i 1#1#2.% {% - \XINT_div_sub_A 1{}% + 1#2\expandafter!\the\numexpr\XINT_div_sub_a #1% }% -\def\XINT_div_sub_A #1#2#3#4#5#6% +\def\XINT_div_sub_bi\Z + \expandafter\XINT_div_sub_c\the\numexpr#1-#2+#3.#4!#5!#6!#7!#8!#9!\Z !\W {% - \xint_gob_til_W #3\xint_div_sub_az\W - \XINT_div_sub_B #1{#3#4#5#6}{#2}% + \XINT_div_sub_l #1#2!#5!#7!#9!% }% -\def\XINT_div_sub_B #1#2#3#4\W\X\Y\Z #5#6#7#8% +\def\XINT_div_sub_di\Z + \expandafter\XINT_div_sub_e\the\numexpr#1-#2+#3.#4!#5!#6!#7!#8\W {% - \xint_gob_til_W #5\xint_div_sub_bz\W - \XINT_div_sub_onestep #1#2{#8#7#6#5}{#3}#4\W\X\Y\Z + \XINT_div_sub_l #1#2!#5!#7!% }% -\def\XINT_div_sub_onestep #1#2#3#4#5#6% +\def\XINT_div_sub_fi\Z + \expandafter\XINT_div_sub_g\the\numexpr#1-#2+#3.#4!#5!#6\W {% - \expandafter\XINT_div_sub_backtoA - \the\numexpr 11#6-#5#4#3#2+#1-\xint_c_i.% + \XINT_div_sub_l #1#2!#5!% }% -\def\XINT_div_sub_backtoA #1#2#3.#4% +\def\XINT_div_sub_hi\Z + \expandafter\XINT_div_sub_i\the\numexpr#1-#2+#3.#4\W {% - \XINT_div_sub_A #2{#3#4}% + \XINT_div_sub_l #1#2!% }% -% \end{macrocode} -% \lverb|si on arrive en sub_bz c'est que qB était de longueur K+4 et A -% seulement de longueur K, le résultat est donc < 0, renvoyer juste -| -% \begin{macrocode} -\def\xint_div_sub_bz\W\XINT_div_sub_onestep #1\Z { -}% -% \end{macrocode} -% \lverb|si on arrive en sub_az c'est que qB était de longueur inférieure ou -% égale à celle de A, donc on continue jusqu'à la fin de A, et on vérifiera la -% retenue à la fin.| -% \begin{macrocode} -\def\xint_div_sub_az\W\XINT_div_sub_B #1#2{\XINT_div_sub_C #1}% -\def\XINT_div_sub_C #1#2#3#4#5#6% +\def\XINT_div_sub_l #1% +{% + \xint_UDzerofork + #1{-2\relax}% + 0\XINT_div_sub_r + \krof +}% +\def\XINT_div_sub_r #1!% +{% + -\ifnum 0#1=\xint_c_ 1\else2\fi\relax +}% +%%%%%%%%%%%% +\def\XINT_sdiv_out #1\Z #2\W% + {\expandafter + {\romannumeral0\XINT_unsep_cuzsmall#11\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W}% + {#2}}% +\def\XINT_smalldivx_a #1.1#2!1#3!% +{% + \expandafter\XINT_smalldivx_b + \the\numexpr (#3+#1)/#2-\xint_c_i!#1.#2!#3!% +}% +\def\XINT_smalldivx_b #1!% +{% + \if0#1\else + \xint_c_x^viii+#1\xint_afterfi{\expandafter!\the\numexpr}\fi + \XINT_smalldiv_c #1!% +}% +\def\XINT_smalldiv_c #1!#2.#3!#4!% +{% + \expandafter\XINT_smalldiv_d\the\numexpr #4-#1*#3!#2.#3!% +}% +\def\XINT_smalldiv_d #1!#2!#3#4!% +{% + \xint_gob_til_Z #4\XINT_smalldiv_end \Z + \XINT_smalldiv_e #1!#2!#3#4!% +}% +\def\XINT_smalldiv_end\Z\XINT_smalldiv_e #1!#2!1\Z!{1!\Z #1\W }% +\def\XINT_smalldiv_e #1!#2.#3!% +{% + \expandafter\XINT_smalldiv_f\the\numexpr + \xint_c_xi_e_viii_mone+#1*\xint_c_x^viii/#3!#2.#3!#1!% +}% +\def\XINT_smalldiv_f 1#1#2#3#4#5#6!#7.#8!% +{% + \xint_gob_til_zero #1\XINT_smalldiv_fz 0% + \expandafter\XINT_smalldiv_g + \the\numexpr\XINT_minimul_a #2#3#4#5.#6!#8!#2#3#4#5#6!#7.#8!% +}% +\def\XINT_smalldiv_fz 0% + \expandafter\XINT_smalldiv_g\the\numexpr\XINT_minimul_a + 9999.9999!#1!99999999!#2!0!1#3!% +{% + \XINT_smalldiv_i .#3!\xint_c_!#2!% +}% +\def\XINT_smalldiv_g 1#1!1#2!#3!#4!#5!#6!% +{% + \expandafter\XINT_smalldiv_h + \the\numexpr 1#6-#1.#2!#5!#3!#4!% +}% +\def\XINT_smalldiv_h 1#1#2.#3!#4!% +{% + \expandafter\XINT_smalldiv_i + \the\numexpr #4-#3+#1-\xint_c_i.#2!% +}% +\def\XINT_smalldiv_i #1.#2!#3!#4.#5!% +{% + \expandafter\XINT_smalldiv_j + \the\numexpr (#1#2+#4)/#5-\xint_c_i!#3!#1#2!#4.#5!% +}% +\def\XINT_smalldiv_j #1!#2!% {% - \xint_gob_til_W #3\xint_div_sub_cz\W - \XINT_div_sub_C_onestep #1{#6#5#4#3}{#2}% + \xint_c_x^viii+#1+#2\expandafter!\the\numexpr\XINT_smalldiv_k + #1!% }% -\def\XINT_div_sub_C_onestep #1#2% +\def\XINT_smalldiv_k #1!#2!#3.#4!% {% - \expandafter\XINT_div_sub_backtoC \the\numexpr 11#2+#1-\xint_c_i.% + \expandafter\XINT_smalldiv_d\the\numexpr #2-#1*#4!#3.#4!% }% -\def\XINT_div_sub_backtoC #1#2#3.#4% +%%%%%%%%%%%% +\def\XINT_div_mini #1.#2!1#3!% {% - \XINT_div_sub_C #2{#3#4}% + \expandafter\XINT_div_mini_a\the\numexpr + \xint_c_xi_e_viii_mone+#3*\xint_c_x^viii/#1!#1.#2!#3!% }% % \end{macrocode} -% \lverb|une fois arrivé en sub_cz on teste la retenue pour voir si le résultat -% final est en fait négatif, dans ce cas on renvoie seulement -| +% \lverb|Note (2015/10/08). Attention à la différence dans l'ordre des +% arguments avec ce que je vois en comparaison avec \XINT_smalldiv_f. Je ne me +% souviens plus du tout s'il y a une raison quelconque.| % \begin{macrocode} -\def\xint_div_sub_cz\W\XINT_div_sub_C_onestep #1#2% +\def\XINT_div_mini_a 1#1#2#3#4#5#6!#7.#8!% {% - \if#10% retenue - \expandafter\xint_div_sub_neg - \else\expandafter\xint_div_sub_ok - \fi + \xint_gob_til_zero #1\XINT_div_mini_w 0% + \expandafter\XINT_div_mini_b + \the\numexpr\XINT_minimul_a #2#3#4#5.#6!#7!#2#3#4#5#6!#7.#8!% +}% +\def\XINT_div_mini_w 0% + \expandafter\XINT_div_mini_b\the\numexpr\XINT_minimul_a + 9999.9999!#1!99999999!#2.#3!00000000!#4!% +{% + \xint_c_x^viii_mone+(#4+#3)/#2!% +}% +\def\XINT_div_mini_b 1#1!1#2!#3!#4!#5!#6!% +{% + \expandafter\XINT_div_mini_c + \the\numexpr 1#6-#1.#2!#5!#3!#4!% +}% +\def\XINT_div_mini_c 1#1#2.#3!#4!% +{% + \expandafter\XINT_div_mini_d + \the\numexpr #4-#3+#1-\xint_c_i.#2!% +}% +\def\XINT_div_mini_d #1.#2!#3!#4.#5!% +{% + \xint_c_x^viii_mone+#3+(#1#2+#5)/#4!% }% -\def\xint_div_sub_neg #1{ -}% -\def\xint_div_sub_ok #1{ #1}% % \end{macrocode} % \subsection{\csh{xintiDivRound}, \csh{xintiiDivRound}} -% \lverb|v1.1, transferred from first release of bnumexpr.| +% \lverb|v1.1, transferred from first release of bnumexpr. Rewritten for v1.2.| % \begin{macrocode} \def\xintiDivRound {\romannumeral0\xintidivround }% -\def\xintidivround #1{\expandafter\XINT_iidivround\romannumeral0\xintnum{#1}\Z }% +\def\xintidivround #1% + {\expandafter\XINT_idivround\romannumeral0\xintnum{#1}\Z }% \def\xintiiDivRound {\romannumeral0\xintiidivround }% \def\xintiidivround #1{\expandafter\XINT_iidivround \romannumeral-`0#1\Z }% -\def\XINT_iidivround #1#2\Z #3{\expandafter\XINT_iidivround_a\expandafter #1% - \romannumeral-`0#3\Z #2\Z }% +\def\XINT_idivround #1#2\Z #3% + {\expandafter\XINT_iidivround_a\expandafter #1% + \romannumeral0\xintnum{#3}\Z #2\Z }% +\def\XINT_iidivround #1#2\Z #3% + {\expandafter\XINT_iidivround_a\expandafter #1\romannumeral-`0#3\Z #2\Z }% \def\XINT_iidivround_a #1#2% #1 de A, #2 de B. {% \if0#2\xint_dothis\XINT_iidivround_divbyzero\fi @@ -18008,19 +17891,50 @@ $1$ or $-1$. -{\xintiiopp\XINT_iidivround_pos #1}% \krof }% -\def\XINT_iidivround_pos #1#2\Z #3\Z{\expandafter\XINT_iidivround_pos_a - \romannumeral0\XINT_div_prepare {#2}{#1#30}}% -\def\XINT_iidivround_pos_a #1#2{\xintReverseOrder {#1\XINT_iidivround_pos_b}\Z }% -\def\XINT_iidivround_pos_b #1#2{\xint_gob_til_Z #2\XINT_iidivround_pos_small\Z - \XINT_iidivround_pos_c #1#2}% -\def\XINT_iidivround_pos_c #1#2\Z {\ifnum #1>\xint_c_iv - \expandafter\XINT_iidivround_pos_up - \else \expandafter\xintreverseorder - \fi {#2}}% -\def\XINT_iidivround_pos_up #1{\xintinc {\xintReverseOrder{#1}}}% -\def\XINT_iidivround_pos_small\Z\XINT_iidivround_pos_c #1#2% - {\ifnum #1>\xint_c_iv\expandafter\xint_secondoftwo\else\expandafter - \xint_firstoftwo\fi { 0}{ 1}}% +\def\XINT_iidivround_pos #1#2\Z #3\Z +{% + \expandafter\XINT_iidivround_pos_a + \romannumeral0\XINT_div_prepare {#2}{#1#30}% +}% +\def\XINT_iidivround_pos_a #1#2% +{% + \expandafter\XINT_iidivround_pos_b + \romannumeral0\expandafter\XINT_sepandrev + \romannumeral0\XINT_zeroes_forviii #1\R\R\R\R\R\R\R\R{10}0000001\W + #1\XINT_rsepbyviii_end_A 2345678\XINT_rsepbyviii_end_B 2345678\relax XX% + \R.\R.\R.\R.\R.\R.\R.\R.\W + \Z!\Z!\Z!\Z!\Z!\W +}% +\def\XINT_iidivround_pos_b 1#1#2#3#4#5#6#7#8!#9% +{% + \xint_gob_til_Z #9\XINT_iidivround_small\Z + \ifnum #8>\xint_c_iv + \expandafter\XINT_iidivround_pos_up + \else \expandafter\XINT_iidivround_pos_finish + \fi + 1#1#2#3#4#5#6#70!#9% +}% +\def\XINT_iidivround_pos_up +{% + \expandafter\XINT_iidivround_pos_finish + \the\numexpr\XINT_add_a\xint_c_ii 100000010!\Z!\Z!\Z!\Z!\Z!\W +}% +\def\XINT_iidivround_pos_finish #10!#2\Z #3\W +{% + \expandafter\XINT_cuz_small\romannumeral0\XINT_unrevbyviii {}% + #1!#21\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W +}% +\def\XINT_iidivround_small\Z\ifnum #1>#2\fi 1#30!#4\W +{% + \ifnum #1>\xint_c_iv + \expandafter\XINT_iidivround_small_up + \else \expandafter\XINT_iidivround_small_trunc + \fi {#3}% +}% +\edef\XINT_iidivround_small_up #1% + {\noexpand\expandafter\space\noexpand\the\numexpr #1+\xint_c_i\relax }% +\edef\XINT_iidivround_small_trunc #1% + {\noexpand\expandafter\space\noexpand\the\numexpr #1\relax }% % \end{macrocode} % \subsection{\csh{xintiDivTrunc}, \csh{xintiiDivTrunc}} % \begin{macrocode} @@ -18052,7 +17966,8 @@ $1$ or $-1$. \krof }% \def\XINT_iidivtrunc_pos #1#2\Z #3\Z% - {\expandafter\xint_firstoftwo_thenstop\romannumeral0\XINT_div_prepare {#2}{#1#3}}% + {\expandafter\xint_firstoftwo_thenstop + \romannumeral0\XINT_div_prepare {#2}{#1#3}}% % \end{macrocode} % \subsection{\csh{xintiMod}, \csh{xintiiMod}} % \begin{macrocode} @@ -18084,7 +17999,20 @@ $1$ or $-1$. \krof }% \def\XINT_iimod_pos #1#2\Z #3\Z% - {\expandafter\xint_secondoftwo_thenstop\romannumeral0\XINT_div_prepare {#2}{#1#3}}% + {\expandafter\xint_secondoftwo_thenstop\romannumeral0\XINT_div_prepare + {#2}{#1#3}}% +% \end{macrocode} +% \subsection{``Load \xintfracnameimp'' macros} +% \lverb|Originally was used in \xintiiexpr. Transferred from xintfrac for 1.1.| +% \begin{macrocode} +\catcode`! 11 +\def\xintAbs {\Did_you_mean_iiAbs?or_load_xintfrac!}% +\def\xintOpp {\Did_you_mean_iiOpp?or_load_xintfrac!}% +\def\xintAdd {\Did_you_mean_iiAdd?or_load_xintfrac!}% +\def\xintSub {\Did_you_mean_iiSub?or_load_xintfrac!}% +\def\xintMul {\Did_you_mean_iiMul?or_load_xintfrac!}% +\def\xintPow {\Did_you_mean_iiPow?or_load_xintfrac!}% +\def\xintSqr {\Did_you_mean_iiSqr?or_load_xintfrac!}% \XINT_restorecatcodes_endinput% % \end{macrocode} %\catcode`\<=0 \catcode`\>=11 \catcode`\*=11 \catcode`\/=11 @@ -18099,9 +18027,10 @@ $1$ or $-1$. % % \localtableofcontents % -% The basic arithmetic routines |\xintiiAdd|, |\xintiiSub|, -% |\xintiiMul|, |\xintiiQuo| and |\xintiiPow| have been moved to new -% package \xintcorenameimp. +% With release |1.1| the core arithmetic routines |\xintiiAdd|, +% |\xintiiSub|, |\xintiiMul|, |\xintiiQuo|, |\xintiiPow| were separated to be +% the main component of the then new +% \xintcorenameimp. % \begin{macrocode} \begingroup\catcode61\catcode48\catcode32=10\relax% \catcode13=5 % ^^M @@ -18151,7 +18080,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xint}% - [2015/09/12 v1.1c Expandable operations on big integers (jfB)]% + [2015/10/10 v1.2 Expandable operations on big integers (jfB)]% % \end{macrocode} % \subsection{More token management} % \begin{macrocode} @@ -18161,6 +18090,10 @@ $1$ or $-1$. \long\def\xint_firstofthree_thenstop #1#2#3{ #1}% 1.09i \long\def\xint_secondofthree_thenstop #1#2#3{ #2}% \long\def\xint_thirdofthree_thenstop #1#2#3{ #3}% +\edef\xint_cleanupzeros_andstop #1#2#3#4% +{% + \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4\relax +}% % \end{macrocode} % \subsection{\csh{xintSgnFork}} % \lverb|Expandable three-way fork added in 1.07. The argument #1 must expand @@ -18201,24 +18134,12 @@ $1$ or $-1$. % However this last aspect does not appear like a very useful thing. And despite % the fact that a special check is made for a sign, actually the input is not % given to \xintnum, contrarily to \xintLen. This is all a bit incoherent. -% Should be fixed.| +% Should be fixed. +% +% 1.2 has \xintReverseDigits and I thus make \xintRev an alias. Remarks above +% not addressed.| % \begin{macrocode} -\def\xintRev {\romannumeral0\xintrev }% -\def\xintrev #1% -{% - \expandafter\XINT_rev_fork - \romannumeral-`0#1\xint_relax % empty #1 ok, \xint_relax stops expansion - \xint_bye\xint_bye\xint_bye\xint_bye - \xint_bye\xint_bye\xint_bye\xint_bye - \xint_relax -}% -\def\XINT_rev_fork #1% -{% - \xint_UDsignfork - #1{\expandafter\xint_minus_thenstop\romannumeral0\XINT_rord_main {}}% - -{\XINT_rord_main {}#1}% - \krof -}% +\let\xintRev\xintReverseDigits % \end{macrocode} % \subsection{\csh{xintLen}} % \lverb|\xintLen is ONLY for (possibly long) integers. Gets extended to @@ -18463,143 +18384,183 @@ $1$ or $-1$. }% % \end{macrocode} % \subsection{\csh{xintCmp}, \csh{xintiiCmp}} -% \lverb|Release 1.09a has \xintnum inserted into \xintCmp. Unnecessary -% \xintiCmp suppressed in 1.09f. And 1.1a does \xintiiCmp, for -% optimization in \xintiiexpr. (not needed before, because \XINT_cmp_fork was -% directly used, or \XINT_Cmp)| +% \lverb|Faster than doing the full subtraction.| % \begin{macrocode} -\def\xintCmp {\romannumeral0\xintcmp }% -\def\xintcmp #1% +\def\xintCmp {\romannumeral0\xintcmp }% +\def\xintcmp #1{\expandafter\XINT_icmp\romannumeral0\xintnum{#1}\Z }% +\def\xintiiCmp {\romannumeral0\xintiicmp }% +\def\xintiicmp #1{\expandafter\XINT_iicmp\romannumeral-`0#1\Z }% +\def\XINT_iicmp #1#2\Z #3% {% - \expandafter\xint_cmp\expandafter{\romannumeral0\xintnum{#1}}% + \expandafter\XINT_cmp_nfork\expandafter #1\romannumeral-`0#3\Z #2\Z }% -\def\xint_cmp #1#2% +% \end{macrocode} +% \lverb|New fork of 1.2 makes it less convenient here for \XINT_cmp_pre and +% \XINT_Cmp, which just avoided the \romannumeral-`0. Nanosecond loss ? I +% vaguely recalled that for \xintNewExpr things, I did need another name such +% as \XINT_cmp for \xintiiCmp.| +% \begin{macrocode} +\let\XINT_Cmp \xintiiCmp +\def\XINT_icmp #1#2\Z #3% {% - \expandafter\XINT_cmp_fork \romannumeral0\xintnum{#2}\Z #1\Z + \expandafter\XINT_cmp_nfork\expandafter #1\romannumeral0\xintnum{#3}\Z #2\Z }% -\def\xintiiCmp {\romannumeral0\xintiicmp }% -\def\xintiicmp #1% +\def\XINT_cmp_nfork #1#2% {% - \expandafter\xint_iicmp\expandafter{\romannumeral-`0#1}% + \xint_UDzerofork + #1\XINT_cmp_firstiszero + #2\XINT_cmp_secondiszero + 0{}% + \krof + \xint_UDsignsfork + #1#2\XINT_cmp_minusminus + #1-\XINT_cmp_minusplus + #2-\XINT_cmp_plusminus + --\XINT_cmp_plusplus + \krof #1#2% }% -\def\xint_iicmp #1#2% +\def\XINT_cmp_firstiszero #1\krof 0#2#3\Z #4\Z {% - \expandafter\XINT_cmp_fork \romannumeral-`0#2\Z #1\Z -}% -\def\XINT_Cmp #1#2{\romannumeral0\XINT_cmp_fork #2\Z #1\Z }% -% \end{macrocode} -% \lverb|& -% COMPARAISON $\ -% 1 si #3#4>#1#2, 0 si #3#4=#1#2, -1 si #3#4<#1#2$\ -% #3#4 vient du *premier*,$ -% #1#2 vient du *second*| -% \begin{macrocode} -\def\XINT_cmp_fork #1#2\Z #3#4\Z + \xint_UDzerominusfork + #2-{ 0}% + 0#2{ 1}% + 0-{ -1}% + \krof +}% +\def\XINT_cmp_secondiszero #1\krof #20#3\Z #4\Z {% - \xint_UDsignsfork - #1#3\XINT_cmp_minusminus - #1-\XINT_cmp_minusplus - #3-\XINT_cmp_plusminus - --{\xint_UDzerosfork - #1#3\XINT_cmp_zerozero - #10\XINT_cmp_zeroplus - #30\XINT_cmp_pluszero - 00\XINT_cmp_plusplus - \krof }% + \xint_UDzerominusfork + #2-{ 0}% + 0#2{ -1}% + 0-{ 1}% \krof - {#2}{#4}#1#3% +}% +\def\XINT_cmp_plusminus #1\Z #2\Z{ 1}% +\def\XINT_cmp_minusplus #1\Z #2\Z{ -1}% +\def\XINT_cmp_minusminus + --{\expandafter\XINT_opp\romannumeral0\XINT_cmp_plusplus {}{}}% +\def\XINT_cmp_plusplus #1#2#3\Z +{% + \expandafter\XINT_cmp_pp + \romannumeral0\expandafter\XINT_sepandrev_andcount + \romannumeral0\XINT_zeroes_forviii #2#3\R\R\R\R\R\R\R\R{10}0000001\W + #2#3\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax\xint_c_ii\xint_c_iii + \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii + \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W + \X #1% +}% +\def\XINT_cmp_pp #1.#2\X #3\Z +{% + \expandafter\XINT_cmp_checklengths + \the\numexpr #1\expandafter.% + \romannumeral0\expandafter\XINT_sepandrev_andcount + \romannumeral0\XINT_zeroes_forviii #3\R\R\R\R\R\R\R\R{10}0000001\W + #3\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax \xint_c_ii\xint_c_iii + \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii + \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W + \Z!\Z!\Z!\Z!\Z!\W #2\Z!\Z!\Z!\Z!\Z!\W +}% +\def\XINT_cmp_checklengths #1.#2.% +{% + \ifnum #1=#2 + \expandafter\xint_firstoftwo + \else + \expandafter\xint_secondoftwo + \fi + \XINT_cmp_aa {\XINT_cmp_distinctlengths {#1}{#2}}% }% -\def\XINT_cmp_minusplus #1#2#3#4{ 1}% -\def\XINT_cmp_plusminus #1#2#3#4{ -1}% -\def\XINT_cmp_zerozero #1#2#3#4{ 0}% -\def\XINT_cmp_zeroplus #1#2#3#4{ 1}% -\def\XINT_cmp_pluszero #1#2#3#4{ -1}% -\def\XINT_cmp_plusplus #1#2#3#4% +\def\XINT_cmp_distinctlengths #1#2#3\W #4\W {% - \XINT_cmp_pre {#4#2}{#3#1}% + \ifnum #1>#2 + \expandafter\xint_firstoftwo + \else + \expandafter\xint_secondoftwo + \fi + { -1}{ 1}% }% -\def\XINT_cmp_minusminus #1#2#3#4% +%%%%%%%%%%%% +\def\XINT_cmp_aa {\expandafter\XINT_cmp_w\the\numexpr\XINT_cmp_a \xint_c_i }% +%%%%%%%%%%%% +\def\XINT_cmp_a #1!#2!#3!#4!#5\W #6!#7!#8!#9!% {% - \XINT_cmp_pre {#1}{#2}% + \XINT_cmp_b #1!#6!#2!#7!#3!#8!#4!#9!#5\W }% -\def\XINT_cmp_pre #1% +\def\XINT_cmp_b #1#2#3!#4!% {% - \expandafter\XINT_cmp_pre_b\expandafter - {\romannumeral0\XINT_RQ {}#1\R\R\R\R\R\R\R\R\Z }% + \xint_gob_til_Z #2\XINT_cmp_bi \Z + \expandafter\XINT_cmp_c\the\numexpr#1+1#4-#3-\xint_c_i.% }% -\def\XINT_cmp_pre_b #1#2% +\def\XINT_cmp_c 1#1#2.% {% - \expandafter\XINT_cmp_A - \expandafter1\expandafter{\expandafter}% - \romannumeral0\XINT_RQ {}#2\R\R\R\R\R\R\R\R\Z - \W\X\Y\Z #1\W\X\Y\Z + 1#2\expandafter!\the\numexpr\XINT_cmp_d #1% }% -% \end{macrocode} -% \lverb|& -% COMPARAISON$\ -% N1 et N2 sont présentés à l'envers ET ON A RAJOUTÉ DES ZÉROS -% POUR QUE LEUR LONGUEURS À CHACUN SOIENT MULTIPLES DE 4, MAIS -% AUCUN NE SE TERMINE EN 0000. -% routine appelée via$\ -% \XINT_cmp_A 1{}\W\X\Y\Z\W\X\Y\Z$\ -% ATTENTION RENVOIE 1 SI N1 < N2, 0 si N1 = N2, -1 si N1 > N2| -% \begin{macrocode} -\def\XINT_cmp_A #1#2#3\W\X\Y\Z #4#5#6#7% +\def\XINT_cmp_d #1#2#3!#4!% {% - \xint_gob_til_W #4\xint_cmp_az\W - \XINT_cmp_B #1{#4#5#6#7}{#2}#3\W\X\Y\Z + \xint_gob_til_Z #2\XINT_cmp_di \Z + \expandafter\XINT_cmp_e\the\numexpr#1+1#4-#3-\xint_c_i.% }% -\def\XINT_cmp_B #1#2#3#4#5#6#7% +\def\XINT_cmp_e 1#1#2.% {% - \xint_gob_til_W#4\xint_cmp_bz\W - \XINT_cmp_onestep #1#2{#7#6#5#4}{#3}% + 1#2\expandafter!\the\numexpr\XINT_cmp_f #1% }% -\def\XINT_cmp_onestep #1#2#3#4#5#6% +\def\XINT_cmp_f #1#2#3!#4!% {% - \expandafter\XINT_cmp_backtoA\the\numexpr 11#5#4#3#2-#6+#1-\xint_c_i.% + \xint_gob_til_Z #2\XINT_cmp_fi \Z + \expandafter\XINT_cmp_g\the\numexpr#1+1#4-#3-\xint_c_i.% }% -\def\XINT_cmp_backtoA #1#2#3.#4% +\def\XINT_cmp_g 1#1#2.% {% - \XINT_cmp_A #2{#3#4}% + 1#2\expandafter!\the\numexpr\XINT_cmp_h #1% }% -\def\xint_cmp_bz\W\XINT_cmp_onestep #1\Z { 1}% -\def\xint_cmp_az\W\XINT_cmp_B #1#2#3#4#5#6#7% +\def\XINT_cmp_h #1#2#3!#4!% {% - \xint_gob_til_W #4\xint_cmp_ez\W - \XINT_cmp_Eenter #1{#3}#4#5#6#7% + \xint_gob_til_Z #2\XINT_cmp_hi \Z + \expandafter\XINT_cmp_i\the\numexpr#1+1#4-#3-\xint_c_i.% }% -\def\XINT_cmp_Eenter #1\Z { -1}% -\def\xint_cmp_ez\W\XINT_cmp_Eenter #1% +\def\XINT_cmp_i 1#1#2.% {% - \xint_UDzerofork - #1\XINT_cmp_K % il y a une retenue - 0\XINT_cmp_L % pas de retenue - \krof + 1#2\expandafter!\the\numexpr\XINT_cmp_a #1% +}% +\def\XINT_cmp_bi\Z + \expandafter\XINT_cmp_c\the\numexpr#1+1#2-#3.#4!#5!#6!#7!#8!#9!\Z !\W +{% + \XINT_cmp_k #1#2!#5!#7!#9!% }% -\def\XINT_cmp_K #1\Z { -1}% -\def\XINT_cmp_L #1{\XINT_OneIfPositive_main #1}% -\def\XINT_OneIfPositive #1% +\def\XINT_cmp_di\Z + \expandafter\XINT_cmp_e\the\numexpr#1+1#2-#3.#4!#5!#6!#7!#8\W {% - \XINT_OneIfPositive_main #1\W\X\Y\Z% + \XINT_cmp_k #1#2!#5!#7!% }% -\def\XINT_OneIfPositive_main #1#2#3#4% +\def\XINT_cmp_fi\Z + \expandafter\XINT_cmp_g\the\numexpr#1+1#2-#3.#4!#5!#6\W {% - \xint_gob_til_Z #4\xint_OneIfPositive_terminated\Z - \XINT_OneIfPositive_onestep #1#2#3#4% + \XINT_cmp_k #1#2!#5!% }% -\def\xint_OneIfPositive_terminated\Z\XINT_OneIfPositive_onestep\W\X\Y\Z { 0}% -\def\XINT_OneIfPositive_onestep #1#2#3#4% +\def\XINT_cmp_hi\Z + \expandafter\XINT_cmp_i\the\numexpr#1+1#2-#3.#4\W {% - \expandafter\XINT_OneIfPositive_check\the\numexpr #1#2#3#4\relax + \XINT_cmp_k #1#2!% }% -\def\XINT_OneIfPositive_check #1% +%%%%%%%%%%%% +\def\XINT_cmp_k #1#2\W {% - \xint_gob_til_zero #1\xint_OneIfPositive_backtomain 0% - \XINT_OneIfPositive_finish #1% + \xint_UDzerofork + #1{-1\relax \XINT_cmp_greater}% + 0{-1\relax \XINT_cmp_lessorequal}% + \krof }% -\def\XINT_OneIfPositive_finish #1\W\X\Y\Z{ 1}% -\def\xint_OneIfPositive_backtomain 0\XINT_OneIfPositive_finish 0% - {\XINT_OneIfPositive_main }% +\def\XINT_cmp_w #1-1#2{#2#11\Z!\W}% +\def\XINT_cmp_greater #1\Z!\W{ 1}% +\def\XINT_cmp_lessorequal 1#1!% + {\xint_gob_til_Z #1\XINT_cmp_equal\Z + \xint_gob_til_eightzeroes #1\XINT_cmp_continue 00000000% + \XINT_cmp_less }% +\def\XINT_cmp_less #1\W { -1}% +\def\XINT_cmp_continue 00000000\XINT_cmp_less {\XINT_cmp_lessorequal }% +\def\XINT_cmp_equal\Z\xint_gob_til_eightzeroes\Z\XINT_cmp_continue + 00000000\XINT_cmp_less\W { 0}% % \end{macrocode} % \subsection{\csh{xintEq}, \csh{xintGt}, \csh{xintLt}} % \lverb|1.09a.| @@ -18711,101 +18672,159 @@ $1$ or $-1$. }% \def\XINT_xorof_e #1\Z #2{ #2}% % \end{macrocode} -% \subsection{\csh{xintGeq}} -% \lverb|& -% Release 1.09a has \xintnum added into \xintGeq. -% PLUS GRAND OU ÉGAL -% attention compare les **valeurs absolues**| -% \begin{macrocode} -\def\xintGeq {\romannumeral0\xintgeq }% -\def\xintgeq #1% -{% - \expandafter\xint_geq\expandafter {\romannumeral0\xintnum{#1}}% -}% -\def\xint_geq #1#2% -{% - \expandafter\XINT_geq_fork \romannumeral0\xintnum{#2}\Z #1\Z -}% -\def\XINT_Geq #1#2{\romannumeral0\XINT_geq_fork #2\Z #1\Z }% -% \end{macrocode} +% \subsection{\csh{xintGeq}, \csh{xintiiGeq}} % \lverb|& % PLUS GRAND OU ÉGAL -% ATTENTION, TESTE les VALEURS ABSOLUES| +% attention compare les **valeurs absolues**| % \begin{macrocode} -\def\XINT_geq_fork #1#2\Z #3#4\Z +\def\xintGeq {\romannumeral0\xintgeq }% +\def\xintgeq #1{\expandafter\XINT_geq\romannumeral0\xintnum{#1}\Z }% +\def\xintiiGeq {\romannumeral0\xintiigeq }% +\def\xintiigeq #1{\expandafter\XINT_iigeq\romannumeral-`0#1\Z }% +\def\XINT_iigeq #1#2\Z #3% +{% + \expandafter\XINT_geq_fork\expandafter #1\romannumeral-`0#3\Z #2\Z +}% +\let\XINT_geq_pre \xintiigeq % TEMPORAIRE +\let\XINT_Geq \xintGeq % TEMPORAIRE ATTENTION FAIT xintNum +\def\XINT_geq #1#2\Z #3% +{% + \expandafter\XINT_geq_fork\expandafter #1\romannumeral0\xintnum{#3}\Z #2\Z +}% +\def\XINT_geq_fork #1#2% {% \xint_UDzerofork - #1\XINT_geq_secondiszero % |#1#2|=0 - #3\XINT_geq_firstiszero % |#1#2|>0 - 0{\xint_UDsignsfork - #1#3\XINT_geq_minusminus - #1-\XINT_geq_minusplus - #3-\XINT_geq_plusminus - --\XINT_geq_plusplus - \krof }% + #1\XINT_geq_firstiszero + #2\XINT_geq_secondiszero + 0{}% \krof - {#2}{#4}#1#3% + \xint_UDsignsfork + #1#2\XINT_geq_minusminus + #1-\XINT_geq_minusplus + #2-\XINT_geq_plusminus + --\XINT_geq_plusplus + \krof #1#2% +}% +\def\XINT_geq_firstiszero #1\krof 0#2#3\Z #4\Z + {\xint_UDzerofork #2{ 1}0{ 0}\krof }% +\def\XINT_geq_secondiszero #1\krof #20#3\Z #4\Z { 1}% +\def\XINT_geq_plusminus #1-{\XINT_geq_plusplus #1{}}% +\def\XINT_geq_minusplus -#1{\XINT_geq_plusplus {}#1}% +\def\XINT_geq_minusminus --{\XINT_geq_plusplus {}{}}% +\def\XINT_geq_plusplus #1#2#3\Z #4\Z {\XINT_geq_pp #1#4\Z #2#3\Z }% +\def\XINT_geq_pp #1\Z +{% + \expandafter\XINT_geq_pp_a + \romannumeral0\expandafter\XINT_sepandrev_andcount + \romannumeral0\XINT_zeroes_forviii #1\R\R\R\R\R\R\R\R{10}0000001\W + #1\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax\xint_c_ii\xint_c_iii + \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii + \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W + \X +}% +\def\XINT_geq_pp_a #1.#2\X #3\Z +{% + \expandafter\XINT_geq_checklengths + \the\numexpr #1\expandafter.% + \romannumeral0\expandafter\XINT_sepandrev_andcount + \romannumeral0\XINT_zeroes_forviii #3\R\R\R\R\R\R\R\R{10}0000001\W + #3\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678\relax \xint_c_ii\xint_c_iii + \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii + \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W + \Z!\Z!\Z!\Z!\Z!\W #2\Z!\Z!\Z!\Z!\Z!\W +}% +\def\XINT_geq_checklengths #1.#2.% +{% + \ifnum #1=#2 + \expandafter\xint_firstoftwo + \else + \expandafter\xint_secondoftwo + \fi + \XINT_geq_aa {\XINT_geq_distinctlengths {#1}{#2}} }% -\def\XINT_geq_secondiszero #1#2#3#4{ 1}% -\def\XINT_geq_firstiszero #1#2#3#4{ 0}% -\def\XINT_geq_plusplus #1#2#3#4{\XINT_geq_pre {#4#2}{#3#1}}% -\def\XINT_geq_minusminus #1#2#3#4{\XINT_geq_pre {#2}{#1}}% -\def\XINT_geq_minusplus #1#2#3#4{\XINT_geq_pre {#4#2}{#1}}% -\def\XINT_geq_plusminus #1#2#3#4{\XINT_geq_pre {#2}{#3#1}}% -\def\XINT_geq_pre #1% +\def\XINT_geq_distinctlengths #1#2#3\W #4\W {% - \expandafter\XINT_geq_pre_b\expandafter - {\romannumeral0\XINT_RQ {}#1\R\R\R\R\R\R\R\R\Z }% + \ifnum #1>#2 + \expandafter\xint_firstoftwo + \else + \expandafter\xint_secondoftwo + \fi + { 1}{ 0}% }% -\def\XINT_geq_pre_b #1#2% +%%%%%%%%%%%% +\def\XINT_geq_aa {\expandafter\XINT_geq_w\the\numexpr\XINT_geq_a \xint_c_i }% +%%%%%%%%%%%% +\def\XINT_geq_a #1!#2!#3!#4!#5\W #6!#7!#8!#9!% {% - \expandafter\XINT_geq_A - \expandafter1\expandafter{\expandafter}% - \romannumeral0\XINT_RQ {}#2\R\R\R\R\R\R\R\R\Z - \W\X\Y\Z #1 \W\X\Y\Z + \XINT_geq_b #1!#6!#2!#7!#3!#8!#4!#9!#5\W }% -% \end{macrocode} -% \lverb|& -% PLUS GRAND OU ÉGAL$\ -% N1 et N2 sont présentés à l'envers ET ON A RAJOUTÉ DES ZÉROS -% POUR QUE LEURS LONGUEURS À CHACUN SOIENT MULTIPLES DE 4, MAIS -% AUCUN NE SE TERMINE EN 0000$\ -% routine appelée via$\ -% \romannumeral0\XINT_geq_A 1{}\W\X\Y\Z\W\X\Y\Z$\ -% ATTENTION RENVOIE 1 SI N1 < N2 ou N1 = N2 et 0 si N1 > N2| -% \begin{macrocode} -\def\XINT_geq_A #1#2#3\W\X\Y\Z #4#5#6#7% +\def\XINT_geq_b #1#2#3!#4!% {% - \xint_gob_til_W #4\xint_geq_az\W - \XINT_geq_B #1{#4#5#6#7}{#2}#3\W\X\Y\Z + \xint_gob_til_Z #2\XINT_geq_bi \Z + \expandafter\XINT_geq_c\the\numexpr#1+1#4-#3-\xint_c_i.% }% -\def\XINT_geq_B #1#2#3#4#5#6#7% +\def\XINT_geq_c 1#1#2.% {% - \xint_gob_til_W #4\xint_geq_bz\W - \XINT_geq_onestep #1#2{#7#6#5#4}{#3}% + 1#2\expandafter!\the\numexpr\XINT_geq_d #1% }% -\def\XINT_geq_onestep #1#2#3#4#5#6% +\def\XINT_geq_d #1#2#3!#4!% {% - \expandafter\XINT_geq_backtoA\the\numexpr 11#5#4#3#2-#6+#1-\xint_c_i.% + \xint_gob_til_Z #2\XINT_geq_di \Z + \expandafter\XINT_geq_e\the\numexpr#1+1#4-#3-\xint_c_i.% }% -\def\XINT_geq_backtoA #1#2#3.#4% +\def\XINT_geq_e 1#1#2.% {% - \XINT_geq_A #2{#3#4}% + 1#2\expandafter!\the\numexpr\XINT_geq_f #1% }% -\def\xint_geq_bz\W\XINT_geq_onestep #1\W\X\Y\Z { 1}% -\def\xint_geq_az\W\XINT_geq_B #1#2#3#4#5#6#7% +\def\XINT_geq_f #1#2#3!#4!% {% - \xint_gob_til_W #4\xint_geq_ez\W - \XINT_geq_Eenter #1% + \xint_gob_til_Z #2\XINT_geq_fi \Z + \expandafter\XINT_geq_g\the\numexpr#1+1#4-#3-\xint_c_i.% }% -\def\XINT_geq_Eenter #1\W\X\Y\Z { 0}% -\def\xint_geq_ez\W\XINT_geq_Eenter #1% +\def\XINT_geq_g 1#1#2.% {% - \xint_UDzerofork - #1{ 0} % il y a une retenue - 0{ 1} % pas de retenue - \krof + 1#2\expandafter!\the\numexpr\XINT_geq_h #1% +}% +\def\XINT_geq_h #1#2#3!#4!% +{% + \xint_gob_til_Z #2\XINT_geq_hi \Z + \expandafter\XINT_geq_i\the\numexpr#1+1#4-#3-\xint_c_i.% +}% +\def\XINT_geq_i 1#1#2.% +{% + 1#2\expandafter!\the\numexpr\XINT_geq_a #1% +}% +\def\XINT_geq_bi\Z + \expandafter\XINT_geq_c\the\numexpr#1+1#2-#3.#4!#5!#6!#7!#8!#9!\Z !\W +{% + \XINT_geq_k #1#2!#5!#7!#9!% +}% +\def\XINT_geq_di\Z + \expandafter\XINT_geq_e\the\numexpr#1+1#2-#3.#4!#5!#6!#7!#8\W +{% + \XINT_geq_k #1#2!#5!#7!% +}% +\def\XINT_geq_fi\Z + \expandafter\XINT_geq_g\the\numexpr#1+1#2-#3.#4!#5!#6\W +{% + \XINT_geq_k #1#2!#5!% +}% +\def\XINT_geq_hi\Z + \expandafter\XINT_geq_i\the\numexpr#1+1#2-#3.#4\W +{% + \XINT_geq_k #1#2!% }% +%%%%%%%%%%%% +\def\XINT_geq_k #1#2\W +{% + \xint_UDzerofork + #1{-1\relax { 0}}% + 0{-1\relax { 1}}% + \krof +}% +\def\XINT_geq_w #1-1#2{#2}% % \end{macrocode} % \subsection{\csh{xintiMax}, \csh{xintiiMax}} % \lverb|& @@ -18816,7 +18835,9 @@ $1$ or $-1$. % 1.09a has \xintnum added into \xintiMax. % % 1.1 adds the missing \xintiiMax. Using \xintMax and not \xintiMax in xint is -% deprecated.| +% deprecated. +% +% 1.2 REMOVES \xintMax, \xintMin, \xintMaxof, \xintMinof.| % \begin{macrocode} \def\xintiMax {\romannumeral0\xintimax }% \def\xintimax #1% @@ -18836,7 +18857,6 @@ $1$ or $-1$. {% \expandafter\XINT_max_pre\expandafter {\romannumeral-`0#2}{#1}% }% -\let\xintMax\xintiMax \let\xintmax\xintimax % deprecated, should be only with xintfrac \def\XINT_max_pre #1#2{\XINT_max_fork #1\Z #2\Z {#2}{#1}}% \def\XINT_Max #1#2{\romannumeral0\XINT_max_fork #2\Z #1\Z {#1}{#2}}% % \end{macrocode} @@ -18888,8 +18908,8 @@ $1$ or $-1$. \fi }% % \end{macrocode} -% \subsection{\csh{xintMaxof}} -% \lverb|New with 1.09a.| +% \subsection{\csh{xintiMaxof}} +% \lverb|New with 1.09a. 1.2 has NO MORE \xintMaxof, requires \xintfracname.| % \begin{macrocode} \def\xintiMaxof {\romannumeral0\xintimaxof }% \def\xintimaxof #1{\expandafter\XINT_imaxof_a\romannumeral-`0#1\relax }% @@ -18901,11 +18921,11 @@ $1$ or $-1$. \def\XINT_imaxof_d #1\Z {\expandafter\XINT_imaxof_b\romannumeral0\xintimax {#1}}% \def\XINT_imaxof_e #1\Z #2\Z { #2}% -\let\xintMaxof\xintiMaxof \let\xintmaxof\xintimaxof % \end{macrocode} % \subsection{\csh{xintiMin}, \csh{xintiiMin}} % \lverb|\xintnum added New with 1.09a. I add \xintiiMin in 1.1 and mark as -% deprecated \xintMin, renamed \xintiMin.| +% deprecated \xintMin, renamed \xintiMin. \xintMin NOW REMOVED (1.2, as +% \xintMax, \xintMaxof), only provided by \xintfracnameimp.| % \begin{macrocode} \def\xintiMin {\romannumeral0\xintimin }% \def\xintimin #1% @@ -18925,7 +18945,6 @@ $1$ or $-1$. {% \expandafter\XINT_min_pre\expandafter {\romannumeral-`0#2}{#1}% }% -\let\xintMin\xintiMin \let\xintmin\xintimin % deprecated \def\XINT_min_pre #1#2{\XINT_min_fork #1\Z #2\Z {#2}{#1}}% \def\XINT_Min #1#2{\romannumeral0\XINT_min_fork #2\Z #1\Z {#1}{#2}}% % \end{macrocode} @@ -18990,12 +19009,11 @@ $1$ or $-1$. \def\XINT_iminof_d #1\Z {\expandafter\XINT_iminof_b\romannumeral0\xintimin {#1}}% \def\XINT_iminof_e #1\Z #2\Z { #2}% -\let\xintMinof\xintiMinof \let\xintminof\xintiminof % \end{macrocode} % \subsection{\csh{xintiiSum}} % \lverb|& -% \xintSum {{a}{b}...{z}}$\ -% \xintSumExpr {a}{b}...{z}\relax$\ +% \xintiiSum {{a}{b}...{z}}$\ +% \xintiiSumExpr {a}{b}...{z}\relax$\ % 1.03 (drastically) simplifies and makes the routines more efficient (for big % computations). Also the way \xintSum and \xintSumExpr ...\relax are related. % has been modified. Now \xintSumExpr \z \relax is accepted input when @@ -19003,55 +19021,36 @@ $1$ or $-1$. % was possible). % % 1.09a does NOT add the \xintnum overhead. 1.09h renames \xintiSum to -% \xintiiSum to correctly reflect this.| +% \xintiiSum to correctly reflect this. +% +% The xint 1.0x routine could benefit from the fact that addition and +% subtraction did not check the lengths of the arguments and were able to do +% their job independently of the order (but not at equal speed). Thus it was +% possible to add separately positive and negative summands and do one big +% subtraction at the end, keeping during all that time the intermediate result +% in reverse order suitable for both addition and subtraction. The lazy +% programmer being a bit tired after the 95$% rewrite of xintcore has not +% tried to do the same with the new model. Thus we just do stupidly repeated +% additions. The code is thus much shorter... and in fact I just copied the +% routine for products and changed products to sums.| % \begin{macrocode} \def\xintiiSum {\romannumeral0\xintiisum }% \def\xintiisum #1{\xintiisumexpr #1\relax }% \def\xintiiSumExpr {\romannumeral0\xintiisumexpr }% \def\xintiisumexpr {\expandafter\XINT_sumexpr\romannumeral-`0}% -\let\xintSum\xintiiSum \let\xintsum\xintiisum -\let\xintSumExpr\xintiiSumExpr \let\xintsumexpr\xintiisumexpr -\def\XINT_sumexpr {\XINT_sum_loop {0000}{0000}}% -\def\XINT_sum_loop #1#2#3% -{% - \expandafter\XINT_sum_checksign\romannumeral-`0#3\Z {#1}{#2}% -}% -\def\XINT_sum_checksign #1% -{% - \xint_gob_til_relax #1\XINT_sum_finished\relax - \xint_gob_til_zero #1\XINT_sum_skipzeroinput0% - \xint_UDsignfork - #1\XINT_sum_N - -{\XINT_sum_P #1}% - \krof -}% -\def\XINT_sum_finished #1\Z #2#3% -{% - \XINT_sub_A 1{}#3\W\X\Y\Z #2\W\X\Y\Z -}% -\def\XINT_sum_skipzeroinput #1\krof #2\Z {\XINT_sum_loop }% -\def\XINT_sum_P #1\Z #2% -{% - \expandafter\XINT_sum_loop\expandafter - {\romannumeral0\expandafter - \XINT_addr_A\expandafter0\expandafter{\expandafter}% - \romannumeral0\XINT_RQ {}#1\R\R\R\R\R\R\R\R\Z - \W\X\Y\Z #2\W\X\Y\Z }% -}% -\def\XINT_sum_N #1\Z #2#3% -{% - \expandafter\XINT_sum_NN\expandafter - {\romannumeral0\expandafter - \XINT_addr_A\expandafter0\expandafter{\expandafter}% - \romannumeral0\XINT_RQ {}#1\R\R\R\R\R\R\R\R\Z - \W\X\Y\Z #3\W\X\Y\Z }{#2}% -}% -\def\XINT_sum_NN #1#2{\XINT_sum_loop {#2}{#1}}% +\def\XINT_sumexpr {\XINT_sum_loop_a 0\Z }% +\def\XINT_sum_loop_a #1\Z #2% + {\expandafter\XINT_sum_loop_b \romannumeral-`0#2\Z #1\Z \Z}% +\def\XINT_sum_loop_b #1% + {\xint_gob_til_relax #1\XINT_sum_finished\relax\XINT_sum_loop_c #1}% +\def\XINT_sum_loop_c + {\expandafter\XINT_sum_loop_a\romannumeral0\XINT_add_fork }% +\def\XINT_sum_finished #1\Z #2\Z \Z { #2}% % \end{macrocode} % \subsection{\csh{xintiiPrd}} % \lverb|& -% \xintPrd {{a}...{z}}$\ -% \xintPrdExpr {a}...{z}\relax$\ +% \xintiiPrd {{a}...{z}}$\ +% \xintiiPrdExpr {a}...{z}\relax$\ % Release 1.02 modified the product routine. The earlier version was faster in % situations where each new term is bigger than the product of all previous % terms, a situation which arises in the algorithm for computing powers. The @@ -19077,119 +19076,16 @@ $1$ or $-1$. % \begin{macrocode} \def\xintiiPrd {\romannumeral0\xintiiprd }% \def\xintiiprd #1{\xintiiprdexpr #1\relax }% -\let\xintPrd\xintiiPrd -\let\xintprd\xintiiprd \def\xintiiPrdExpr {\romannumeral0\xintiiprdexpr }% \def\xintiiprdexpr {\expandafter\XINT_prdexpr\romannumeral-`0}% -\let\xintPrdExpr\xintiiPrdExpr -\let\xintprdexpr\xintiiprdexpr \def\XINT_prdexpr {\XINT_prod_loop_a 1\Z }% \def\XINT_prod_loop_a #1\Z #2% - {\expandafter\XINT_prod_loop_b \romannumeral-`0#2\Z #1\Z \Z}% + {\expandafter\XINT_prod_loop_b \romannumeral-`0#2\Z #1\Z \Z}% \def\XINT_prod_loop_b #1% {\xint_gob_til_relax #1\XINT_prod_finished\relax\XINT_prod_loop_c #1}% \def\XINT_prod_loop_c {\expandafter\XINT_prod_loop_a\romannumeral0\XINT_mul_fork }% -\def\XINT_prod_finished #1\Z #2\Z \Z { #2}% -% \end{macrocode} -% \subsection{\csh{xintFac}} -% \lverb|& -% Modified with 1.02 and again in 1.03 for greater efficiency. I am -% tempted, -% here and elsewhere, to use \ifcase\XINT_Geq {#1}{1000000000} rather than -% \ifnum\xintLength {#1}>9 but for the time being I leave things as they stand. -% With release 1.05, rather than using \xintLength I opt finally for direct use -% of \numexpr (which will throw a suitable number too big message), and to raise -% the \xintError:$\ FactorialOfTooBigNumber for argument larger than 1000000 -% (rather than 1000000000). With 1.09a, \xintFac uses \xintnum. -% -% 1.09j for no special reason, I lower the maximal number from 999999 to 100000. -% Any how this computation would need more memory than TL2013 standard allows to -% TeX. And I don't even mention time... | -% \begin{macrocode} -\def\xintiFac {\romannumeral0\xintifac }% -\def\xintifac #1% -{% - \expandafter\XINT_fac_fork\expandafter{\the\numexpr #1}% -}% -\let\xintFac\xintiFac \let\xintfac\xintifac -\def\XINT_fac_fork #1% -{% - \ifcase\XINT_cntSgn #1\Z - \xint_afterfi{\expandafter\space\expandafter 1\xint_gobble_i }% - \or - \expandafter\XINT_fac_checklength - \else - \xint_afterfi{\expandafter\xintError:FactorialOfNegativeNumber - \expandafter\space\expandafter 1\xint_gobble_i }% - \fi - {#1}% -}% -\def\XINT_fac_checklength #1% -{% - \ifnum #1>100000 - \xint_afterfi{\expandafter\xintError:FactorialOfTooBigNumber - \expandafter\space\expandafter 1\xint_gobble_i }% - \else - \xint_afterfi{\ifnum #1>\xint_c_ixixixix - \expandafter\XINT_fac_big_loop - \else - \expandafter\XINT_fac_loop - \fi }% - \fi - {#1}% -}% -\def\XINT_fac_big_loop #1{\XINT_fac_big_loop_main {10000}{#1}{}}% -\def\XINT_fac_big_loop_main #1#2#3% -{% - \ifnum #1<#2 - \expandafter - \XINT_fac_big_loop_main - \expandafter - {\the\numexpr #1+1\expandafter }% - \else - \expandafter\XINT_fac_big_docomputation - \fi - {#2}{#3{#1}}% -}% -\def\XINT_fac_big_docomputation #1#2% -{% - \expandafter \XINT_fac_bigcompute_loop \expandafter - {\romannumeral0\XINT_fac_loop {9999}}#2\relax -}% -\def\XINT_fac_bigcompute_loop #1#2% -{% - \xint_gob_til_relax #2\XINT_fac_bigcompute_end\relax - \expandafter\XINT_fac_bigcompute_loop\expandafter - {\expandafter\XINT_mul_enter - \romannumeral0\XINT_RQ {}#2\R\R\R\R\R\R\R\R\Z - \Z\Z\Z\Z #1\W\W\W\W }% -}% -\def\XINT_fac_bigcompute_end #1#2#3#4#5% -{% - \XINT_fac_bigcompute_end_ #5% -}% -\def\XINT_fac_bigcompute_end_ #1\R #2\Z \W\X\Y\Z #3\W\X\Y\Z { #3}% -\def\XINT_fac_loop #1{\XINT_fac_loop_main 1{1000}{#1}}% -\def\XINT_fac_loop_main #1#2#3% -{% - \ifnum #3>#1 - \else - \expandafter\XINT_fac_loop_exit - \fi - \expandafter\XINT_fac_loop_main\expandafter - {\the\numexpr #1+1\expandafter }\expandafter - {\romannumeral0\XINT_mul_Mr {#1}#2\Z\Z\Z\Z }% - {#3}% -}% -\def\XINT_fac_loop_exit #1#2#3#4#5#6#7% -{% - \XINT_fac_loop_exit_ #6% -}% -\def\XINT_fac_loop_exit_ #1#2#3% -{% - \XINT_mul_M -}% +\def\XINT_prod_finished\relax\XINT_prod_loop_c #1\Z #2\Z \Z { #2}% % \end{macrocode} % \lverb|& % & @@ -19735,15 +19631,15 @@ $1$ or $-1$. \def\xintisqrt {\expandafter\XINT_sqrt_post\romannumeral0\xintisquareroot }% \def\xintiisqrt {\expandafter\XINT_sqrt_post\romannumeral0\xintiisquareroot }% \def\xintiisqrtr {\expandafter\XINT_sqrtr_post\romannumeral0\xintiisquareroot }% -\def\XINT_sqrt_post #1#2{\XINT_dec_pos #1\R\R\R\R\R\R\R\R\Z \W\W\W\W\W\W\W\W }% +\def\XINT_sqrt_post #1#2{\XINT_dec_pos #1\Z }% % \end{macrocode} % \lverb|N = (#1)^2 - #2 avec #1 le plus petit possible et #2>0 (hence #2<2*#1). % (#1-.5)^2=#1^2-#1+.25=N+#2-#1+.25. Si 0<#2<#1, <= N-0.75#1 % si #2>=#1, (#1-.5)^2>=N+.25>N, donc rounded->#1-1.| % \begin{macrocode} -\def\XINT_sqrtr_post #1#2{\xintiiifLt {#2}{#1}% Lt <-> a\xint_c_ \xint_dothis{\xint_dsh {#2}{-#1}}\fi \xint_orthat{ #2}}% +% \end{macrocode} +% \subsection{``Load \xintfracnameimp'' macros} +% \lverb|Originally was used in \xintiiexpr. Transferred from xintfrac for 1.1.| +% \begin{macrocode} +\catcode`! 11 +\def\xintMax {\Did_you_mean_iiMax?or_load_xintfrac!}% +\def\xintMin {\Did_you_mean_iiMin?or_load_xintfrac!}% +\def\xintMaxof {\Did_you_mean_iMaxof?or_load_xintfrac!}% +\def\xintMinof {\Did_you_mean_iMinof?or_load_xintfrac!}% +\def\xintSum {\Did_you_mean_iiSum?or_load_xintfrac!}% +\def\xintPrd {\Did_you_mean_iiPrd?or_load_xintfrac!}% +\def\xintPrdExpr {\Did_you_mean_iiPrdExpr?or_load_xintfrac!}% +\def\xintSumExpr {\Did_you_mean_iiSumExpr?or_load_xintfrac!}% \XINT_restorecatcodes_endinput% % \end{macrocode} %\catcode`\<=0 \catcode`\>=11 \catcode`\*=11 \catcode`\/=11 @@ -19994,21 +19902,14 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintbinhex}% - [2015/09/12 v1.1c Expandable binary and hexadecimal conversions (jfB)]% + [2015/10/10 v1.2 Expandable binary and hexadecimal conversions (jfB)]% % \end{macrocode} % \subsection{Constants, etc...} % \lverb!v1.08! % \begin{macrocode} -\chardef\xint_c_xvi 16 -% \chardef\xint_c_ii^v 32 % already in xint.sty -% \chardef\xint_c_ii^vi 64 % already in xint.sty -\chardef\xint_c_ii^vii 128 -\mathchardef\xint_c_ii^viii 256 -\mathchardef\xint_c_ii^xii 4096 -\newcount\xint_c_ii^xv \xint_c_ii^xv 32768 -\newcount\xint_c_ii^xvi \xint_c_ii^xvi 65536 +\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 -\newcount\xint_c_x^ix \xint_c_x^ix 1000000000 \def\XINT_tmpa #1{\ifx\relax#1\else \expandafter\edef\csname XINT_sdth_#1\endcsname {\ifcase #1 0\or 1\or 2\or 3\or 4\or 5\or 6\or 7\or @@ -20103,6 +20004,40 @@ $1$ or $-1$. \csname XINT_sdtb_\the\numexpr #2-\xint_c_xvi*#1\endcsname }% % \end{macrocode} +% \subsection{\csh{XINT_OQ}} +% \lverb|Moved with release 1.2 from xintcore 1.1 as it is used only here. +% Will be probably suppressed once I review the code of xintbinhex.| +% \begin{macrocode} +\def\XINT_OQ #1#2#3#4#5#6#7#8#9% +{% + \xint_gob_til_R #9\XINT_OQ_end_a\R\XINT_OQ {#9#8#7#6#5#4#3#2#1}% +}% +\def\XINT_OQ_end_a\R\XINT_OQ #1#2\Z +{% + \XINT_OQ_end_b #1\Z +}% +\def\XINT_OQ_end_b #1#2#3#4#5#6#7#8% +{% + \xint_gob_til_R + #8\XINT_OQ_end_viii + #7\XINT_OQ_end_vii + #6\XINT_OQ_end_vi + #5\XINT_OQ_end_v + #4\XINT_OQ_end_iv + #3\XINT_OQ_end_iii + #2\XINT_OQ_end_ii + \R\XINT_OQ_end_i + \Z #2#3#4#5#6#7#8% +}% +\def\XINT_OQ_end_viii #1\Z #2#3#4#5#6#7#8#9\Z { #9}% +\def\XINT_OQ_end_vii #1\Z #2#3#4#5#6#7#8#9\Z { #8#90000000}% +\def\XINT_OQ_end_vi #1\Z #2#3#4#5#6#7#8#9\Z { #7#8#9000000}% +\def\XINT_OQ_end_v #1\Z #2#3#4#5#6#7#8#9\Z { #6#7#8#900000}% +\def\XINT_OQ_end_iv #1\Z #2#3#4#5#6#7#8#9\Z { #5#6#7#8#90000}% +\def\XINT_OQ_end_iii #1\Z #2#3#4#5#6#7#8#9\Z { #4#5#6#7#8#9000}% +\def\XINT_OQ_end_ii #1\Z #2#3#4#5#6#7#8#9\Z { #3#4#5#6#7#8#900}% +\def\XINT_OQ_end_i \Z #1#2#3#4#5#6#7#8\Z { #1#2#3#4#5#6#7#80}% +% \end{macrocode} % \subsection{\csh{xintDecToHex}, \csh{xintDecToBin}} % \lverb!v1.08! % \begin{macrocode} @@ -20668,7 +20603,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintgcd}% - [2015/09/12 v1.1c Euclide algorithm with xint package (jfB)]% + [2015/10/10 v1.2 Euclide algorithm with xint package (jfB)]% % \end{macrocode} % \subsection{\csh{xintGCD}, \csh{xintiiGCD}} % \lverb|The macros of 1.09a benefits from the \xintnum which has been inserted @@ -20918,8 +20853,8 @@ $1$ or $-1$. \def\XINT_bezout_loop_b #1#2#3#4#5#6#7#8% {% \expandafter \XINT_bezout_loop_c \expandafter - {\romannumeral0\xintiiadd{\XINT_Mul{#5}{#2}}{#7}}% - {\romannumeral0\xintiiadd{\XINT_Mul{#6}{#2}}{#8}}% + {\romannumeral0\xintiiadd{\XINT_mul_fork #5\Z #2\Z}{#7}}% + {\romannumeral0\xintiiadd{\XINT_mul_fork #6\Z #2\Z}{#8}}% {#1}{#3}{#4}{#5}{#6}% }% % \end{macrocode} @@ -21370,8 +21305,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintfrac}% - [2015/09/12 v1.1c Expandable operations on fractions (jfB)]% -\chardef\xint_c_xviii 18 + [2015/10/10 v1.2 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 @@ -21481,137 +21415,168 @@ $1$ or $-1$. % e only. The \xintexpr parser does accept uppercase E also. Ah, by the way, % perhaps I should at least say what this macro does? (belated addition % 2014/10/22...), before I forget! It prepares the fraction in the internal -% format {exponent}{Numerator}{Denominator} where Denominator is at least 1.| +% format {exponent}{Numerator}{Denominator} where Denominator is at least 1. +% +% 2015/10/09: this venerable macro from the early days (1.03, 2013/04/14) has +% gotten a lifting for release 1.2. There were two kinds of issues:$newline +% +% 1) use of \W, \Z, \T delimiters was very poor choice as this could clash with +% user input, +% +% 2) the new \XINT_frac_gen handles macros (possibly empty) in the input as +% general as \A.\Be\C/\D.\Ee\F. The earlier version would not have expanded +% the \B for example (only \A, \D, \C, \F). +% +% I wanted to make stricter the restricted A/B[N] case, doing no expansion of +% B, but this clashed with some established uses in the documentation like +% 1/\xintiiSqr{...}[0] for example. Thus I maintained it despite overhead of +% having to go over A one more time. Careful also here about potential brace +% removals if one does stuff like #1/#2#3[#4] regarding the #3. And while I +% was at it I added \numexpr parsing of the N, which earlier was restricted to +% be only explicit digits, and I even allowed [] with an empty N. +% +% This little event makes me think I should read again other remaining +% portions my early code, as I was still learning TeX coding at that time.| % \begin{macrocode} \def\XINT_inFrac {\romannumeral0\XINT_infrac }% \def\XINT_infrac #1% {% - \expandafter\XINT_infrac_ \romannumeral-`0#1[\W]\Z\T + \expandafter\XINT_infrac_fork\romannumeral-`0#1/\XINT_W[\XINT_W\XINT_T }% -\def\XINT_infrac_ #1[#2#3]#4\Z +\def\XINT_infrac_fork #1[#2% {% - \xint_UDwfork - #2\XINT_infrac_A - \W\XINT_infrac_B + \xint_UDXINTWfork + #2\XINT_frac_gen + \XINT_W\XINT_infrac_res_a % strict A[N] or A/B[N] input \krof - #1[#2#3]#4% -}% -\def\XINT_infrac_A #1[\W]\T -{% - \XINT_frac #1/\W\Z + #1[#2% }% -\def\XINT_infrac_B #1% +\def\XINT_infrac_res_a #1% {% - \xint_gob_til_zero #1\XINT_infrac_Zero0\XINT_infrac_BB #1% + \xint_gob_til_zero #1\XINT_infrac_res_zero 0\XINT_infrac_res_b #1% }% -\def\XINT_infrac_BB #1[\W]\T {\XINT_infrac_BC #1/\W\Z }% -\def\XINT_infrac_BC #1/#2#3\Z +\def\XINT_infrac_res_zero 0\XINT_infrac_res_b #1\XINT_T {{0}{0}{1}}% +\def\XINT_infrac_res_b #1/#2% {% - \xint_UDwfork - #2\XINT_infrac_BCa - \W{\expandafter\XINT_infrac_BCb \romannumeral-`0#2}% + \xint_UDXINTWfork + #2\XINT_infrac_res_ca + \XINT_W\XINT_infrac_res_cb \krof - #3\Z #1\Z + #1/#2% }% -\def\XINT_infrac_BCa \Z #1[#2]#3\Z { {#2}{#1}{1}}% -\def\XINT_infrac_BCb #1[#2]/\W\Z #3\Z { {#2}{#3}{#1}}% -\def\XINT_infrac_Zero #1\T { {0}{0}{1}}% +\def\XINT_infrac_res_ca #1[#2]/\XINT_W[\XINT_W\XINT_T + {\expandafter{\the\numexpr 0#2}{#1}{1}}% +\def\XINT_infrac_res_cb #1/#2[% + {\expandafter\XINT_infrac_res_cc\romannumeral-`0#2~#1[}% +\def\XINT_infrac_res_cc #1~#2[#3]/\XINT_W[\XINT_W\XINT_T + {\expandafter{\the\numexpr 0#3}{#2}{#1}}% % \end{macrocode} -% \subsection{\csh{XINT_frac}} +% \subsection{\csh{XINT_frac_gen}} % \lverb|Extended in 1.07 to recognize and accept scientific notation both at % the numerator and (possible) denominator. Only a lowercase e will do here, but -% uppercase E is possible within an \xintexpr..\relax | +% uppercase E is possible within an \xintexpr..\relax +% +% Completely rewritten for 1.2 2015/10/10. It now is able to handles inputs +% such as \A.\Be\C/\D.\Ee\F where each of \A, \B, \D, and \E may need +% \fexpan sion and \C and \F will end up in \numexpr.| % \begin{macrocode} -\def\XINT_frac #1/#2#3\Z +\def\XINT_frac_gen #1/#2% {% - \xint_UDwfork - #2\XINT_frac_A - \W{\expandafter\XINT_frac_U \romannumeral-`0#2}% + \xint_UDXINTWfork + #2\XINT_frac_gen_A + \XINT_W\XINT_frac_gen_B \krof - #3e\W\Z #1e\W\Z + #1/#2% }% -\def\XINT_frac_U #1e#2#3\Z +\def\XINT_frac_gen_A #1/\XINT_W [\XINT_W {\XINT_frac_gen_C 0~1!#1ee.\XINT_W }% +\def\XINT_frac_gen_B #1/#2/\XINT_W[%\XINT_W {% - \xint_UDwfork - #2\XINT_frac_Ua - \W{\XINT_frac_Ub #2}% - \krof - #3\Z #1\Z + \expandafter\XINT_frac_gen_Ba + \romannumeral-`0#2ee.\XINT_W\XINT_Z #1ee.%\XINT_W }% -\def\XINT_frac_Ua \Z #1/\W\Z {\XINT_frac_B #1.\W\Z {0}}% -\def\XINT_frac_Ub #1/\W e\W\Z #2\Z {\XINT_frac_B #2.\W\Z {#1}}% -\def\XINT_frac_B #1.#2#3\Z +\def\XINT_frac_gen_Ba #1.#2% {% - \xint_UDwfork - #2\XINT_frac_Ba - \W{\XINT_frac_Bb #2}% + \xint_UDXINTWfork + #2\XINT_frac_gen_Bb + \XINT_W\XINT_frac_gen_Bc \krof - #3\Z #1\Z + #1.#2% }% -\def\XINT_frac_Ba \Z #1\Z {\XINT_frac_T {0}{#1}}% -\def\XINT_frac_Bb #1.\W\Z #2\Z +\def\XINT_frac_gen_Bb #1e#2e#3\XINT_Z + {\expandafter\XINT_frac_gen_C\the\numexpr 0#2~#1!}% +\def\XINT_frac_gen_Bc #1.#2e% {% - \expandafter \XINT_frac_T \expandafter - {\romannumeral0\xintlength {#1}}{#2#1}% + \expandafter\XINT_frac_gen_Bd\romannumeral-`0#2.#1e% }% -\def\XINT_frac_A e\W\Z {\XINT_frac_T {0}{1}{0}}% -\def\XINT_frac_T #1#2#3#4e#5#6\Z +\def\XINT_frac_gen_Bd #1.#2e#3e#4\XINT_Z {% - \xint_UDwfork - #5\XINT_frac_Ta - \W{\XINT_frac_Tb #5}% - \krof - #6\Z #4\Z {#1}{#2}{#3}% + \expandafter\XINT_frac_gen_C\the\numexpr 0#3-\romannumeral0\expandafter + \XINT_length_loop + 0.#1\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye~#2#1!% }% -\def\XINT_frac_Ta \Z #1\Z {\XINT_frac_C #1.\W\Z {0}}% -\def\XINT_frac_Tb #1e\W\Z #2\Z {\XINT_frac_C #2.\W\Z {#1}}% -\def\XINT_frac_C #1.#2#3\Z +\def\XINT_frac_gen_C #1!#2.#3% {% - \xint_UDwfork - #2\XINT_frac_Ca - \W{\XINT_frac_Cb #2}% + \xint_UDXINTWfork + #3\XINT_frac_gen_Ca + \XINT_W\XINT_frac_gen_Cb \krof - #3\Z #1\Z + #1!#2.#3% }% -\def\XINT_frac_Ca \Z #1\Z {\XINT_frac_D {0}{#1}}% -\def\XINT_frac_Cb #1.\W\Z #2\Z +\def\XINT_frac_gen_Ca #1~#2!#3e#4e#5\XINT_T {% - \expandafter\XINT_frac_D\expandafter - {\romannumeral0\xintlength {#1}}{#2#1}% + \expandafter\XINT_frac_gen_F\the\numexpr #4-#1\expandafter + ~\romannumeral0\XINT_num_loop + #2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\Z~#3~% }% -\def\XINT_frac_D #1#2#3#4#5#6% +\def\XINT_frac_gen_Cb #1.#2e% {% - \expandafter \XINT_frac_E \expandafter - {\the\numexpr -#1+#3+#4-#6\expandafter}\expandafter - {\romannumeral0\XINT_num_loop #2% - \xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_relax\Z }% - {\romannumeral0\XINT_num_loop #5% - \xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_relax\Z }% + \expandafter\XINT_frac_gen_Cc\romannumeral-`0#2.#1e% }% -\def\XINT_frac_E #1#2#3% +\def\XINT_frac_gen_Cc #1.#2~#3!#4e#5e#6\XINT_T {% - \expandafter \XINT_frac_F #3\Z {#2}{#1}% + \expandafter\XINT_frac_gen_F\the\numexpr #5-#2-% + \romannumeral0\XINT_length_loop + 0.#1\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye\expandafter + ~\romannumeral0\XINT_num_loop + #3\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\Z + ~#4#1~% }% -\def\XINT_frac_F #1% +\def\XINT_frac_gen_F #1~#2% {% \xint_UDzerominusfork - #1-\XINT_frac_Gdivisionbyzero - 0#1\XINT_frac_Gneg - 0-{\XINT_frac_Gpos #1}% - \krof + #2-\XINT_frac_gen_Gdivbyzero + 0#2{\XINT_frac_gen_G -{}}% + 0-{\XINT_frac_gen_G {}#2}% + \krof #1~% +}% +\def\XINT_frac_gen_Gdivbyzero #1~~#2~% +{% + \expandafter\XINT_frac_gen_Gdivbyzero_a + \romannumeral0\XINT_num_loop + #2\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\Z~#1~% +}% +\def\XINT_frac_gen_Gdivbyzero_a #1~#2~% +{% + \xintError:DivisionByZero {#2}{#1}{0}% }% -\edef\XINT_frac_Gdivisionbyzero #1\Z #2#3% +\def\XINT_frac_gen_G #1#2#3~#4~#5~% {% - \noexpand\xintError:DivisionByZero\space {0}{#2}{0}% + \expandafter\XINT_frac_gen_Ga + \romannumeral0\XINT_num_loop + #1#5\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\Z~#3~{#2#4}% }% -\def\XINT_frac_Gneg #1\Z #2#3% +\def\XINT_frac_gen_Ga #1#2~#3~% {% - \expandafter\XINT_frac_H \expandafter{\romannumeral0\XINT_opp #2}{#3}{#1}% + \xint_gob_til_zero #1\XINT_frac_gen_zero 0% + {#3}{#1#2}% }% -\def\XINT_frac_H #1#2{ {#2}{#1}}% -\def\XINT_frac_Gpos #1\Z #2#3{ {#3}{#2}{#1}}% +\def\XINT_frac_gen_zero 0#1#2#3{{0}{0}{1}}% % \end{macrocode} % \subsection{\csh{XINT_factortens}, \csh{XINT_cuz_cnt}} % \begin{macrocode} @@ -21640,74 +21605,170 @@ $1$ or $-1$. {% \XINT_cuz_cnt_toofarb {#1}#2% }% -\def\XINT_cuz_cnt_toofarb #1#2\Z {\XINT_cuz_cnt_toofarc #2\Z {#1}}% -\def\XINT_cuz_cnt_toofarc #1#2#3#4#5#6#7#8% +\def\XINT_cuz_cnt_toofarb #1#2\Z {\XINT_cuz_cnt_toofarc #2\Z {#1}}% +\def\XINT_cuz_cnt_toofarc #1#2#3#4#5#6#7#8% +{% + \xint_gob_til_R #2\XINT_cuz_cnt_toofard 7% + #3\XINT_cuz_cnt_toofard 6% + #4\XINT_cuz_cnt_toofard 5% + #5\XINT_cuz_cnt_toofard 4% + #6\XINT_cuz_cnt_toofard 3% + #7\XINT_cuz_cnt_toofard 2% + #8\XINT_cuz_cnt_toofard 1% + \Z #1#2#3#4#5#6#7#8% +}% +\def\XINT_cuz_cnt_toofard #1#2\Z #3\R #4\Z #5% +{% + \expandafter\XINT_cuz_cnt_toofare + \the\numexpr #3\relax \R\R\R\R\R\R\R\R\Z + {\the\numexpr #5-#1\relax}\R\Z +}% +\def\XINT_cuz_cnt_toofare #1#2#3#4#5#6#7#8% +{% + \xint_gob_til_R #2\XINT_cuz_cnt_stopc 1% + #3\XINT_cuz_cnt_stopc 2% + #4\XINT_cuz_cnt_stopc 3% + #5\XINT_cuz_cnt_stopc 4% + #6\XINT_cuz_cnt_stopc 5% + #7\XINT_cuz_cnt_stopc 6% + #8\XINT_cuz_cnt_stopc 7% + \Z #1#2#3#4#5#6#7#8% +}% +\def\XINT_cuz_cnt_checka #1#2% +{% + \expandafter\XINT_cuz_cnt_checkb\the\numexpr #2\relax \Z {#1}% +}% +\def\XINT_cuz_cnt_checkb #1% +{% + \xint_gob_til_zero #1\expandafter\XINT_cuz_cnt_loop\xint_gob_til_Z + 0\XINT_cuz_cnt_stopa #1% +}% +\def\XINT_cuz_cnt_stopa #1\Z +{% + \XINT_cuz_cnt_stopb #1\R\R\R\R\R\R\R\R\Z % +}% +\def\XINT_cuz_cnt_stopb #1#2#3#4#5#6#7#8#9% +{% + \xint_gob_til_R #2\XINT_cuz_cnt_stopc 1% + #3\XINT_cuz_cnt_stopc 2% + #4\XINT_cuz_cnt_stopc 3% + #5\XINT_cuz_cnt_stopc 4% + #6\XINT_cuz_cnt_stopc 5% + #7\XINT_cuz_cnt_stopc 6% + #8\XINT_cuz_cnt_stopc 7% + #9\XINT_cuz_cnt_stopc 8% + \Z #1#2#3#4#5#6#7#8#9% +}% +\def\XINT_cuz_cnt_stopc #1#2\Z #3\R #4\Z #5% +{% + \expandafter\XINT_cuz_cnt_stopd\expandafter + {\the\numexpr #5-#1}#3% +}% +\def\XINT_cuz_cnt_stopd #1#2\R #3\Z +{% + \expandafter\space\expandafter + {\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}% +}% +% \end{macrocode} +% \subsection{\csh{XINT_addm_A}} +% \lverb|This is a routine from xintcore 1.0x, which is needed by \xintFloat, +% \XINTinFloat and \xintRound, for the time being. I should moved it here, now +% that xintcore has been entirely rewritten with release 1.2.| +% \begin{macrocode} +\def\XINT_addm_A #1#2#3#4#5#6% +{% + \xint_gob_til_W #3\xint_addm_az\W + \XINT_addm_AB #1{#3#4#5#6}{#2}% +}% +\def\xint_addm_az\W\XINT_addm_AB #1#2% +{% + \XINT_addm_AC_checkcarry #1% +}% +\def\XINT_addm_AB #1#2#3#4\W\X\Y\Z #5#6#7#8% +{% + \XINT_addm_ABE #1#2{#8#7#6#5}{#3}#4\W\X\Y\Z +}% +\def\XINT_addm_ABE #1#2#3#4#5#6% +{% + \expandafter\XINT_addm_ABEA\the\numexpr #1+10#5#4#3#2+#6.% +}% +\def\XINT_addm_ABEA #1#2#3.#4% +{% + \XINT_addm_A #2{#3#4}% +}% +\def\XINT_addm_AC_checkcarry #1% +{% + \xint_gob_til_zero #1\xint_addm_AC_nocarry 0\XINT_addm_C +}% +\def\xint_addm_AC_nocarry 0\XINT_addm_C #1#2\W\X\Y\Z +{% + \expandafter + \xint_cleanupzeros_andstop + \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_addm_C #1#2#3#4#5% {% - \xint_gob_til_R #2\XINT_cuz_cnt_toofard 7% - #3\XINT_cuz_cnt_toofard 6% - #4\XINT_cuz_cnt_toofard 5% - #5\XINT_cuz_cnt_toofard 4% - #6\XINT_cuz_cnt_toofard 3% - #7\XINT_cuz_cnt_toofard 2% - #8\XINT_cuz_cnt_toofard 1% - \Z #1#2#3#4#5#6#7#8% + \xint_gob_til_W + #5\xint_addm_cw + #4\xint_addm_cx + #3\xint_addm_cy + #2\xint_addm_cz + \W\XINT_addm_CD {#5#4#3#2}{#1}% }% -\def\XINT_cuz_cnt_toofard #1#2\Z #3\R #4\Z #5% +\def\XINT_addm_CD #1% {% - \expandafter\XINT_cuz_cnt_toofare - \the\numexpr #3\relax \R\R\R\R\R\R\R\R\Z - {\the\numexpr #5-#1\relax}\R\Z + \expandafter\XINT_addm_CC\the\numexpr 1+10#1.% }% -\def\XINT_cuz_cnt_toofare #1#2#3#4#5#6#7#8% +\def\XINT_addm_CC #1#2#3.#4% {% - \xint_gob_til_R #2\XINT_cuz_cnt_stopc 1% - #3\XINT_cuz_cnt_stopc 2% - #4\XINT_cuz_cnt_stopc 3% - #5\XINT_cuz_cnt_stopc 4% - #6\XINT_cuz_cnt_stopc 5% - #7\XINT_cuz_cnt_stopc 6% - #8\XINT_cuz_cnt_stopc 7% - \Z #1#2#3#4#5#6#7#8% + \XINT_addm_AC_checkcarry #2{#3#4}% }% -\def\XINT_cuz_cnt_checka #1#2% +\def\xint_addm_cw + #1\xint_addm_cx + #2\xint_addm_cy + #3\xint_addm_cz + \W\XINT_addm_CD {% - \expandafter\XINT_cuz_cnt_checkb\the\numexpr #2\relax \Z {#1}% + \expandafter\XINT_addm_CDw\the\numexpr 1+#1#2#3.% }% -\def\XINT_cuz_cnt_checkb #1% +\def\XINT_addm_CDw #1.#2#3\X\Y\Z {% - \xint_gob_til_zero #1\expandafter\XINT_cuz_cnt_loop\xint_gob_til_Z - 0\XINT_cuz_cnt_stopa #1% + \XINT_addm_end #1#3% }% -\def\XINT_cuz_cnt_stopa #1\Z +\def\xint_addm_cx + #1\xint_addm_cy + #2\xint_addm_cz + \W\XINT_addm_CD {% - \XINT_cuz_cnt_stopb #1\R\R\R\R\R\R\R\R\Z % + \expandafter\XINT_addm_CDx\the\numexpr 1+#1#2.% }% -\def\XINT_cuz_cnt_stopb #1#2#3#4#5#6#7#8#9% +\def\XINT_addm_CDx #1.#2#3\Y\Z {% - \xint_gob_til_R #2\XINT_cuz_cnt_stopc 1% - #3\XINT_cuz_cnt_stopc 2% - #4\XINT_cuz_cnt_stopc 3% - #5\XINT_cuz_cnt_stopc 4% - #6\XINT_cuz_cnt_stopc 5% - #7\XINT_cuz_cnt_stopc 6% - #8\XINT_cuz_cnt_stopc 7% - #9\XINT_cuz_cnt_stopc 8% - \Z #1#2#3#4#5#6#7#8#9% + \XINT_addm_end #1#3% }% -\def\XINT_cuz_cnt_stopc #1#2\Z #3\R #4\Z #5% +\def\xint_addm_cy + #1\xint_addm_cz + \W\XINT_addm_CD {% - \expandafter\XINT_cuz_cnt_stopd\expandafter - {\the\numexpr #5-#1}#3% + \expandafter\XINT_addm_CDy\the\numexpr 1+#1.% }% -\def\XINT_cuz_cnt_stopd #1#2\R #3\Z +\def\XINT_addm_CDy #1.#2#3\Z {% - \expandafter\space\expandafter - {\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}% + \XINT_addm_end #1#3% }% +\def\xint_addm_cz\W\XINT_addm_CD #1#2#3{\XINT_addm_end #1#3}% +\edef\XINT_addm_end #1#2#3#4#5% + {\noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5\relax}% % \end{macrocode} % \subsection{\csh{xintRaw}} % \lverb|& @@ -22175,8 +22236,8 @@ $1$ or $-1$. \def\XINT_jrr_loop_b #1#2#3#4#5#6#7% {% \expandafter \XINT_jrr_loop_c \expandafter - {\romannumeral0\xintiiadd{\XINT_Mul{#4}{#1}}{#6}}% - {\romannumeral0\xintiiadd{\XINT_Mul{#5}{#1}}{#7}}% + {\romannumeral0\xintiiadd{\XINT_mul_fork #4\Z #1\Z}{#6}}% + {\romannumeral0\xintiiadd{\XINT_mul_fork #5\Z #1\Z}{#7}}% {#2}{#3}{#4}{#5}% }% \def\XINT_jrr_loop_c #1#2% @@ -22489,7 +22550,15 @@ $1$ or $-1$. % D-|N| last digits from Q, etc.. we compare D-|N| with the length M of Q etc... % (well in this last, very uncommon, branch, I stopped trying to optimize things % and I even do an \xintnum to ensure a 0 if something comes out empty from -% \xintDecSplit).@ +% \xintDecSplit). +% +% [2015/10/04] Although the explanations above are extremely clear, there are +% just too complicated for me to be now able to understand them fully. I +% miraculously managed to do the minimal changes (all happens between +% \XINT_xtrunc_Q and \XINT_xtrunc_Pa) in order for \xintXTrunc to use the 1.2 +% division routine. Seems to work. But some thought should be given to how to +% adapt \xintXTrunc for it to better use the abilities and characteristics of +% the new division routines in xincore.@ % \begin{macrocode} \def\xintXTrunc #1#2% {% @@ -22615,33 +22684,7 @@ $1$ or $-1$. \expandafter\XINT_xtrunc_negNC\expandafter {\the\numexpr\xintLength {#1}-#2}{#1}% }% -\def\XINT_xtrunc_Q #1% -{% - \expandafter\XINT_xtrunc_prepare_I - \romannumeral0\XINT_dsx_zeroloop {#1}{}\Z -}% -\def\XINT_xtrunc_prepare_I #1.#2#3% -{% - \expandafter\XINT_xtrunc_prepareB_aa\expandafter - {\romannumeral0\xintlength {#2}}{#2}{#1}% -}% -\def\XINT_xtrunc_prepareB_aa #1% -{% - \ifnum #1=\xint_c_i - \expandafter\XINT_xtrunc_prepareB_onedigit - \else - \expandafter\XINT_xtrunc_prepareB_PaBa - \fi - {#1}% -}% -\def\XINT_xtrunc_prepareB_onedigit #1#2% -{% - \ifcase#2 - \or\expandafter\XINT_xtrunc_BisOne - \or\expandafter\XINT_xtrunc_BisTwo - \else\expandafter\XINT_xtrunc_prepareB_PaBe - \fi {000}{0}{4}{#2}% -}% +%%%%%%%%%%%% \def\XINT_xtrunc_BisOne #1#2#3#4#5#6#7% {% #5.\romannumeral0\expandafter\XINT_dsx_zeroloop\expandafter @@ -22661,48 +22704,76 @@ $1$ or $-1$. 0000000000000000000000000000000000000000000000000000000000000000% \repeat }% -\def\XINT_xtrunc_prepareB_PaBa #1#2% +%%%%%%%%%%%% +\def\XINT_xtrunc_Q #1% +{% + \expandafter\XINT_xtrunc_prepare + \romannumeral0\XINT_dsx_zeroloop {#1}{}\Z +}% +\def\XINT_xtrunc_prepare #1.#2#3% {% \expandafter\XINT_xtrunc_Pa\expandafter - {\romannumeral0\XINT_xtrunc_prepareB_a {#1}{#2}}% + {\romannumeral0% + \XINT_xtrunc_prepare_a #2\R\R\R\R\R\R\R\R {10}0000001\W !{#2}}{#1}% }% -\def\XINT_xtrunc_prepareB_a #1% +%%%%%%%%%%%% +\def\XINT_xtrunc_prepare_a #1#2#3#4#5#6#7#8#9% {% - \expandafter\XINT_xtrunc_prepareB_c\expandafter - {\the\numexpr \xint_c_iv*((#1+\xint_c_i)/\xint_c_iv)}{#1}% + \xint_gob_til_R #9\XINT_xtrunc_prepare_small\R + \XINT_xtrunc_prepare_b #9% }% -\def\XINT_xtrunc_prepareB_c #1#2% +\def\XINT_xtrunc_prepare_small\R #1!#2% {% - \csname XINT_xtrunc_prepareB_d\romannumeral\numexpr#1-#2\endcsname - {#1}% + \ifcase #2 + \or\xint_afterfi{ \XINT_div_BisOne}% + \or\xint_afterfi{ \XINT_div_BisTwo}% + \else\expandafter\XINT_xtrunc_small_aa + \fi {#2}% }% -\def\XINT_xtrunc_prepareB_d {\XINT_xtrunc_prepareB_e {}{0000}}% -\def\XINT_xtrunc_prepareB_di {\XINT_xtrunc_prepareB_e {0}{000}}% -\def\XINT_xtrunc_prepareB_dii {\XINT_xtrunc_prepareB_e {00}{00}}% -\def\XINT_xtrunc_prepareB_diii {\XINT_xtrunc_prepareB_e {000}{0}}% -\def\XINT_xtrunc_prepareB_PaBe #1#2#3#4% +\def\XINT_xtrunc_small_aa #1% {% - \expandafter\XINT_xtrunc_Pa\expandafter - {\romannumeral0\XINT_xtrunc_prepareB_e {#1}{#2}{#3}{#4}}% + \expandafter\space\expandafter\XINT_xtrunc_small_a + \the\numexpr #1/\xint_c_ii\expandafter + .\the\numexpr \xint_c_x^viii+#1!% }% -\def\XINT_xtrunc_prepareB_e #1#2#3#4% +%%%%%%%%%%%% +\def\XINT_xtrunc_small_a #1.#2!#3% {% - \ifnum#3=\xint_c_iv\expandafter\XINT_xtrunc_prepareLittleB_f - \else\expandafter\XINT_xtrunc_prepareB_f - \fi - #4#1{#3}{#2}{#1}% + \expandafter\XINT_div_small_b\the\numexpr #1\expandafter + .\the\numexpr #2\expandafter!% + \romannumeral0\XINT_div_small_ba #3\R\R\R\R\R\R\R\R{10}0000001\W + #3\XINT_sepbyviii_Z_end 2345678\relax }% -\def\XINT_xtrunc_prepareB_f #1#2#3#4#5#{% - \expandafter\space - \expandafter\XINT_div_prepareB_g - \the\numexpr #1#2#3#4+\xint_c_i\expandafter - .\the\numexpr (#1#2#3#4+\xint_c_i)/\xint_c_ii\expandafter - .\romannumeral0\xintreverseorder {#1#2#3#4#5}.{#1#2#3#4}% +%%%%%%%%%%%% +\def\XINT_xtrunc_prepare_b + {\expandafter\XINT_xtrunc_prepare_c\romannumeral0\XINT_zeroes_forviii }% +\def\XINT_xtrunc_prepare_c #1!% +{% + \XINT_xtrunc_prepare_d #1.00000000!{#1}% }% -\def\XINT_xtrunc_prepareLittleB_f #1#{% - \expandafter\space\expandafter - \XINT_div_prepareB_g \the\numexpr #1/\xint_c_ii.{}.{}.{#1}% +\def\XINT_xtrunc_prepare_d #1#2#3#4#5#6#7#8#9% +{% + \expandafter\XINT_xtrunc_prepare_e\xint_gob_til_dot #1#2#3#4#5#6#7#8#9!% +}% +\def\XINT_xtrunc_prepare_e #1!#2!#3#4% +{% + \XINT_xtrunc_prepare_f #4#3\X {#1}{#3}% +}% +\def\XINT_xtrunc_prepare_f #1#2#3#4#5#6#7#8#9\X +{% + \expandafter\space\expandafter\XINT_div_prepare_g + \the\numexpr #1#2#3#4#5#6#7#8+\xint_c_i\expandafter + .\the\numexpr (#1#2#3#4#5#6#7#8+\xint_c_i)/\xint_c_ii\expandafter + .\the\numexpr #1#2#3#4#5#6#7#8\expandafter + .\romannumeral0\XINT_sepandrev_andcount + #1#2#3#4#5#6#7#8#9\XINT_rsepbyviii_end_A 2345678% + \XINT_rsepbyviii_end_B 2345678% + \relax\xint_c_ii\xint_c_iii + \R.\xint_c_vi\R.\xint_c_v\R.\xint_c_iv\R.\xint_c_iii + \R.\xint_c_ii\R.\xint_c_i\R.\xint_c_\W + \X }% +%%%%%%%%%%%% \def\XINT_xtrunc_Pa #1#2% {% \expandafter\XINT_xtrunc_Pb\romannumeral0#1{#2}{#1}% @@ -22758,10 +22829,7 @@ $1$ or $-1$. % gains. The earlier version was seriously silly when dealing with % inputs having a big power of ten. Again some modifications in 1.08b % for a better treatment of cases with long explicit numerators or -% denominators. -% -% Here again some inner macros used the \xintiquo with extra \xintnum overhead -% in 1.09a, 1.09f reinstalled use of \xintiiquo without this overhead.| +% denominators.| % \begin{macrocode} \def\xintFloat {\romannumeral0\xintfloat }% \def\xintfloat #1{\XINT_float_chkopt #1\xint_relax }% @@ -23147,7 +23215,7 @@ $1$ or $-1$. }% \def\XINT_fadd_C #1#2#3% {% - \ifcase\romannumeral0\XINT_cmp_pre {#2}{#3} %<- intentional space here. + \ifcase\romannumeral0\xintiicmp {#2}{#3} %<- intentional space here. \expandafter\XINT_fadd_eq \or\expandafter\XINT_fadd_D \else\expandafter\XINT_fadd_Da @@ -23636,8 +23704,8 @@ $1$ or $-1$. \def\XINT_minof_e #1\Z #2\Z { #2}% % \end{macrocode} % \subsection{\csh{xintCmp}} -% \lverb|Rewritten completely in 1.08a to be less dumb when comparing fractions having -% big powers of tens.| +% \lverb|Rewritten completely in 1.08a to be less dumb when comparing +% fractions having big powers of tens.| % \begin{macrocode} %\def\xintCmp {\romannumeral0\xintcmp }% \def\xintcmp #1% @@ -23708,32 +23776,42 @@ $1$ or $-1$. \expandafter\XINT_fcmp_Fe\expandafter {\romannumeral0\XINT_dsx_addzerosnofuss {#1}{#3}}{#2}% }% -\def\XINT_fcmp_Fe #1#2{\XINT_cmp_pre {#2}{#1}}% +\def\XINT_fcmp_Fe #1#2{\xintiicmp {#2}{#1}}% \def\XINT_fcmp_Fn #1\Z #2#3% {% - \expandafter\XINT_cmp_pre\expandafter + \expandafter\xintiicmp\expandafter {\romannumeral0\XINT_dsx_addzerosnofuss {#1}{#2}}{#3}% }% % \end{macrocode} % \subsection{\csh{xintAbs}} -% \lverb|Simplified in 1.09i. (original macro had been written before \xintRaw)| % \begin{macrocode} \def\xintAbs {\romannumeral0\xintabs }% \def\xintabs #1{\expandafter\XINT_abs\romannumeral0\xintraw {#1}}% % \end{macrocode} % \subsection{\csh{xintOpp}} -% \lverb|caution that -#1 would not be ok if #1 has [n] -% stuff. Simplified in 1.09i. (original macro had been written before \xintRaw)| % \begin{macrocode} \def\xintOpp {\romannumeral0\xintopp }% \def\xintopp #1{\expandafter\XINT_opp\romannumeral0\xintraw {#1}}% % \end{macrocode} % \subsection{\csh{xintSgn}} -% \lverb|Simplified in 1.09i. (original macro had been written before \xintRaw)| % \begin{macrocode} \def\xintSgn {\romannumeral0\xintsgn }% \def\xintsgn #1{\expandafter\XINT_sgn\romannumeral0\xintraw {#1}\Z }% % \end{macrocode} +% \subsection{Floating point macros} +% \begin{framed} +% 1.2 release has not touched the floating point routines apart from adding +% the new \csh{xintFloatFac}. The others should be revised for some +% optimizations related to the underlying model of the new core routines. +% This is particularly the case for \csh{xintFloatPow} and +% \csh{xintFloatPower} which should keep intermediate results in a suitable +% format, like \csh{xintiiPow} does. +% +% The switch to 1.2 was smooth (apart from the writing up of the new +% \csh{xintFloatFac}), as I didn't have to change a single line of code +% anywhere here ! +% \end{framed} +% % \subsection{\csh{xintFloatAdd}, \csh{XINTinFloatAdd}} % \lverb|1.07; 1.09ka improves a bit the efficieny of the coding of % \XINT_FL_Add_d.| @@ -23810,6 +23888,10 @@ $1$ or $-1$. }% % \end{macrocode} % \subsection{\csh{xintFloatMul}, \csh{XINTinFloatMul}} +% \begin{framed} +% It is a long-standing issue here that I must at some point revise the code +% and avoid compute with 2P digits the exact intermediate result. +% \end{framed} % \lverb|1.07| % \begin{macrocode} \def\xintFloatMul {\romannumeral0\xintfloatmul}% @@ -23874,6 +23956,11 @@ $1$ or $-1$. \def\XINT_FL_Div_b #1[#2]#3[#4]{\xintE{#3/#1}{#4-#2}}% % \end{macrocode} % \subsection{\csh{xintFloatPow}, \csh{XINTinFloatPow}} +% \begin{framed} +% This definitely should be revised to better take into account the new +% multiplication to maintain through intermediate states a suitable internal +% format, optimized for calls to \csh{XINT_mul_loop}. +% \end{framed} % \lverb|1.07. Release 1.09j has re-organized the core loop, and % \XINT_flpow_prd sub-routine has been removed.| % \begin{macrocode} @@ -24144,6 +24231,215 @@ $1$ or $-1$. #4{#3}{#5}% }% % \end{macrocode} +% \subsection{\csh{xintFloatFac}, \csh{XINTFloatFac}} +% \lverb|1.2. Je dois documenter le raisonnement sur la précision à imposer +% pour les calculs par blocs de huit faits en sous-main. Par ailleurs j'ai été +% amené à une routine smallmul spéciale.| +% \begin{macrocode} +\def\xintFloatFac {\romannumeral0\xintfloatfac}% +\def\xintfloatfac #1{\XINT_flfac_chkopt \xintfloat #1\xint_relax }% +\def\XINTinFloatFac {\romannumeral0\XINTinfloatfac }% +\def\XINTinfloatfac #1{\XINT_flfac_chkopt \XINTinfloat #1\xint_relax }% +\def\XINT_flfac_chkopt #1#2% +{% + \ifx [#2\expandafter\XINT_flfac_opt + \else\expandafter\XINT_flfac_noopt + \fi + #1#2% +}% +\def\XINT_flfac_noopt #1#2\xint_relax +{% + \expandafter\XINT_FL_fac_start\expandafter + {\the\numexpr #2}{\XINTdigits}{#1[\XINTdigits]}% +}% +\def\XINT_flfac_opt #1[\xint_relax #2]#3% +{% + \expandafter\XINT_FL_fac_start\expandafter + {\the\numexpr #3\expandafter}\expandafter{\the\numexpr#2}{#1[#2]}% +}% +\def\XINT_FL_fac_start #1% +{% + \ifcase\XINT_cntSgn #1\Z + \expandafter\XINT_FL_fac_iszero + \or + \expandafter\XINT_FL_fac_increaseP + \else + \expandafter\XINT_FL_fac_isneg + \fi {#1}% +}% +\def\XINT_FL_fac_iszero #1#2#3{#3{1/1[0]}}% +\def\XINT_FL_fac_isneg #1#2#3% + {\expandafter\xintError:FactorialOfNegativeNumber #3{1/1[0]}}% +\def\XINT_FL_fac_increaseP #1#2% +{% + \expandafter\XINT_FL_fac_fork + \the\numexpr \xint_c_viii*% + ((\xint_c_v+#2+\XINT_FL_fac_extradigits #187654321\Z)/\xint_c_viii).% + #1.% +}% +\def\XINT_FL_fac_extradigits #1#2#3#4#5#6#7#8{\XINT_FL_fac_extra_a }% +\def\XINT_FL_fac_extra_a #1#2\Z {#1}% +\def\XINT_FL_fac_fork #1.#2.#3% +{% + \ifnum #2>99999999 \xint_dothis{\XINT_FL_fac_toobig }\fi + \ifnum #2>9999 \xint_dothis{\XINT_FL_fac_vbigloop_a }\fi + \ifnum #2>465 \xint_dothis{\XINT_FL_fac_bigloop_a }\fi + \ifnum #2>101 \xint_dothis{\XINT_FL_fac_medloop_a }\fi + \xint_orthat{\XINT_FL_fac_smallloop_a }% + #2.#1.{\XINT_FL_fac_out}{#3}% +}% +\def\XINT_FL_fac_toobig #1.#2.#3#4% + {\expandafter\xintError:FactorialOfTooBigNumber #4{1/1[0]}}% +\def\XINT_FL_fac_out #1\Z![#2]#3{#3{\romannumeral0\XINT_mul_out + #1\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W [#2]}}% +\def\XINT_FL_fac_vbigloop_a #1.#2.% +{% + \XINT_FL_fac_bigloop_a 9999.#2.% + {\expandafter\XINT_FL_fac_vbigloop_loop\the\numexpr 100010000\expandafter.% + \the\numexpr \xint_c_x^viii+#1.}% +}% +\def\XINT_FL_fac_vbigloop_loop #1.#2.% +{% + \ifnum #1>#2 \expandafter\XINT_FL_fac_loop_exit\fi + \expandafter\XINT_FL_fac_vbigloop_loop + \the\numexpr #1+\xint_c_i\expandafter.% + \the\numexpr #2\expandafter.\the\numexpr\XINT_FL_fac_mul #1!% +}% +\def\XINT_FL_fac_bigloop_a #1.% +{% + \expandafter\XINT_FL_fac_bigloop_b \the\numexpr + #1+\xint_c_i-\xint_c_ii*((#1-464)/\xint_c_ii).#1.% +}% +\def\XINT_FL_fac_bigloop_b #1.#2.#3.% +{% + \expandafter\XINT_FL_fac_medloop_a + \the\numexpr #1-\xint_c_i.#3.{\XINT_FL_fac_bigloop_loop #1.#2.}% +}% +\def\XINT_FL_fac_bigloop_loop #1.#2.% +{% + \ifnum #1>#2 \expandafter\XINT_FL_fac_loop_exit\fi + \expandafter\XINT_FL_fac_bigloop_loop + \the\numexpr #1+\xint_c_ii\expandafter.% + \the\numexpr #2\expandafter.\the\numexpr\XINT_FL_fac_bigloop_mul #1!% +}% +\def\XINT_FL_fac_bigloop_mul #1!% +{% + \expandafter\XINT_FL_fac_mul + \the\numexpr \xint_c_x^viii+#1*(#1+\xint_c_i)!% +}% +\def\XINT_FL_fac_medloop_a #1.% +{% + \expandafter\XINT_FL_fac_medloop_b + \the\numexpr #1+\xint_c_i-\xint_c_iii*((#1-100)/\xint_c_iii).#1.% +}% +\def\XINT_FL_fac_medloop_b #1.#2.#3.% +{% + \expandafter\XINT_FL_fac_smallloop_a + \the\numexpr #1-\xint_c_i.#3.{\XINT_FL_fac_medloop_loop #1.#2.}% +}% +\def\XINT_FL_fac_medloop_loop #1.#2.% +{% + \ifnum #1>#2 \expandafter\XINT_FL_fac_loop_exit\fi + \expandafter\XINT_FL_fac_medloop_loop + \the\numexpr #1+\xint_c_iii\expandafter.% + \the\numexpr #2\expandafter.\the\numexpr\XINT_FL_fac_medloop_mul #1!% +}% +\def\XINT_FL_fac_medloop_mul #1!% +{% + \expandafter\XINT_FL_fac_mul + \the\numexpr + \xint_c_x^viii+#1*(#1+\xint_c_i)*(#1+\xint_c_ii)!% +}% +\def\XINT_FL_fac_smallloop_a #1.% +{% + \csname + XINT_FL_fac_smallloop_\the\numexpr #1-\xint_c_iv*(#1/\xint_c_iv)\relax + \endcsname #1.% +}% +\expandafter\def\csname XINT_FL_fac_smallloop_1\endcsname #1.#2.% +{% + \XINT_FL_fac_addzeros #2.100000001!.{2.#1.}{#2}% +}% +\expandafter\def\csname XINT_FL_fac_smallloop_-2\endcsname #1.#2.% +{% + \XINT_FL_fac_addzeros #2.100000002!.{3.#1.}{#2}% +}% +\expandafter\def\csname XINT_FL_fac_smallloop_-1\endcsname #1.#2.% +{% + \XINT_FL_fac_addzeros #2.100000006!.{4.#1.}{#2}% +}% +\expandafter\def\csname XINT_FL_fac_smallloop_0\endcsname #1.#2.% +{% + \XINT_FL_fac_addzeros #2.100000024!.{5.#1.}{#2}% +}% +\def\XINT_FL_fac_addzeros #1.% +{% + \ifnum #1=\xint_c_viii \expandafter\XINT_FL_fac_addzeros_exit\fi + \expandafter\XINT_FL_fac_addzeros\the\numexpr #1-\xint_c_viii.100000000!% +}% +\def\XINT_FL_fac_addzeros_exit #1.#2.#3#4% + {\XINT_FL_fac_smallloop_loop #3#21\Z![-#4]}% +\def\XINT_FL_fac_smallloop_loop #1.#2.% +{% + \ifnum #1>#2 \expandafter\XINT_FL_fac_loop_exit\fi + \expandafter\XINT_FL_fac_smallloop_loop + \the\numexpr #1+\xint_c_iv\expandafter.% + \the\numexpr #2\expandafter.\romannumeral0\XINT_FL_fac_smallloop_mul #1!% +}% +\def\XINT_FL_fac_smallloop_mul #1!% +{% + \expandafter\XINT_FL_fac_mul + \the\numexpr + \xint_c_x^viii+#1*(#1+\xint_c_i)*(#1+\xint_c_ii)*(#1+\xint_c_iii)!% +}%[[ +\def\XINT_FL_fac_loop_exit #1!#2]#3{#3#2]}% +\def\XINT_FL_fac_mul 1#1!% + {\expandafter\XINT_FL_fac_mul_a\the\numexpr\XINT_FL_fac_smallmul 10!{#1}}% +\def\XINT_FL_fac_mul_a #1-#2% +{% + \if#21\xint_afterfi{\expandafter\space\xint_gob_til_exclam}\else + \expandafter\space\fi #11\Z!% +}% +\def\XINT_FL_fac_minimulwc_a #1#2#3#4#5!#6#7#8#9% +{% + \XINT_FL_fac_minimulwc_b {#1#2#3#4}{#5}{#6#7#8#9}% +}% +\def\XINT_FL_fac_minimulwc_b #1#2#3#4!#5% +{% + \expandafter\XINT_FL_fac_minimulwc_c + \the\numexpr \xint_c_x^ix+#5+#2*#4.{{#1}{#2}{#3}{#4}}% +}% +\def\XINT_FL_fac_minimulwc_c 1#1#2#3#4#5#6.#7% +{% + \expandafter\XINT_FL_fac_minimulwc_d {#1#2#3#4#5}#7{#6}% +}% +\def\XINT_FL_fac_minimulwc_d #1#2#3#4#5% +{% + \expandafter\XINT_FL_fac_minimulwc_e + \the\numexpr \xint_c_x^ix+#1+#2*#5+#3*#4.{#2}{#4}% +}% +\def\XINT_FL_fac_minimulwc_e 1#1#2#3#4#5#6.#7#8#9% +{% + 1#6#9\expandafter!% + \the\numexpr\expandafter\XINT_FL_fac_smallmul + \the\numexpr \xint_c_x^viii+#1#2#3#4#5+#7*#8!% +}% +\def\XINT_FL_fac_smallmul 1#1!#21#3!% +{% + \xint_gob_til_Z #3\XINT_FL_fac_smallmul_end\Z + \XINT_FL_fac_minimulwc_a #2!#3!{#1}{#2}% +}% +\def\XINT_FL_fac_smallmul_end\Z\XINT_FL_fac_minimulwc_a #1!\Z!#2#3[#4]% +{% + \ifnum #2=\xint_c_ + \expandafter\xint_firstoftwo\else + \expandafter\xint_secondoftwo + \fi + {-2\relax[#4]}% + {1#2\expandafter!\expandafter-\expandafter1\expandafter + [\the\numexpr #4+\xint_c_viii]}% +}% +% \end{macrocode} % \subsection{\csh{xintFloatSqrt}, \csh{XINTinFloatSqrt}} % \lverb|1.08| % \begin{macrocode} @@ -24295,7 +24591,7 @@ $1$ or $-1$. {% \expandafter\XINT_flsqrt_big_j \romannumeral0\xintiidivision - {#1}{\romannumeral0\XINT_dbl_pos #2\R\R\R\R\R\R\R\Z \W\W\W\W\W\W\W }{#2}% + {#1}{\romannumeral0\XINT_dbl_pos #2\Z}{#2}% }% \def\XINT_flsqrt_big_j #1% {% @@ -24307,8 +24603,8 @@ $1$ or $-1$. \def\XINT_flsqrt_big_k #1#2#3% {% \expandafter\XINT_flsqrt_big_l\expandafter - {\romannumeral0\XINT_sub_pre {#3}{#1}}% - {\romannumeral0\xintiiadd {#2}{\romannumeral0\XINT_sqr {#1}}}% + {\romannumeral0\xintiisub {#3}{#1}}% + {\romannumeral0\xintiiadd {#2}{\romannumeral0\XINT_sqr #1\Z}}% }% \def\XINT_flsqrt_big_l #1#2% {% @@ -24398,7 +24694,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintseries}% - [2015/09/12 v1.1c Expandable partial sums with xint package (jfB)]% + [2015/10/10 v1.2 Expandable partial sums with xint package (jfB)]% % \end{macrocode} % \subsection{\csh{xintSeries}} % \lverb|& @@ -24903,7 +25199,7 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintcfrac}% - [2015/09/12 v1.1c Expandable continued fractions with xint package (jfB)]% + [2015/10/10 v1.2 Expandable continued fractions with xint package (jfB)]% % \end{macrocode} % \subsection{\csh{xintCFrac}} % \begin{macrocode} @@ -25362,8 +25658,8 @@ $1$ or $-1$. \expandafter\XINT_ctf_loop_c\expandafter {\romannumeral0\XINT_mul_fork #2\Z #4\Z }% {\romannumeral0\XINT_mul_fork #2\Z #3\Z }% - {\romannumeral0\xintiiadd {\XINT_Mul {#2}{#6}}{\XINT_Mul {#1}{#4}}}% - {\romannumeral0\xintiiadd {\XINT_Mul {#2}{#5}}{\XINT_Mul {#1}{#3}}}% + {\romannumeral0\xintiiadd {\XINT_mul_fork #2\Z #6\Z}{\XINT_mul_fork #1\Z #4\Z}}% + {\romannumeral0\xintiiadd {\XINT_mul_fork #2\Z #5\Z}{\XINT_mul_fork #1\Z #3\Z}}% }% \def\XINT_ctf_loop_c #1#2% {% @@ -25399,8 +25695,8 @@ $1$ or $-1$. \def\XINT_icstf_loop_b #1.#2#3#4#5% {% \expandafter\XINT_icstf_loop_c\expandafter - {\romannumeral0\xintiiadd {#5}{\XINT_Mul {#1}{#3}}}% - {\romannumeral0\xintiiadd {#4}{\XINT_Mul {#1}{#2}}}% + {\romannumeral0\xintiiadd {#5}{\XINT_mul_fork #1\Z #3\Z}}% + {\romannumeral0\xintiiadd {#4}{\XINT_mul_fork #1\Z #2\Z}}% {#2}{#3}% }% \def\XINT_icstf_loop_c #1#2% @@ -25430,8 +25726,8 @@ $1$ or $-1$. \expandafter\XINT_gctf_loop_c\expandafter {\romannumeral0\XINT_mul_fork #2\Z #4\Z }% {\romannumeral0\XINT_mul_fork #2\Z #3\Z }% - {\romannumeral0\xintiiadd {\XINT_Mul {#2}{#6}}{\XINT_Mul {#1}{#4}}}% - {\romannumeral0\xintiiadd {\XINT_Mul {#2}{#5}}{\XINT_Mul {#1}{#3}}}% + {\romannumeral0\xintiiadd {\XINT_mul_fork #2\Z #6\Z}{\XINT_mul_fork #1\Z #4\Z}}% + {\romannumeral0\xintiiadd {\XINT_mul_fork #2\Z #5\Z}{\XINT_mul_fork #1\Z #3\Z}}% }% \def\XINT_gctf_loop_c #1#2% {% @@ -25492,8 +25788,8 @@ $1$ or $-1$. \def\XINT_igctf_loop_b #1.#2#3#4#5% {% \expandafter\XINT_igctf_loop_c\expandafter - {\romannumeral0\xintiiadd {#5}{\XINT_Mul {#1}{#3}}}% - {\romannumeral0\xintiiadd {#4}{\XINT_Mul {#1}{#2}}}% + {\romannumeral0\xintiiadd {#5}{\XINT_mul_fork #1\Z #3\Z}}% + {\romannumeral0\xintiiadd {#4}{\XINT_mul_fork #1\Z #2\Z}}% {#2}{#3}% }% \def\XINT_igctf_loop_c #1#2% @@ -25553,8 +25849,8 @@ $1$ or $-1$. \expandafter\XINT_ctcv_loop_c\expandafter {\romannumeral0\XINT_mul_fork #2\Z #4\Z }% {\romannumeral0\XINT_mul_fork #2\Z #3\Z }% - {\romannumeral0\xintiiadd {\XINT_Mul {#2}{#6}}{\XINT_Mul {#1}{#4}}}% - {\romannumeral0\xintiiadd {\XINT_Mul {#2}{#5}}{\XINT_Mul {#1}{#3}}}% + {\romannumeral0\xintiiadd {\XINT_mul_fork #2\Z #6\Z}{\XINT_mul_fork #1\Z #4\Z}}% + {\romannumeral0\xintiiadd {\XINT_mul_fork #2\Z #5\Z}{\XINT_mul_fork #1\Z #3\Z}}% }% \def\XINT_ctcv_loop_c #1#2% {% @@ -25596,8 +25892,8 @@ $1$ or $-1$. \def\XINT_icstcv_loop_b #1.#2#3#4#5% {% \expandafter\XINT_icstcv_loop_c\expandafter - {\romannumeral0\xintiiadd {#5}{\XINT_Mul {#1}{#3}}}% - {\romannumeral0\xintiiadd {#4}{\XINT_Mul {#1}{#2}}}% + {\romannumeral0\xintiiadd {#5}{\XINT_mul_fork #1\Z #3\Z}}% + {\romannumeral0\xintiiadd {#4}{\XINT_mul_fork #1\Z #2\Z}}% {{#2}{#3}}% }% \def\XINT_icstcv_loop_c #1#2% @@ -25633,8 +25929,8 @@ $1$ or $-1$. \expandafter\XINT_gctcv_loop_c\expandafter {\romannumeral0\XINT_mul_fork #2\Z #4\Z }% {\romannumeral0\XINT_mul_fork #2\Z #3\Z }% - {\romannumeral0\xintiiadd {\XINT_Mul {#2}{#6}}{\XINT_Mul {#1}{#4}}}% - {\romannumeral0\xintiiadd {\XINT_Mul {#2}{#5}}{\XINT_Mul {#1}{#3}}}% + {\romannumeral0\xintiiadd {\XINT_mul_fork #2\Z #6\Z}{\XINT_mul_fork #1\Z #4\Z}}% + {\romannumeral0\xintiiadd {\XINT_mul_fork #2\Z #5\Z}{\XINT_mul_fork #1\Z #3\Z}}% }% \def\XINT_gctcv_loop_c #1#2% {% @@ -25705,8 +26001,8 @@ $1$ or $-1$. \def\XINT_igctcv_loop_b #1.#2#3#4#5% {% \expandafter\XINT_igctcv_loop_c\expandafter - {\romannumeral0\xintiiadd {#5}{\XINT_Mul {#1}{#3}}}% - {\romannumeral0\xintiiadd {#4}{\XINT_Mul {#1}{#2}}}% + {\romannumeral0\xintiiadd {#5}{\XINT_mul_fork #1\Z #3\Z}}% + {\romannumeral0\xintiiadd {#4}{\XINT_mul_fork #1\Z #2\Z}}% {{#2}{#3}}% }% \def\XINT_igctcv_loop_c #1#2% @@ -26029,6 +26325,32 @@ $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 |\fontcharit| 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} @@ -26302,18 +26624,52 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintexpr}% - [2015/09/12 v1.1c Expandable expression parser (jfB)]% + [2015/10/10 v1.2 Expandable expression parser (jfB)]% +\catcode`! 11 % \end{macrocode} % \subsection{Locking and unlocking} -% je dois réfléchir si je dois bloquer expansion après |unlock_a|, à -% cause de nil. -% \begin{macrocode} -\def\xint_gob_til_! #1!{}% this ! has catcode 11 -\edef\XINT_expr_lockscan#1!{\noexpand\expandafter\space\noexpand\csname .=#1\endcsname }% -\edef\XINT_expr_lockit #1{\noexpand\expandafter\space\noexpand\csname .=#1\endcsname }% -\def\XINT_expr_inintpart #1!{\XINT_num{#1}}% -\def\XINT_expr_infracpart #1e#2!{#1![\the\numexpr#2-\xintLength{#1}]!}% -\def\XINT_expr_inexppart e#1!{![\the\numexpr #1]!}% +% \lverb|Some renaming and modifications here with release 1.2 to switch from +% using chains of \romannumeral-`0 in order to gather numbers, possibly +% hexadecimals, to using a \csname governed expansion. In this way no more +% limit at 5000 digits, and besides this is a logical move because the +% \xintexpr parser is already based on \csname...\endcsname storage of numbers +% as one token. +% +% The limitation at 5000 digits didn't worry me too much because it was not +% very realistic to launch computations with thousands of digits... such +% computations are still slow with 1.2 but less so now. Chains or +% \romannumeral are still used for the gathering of function names and other +% stuff which I have half-forgotten because the parser does many things. +% +% In the earlier versions we used the lockscan macro after a chain of +% \romannumeral-`0 had ended gathering digits; this uses has been replaced by +% direct processing inside a \csname...\endcsname and the macro is kept only +% for matters of dummy variables. +% +% Currently, the parsing of hexadecimal numbers needs two nested +% \csname...\endcsname, first to gather the letters (possibly with a hexadecimal +% fractional part), and in a second stage to apply \xintHexToDec to do the +% actual conversion. This should be faster than updating on the fly the number +% (which would be hard for the fraction part...). The macro \xintHexToDec +% could probably be made faster by using techniques similar as the ones v1.2 +% uses in xintcore.sty.| +% \begin{macrocode} +\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 + {\noexpand\expandafter\space\noexpand\csname .=#1\endcsname }% +\edef\XINT_expr_lockit + #1{\noexpand\expandafter\space\noexpand\csname .=#1\endcsname }% +\def\XINT_expr_unlock_hex_in #1% expanded inside \csname..\endcsname + {\expandafter\XINT_expr_inhex\romannumeral-`0\XINT_expr_unlock#1;}% +\def\XINT_expr_inhex #1.#2#3;% expanded inside \csname..\endcsname +{% + \if#2>\xintHexToDec{#1}% + \else + \xintiiMul{\xintiiPow{625}{\xintLength{#3}}}{\xintHexToDec{#1#3}}% + [\the\numexpr-4*\xintLength{#3}]% + \fi +}% +%%%%%%%%%%%% \def\XINT_expr_unlock {\expandafter\XINT_expr_unlock_a\string }% \def\XINT_expr_unlock_a #1.={}% \def\XINT_expr_unexpectedtoken {\xintError:ignored }% @@ -26395,7 +26751,7 @@ $1$ or $-1$. \def\xintiieval {\expandafter\XINT_iiexpr_wrap\romannumeral0\xintbareiieval }% % \end{macrocode} % \subsection{\csh{xintieval}, \csh{XINT_iexpr_wrap}} -% \lverb|Optional argument since 1.1| +% \lverb|Optional argument since 1.1.| % \begin{macrocode} \def\xintieval #1% {\ifx [#1\expandafter\XINT_iexpr_withopt\else\expandafter\XINT_iexpr_noopt \fi #1}% @@ -26592,16 +26948,23 @@ $1$ or $-1$. #1% }% \def\XINT_expr_subexpr !#1\fi !{\expandafter\XINT_expr_getop\xint_gobble_iii }% +% \end{macrocode} +% \lverb|1.2 adds \ht, \dp, \wd and the eTeX font things.| +% \begin{macrocode} \def\XINT_expr_countetc #1% {% - \ifx\count#1\else\ifx#1\dimen\else\ifx#1\numexpr\else\ifx#1\dimexpr\else - \ifx\skip#1\else\ifx\glueexpr#1\else\ifx\fontdimen#1\else + \ifx\count#1\else\ifx\dimen#1\else\ifx\numexpr#1\else\ifx\dimexpr#1\else + \ifx\skip#1\else\ifx\glueexpr#1\else\ifx\fontdimen#1\else\ifx\ht#1\else + \ifx\dp#1\else\ifx\wd#1\else\ifx\fontcharht#1\else\ifx\fontcharwd#1\else + \ifx\fontchardp#1\else\ifx\fontcharic#1\else \XINT_expr_unpackvar - \fi\fi\fi\fi\fi\fi\fi + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \expandafter\XINT_expr_getnext\number #1% }% -\def\XINT_expr_unpackvar\fi\fi\fi\fi\fi\fi\fi\expandafter\XINT_expr_getnext\number #1% - {\fi\fi\fi\fi\fi\fi\fi\expandafter\XINT_expr_getop\csname .=\number#1\endcsname }% +\def\XINT_expr_unpackvar\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \expandafter\XINT_expr_getnext\number #1% + {\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi + \expandafter\XINT_expr_getop\csname .=\number#1\endcsname }% \begingroup \lccode`*=`# \lowercase{\endgroup @@ -26609,7 +26972,7 @@ $1$ or $-1$. \if#1*\xint_dothis {\XINT_expr_scan_macropar *}\fi \if#1[\xint_dothis {\xint_c_xviii ({}}\fi \if#1+\xint_dothis \XINT_expr_getnext \fi - \if#1.\xint_dothis {\XINT_expr_scandec_II\XINT_expr_infracpart}\fi + \if#1.\xint_dothis {\XINT_expr_startdec}\fi \if#1-\xint_dothis -\fi \if#1(\xint_dothis {\xint_c_xviii ({}}\fi \xint_orthat {\XINT_expr_scan_nbr_or_func #1}% @@ -26618,158 +26981,220 @@ $1$ or $-1$. % \end{macrocode} % \subsection{The integer or decimal number or hexa-decimal number or % function name or variable name or special hacky things big parser} +% \lverb|1.2 release has replaced chains of \romannumeral-`0 by \csname +% governed expansion. Thus there is no more the limit at about 5000 digits for +% parsed numbers. +% +% In order to avoid having to lock and unlock in succession to handle the +% scientific part and adjust the exponent according to the number of digits of +% the decimal part, the parsing of this decimal part counts on the fly the +% number of digits it encounters. +% +% There is some slight annoyance with \xintiiexpr which should never be given +% a [n] inside its \csname.=\endcsname storage of numbers (because its +% arithmetic uses the ii macros which know nothing about the [N] notation). +% Hence if the parser has only seen digits when hitting something else than +% the dot or e (or E), it will not insert a [0]. Thus we very slightly +% compromise the efficiency of \xintexpr and \xintfloatexpr in order to be +% able to share the same code with \xintiiexpr. +% +% Indeed, the parser at this location is completely common to all, it does not +% know if it is working inside \xintexpr or \xintiiexpr. On the other hand if +% a dot or a e (or E) is met, then the (common) parser has no scrupules ending +% this number with a [n], this will provoke an error later if that was within +% an \xintiiexpr, as soon as an arithmetic macro is used. +% +% As the gathered numbers have no spaces, no pluses, no minuses, the only +% remaining issue is with leading zeroes, which are discarded on the fly. The +% hexadecimal numbers leading zeroes are stripped in a second stage by the +% \xintHexToDec macro. +% +% With v1.2, \xinttheexpr . \relax does not work anymore (it did in earlier +% releases). There must be digits either before or after the decimal mark. Thus +% both \xinttheexpr 1.\relax and \xinttheexpr .1\relax are legal.| % \begin{macrocode} \catcode96 11 % ` \def\XINT_expr_scan_nbr_or_func #1% this #1 has necessarily here catcode 12 {% \if "#1\xint_dothis \XINT_expr_scanhex_I\fi \if `#1\xint_dothis {\XINT_expr_onlitteral_`}\fi - \ifnum \xint_c_ix<1#1 \xint_dothis \XINT_expr_scandec_I\fi + \ifnum \xint_c_ix<1#1 \xint_dothis \XINT_expr_startint\fi \xint_orthat \XINT_expr_scanfunc #1% }% \catcode96 12 % ` -\def\XINT_expr_scandec_I -{% - \expandafter\XINT_expr_getop\romannumeral-`0\expandafter - \XINT_expr_lockscan\romannumeral0\expandafter\XINT_expr_inintpart - \romannumeral-`0\XINT_expr_scanintpart_b -}% -\def\XINT_expr_scandec_II +\def\XINT_expr_startint #1% {% - \expandafter\XINT_expr_getop\romannumeral-`0\expandafter - \XINT_expr_lockscan\romannumeral0\expandafter\XINT_expr_inintpart - \romannumeral-`0\XINT_expr_scanfracpart_b + \if #10\expandafter\XINT_expr_gobz_a\else\XINT_expr_scanint_a\fi #1% }% +\def\XINT_expr_scanint_a #1#2% + {\expandafter\XINT_expr_getop\csname.=#1% + \expandafter\XINT_expr_scanint_b\romannumeral-`0#2}% +\def\XINT_expr_gobz_a #1% + {\expandafter\XINT_expr_getop\csname.=% + \expandafter\XINT_expr_gobz_scanint_b\romannumeral-`0#1}% +\def\XINT_expr_startdec #1% + {\expandafter\XINT_expr_getop\csname.=% + \expandafter\XINT_expr_scandec_a\romannumeral-`0#1}% % \end{macrocode} -% \subsubsection{Integral part} -% \begin{macrocode} -\def\XINT_expr_scanintpart_a #1% -{% careful that ! has catcode letter here - \ifcat \relax #1\xint_dothis{!!#1}\fi % stops the scan - \if e#1\xint_dothis{\expandafter\XINT_expr_inexppart - \romannumeral-`0\XINT_expr_scanexppart_a e}\fi - \if E#1\xint_dothis{\expandafter\XINT_expr_inexppart - \romannumeral-`0\XINT_expr_scanexppart_a e}\fi -% \end{macrocode} -% \lverb|\if @#1\xint_dothis{!*#1}\fi % tacit multiplication later| +% \subsubsection{Integral part (skipping zeroes)} +% \lverb|Sub-expressions are recognized as startaing with catcode 11 +% exclamation mark, which is treated together with variable names composed of +% letters below, hence induces a tacit multiplication if encountered while +% gathering a number. % -% \lverb|\if _#1\xint_dothis{!*#1}\fi % tacit multiplication for variables| +% 1.2 has modified the code to give highest priority to digits, the impact is +% non-negligeable. I don't think the doubled \string is a serious penalty.| % \begin{macrocode} - \ifcat a#1\xint_dothis{!!*#1}\fi % includes subexpressions (#1=! letter) - \xint_orthat {\expandafter\XINT_expr_scanintpart_aa\string #1}% +\def\XINT_expr_scanint_b #1% +{% + \ifcat \relax #1\expandafter\XINT_expr_scanint_endbycs\expandafter #1\fi + \ifnum\xint_c_ix<1\string#1 \else\expandafter\XINT_expr_scanint_c\fi + \string#1\XINT_expr_scanint_d +}% +\def\XINT_expr_scanint_d #1% +{% + \expandafter\XINT_expr_scanint_b\romannumeral-`0#1% +}% +\def\XINT_expr_scanint_endbycs#1#2\XINT_expr_scanint_d{\endcsname #1}% +\def\XINT_expr_scanint_c\string #1\XINT_expr_scanint_d +{% + \if e#1\xint_dothis{[\the\numexpr0\XINT_expr_scanexp_a +}\fi + \if E#1\xint_dothis{[\the\numexpr0\XINT_expr_scanexp_a +}\fi + \ifcat a#1\xint_dothis{\endcsname*#1}\fi + \if .#1\xint_dothis{\XINT_expr_startdec_a .}\fi + \xint_orthat {\expandafter\endcsname \string#1}% +}% +\def\XINT_expr_startdec_a .#1% +{% + \expandafter\XINT_expr_scandec_a\romannumeral-`0#1% +}% +\def\XINT_expr_scandec_a #1% +{% + \if .#1\xint_dothis{\endcsname..}\fi + \xint_orthat {\XINT_expr_scandec_b 0.#1}% }% -\def\XINT_expr_scanintpart_aa #1% +\def\XINT_expr_gobz_scanint_b #1% {% - \if .#1\xint_dothis\XINT_expr_scandec_transition\fi - \ifnum \xint_c_ix<1#1 \xint_dothis\XINT_expr_scanintpart_b\fi - \xint_orthat {!!}#1% + \ifcat \relax #1\expandafter\XINT_expr_gobz_scanint_endbycs\expandafter #1\fi + \ifnum\xint_c_x<1\string#1 \else\expandafter\XINT_expr_gobz_scanint_c\fi + \string#1\XINT_expr_scanint_d }% -\def\XINT_expr_scanintpart_b #1#2% +\def\XINT_expr_gobz_scanint_endbycs#1#2\XINT_expr_scanint_d{0\endcsname #1}% +\def\XINT_expr_gobz_scanint_c\string #1\XINT_expr_scanint_d {% - \expandafter #1\romannumeral-`0\expandafter - \XINT_expr_scanintpart_a\romannumeral-`0#2% + \if e#1\xint_dothis{0[\the\numexpr0\XINT_expr_scanexp_a +}\fi + \if E#1\xint_dothis{0[\the\numexpr0\XINT_expr_scanexp_a +}\fi + \ifcat a#1\xint_dothis{0\endcsname*#1}\fi + \if .#1\xint_dothis{\XINT_expr_gobz_startdec_a .}\fi + \if 0#1\xint_dothis\XINT_expr_gobz_scanint_d\fi + \xint_orthat {0\expandafter\endcsname \string#1}% }% -\def\XINT_expr_scandec_transition .#1% +\def\XINT_expr_gobz_scanint_d #1% {% - \expandafter\XINT_expr_scandec_trans_a\romannumeral-`0#1% + \expandafter\XINT_expr_gobz_scanint_b\romannumeral-`0#1% }% -\def\XINT_expr_scandec_trans_a #1% +\def\XINT_expr_gobz_startdec_a .#1% {% - \if .#1\xint_dothis{!!..}\fi - \xint_orthat {\expandafter\XINT_expr_infracpart - \romannumeral-`0\XINT_expr_scanfracpart_a #1}% + \expandafter\XINT_expr_gobz_scandec_a\romannumeral-`0#1% +}% +\def\XINT_expr_gobz_scandec_a #1% +{% + \if .#1\xint_dothis{0\endcsname..}\fi + \xint_orthat {\XINT_expr_gobz_scandec_b 0.#1}% }% % \end{macrocode} % \subsubsection{Fractional part} +% \lverb|Annoying duplication of code to allow 0. as input.| % \begin{macrocode} -\def\XINT_expr_scanfracpart_a #1% +\def\XINT_expr_scandec_b #1.#2% {% - \ifcat \relax #1\xint_dothis{e!#1}\fi % stops the scan - \if e#1\xint_dothis{\XINT_expr_scanexppart_a e}\fi - \if E#1\xint_dothis{\XINT_expr_scanexppart_a e}\fi - \ifcat a#1\xint_dothis{e!*#1}\fi % and also the case of subexpressions (!) - \xint_orthat {\expandafter\XINT_expr_scanfracpart_aa\string #1}% + \ifcat \relax #2\expandafter\XINT_expr_scandec_endbycs\expandafter#2\fi + \ifnum\xint_c_ix<1\string#2 \else\expandafter\XINT_expr_scandec_c\fi + \string#2\expandafter\XINT_expr_scandec_d\the\numexpr #1-\xint_c_i.% }% -\def\XINT_expr_scanfracpart_aa #1% +\def\XINT_expr_scandec_endbycs #1#2\XINT_expr_scandec_d + \the\numexpr#3-\xint_c_i.{[#3]\endcsname #1}% +\def\XINT_expr_scandec_d #1.#2% {% - \ifnum \xint_c_ix<1#1 - \expandafter\XINT_expr_scanfracpart_b - \else - \xint_afterfi {e!}% - \fi - #1% + \expandafter\XINT_expr_scandec_b + \the\numexpr #1\expandafter.\romannumeral-`0#2% +}% +\def\XINT_expr_scandec_c\string #1#2\the\numexpr#3-\xint_c_i.% +{% + \if e#1\xint_dothis{[\the\numexpr#3\XINT_expr_scanexp_a +}\fi + \if E#1\xint_dothis{[\the\numexpr#3\XINT_expr_scanexp_a +}\fi + \ifcat a#1\xint_dothis{[#3]\endcsname *#1}\fi + \xint_orthat {[#3]\expandafter\endcsname \string#1}% +}% +\def\XINT_expr_gobz_scandec_b 0.#1% +{% + \ifcat \relax #1\expandafter\XINT_expr_gobz_scandec_endbycs\expandafter#1\fi + \ifnum\xint_c_ix<1\string#1 \else\expandafter\XINT_expr_gobz_scandec_c\fi + \string#1\expandafter\XINT_expr_scandec_d\the\numexpr\xint_c_mone.% }% -\def\XINT_expr_scanfracpart_b #1#2% +\def\XINT_expr_gobz_scandec_endbycs #1#2\xint_c_mone.{0[0]\endcsname #1}% +\def\XINT_expr_gobz_scandec_c\string #1#2\xint_c_mone.% {% - \expandafter #1\romannumeral-`0\expandafter - \XINT_expr_scanfracpart_a\romannumeral-`0#2% + \if e#1\xint_dothis{0[\the\numexpr0\XINT_expr_scanexp_a +}\fi + \if E#1\xint_dothis{0[\the\numexpr0\XINT_expr_scanexp_a +}\fi + \ifcat a#1\xint_dothis{0[0]\endcsname *#1}\fi + \xint_orthat {0[0]\expandafter\endcsname \string#1}% }% % \end{macrocode} % \subsubsection{Scientific notation} +% \lverb|Some pluses and minuses are allowed at the start of the scientific +% part, however not later, and no parenthesis.| % \begin{macrocode} -\def\XINT_expr_scanexppart_a #1#2% +\def\XINT_expr_scanexp_a #1#2% {% - \expandafter #1\romannumeral-`0\expandafter - \XINT_expr_scanexppart_b\romannumeral-`0#2% + #1\expandafter\XINT_expr_scanexp_b\romannumeral-`0#2% }% -\def\XINT_expr_scanexppart_b #1% +\def\XINT_expr_scanexp_b #1% {% - \ifcat \relax #1\xint_dothis{0!#1}\fi % stops the scan (incorrect syntax) - \ifcat a#1\xint_dothis{0!*#1}\fi % idem - \if +#1\xint_dothis {\XINT_expr_scanexppart_a +}\fi - \if -#1\xint_dothis {\XINT_expr_scanexppart_a -}\fi - \xint_orthat {\expandafter\XINT_expr_scanexppart_c\string #1}% + \ifcat \relax #1\expandafter\XINT_expr_scanexp_endbycs\expandafter #1\fi + \ifnum\xint_c_ix<1\string#1 \else\expandafter\XINT_expr_scanexp_c\fi + \string#1\XINT_expr_scanexp_d }% -\def\XINT_expr_scanexppart_c #1% +\def\XINT_expr_scanexpr_endbycs#1#2\XINT_expr_scanexp_d {]\endcsname #1}% +\def\XINT_expr_scanexp_d #1% {% - \ifnum \xint_c_ix<1#1 - \expandafter\XINT_expr_scanexppart_d - \else - \expandafter !% - \fi - #1% + \expandafter\XINT_expr_scanexp_bb\romannumeral-`0#1% }% -\def\XINT_expr_scanexppart_d #1#2% +\def\XINT_expr_scanexp_c\string #1\XINT_expr_scanexp_d {% - \expandafter #1\romannumeral-`0\expandafter - \XINT_expr_scanexppart_e\romannumeral-`0#2% + \ifcat a#1\xint_dothis {]\endcsname *#1}\fi + \if +#1\xint_dothis {\XINT_expr_scanexp_a +}\fi + \if -#1\xint_dothis {\XINT_expr_scanexp_a -}\fi + \xint_orthat {]\expandafter\endcsname\string #1}% }% -\def\XINT_expr_scanexppart_e #1% +\def\XINT_expr_scanexp_bb #1% {% - \ifcat \relax #1\xint_dothis{!#1}\fi % stops the scan - \ifcat a#1\xint_dothis{!*#1}\fi % idem - \xint_orthat {\expandafter\XINT_expr_scanexppart_f\string #1}% + \ifcat \relax #1\expandafter\XINT_expr_scanexp_endbycs_b\expandafter #1\fi + \ifnum\xint_c_ix<1\string#1 \else\expandafter\XINT_expr_scanexp_cb\fi + \string#1\XINT_expr_scanexp_db }% -\def\XINT_expr_scanexppart_f #1% +\def\XINT_expr_scanexp_endbycs_b#1#2\XINT_expr_scanexp_db {]\endcsname #1}% +\def\XINT_expr_scanexp_db #1% {% - \ifnum \xint_c_ix<1#1 - \expandafter\XINT_expr_scanexppart_d - \else - \expandafter !% - \fi - #1% + \expandafter\XINT_expr_scanexp_bb\romannumeral-`0#1% +}% +\def\XINT_expr_scanexp_cb\string #1\XINT_expr_scanexp_db +{% + \ifcat a#1\xint_dothis {]\endcsname *#1}\fi + \xint_orthat {]\expandafter\endcsname\string #1}% }% % \end{macrocode} % \subsubsection{Hexadecimal numbers} % \begin{macrocode} -\def\XINT_expr_scanhex_I #1% -{% - \expandafter\XINT_expr_getop\romannumeral-`0\expandafter - \XINT_expr_lockscan\expandafter\XINT_expr_inhex - \romannumeral-`0\XINT_expr_scanhexI_a -}% -\def\XINT_expr_inhex #1.#2#3;% expanded inside \csname..\endcsname +\def\XINT_expr_scanhex_I #1% #1=" {% - \if#2I\xintHexToDec{#1}% - \else - \xintiiMul{\xintiiPow{625}{\xintLength{#3}}}{\xintHexToDec{#1#3}}% - [\the\numexpr-4*\xintLength{#3}]% - \fi + \expandafter\XINT_expr_getop\csname.=\expandafter + \XINT_expr_unlock_hex_in\csname.=\XINT_expr_scanhexI_a }% \def\XINT_expr_scanhexI_a #1% {% - \ifcat #1\relax\xint_dothis{.I;!#1}\fi - \ifx !#1\xint_dothis{.I;!*!}\fi % tacit multiplication + \ifcat #1\relax\xint_dothis{.>\endcsname\endcsname #1}\fi + \ifx !#1\xint_dothis{.>\endcsname\endcsname*!}\fi % tacit multiplication \xint_orthat {\expandafter\XINT_expr_scanhexI_aa\string #1}% }% \def\XINT_expr_scanhexI_aa #1% @@ -26787,24 +27212,23 @@ $1$ or $-1$. \expandafter\xint_secondoftwo \fi {\expandafter\XINT_expr_scanhex_transition}% - {\xint_afterfi {.I;!}}% + {\xint_afterfi {.>\endcsname\endcsname}}% \fi #1% }% \def\XINT_expr_scanhexI_b #1#2% {% - \expandafter #1\romannumeral-`0\expandafter - \XINT_expr_scanhexI_a\romannumeral-`0#2% + #1\expandafter\XINT_expr_scanhexI_a\romannumeral-`0#2% }% \def\XINT_expr_scanhex_transition .#1% {% - \expandafter.\expandafter.\romannumeral-`0\expandafter + \expandafter.\expandafter.\expandafter \XINT_expr_scanhexII_a\romannumeral-`0#1% }% \def\XINT_expr_scanhexII_a #1% {% - \ifcat #1\relax\xint_dothis{;!#1}\fi - \ifx !#1\xint_dothis{;!*!}\fi % tacit multiplication + \ifcat #1\relax\xint_dothis{\endcsname\endcsname#1}\fi + \ifx !#1\xint_dothis{\endcsname\endcsname*!}\fi % tacit multiplication \xint_orthat {\expandafter\XINT_expr_scanhexII_aa\string #1}% }% \def\XINT_expr_scanhexII_aa #1% @@ -26816,14 +27240,13 @@ $1$ or $-1$. 0\else1\fi\else0\fi\else1\fi\else0\fi 1% \expandafter\XINT_expr_scanhexII_b \else - \xint_afterfi {;!}% + \xint_afterfi {\endcsname\endcsname}% \fi #1% }% \def\XINT_expr_scanhexII_b #1#2% {% - \expandafter #1\romannumeral-`0\expandafter - \XINT_expr_scanhexII_a\romannumeral-`0#2% + #1\expandafter\XINT_expr_scanhexII_a\romannumeral-`0#2% }% % \end{macrocode} % \subsubsection{Function and variable names} @@ -27684,22 +28107,25 @@ $1$ or $-1$. }% % \end{macrocode} % \subsection{! as postfix factorial operator} -% \lverb|As of 2014/11/07, not yet a float version of factorial. I must do it!| +% \lverb|Float version was at last done 2015/10/06. As xint does not have yet +% exp/log, Stirling is no go.| % \begin{macrocode} \let\XINT_expr_precedence_! \xint_c_x \def\XINT_expr_op_! #1{\expandafter\XINT_expr_getop \csname .=\xintFac{\XINT_expr_unlock #1}\endcsname }% -\let\XINT_flexpr_op_!\XINT_expr_op_! +\def\XINT_flexpr_op_! #1{\expandafter\XINT_expr_getop + \csname .=\XINTinFloatFac{\XINT_expr_unlock #1}\endcsname }% \def\XINT_iiexpr_op_! #1{\expandafter\XINT_expr_getop - \csname .=\xintiFac{\XINT_expr_unlock #1}\endcsname }% + \csname .=\xintiiFac{\XINT_expr_unlock #1}\endcsname }% % \end{macrocode} % \subsection{The A/B[N] mechanism} % \lverb|Releases earlier than 1.1 required the use of braces around A/B[N] -% input. The [N] is now implemented directly. *BUT* uses a delimited macro! +% input. The [N] is now implemented directly. *BUT* this uses a delimited macro! % thus N is not allowed to be itself an expression (I could add it...). -% \xintE, \xintiiE, and \XINTinFloatE all put #2 in a \numexpr. BUT ATTENTION -% TO CRAZYNESS OF NUMEXPR: \the\numexpr 3 + 7 9 \relax !! Hence we have to do -% the job ourselves.| +% \xintE, \xintiiE, and \XINTinFloatE all put #2 in a \numexpr. But attention +% to the fact that \numexpr stops at spaces separating digits: +% \the\numexpr 3 + 7 9\relax gives 109\relax !! Hence we have to be +% careful.| % \begin{macrocode} \catcode`[ 11 \catcode`* 11 @@ -27742,7 +28168,7 @@ $1$ or $-1$. % all high punctuation ?, !, :, ;. % % It is not recommended to overwrite single Latin letters which are -% pre-defined to serve as dummy variables. Variable names may contains +% pre-defined to serve as dummy variables. Variable names may contain % letters, digits, underscores, and must not start with a digit.| % \begin{macrocode} \catcode`: 12 @@ -27848,7 +28274,7 @@ $1$ or $-1$. }% \expandafter\def\csname XINT_expr_onlitteral_`\endcsname #1#2#3({\xint_c_xviii `{#2}}% % \end{macrocode} -% \subsection{The bool, togl, protect, unknown, and break "functions"} +% \subsection{The bool, togl, protect, unknown, and break ``functions''} % \lverb|bool, togl and protect use delimited macros. Only unknown and break % are true functions with a more flexible parsing of the opening and closing % parentheses, which may possibly arise from expansion itself.| @@ -27859,12 +28285,24 @@ $1$ or $-1$. {\expandafter\XINT_expr_getop\csname .=\xintToggle{#1}\endcsname }% \def\XINT_expr_onlitteral_protect #1)% {\expandafter\XINT_expr_getop\csname .=\detokenize{#1}\endcsname }% -\def\XINT_expr_func_unknown #1#2#3{\expandafter #1\expandafter #2\csname .=0\endcsname }% +\def\XINT_expr_func_unknown #1#2#3% + {\expandafter #1\expandafter #2\csname .=0\endcsname }% \def\XINT_expr_func_break #1#2#3% -{\expandafter #1\expandafter #2\csname.=?\romannumeral-`0\XINT_expr_unlock #3\endcsname }% + {\expandafter #1\expandafter #2\csname.=?\romannumeral-`0\XINT_expr_unlock #3\endcsname }% \let\XINT_flexpr_func_break \XINT_expr_func_break \let\XINT_iiexpr_func_break \XINT_expr_func_break % \end{macrocode} +% \subsection{The qint, qfrac, qfloat ``functions''} +% \lverb|New with 1.2. Allows the user to hand over quickly a big number to the +% parser, spaces not immediately removed but should be harmless in general.| +% \begin{macrocode} +\def\XINT_expr_onlitteral_qint #1)% + {\expandafter\XINT_expr_getop\csname .=\xintiNum{#1}\endcsname }% +\def\XINT_expr_onlitteral_qfrac #1)% + {\expandafter\XINT_expr_getop\csname .=\xintRaw{#1}\endcsname }% +\def\XINT_expr_onlitteral_qfloat #1)% + {\expandafter\XINT_expr_getop\csname .=\XINTinFloatdigits{#1}\endcsname }% +% \end{macrocode} % \subsection{seq and the implementation of dummy variables} % \lverb|All of seq, add, mul, rseq, etc... (actually all of the extensive % changes from xintexpr 1.09n to 1.1) was done around June 15-25th 2014, but the @@ -27921,9 +28359,9 @@ $1$ or $-1$. \def\XINT_expr_onlitteral_seq_e #1#2{\XINT_expr_onlitteral_seq_d {#1}{#2)}}% % \end{macrocode} % \subsubsection{\csh{XINT_isbalanced_a} for \csh{XINT_expr_onlitteral_seq_a}} -%\lverb|Expands to \m@ne in case a closing ) had no opening ( matching it, to -% \@ne if opening ) had no closing ) matching it, to \z@ if expression was -% balanced.| +% \lverb|Expands to \xint_c_mone in case a closing ) had no opening ( matching +% it, to \@ne if opening ) had no closing ) matching it, to \z@ if expression +% was balanced.| % \begin{macrocode} % use as \XINT_isbalanced_a \relax #1(\xint_bye)\xint_bye \def\XINT_isbalanced_a #1({\XINT_isbalanced_b #1)\xint_bye }% @@ -27932,7 +28370,7 @@ $1$ or $-1$. % \end{macrocode} % \lverb|if #2 is not \xint_bye, a ) was found, but there was no (. Hence error -> -1| % \begin{macrocode} -\def\XINT_isbalanced_error #1)\xint_bye {\m@ne}% +\def\XINT_isbalanced_error #1)\xint_bye {\xint_c_mone}% % \end{macrocode} % \lverb|#2 was \xint_bye, was there a ) in original #1?| % \begin{macrocode} @@ -28978,10 +29416,11 @@ $1$ or $-1$. \romannumeral-`0\expandafter\XINT_xptwo_getab_b \romannumeral-`0####2!{####1}{~xint#1}{xint#1}}% }% -}% +}% cela aurait-il un sens d'ajouter Raw et iNum (à cause de qint, qfrac, + % qfloat?). Pas le temps d'y réfléchir. Je ne fais rien. \xintFor #1 in {Num,Irr,Abs,iiAbs,Sgn,iiSgn,TFrac,Floor,iFloor,Ceil,iCeil,% Sqr,iiSqr,iiSqrt,iiSqrtR,iiIsZero,iiIsNotZero,iiifNotZero,iiifSgn,% - Odd,Even,iiOdd,iiEven,Opp,iiOpp,iiifZero,Fac,iFac,Bool,Toggle}\do + Odd,Even,iiOdd,iiEven,Opp,iiOpp,iiifZero,Fac,iiFac,Bool,Toggle}\do {\toks0 \expandafter{\the\toks0% \expandafter\let\csname xint#1NE\expandafter\endcsname\csname xint#1\expandafter @@ -28989,6 +29428,13 @@ $1$ or $-1$. \expandafter\XINT_NEfork_one\romannumeral-`0####1!{~xint#1}{xint#1}{}{}}% }% }% +\toks0 + \expandafter{\the\toks0 + \let\XINTinFloatFacNE\XINTinFloatFac + \def\XINTinFloatFac ##1{% + \expandafter\XINT_NEfork_one + \romannumeral-`0##1!{~XINTinFloatFac}{XINTinFloatFac}{}{}}% + }% \xintFor #1 in {Add,Sub,Mul,Div,Power,E,Mod,SeqA::csv}\do {\toks0 \expandafter{\the\toks0% @@ -29189,12 +29635,41 @@ $1$ or $-1$. \def\mymacroaux #1#2{#2}% % \parbox[t]{10cm}{Total number of code lines: - \dtt{\the\numexpr - \xintListWithSep+{\xintApply\mymacro\storedlinecounts}\relax }. Each - package starts - with circa \dtt{50} lines dealing with catcodes, package identification - and reloading management, also for Plain \TeX\strut. Version - {\xintbndlversion} of {\xintbndldate}.\par} + \dtt{\the\numexpr + \xintListWithSep+{\xintApply\mymacro\storedlinecounts}\relax }. + Among those, release 1.2 has about 3000 lines starting with either + \{\% or \}\%.% en fait 3013 mais je devrais automatiser. + + Each package starts with circa \dtt{50} lines dealing with catcodes, + package identification and reloading management, also for Plain + \TeX\strut. Version {\xintbndlversion} of {\xintbndldate}.\par +} + +% il faut que je patche doc.sty pour faire ça automatiquement: +% +% TEMP$ grep -c -e "^{%" *sty +% xint.sty:170 +% xintbinhex.sty:69 +% xintcfrac.sty:183 +% xintcore.sty:296 +% xintexpr.sty:133 +% xintfrac.sty:415 +% xintgcd.sty:59 +% xintkernel.sty:7 +% xintseries.sty:48 +% xinttools.sty:112 +% +% TEMP$ grep -c -e "^}%" *sty +% xint.sty:170 +% xintbinhex.sty:69 +% xintcfrac.sty:183 +% xintcore.sty:296 +% xintexpr.sty:163 +% xintfrac.sty:415 +% xintgcd.sty:61 +% xintkernel.sty:8 +% xintseries.sty:48 +% xinttools.sty:112 \CharacterTable {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z @@ -29211,7 +29686,7 @@ $1$ or $-1$. Right bracket \] Circumflex \^ Underscore \_ Grave accent \` Left brace \{ Vertical bar \| Right brace \} Tilde \~} -\CheckSum {25543} +\CheckSum {26711}% \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 5244bbf6c17..2be4ee69a10 100644 --- a/Master/texmf-dist/source/generic/xint/xint.ins +++ b/Master/texmf-dist/source/generic/xint/xint.ins @@ -21,7 +21,7 @@ %% same distribution. (The sources need not necessarily be %% in the same archive or directory.) %% --------------------------------------------------------------- -%% The xint bundle v1.1c 2015/09/12 +%% The xint bundle v1.2 2015/10/10 %% Copyright (C) 2013-2015 by Jean-Francois Burnol %% --------------------------------------------------------------- %% -- cgit v1.2.3