diff options
author | Karl Berry <karl@freefriends.org> | 2015-10-11 21:21:00 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2015-10-11 21:21:00 +0000 |
commit | c42b50b291d00f547400888b81ef4d2bcad45142 (patch) | |
tree | 9ab2f5792d7627887e9f858a103ba1c7de329a67 /Master/texmf-dist/source/generic/xint | |
parent | ced6522f86e501ede0097c2b6362bc17603b6eef (diff) |
xint (11oct15)
git-svn-id: svn://tug.org/texlive/trunk@38612 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/generic/xint')
-rw-r--r-- | Master/texmf-dist/source/generic/xint/xint.dtx | 8641 | ||||
-rw-r--r-- | Master/texmf-dist/source/generic/xint/xint.ins | 2 |
2 files changed, 4559 insertions, 4084 deletions
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>} %</dtx> %<*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} %</drv> %<*dtx> \iffalse % meta-comment %</dtx> %<readme>% README %<changes>% CHANGE LOG -%<readme|changes>% xint v1.1c -%<readme|changes>% 2015/09/12 +%<readme|changes>% xint v1.2 +%<readme|changes>% 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> %<*!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>%% xintkernel: Paraphernalia for the xint packages %<xinttools>%% 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.</div> %</readme>-------------------------------------------------------- %<*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. +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|. -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|. - -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,10 +3209,46 @@ 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. + +\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: +% +\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. |;-)| +% 6.342,022,117,488,416,127,3 10^35 +% maple n'aime pas ^-243 il veut les parenthèses, bon et il donne, en Digits +% = 24: 0.634202211748841612732270 10^36 +\end{snugframed} + +\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}$:% @@ -3330,28 +3268,11 @@ Some inputs are simplified by the use of the \xintexprname package. 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;\dtt{\np{\xintthefloatexpr .7123045678952^-243\relax }}} -% -Side note: the exponent |-243| didn't have to be put inside parentheses, -contrarily to what happens with some professional computational -software. |;-)| -% 6.342,022,117,488,416,127,3 10^35 -% maple n'aime pas ^-243 il veut les parenthèses, bon et il donne, en Digits -% = 24: 0.634202211748841612732270 10^36 -\end{snugframed} - -\xintDigits:=16; +\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,37 +4186,63 @@ 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}|} - % - Scientific notation is accepted for both numerator and denominator of a - fraction, and is produced on output by \csbxint{Float}: - % - \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} +\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*} % Produced fractions having a denominator equal to one are, as a general rule, nevertheless printed as fractions. In math mode \csbxint{Frac} @@ -4131,45 +4257,55 @@ the allowed input formats for `long numbers' and `fractions' are: \item the \hyperref[xintexpr]{expression format} is for inclusion in an \csbxint{expr}|...\relax|, it uses infix notations, function names, complete - expansion, 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{<space>\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,434 +5105,6 @@ expandability. Check it out (\autoref{xintiloop}). % \noindent\kern\parindent\input README.md % \endgroup }\x -\section{New features of the \xintexprname package} -\label{sec:expr11} - -Release |1.1| brought many changes to \xintexprname. This chapter is -for people already familiar with earlier versions. A more systematic -item per item syntax description is provided in \autoref{sec:expr}. But be -sure to come back here as the latter chapter has not been compeletely updated. - -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. - -\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 - -\xintDigits:=16;\xintthefloatexpr 1.010101^10-1.0101^10\relax - -\xintthefloatexpr [12] 1.010101^10-1.0101^10\relax -\end{everbatim*} - - \item |\xinttheexpr| and |\xintthefloatexpr| ``pretty-print'' if possible, - the former removing unit denominator or |[0]| brackets, the latter - avoiding scientific notation if decimal notation is practical, - \item the |//| does truncated division and |/:| is the associated modulo, - \item multi-character operators |&&|, \verb+||+, |==|, |<=|, |>=|, |!=|, - |**|, - \item multi-letter infix binary words |'and'|, |'or'|, |'xor'|, |'mod'| - (quotes mandatory), - \item functions |even|, |odd|, |first|, |last|, - \item |\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{Examples with the \texorpdfstring{\unexpanded{\unexpanded{|v1.1|}}}{v1.1} \csh{xintexpr}} - -And now some examples: - -\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*} - -Use |`+`| and |`*`| (left ticks mandatory) for syntax without dummy variables: -\begin{everbatim*} -\xinttheexpr `+`(1,3,19), `*`(1^2,3^2,19^2), `+`(1*2,3*4,19*20)\relax -\end{everbatim*} -\item The |seq| function generates sequences according to a given formula: -\begin{everbatim*} -\xinttheexpr seq(x(x+1)(x+2), x=1,3,19), `+`(seq(x(x+1)(x+2), x=1,3,19)), - add(x(x+1)(x+2), x=1,3,19)\relax -\end{everbatim*} -\begin{everbatim*} -And this is nestable! -\xinttheexpr seq(seq(x^y, y=1..5),x=1..5), add(mul(x^y,y=1..5), x=1..5), - add(x^15, x=1..5)\relax % 15 = 1+2+3+4+5 -\end{everbatim*} - -One should use parentheses appropriately. The \csbxint{expr} parser in normal -operation is not bad at identifying missing or extra opening or closing -parentheses, but when it handles |seq|, |add|, |mul| or similar constructs it -switches to another mode of operation (it starts using delimited macros, -something which is almost non-existent in all its other operations) and ill-formed -expressions are much more likely to let the parser fetch tokens from beyond the -mandatory ending |\relax|. Thus, in case of a missing parenthesis in such -circumstances the error message from \TeX{} might be very cryptic, even for -the seasoned \xintname user. - -\item As seen in the last example |a..b| constructs the integers from |a| to - |b|. This is (small) integer only. A more general |a..[d]..b| works with big - integers, or fractions, from |a| to |b| with step |d|. -\begin{everbatim*} -\xinttheexpr seq(2x+1, x=1..10, 100..110, 3/5..[1/5]..7/5)\relax -\end{everbatim*} -\item itemwise operations on lists are possible, as well as item extractions: -\begin{everbatim*} -\xinttheiiexpr 2*[1,10,100]^3, 5+[2*[1,10,100]^3]*100 \relax -\end{everbatim*} -\begin{everbatim*} -\xinttheiiexpr 1+[seq(3^j, j=1..10, 21..30)][17], 1+3^27\relax -\end{everbatim*} - -We used the |[list][n]| construct which gives the nth item from the list. In -this context there are also the functions |last| and |first|. There is no real -concept of a list object, nor list operations, although itemwise manipulation -are made possible as shown above via the |[..]| constructor. The list -manipulation utilities are so far a bit limited. There is no notion of an -``nuple'' object. The variable |nil| is reserved, it represents an empty list. - -\item |subs| is similar to |seq| in syntax but is for variable substitution: -\begin{everbatim*} -\xinttheexpr subs(100*subs(10*subs(3*x+5,x=y+50)+2,y=z^2),z=10)\relax % 100(10(3*150+5)+2) -\end{everbatim*} -\begin{everbatim*} -\xinttheexpr subs(subs(add(x^2+y^2,x=1..y),y=t),t=20)\relax -\end{everbatim*} - -The substituted variable may be a comma separated list (this is impossible -with |seq| which will always pick one item after the other of a list). -\begin{everbatim*} -\xinttheexpr subs([x]^2,x=-123,17,32)\relax -\end{everbatim*} - -\item last but not least, |seq| has variants |rseq| and |rrseq| which allow - recursive definitions. They start with at least one initial value, then a - semi-colon, then the formula, then the list of indices to iterate over. |@| - (or |@1|) evaluates to the last computed item, and |rrseq| keeps the memory - of the |K| last results, where |K| was the number of initial terms. One - accesses them via |@1, @2, @3, @4| and |@@(N)| for |N>4|. It is even - possible to nest them and use |@@@| to access the values of the master - recursion... -\begin{everbatim*} -\xinttheiiexpr rseq(1; 2*@, i=1..10), `+`(rseq(1; 2*@, i=1..10))\relax -\end{everbatim*} -\begin{everbatim*} -\xinttheiiexpr rseq(2; @(@+1)/2, i=1..5)\relax -\end{everbatim*} -\begin{everbatim*} -\xinttheiiexpr rseq(0,1; (@1,add(x,x=@1)), y=2..10)\relax -\end{everbatim*} - -Some Fibonacci fun -\begin{everbatim*} -\xinttheiiexpr rrseq(0,1; @1+@2, x=2..10), last(rrseq(0,1; @1+@2, x=2..100))\relax -\end{everbatim*} -\begin{everbatim*} -Sum of previous last three: \xinttheiiexpr rrseq(0,0,1; @1+@2+@3, i=1..20)\relax -\end{everbatim*} -\begin{everbatim*} -Big numbers: \printnumber{\xinttheexpr rseq(1; @(@+1), j=1..10)\relax } -\end{everbatim*} - -Nested recursion often quickly leads to gigantic outputs. This is an -experimental feature, susceptible to be removed or altered in the future. -\begin{everbatim*} -\xinttheexpr rrseq(1; `+`(rrseq(0,1; @@@(1)+@1+@2, i=1..10)), j=1..5)\relax -\end{everbatim*} - -\item The special keywords |omit|, |abort| and |break(..)| are available - inside |seq|, |rseq|, |rrseq|, as well as the |n++| for a potentially - infinite iteration. The |n++| construct in conjunction with an |abort| or - |break| is often more efficient, because in other cases the list to iterate - over is first completely constructed. -\begin{everbatim*} -First Fibonacci number at least |2^31| and its index -\xinttheiiexpr iter(0,1; (@1>=2^31)?{break(i)}{@2+@1}, i=1++)\relax -\end{everbatim*} - -\begin{everbatim*} -Prime numbers are always cool -\xinttheiiexpr seq((seq((subs((x/:m)?{(m*m>x)?{1}{0}}{-1},m=2n+1)) - ??{break(0)}{omit}{break(1)},n=1++))?{x}{omit}, - x=10001..[2]..10200)\relax -\end{everbatim*} - -The syntax in this last example may look a bit involved. First |x/:m| computes -|x modulo m| (this is the modulo with respect to truncated division, which -here for positive arguments is like Euclidean division; in -|\xintexpr...\relax|, |a/:b| is such that |a = b*(a//b)+a/:b|, with |a//b| the -algebraic quotient |a/b| truncated to an integer.). The |(x)?{yes}{no}| -construct checks if |x| (which \emph{must} be within parentheses) is true or -false, i.e. non zero or zero. It then executes either the |yes| or the |no| -branch, the non chosen branch is \emph{not} evaluated. Thus if |m| divides |x| -we are in the second (``false'') branch. This gives a |-1|. This |-1| is the -argument to a |??| branch which is of the type |(y)??{y<0}{y=0}{y>0}|, thus here -the |y<0|, i.e., |break(0)| is chosen. This |0| is thus given to another |?| -which consequently chooses |omit|, hence the number is not kept in the list. -The numbers which survive are the prime numbers. - -% A006877 In the `3x+1' problem, these values for the starting value set new -% records for number of steps to reach 1. (Formerly M0748) 14 1, 2, 3, 6, 7, -% 9, 18, 25, 27, 54, 73, 97, 129, 171, 231, 313, 327, 649, 703, 871, 1161, -% 2223, 2463, 2919, 3711, 6171, 10971, 13255, 17647, 23529, 26623, 34239, -% 35655, 52527, 77031, 106239, 142587, 156159, 216367, 230631, 410011, 511935, -% 626331, 837799 - -\item The |iter| function is like |rrseq| but does not leave a trace of earlier items, - it starts with |K| initial values, then it iterates: either a fixed number of times, - or until aborting or breaking. And ultimately it prints |K| final values. -\begin{everbatim*} -The first Fibonacci number beyond the \TeX{} bound is -\xinttheiiexpr subs(iter(0,1;(@1>N)?{break(i)}{@1+@2},i=1++),N=2^31)\relax{} -and the previous number was its index. -\end{everbatim*}But this was a bit too easy, what is the smallest Fibonacci number not representable on 64 bits? -\begin{everbatim*} -The first Fibonacci number beyond |2^64| bound is -\xinttheiiexpr subs(iter(0,1;(@1>N)?{break(i)}{@1+@2},i=1++),N=2^64)\relax{} -and the previous number was its index. -\end{everbatim*} - -One more recursion: -\begin{everbatim*} -\def\syr #1{\xinttheiiexpr rseq(#1; (@<=1)?{break(i)}{odd(@)?{3@+1}{@//2}},i=0++)\relax} -The 3x+1 problem: \syr{231}\par -\end{everbatim*} - -Ok, a final one: -\begin{everbatim*} -\def\syrMax #1{\xinttheiiexpr iter(#1,#1;even(i)? - {(@2<=1)?{break(i/2)}{odd(@2)?{3@2+1}{@2//2}}} - {(@1>@2)?{@1}{@2}},i=0++)\relax } -With initial value 1161, the maximal number attained is \syrMax{1161} and that latter -number is the number of steps which was needed to reach 1.\par -\end{everbatim*} - -Well, one more: - -\begin{everbatim*} -\newcommand\GCD [2]{\xinttheiiexpr rrseq(#1,#2; (@1=0)?{abort}{@2/:@1}, i=1++)\relax } -\GCD {13^10*17^5*29^5}{2^5*3^6*17^2} -\end{everbatim*} - -and the ultimate: - -\begin{everbatim*} -\newcommand\Factors [1]{\xinttheiiexpr - subs(seq((i/:3=2)?{omit}{[L][i]},i=1..([L][0])), - L=rseq(#1;(p^2>[@][1])?{([@][1]>1)?{break(1,[@][1],1)}{abort}} - {(([@][1])/:p)?{omit} - {iter(([@][1])//p; (@/:p)?{break(@,p,e)}{@//p},e=1++)}},p=2++))\relax } -\Factors {41^4*59^2*29^3*13^5*17^8*29^2*59^4*37^6} -\end{everbatim*} - -This might look a bit scary, I admit. \xintexprname has minimal tools and -is obstinate about doing everything expandably! We are hampered by absence of a -notion of ``nuple''. The algorithm divides |N| by |2| until no more possible, -then by |3|, then by |4| (which is silly), then by |5|, then by |6| (silly -again), \dots. - -The variable |L=rseq(#1;...)| expands, if one follows the steps, to a comma -separated list starting with the initial (evaluated) |N=#1| and then -pseudo-triplets where the first item is |N| trimmed of small primes, the -second item is the last prime divisor found, and the third item is its -exponent in original |N|. - -The algorithm needs to keep handy the last computed quotient by prime powers, -hence all of them, but at the very end it will be cleaner to get rid of them -(this corresponds to the first line in the code above). This is achieved in a -cumbersome inefficient way; indeed each item extraction |[L][i]| is costly: it -is not like accessing an array stored in memory, due to expandability, nothing -can be stored in memory! Nevertheless, this step could be done here in a far -less inefficient manner if there was a variant of |seq| which, in the spirit -of \csbxint{iloopindex}, would know how many steps it had been through so far. -This is a feature to be added to |\xintexpr|! (as well as a |++| construct -allowing a non unit step). - -Notice that in |iter(([@][1])//p;| the |@| refers to the previous triplet (or -in the first step to |N|), but the latter |@| showing up in |(@/:p)?| refers -to the previous value computed by |iter|. - -\begin{snugframed} - Parentheses are essential in |..([y][0])| else the parser will see |..[| and - end up in ultimate confusion, and also in |([@][1])/:p| else the parser will - see the itemwise operator |]/| on lists and again be very confused (I could - implement a |]/:| on lists, but in this situation this would also be very - confusing to the parser.) -\end{snugframed} - -For comparison, here is an \fexpan dable macro expanding to the same result, -but coded directly with the \xintname macros. Here |#1| can not be itself an -expression, naturally. But at least we let |\Factorize| \fexpan d its -argument. -\begin{everbatim} -\makeatletter -\newcommand\Factorize [1] - {\romannumeral0\expandafter\factorize\expandafter{\romannumeral-`0#1}}% -\newcommand\factorize [1]{\xintiiifOne{#1}{ 1}{\factors@a #1.{#1};}}% -\def\factors@a #1.{\xintiiifOdd{#1} - {\factors@c 3.#1.}% - {\expandafter\factors@b \expandafter1\expandafter.\romannumeral0\xinthalf{#1}.}}% -\def\factors@b #1.#2.{\xintiiifOne{#2} - {\factors@end {2, #1}}% - {\xintiiifOdd{#2}{\factors@c 3.#2.{2, #1}}% - {\expandafter\factors@b \the\numexpr #1+\@ne\expandafter.% - \romannumeral0\xinthalf{#2}.}}% -}% -\def\factors@c #1.#2.{% - \expandafter\factors@d\romannumeral0\xintiidivision {#2}{#1}{#1}{#2}% -}% -\def\factors@d #1#2#3#4{\xintiiifNotZero{#2} - {\xintiiifGt{#3}{#1} - {\factors@end {#4, 1}}% ultimate quotient is a prime with power 1 - {\expandafter\factors@c\the\numexpr #3+\tw@.#4.}}% - {\factors@e 1.#3.#1.}% -}% -\def\factors@e #1.#2.#3.{\xintiiifOne{#3} - {\factors@end {#2, #1}}% - {\expandafter\factors@f\romannumeral0\xintiidivision {#3}{#2}{#1}{#2}{#3}}% -}% -\def\factors@f #1#2#3#4#5{\xintiiifNotZero{#2} - {\expandafter\factors@c\the\numexpr #4+\tw@.#5.{#4, #3}}% - {\expandafter\factors@e\the\numexpr #3+\@ne.#4.#1.}% -}% -\def\factors@end #1;{\xintlistwithsep{, }{\xintRevWithBraces {#1}}}% -\makeatother -\end{everbatim} - -The macro |\Factorize| puts a little stress on the input save stack in order -not be bothered with previously gathered things. I timed it to be about eight -times faster than |\Factors| in test cases such as -|16246355912554185673266068721806243461403654781833| and others. Among the -various things explaining the speed-up, there is fact that we step by -increments of two, not one, and also that we divide only once, obtaining -quotient and remainder in one go. These two things already make for a speed-up -factor of about four. Thus, our earlier |\Factors| was not completely -inefficient, and was quite easier to come up with than |\Factorize|. - -If we only considered small integers, we could write pure |\numexpr| methods -which would be very much faster (especially if we had a table of small primes -prepared first) but still ridiculously slow compared to any non expandable -implementation, not to mention use of programming languages directly accessing -the CPU registers\dots -\end{itemize} - -%\phantomsection -\phantomsection\label{sec:expr11coords} - -To conclude with this overview of the new features in \xintexprname |1.1|, I -will mention {\bfseries |\xintthecoords|} which converts a comma separated -list as produced by |\xintfloatexpr| or |\xintiexpr [d]| to the format -expected by the |TikZ| |coordinates| syntax. -\begin{everbatim*} -{\centering\begin{tikzpicture}[scale=10]\xintDigits:=8; - \clip (-1.1,-.25) rectangle (.3,.25); - \draw [blue] (-1.1,0)--(1,0); - \draw [blue] (0,-1)--(0,+1); - \draw [red] plot[smooth] coordinates {\xintthecoords - % converts into (x1, y1) (x2, y2)... format - \xintfloatexpr seq((x^2-1,mul(x-t,t=-1+[0..4]/2)),x=-1.2..[0.1]..+1.2) \relax }; -\end{tikzpicture}\par } -\end{everbatim*} - -% Notice: if x goes no take exactly value 1 or -1, the origin appears slightly -% off the curve, not MY fault!!! - -\csbxint{thecoords} should be followed immediately by \csbxint{floatexpr} or -\csbxint{iexpr} or \csbxint{iiexpr}, but not |\xintthefloatexpr|, etc\dots - -Besides, as |TikZ| will not understand the |A/B[N]| format which is used on -output by |\xintexpr|, |\xintexpr| is not really usable with |\xintthecoords| -for a |TikZ| picture, but one may use it on its own, and the reason for the -spaces in and between coordinate pairs is to allow if necessary to print on -the page for examination with about correct line-breaks. - -\begin{everbatim*} -\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}}} @@ -5459,12 +5157,16 @@ them). There is a similar macro |\odef| with only one expansion of the replacement text |<stuff>|, and |\fdef| which expands fully |<stuff>| 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|. +% 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|. 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. \subsection{\csbh{xintReverseOrder}}\label{xintReverseOrder} @@ -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. + +\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} -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? +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,22 +8006,10 @@ 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}} |\xintCmp|\n\m\etype{\Numf\Numf} returns \dtt{1} if |N>M|, \dtt{0} if |N=M|, @@ -8441,9 +8147,7 @@ Important: the macro compares \emph{absolute values}. |\xintiMax|\n\m\etype{\Numf\Numf} returns the largest of the two in the sense of the order structure on the relative integers (\emph{i.e.} the right-most number if they are put on a line with positive numbers on the right): -|\xintiMax {-5}{-6}|\dtt{=\xintiMax{-5}{-6}}. The initial synonym \csbxint{Max} -gets modified by \xintfracname which extends it to fractions. Its usage when -only \xintname is loaded is discouraged. +|\xintiMax {-5}{-6}|\dtt{=\xintiMax{-5}{-6}}. The |\xintiiMax| macro skips the overhead of parsing the operands with \csbxint{Num}.\etype{ff} @@ -8453,9 +8157,7 @@ The |\xintiiMax| macro skips the overhead of parsing the operands with |\xintiMin|\n\m\etype{\Numf\Numf} returns the smallest of the two in the sense of the order structure on the relative integers (\emph{i.e.} the left-most number if they are put on a line with positive numbers on the right): |\xintiMin -{-5}{-6}|\dtt{=\xintiMin{-5}{-6}}. The initial synonym \csbxint{Min} -gets modified by \xintfracname which extends it to fractions. Its usage when -only \xintname is loaded is discouraged. +{-5}{-6}|\dtt{=\xintiMin{-5}{-6}}. The |\xintiiMin| macro skips the overhead of parsing the operands with \csbxint{Num}.\etype{ff} @@ -8465,29 +8167,22 @@ The |\xintiiMin| macro skips the overhead of parsing the operands with \csa{xintiMaxof}|{{a}{b}{c}...}|\etype{f{$\to$}\lowast\Numf} returns the maximum. The list argument may be a macro, it is \fexpan ded first. Each item -is submitted to |\xintNum| normalization. \csbxint{Maxof} is the initial -synonym which gets extended by \xintfracname to fractions. Do not use it when -only \xintname is loaded. +is submitted to |\xintNum| normalization. \subsection{\csbh{xintiMinof}}\label{xintiMinof} %{\small New with release |1.09a|.\par} \csa{xintiMinof}|{{a}{b}{c}...}|\etype{f{$\to$}\lowast\Numf} returns the minimum. The list argument may be a macro, it is \fexpan ded first. Each item -is submitted to |\xintNum| normalization. \csbxint{Minof} is the initial -synonym which gets extended by \xintfracname to fractions. Do not use it when -only \xintname is loaded. +is submitted to |\xintNum| normalization. \subsection{\csbh{xintiiSum}}\label{xintiiSum} \csa{xintiiSum}\marg{braced things}\etype{{\lowast f}} after expanding its argument expects to find a sequence of tokens (or braced material). Each is -expanded (with the usual meaning), and the sum of all these numbers is returned. +\fexpan ded, and the sum of all these numbers is returned. Note: the summands are \emph{not} parsed by \csbxint{Num}. -\csbxint{Sum} is initially a synonym, it gets extended by \xintfracname to -fractions. - % \leftedline{% \csa{xintiiSum}|{{123}{-98763450}{\xintFac{7}}{\xintiMul{3347}{591}}}|% @@ -8533,7 +8228,6 @@ With \xintexprname, this would be easier: % \leftedline {|\xinttheiiexpr 2^200*3^100*7^100\relax |} -The initial synonym \csbxint{Prd} is extended by \xintfracname to fractions. % \subsection{\csbh{xintPrdExpr}}\label{xintiiPrdExpr} @@ -8668,13 +8362,44 @@ odd integer and in that case executes the |YES| branch. \subsection{\csbh{xintiFac}}\label{xintiFac} -|\xintiFac|\x\etype{\numx} returns the factorial. It is an error if the -argument is negative or at least $10^5$.% avant 1.09j c'était 1000000. - -|\xintFac| is a variant using |\xintNum| and thus, when \xintfracname is -loaded, accepting a fraction on input (but it truncates it first). +|\xintiFac|\x\etype{\numx} returns the factorial. It is an error on input if +the argument is negative. -% temps obsolètes, mettre à jour +\begin{framed} + The macro will limits the acceptable inputs to a maximum of $9999$. However + the maximal computation depends on the values of some memory parameters of + the |tex| executable: with the the current default settings of TeXLive 2015, + the maximal computable factorial (a.t.t.o.w. 2015/10/06) turns out to be + $5971!$ which has $19956$ digits.%\footnotemark +\end{framed} +% \footnotetext{The computation with \xintname 1.2 of $5971!$ takes of the order +% of 27 seconds on my laptop. And about half a second for the $2568$ digits of +% $1000!$.} + +Package \xintfracname provides \csbxint{FloatFac} which allows to evaluate +faster significant digits of big factorials and accepts (theoretically) inputs +up to $99999999$. See \autoref{sec:examples} for the example of $2000!$ with +$50$ significant digits. + +% avant 1.09j c'était 1000000. +% avant 1.2 c'était 100000. (n'importe quoi!) + +|\xintFac| is the variant applying |\xintNum| on his input and thus, when +\xintfracname is loaded, accepting a fraction on input (but it truncates it +first). + +% avec xint1.2: 1000!, 2000!, 3000! +% Mercredi 07 octobre 2015 à 14:34:20 +% (0.534s) +% 402387260077093773543702, 2568, 4.023872600770938e2567. +% (2.521s) +% 331627509245063324117539, 5736, 3.316275092450633e5735. +% (6.097s) +% 414935960343785408555686, 9131, 4.149359603437854e9130. + +% ATTENTION TOTALEMENT MAIS TOTALEMENT OBSOLETE +% JE CONSERVE UNIQUEMENT POUR ME SOUVENIR DU PASSÉ +% ---- obsolète, remonte au premier xint % On my laptop $1000!$ (2568 digits) % is computed in a little less than ten seconds, $2000!$ (5736 % digits) is computed in a little less than one hundred seconds, and @@ -8684,6 +8409,12 @@ loaded, accepting a fraction on input (but it truncates it first). % transition from $N=9999$ to $10000$ and higher; $10000!$ has 35660 % digits). Not to mention $100000!$ which, from the Stirling formula, % should have 456574 digits. +% ---- (je rêvais à l'époque avec 100000! ... +% +% Je me souviens qu'au tout début je ne m'attendais pas du tout à rencontrer +% de tels problèmes dès des nombres de quelques milliers de chiffres, car je +% n'étais pas imprégné de la pénalité liée à parcourir par des macros +% délimités de longues séquences de tokens \subsection{\csbh{xintiiMON}, \csbh{xintiiMMON}} \label{xintMON}\label{xintMMON}\label{xintiiMON}\label{xintiiMMON} @@ -8884,6 +8615,7 @@ of \csa{xintDecSplit}. \xintiiE {123}{89} \end{everbatim*} +\pagebreak \section{Commands of the \xintfracname package} \label{sec:frac} @@ -9309,10 +9041,21 @@ xxx:_xint $ | \endgroup -Using |\xintTrunc| rather than |\xintXTrunc| would be hopeless on such long -outputs (and even |\xintXTrunc| needed of the order of seconds to complete -here). But it is not worth it to use |\xintXTrunc| for less than hundreds of -digits. +% \emph{Outdated note: Using |\xintTrunc| rather than |\xintXTrunc| would be +% hopeless on such long outputs (and even |\xintXTrunc| needed of the order of +% seconds to complete here). But it is not worth it to use |\xintXTrunc| for +% less than hundreds of digits.} + +\begin{framed} + The |\xintiiMul {\ZA}{66049}| above can sadly \emph{not} be executed with + \xintname 1.2, due to the new limitation to at most about $19950$ digits for + multiplication. On the other hand |\edef\W {\xintXTrunc {131584}{1/66049}}| + produces the $131584$ digits four times faster. The macro \csbxint{XTrunc} + has not yet been adapted to the new integer model underlying the 1.2 + \xintcorename macros, and perhaps some future improvements are possible. So + far it only benefits from a faster division routine, in that specific case + for a divisor having more than four but less than nine digits. +\end{framed} Fraction arguments to |\xintXTrunc| corresponding to a |A/B[N]| with a negative |N| are treated somewhat less efficiently (additional memory impact) than for positive or zero |N|. This is because the algorithm tries to work with the @@ -9600,6 +9343,17 @@ an integer format on output use \csbxint{iSqr}. exactly and outputs in float format with precision |P| (which is optional), or |\xintDigits| if |P| was absent, the result of this computation. +\begin{framed} + It is obviously much needed that the author improves its algorithms to avoid + going through the exact |2P| or |2P-1| digits (plus safety digits) before + throwing to the waste-bin half of those digits ! + + \xintname initially was purely an \emph{exact} arbitrary precision + arithmetic machine, and the introduction of floating point numbers was an + after-thought. I got it working in release |1.07 (2013/05/25)| and never had + time to come back to it. +\end{framed} + \subsection{\csbh{xintDiv}}\label{xintDiv} Computes the algebraic quotient \etype{\Ff\Ff} of two fractions. @@ -9621,13 +9375,34 @@ exactly and outputs in float format with precision |P| (which is optional), or %{\small Modified in |1.08b| (to allow fractions on input).\par} The original\etype{\Numf} is extended to allow a fraction |f| which will be -truncated first to an integer |n| (non negative and at most |999999|, but -already |100000!| is prohibitively time-costly). On output |n!| (with no -trailing |/1[0]|). +truncated first to an integer |n|. See \csbxint{iFac} for a discussion of the +maximal allowed input. + +Output format is an integer without trailing |/1[0]|. The original macro\etype{\numx} (which parses its input via |\numexpr|) is still available as \csbxint{iFac}. +\subsection{\csbh{xintFloatFac}}\label{xintFloatFac} + +\csa{xintFloatFac}|[P]{f}|\etype{{\upshape[\numx]}\Ff} returns the +factorial. +\begin{everbatim*} +$1000!\approx{}$\xintFloatFac [30]{1000} +\end{everbatim*} +The computation\NewWith{1.2 !} proceeds via doing explicitely the product, as +the Stirling formula cannot be used for lack so far of |exp/\log|. +% \footnote{The computation of $100000!$ with $16$ digits of precision takes +% about three or four seconds and for $1000000!$ it is about fifty seconds on +% my laptop (2015/10/06).} +% +There is no a priori limit set on the |P| optional argument, thus the Stirling +approach would become complicated if that freedom was to be obeyed. + +The macro |\xintFloatFac| chooses dynamically an appropriate number of +digits for the intermediate computations, large enough to achieve the desired +accuracy (hopefully). + \subsection{\csbh{xintPow}}\label{xintPow} \csa{xintPow}{|{f}{g}|}:\etype{\Ff\Numf} computes |f^g| with |f| a fraction @@ -9639,10 +9414,11 @@ vanishes: |\xintPow {2/3}{0}|\dtt{=\xintPow{2/3}{0}}). The original is available as \csbxint{iPow}. -The exponent (after truncation to an integer) will be checked to not exceed -|100000|. Indeed |2^50000| already has \dtt{\xintLen {\xintFloatPow - [1]{2}{50000}}} digits, and squaring such a number would take hours (I -think) with the expandable routine of \xintname. +%%%%% OBSOLETE +% The exponent (after truncation to an integer) will be checked to not exceed +% |100000|. Indeed |2^50000| already has \dtt{\xintLen {\xintFloatPow +% [1]{2}{50000}}} digits, and squaring such a number would take hours (I +% think) with the expandable routine of \xintname. \subsection{\csbh{xintFloatPow}}\label{xintFloatPow} %{\small New with |1.07|.\par} @@ -9688,7 +9464,16 @@ which is, in disguise, an integer. The intermediate multiplications are done with a higher precision than |\xintDigits| or the optional |P| argument, in order for the -final result to hopefully have the desired accuracy. +final result to hopefully have the desired accuracy.% +% +\footnote{\label{fn:floatpow}% + Release |1.2| did not change a single line of code to these macros because + they don't access low-level entry points. There is some sure important + efficiency gains to be obtained in maintaining internally the best inner + format for the successive squarings and multiplications, but I decided to + postpone that, as the more urgent issue is to improve \csbxint{FloatMul} to + not compute exactly with all digits the product before keeping only the + required digits.} \subsection{\csbh{xintFloatSqrt}}\label{xintFloatSqrt} %{\small New with |1.08|.\par} @@ -9870,9 +9655,17 @@ be used when one is dealing exclusively with (big) integers. \localtableofcontents The \xintexprname package was first released with version |1.07| -(|2013/05/25|) of the \xintname bundle. The package loads automatically -\xintfracname and \xinttoolsname (it is now the only arithmetic package from the \xintname -bundle which loads \xinttoolsname). +(|2013/05/25|) of the \xintname bundle. It was substantially enhanced with +release |1.1| from |2014/10/28|. + +Release |1.2| removed a limitation to numbers of at most $5000$ digits, and +there is now a float variant of the factorial. Also the ``pseudo-functions'' +|qint|, |qfrac|, |qfloat| (|'q'| for quick), were added to handle very big +inputs and avoid scanning it digit per digit. + +The package loads automatically \xintfracname and \xinttoolsname (it is now +the only arithmetic package from the \xintname bundle which loads +\xinttoolsname). \begin{itemize} \item for using the |gcd| and |lcm| functions, it is necessary to load package \xintgcdname. @@ -9886,30 +9679,32 @@ bundle which loads \xinttoolsname). \end{everbatim*} \end{itemize} -Release |1.1| has brought many changes to \xintexprname. -See \autoref{sec:expr11} if you are already familiar with the earlier versions. +\begin{framed} + This documentation has repetitions, is a.t.t.of.w generally speaking not + well structured, and mixes old explanations dating back to the first release + and some more recent ones. +\end{framed} + \subsection{The \csbh{xintexpr} expressions}\label{xintexpr}% \label{xinttheexpr}\label{xintthe} An \xintexprname{}ession is a construct -\csbxint{expr}\meta{expandable\_expression}|\relax|\etype{x} where the expandable -expression is read and completely expanded from left to right. - -During this parsing, braced sub-content may be serving as usual as a macro -parameter, or as a branch to the |?| two-way and |??| three-way operators. -Prior to release |1.1|, there were also some other usage, but this has been -removed. It was mainly needed because there was no other way to feed the -number parser directtly with fractions in the |A/B[N]| notation which is the -output format of the \xintfracname macros. There was no real need to use such -macros anyhow. If one really wants to, one can now directly: -\begin{everbatim*} -\xinttheexpr \xintAdd{3/5[2]}{7/13[2]}+199/13[1]\relax -\end{everbatim*} - -Notice in passing that the expressions benefit from the improved handling of -denominators by \csbxint{Add} and \csbxint{Sub} from \xintfracname, which are -the macros to which naturally |+| and |-| are mapped. +\csbxint{expr}\meta{expandable\_expression}|\relax|\etype{x} where the +expandable expression is read and completely expanded from left to right. + +% NOT THE GOOD LOCATION FOR THIS + +% During this parsing, braced sub-content may appear as usual as a macro +% parameter, or as a branch to the |?| two-way and |??| three-way operators. +% Prior to release |1.1|, there were also some other usage, but this has been +% removed. It was mainly needed because there was no other way to feed the +% number parser directtly with fractions in the |A/B[N]| notation which is the +% output format of the \xintfracname macros. There was no real need to use such +% macros anyhow. If one really wants to, one can now directly: +% \begin{everbatim*} +% \xinttheexpr \xintAdd{3/5[2]}{7/13[2]}+199/13[1]\relax +% \end{everbatim*} An |\xintexpr..\relax| \emph{must} end in a |\relax| (which will be absorbed). Like a |\numexpr| expression, it is not printable as is, nor can it be directly @@ -9928,7 +9723,7 @@ or |reduce|.% number of digits of the fractional part; in |float| it is the total number of digits of the mantissa.} % -Here are some examples\par +Here are some examples\par % DO BETTER EXAMPLES !!!!!!!!!!!!!!! \leftedline{|\xinttheexpr 1/5!-1/7!-1/9!\relax|% \dtt{=\xinttheexpr 1/5!-1/7!-1/9!\relax}} \leftedline{|\xinttheexpr round(1/5!-1/7!-1/9!,18)\relax|% @@ -9974,7 +9769,438 @@ choice between parentheses or |\xintexpr...\relax|: |\def\x {(\a+\b)}| or |\def\x {\xintexpr \a+\b\relax}|. The latter is the better choice as it allows also to be prefixed with |\xintthe|. Furthemore, if |\a| and |\b| are already defined |\edef\x {\xintexpr \a+\b\relax}| will do the -computation on the spot. Rather than |\edef| one can use |\oodef|. +computation on the spot.% Rather than |\edef| one can use |\oodef|. + + +\subsection{Some features of the 1.1 release of \xintexprname} +\label{sec:expr11} + +Release |1.1| brought many changes to \xintexprname. This chapter is for +people already familiar with earlier versions. A more systematic item per item +syntax description is provided in the next \autoref{sec:expr}. Both this +section and the next are in need of being improved. + +First, there were some breaking changes: +\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, + itemindent=0pt, leftmargin=\leftmarginii] + \item in |\xintiiexpr|, |/| does \emph{rounded} division, rather than as + in earlier releases the + Euclidean division (for positive arguments, this is truncated division). + The new |//| operator does truncated division, + \item the |:| operator for three-way branching is gone, replaced with |??|, + \item |1e(3+5)| is now illegal. The number parser identifies |e| and |E| + in the same way it does for the decimal mark, earlier versions treated + |e| as |E| rather as postfix operators, + \item the |add| and |mul| have a new syntax, old syntax is with |`+`| and + |`*`| (quotes mandatory), |sum| and |prd| are gone, + \item no more special treatment for encountered brace pairs |{..}| by the + number scanner, |a/b[N]| notation can be used without use of braces (the + |N| will end up space-stripped in a |\numexpr|, it is not parsed by the + |\xintexpr|-ession scanner). + \item although |&| and \verb+|+ are still available as Boolean operators the + use of |&&| and \verb+||+ is strongly recommended. The single + letter operators might be assigned some other meaning in later releases + (bitwise operations, perhaps). Do not use them. + \item place holders for |\xintNewExpr| + could be denoted |#1|, |#2|, ... or also, for special purposes |$1|, |$2|, + ... Only the first form is now accepted and the special cases previously + treated via the second form are now managed via a |protect(...)| function. +\end{itemize} + +Let's now describle some of the numerous additional functionalities. + +\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, + itemindent=\leftmarginii, leftmargin=0em] + \item |\xintiexpr|, |\xinttheiexpr| admit an optional argument within + brackets |[d]|, it then presents the computation result (or results, if + comma separated) after rounding to |d| digits after decimal mark, (the + whole computation is done exactly, as in |xintexpr|), +\begin{everbatim*} +\xinttheiexpr [32] 1.23^50, 1.231^50\relax +\end{everbatim*} + \item |\xintfloatexpr|, |\xintthefloatexpr| similarly admit an optional + argument which serves to keep only |d| digits of precision, getting rid + of cumulated uncertainties in the last digits (the whole computation is + done according to the precision set via |\xintDigits|), +\begin{everbatim*} +\xintDigits:=32;\xintthefloatexpr 1.010101^10-1.0101^10\relax + +\xintDigits:=16;\xintthefloatexpr 1.010101^10-1.0101^10\relax + +\xintthefloatexpr [12] 1.010101^10-1.0101^10\relax +\end{everbatim*} + + \item |\xinttheexpr| and |\xintthefloatexpr| ``pretty-print'' if possible, + the former removing unit denominator or |[0]| brackets, the latter + avoiding scientific notation if decimal notation is practical, + \item the |//| does truncated division and |/:| is the associated modulo, + \item multi-character operators |&&|, \verb+||+, |==|, |<=|, |>=|, |!=|, + |**|, + \item multi-letter infix binary words |'and'|, |'or'|, |'xor'|, |'mod'| + (quotes mandatory), + \item functions |even|, |odd|, |first|, |last|, + \item |\xintdefvar A3:=3.1415;| for variable definitions (non expandable, + naturally), usable in subsequent expressions; variable names may contain + letters, digits, underscores. They should not start with a digit, the + |@| is reserved, and single lowercase and uppercase Latin letters are + predefined to work as dummy variables (see next), + \item generation of comma separated lists |a..b|, |a..[d]..b|, + \item Python syntax-like list extractors |[list][n:]|, |[list][:n]|, |[list][a:b]| + and |[list][n]| (|n=0| for the number of list items), the step is always + |+1|, + \item function |reversed|, to reverse the order of list items, + \item itemwise sequence operations |a*[list]|, etc.., on both sides |a*[list]^b|, + \item dummy variables in |add| and |mul|: |add(x(x+1)(x-1), x=-10..10)|, + \item variable substitutions with |subs|: |subs(subs(add(x^2+y^2,x=1..y),y=t),t=20)|, + \item sequence generation using |seq| with a dummy variable: |seq(x^3, x=-10..10)|, + \item simple recursive sequences with |rseq|, with |@| given the last value, + |rseq(1;2@+1,i=1..10)|, + \item higher recursion with |rrseq|, |@1|, |@2|, |@3|, |@4|, and |@@(n)| + for earlier values, up to |n=K| where |K| is the number of terms of the + initial stretch |rrseq(0,1;@1+@2,i=2..100)|, + \item iteration with |iter| which is like |rrseq| but outputs only the + last |K| terms, where |K| was the number of initial terms, + \item inside |seq|, |rseq|, |rrseq|, |iter|, possibility to use |omit|, + |abort| and |break| to control termination, + \item |n++| potentially infinite index generation for |seq|, |rseq|, + |rrseq|, and |iter|, it is advised to use |abort| or |break(..)| at + some point, + \item the |add|, |mul|, |seq|, ... are nestable,% +\footnote{but |add(seq(x,x=1..t),t=1..2)| fails for the reason that |add| will + receive not a list of numbers but a list of lists.} + \item |\xintthecoords| converts a comma separated list of an even number + of items to the format as expected by the |TikZ| |coordinates| syntax, + \item completely rewritten |\xintNewExpr|, new |protect| function to handle + external macros. However not all constructs are compatible with + |\xintNewExpr|. +\end{itemize} + +% \subsection{Examples with the \texorpdfstring{\unexpanded{\unexpanded{|v1.1|}}}{v1.1} \csh{xintexpr}} + +And now some examples: + +\begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, + itemindent=\leftmarginii, leftmargin=0em] +\item One can define variables (the definition itself is a non expandable + step). The allowed names are composed of letters, digits, and underscores. + The variable should not start with a digit and single letters |a..z|, |A..Z| + are predefined for use as dummy variables --- see below. The |@| is + reserved. +\begin{everbatim*} +\begingroup + \xintdefvar a_1 := 3.14159;\xintdefvar a2 := 2.71828;\xinttheiexpr [5] a_1+a2\relax +\endgroup +\end{everbatim*} +\item |add| and |mul| have a new syntax requiring a dummy variable: +\begin{everbatim*} +\xinttheexpr add(x, x=1,3,19), mul(x^2, x=1,3,19), add(x(x+1), x= 1,3,19)\relax +\end{everbatim*} + +Use |`+`| and |`*`| (left ticks mandatory) for syntax without dummy variables: +\begin{everbatim*} +\xinttheexpr `+`(1,3,19), `*`(1^2,3^2,19^2), `+`(1*2,3*4,19*20)\relax +\end{everbatim*} +\item The |seq| function generates sequences according to a given formula: +\begin{everbatim*} +\xinttheexpr seq(x(x+1)(x+2), x=1,3,19), `+`(seq(x(x+1)(x+2), x=1,3,19)), + add(x(x+1)(x+2), x=1,3,19)\relax +\end{everbatim*} +\begin{everbatim*} +And this is nestable! +\xinttheexpr seq(seq(x^y, y=1..5),x=1..5), add(mul(x^y,y=1..5), x=1..5), + add(x^15, x=1..5)\relax % 15 = 1+2+3+4+5 +\end{everbatim*} + +One should use parentheses appropriately. The \csbxint{expr} parser in normal +operation is not bad at identifying missing or extra opening or closing +parentheses, but when it handles |seq|, |add|, |mul| or similar constructs it +switches to another mode of operation (it starts using delimited macros, +something which is almost non-existent in all its other operations) and ill-formed +expressions are much more likely to let the parser fetch tokens from beyond the +mandatory ending |\relax|. Thus, in case of a missing parenthesis in such +circumstances the error message from \TeX{} might be very cryptic, even for +the seasoned \xintname user. + +\item As seen in the last example |a..b| constructs the integers from |a| to + |b|. This is (small) integer only. A more general |a..[d]..b| works with big + integers, or fractions, from |a| to |b| with step |d|. +\begin{everbatim*} +\xinttheexpr seq(2x+1, x=1..10, 100..110, 3/5..[1/5]..7/5)\relax +\end{everbatim*} +\item itemwise operations on lists are possible, as well as item extractions: +\begin{everbatim*} +\xinttheiiexpr 2*[1,10,100]^3, 5+[2*[1,10,100]^3]*100 \relax +\end{everbatim*} +\begin{everbatim*} +\xinttheiiexpr 1+[seq(3^j, j=1..10, 21..30)][17], 1+3^27\relax +\end{everbatim*} + +We used the |[list][n]| construct which gives the nth item from the list. In +this context there are also the functions |last| and |first|. There is no real +concept of a list object, nor list operations, although itemwise manipulation +are made possible as shown above via the |[..]| constructor. The list +manipulation utilities are so far a bit limited. There is no notion of an +``nuple'' object. The variable |nil| is reserved, it represents an empty list. + +\item |subs| is similar to |seq| in syntax but is for variable substitution: +\begin{everbatim*} +\xinttheexpr subs(100*subs(10*subs(3*x+5,x=y+50)+2,y=z^2),z=10)\relax % 100(10(3*150+5)+2) +\end{everbatim*} +\begin{everbatim*} +\xinttheexpr subs(subs(add(x^2+y^2,x=1..y),y=t),t=20)\relax +\end{everbatim*} + +The substituted variable may be a comma separated list (this is impossible +with |seq| which will always pick one item after the other of a list). +\begin{everbatim*} +\xinttheexpr subs([x]^2,x=-123,17,32)\relax +\end{everbatim*} + +\item last but not least, |seq| has variants |rseq| and |rrseq| which allow + recursive definitions. They start with at least one initial value, then a + semi-colon, then the formula, then the list of indices to iterate over. |@| + (or |@1|) evaluates to the last computed item, and |rrseq| keeps the memory + of the |K| last results, where |K| was the number of initial terms. One + accesses them via |@1, @2, @3, @4| and |@@(N)| for |N>4|. It is even + possible to nest them and use |@@@| to access the values of the master + recursion... +\begin{everbatim*} +\xinttheiiexpr rseq(1; 2*@, i=1..10), `+`(rseq(1; 2*@, i=1..10))\relax +\end{everbatim*} +\begin{everbatim*} +\xinttheiiexpr rseq(2; @(@+1)/2, i=1..5)\relax +\end{everbatim*} +\begin{everbatim*} +\xinttheiiexpr rseq(0,1; (@1,add(x,x=@1)), y=2..10)\relax +\end{everbatim*} + +Some Fibonacci fun +\begin{everbatim*} +\xinttheiiexpr rrseq(0,1; @1+@2, x=2..10), last(rrseq(0,1; @1+@2, x=2..100))\relax +\end{everbatim*} +\begin{everbatim*} +Sum of previous last three: \xinttheiiexpr rrseq(0,0,1; @1+@2+@3, i=1..20)\relax +\end{everbatim*} +\begin{everbatim*} +Big numbers: \printnumber{\xinttheexpr rseq(1; @(@+1), j=1..10)\relax } +\end{everbatim*} + +Nested recursion often quickly leads to gigantic outputs. This is an +experimental feature, susceptible to be removed or altered in the future. +\begin{everbatim*} +\xinttheexpr rrseq(1; `+`(rrseq(0,1; @@@(1)+@1+@2, i=1..10)), j=1..5)\relax +\end{everbatim*} + +\item The special keywords |omit|, |abort| and |break(..)| are available + inside |seq|, |rseq|, |rrseq|, as well as the |n++| for a potentially + infinite iteration. The |n++| construct in conjunction with an |abort| or + |break| is often more efficient, because in other cases the list to iterate + over is first completely constructed. +\begin{everbatim*} +First Fibonacci number at least |2^31| and its index +\xinttheiiexpr iter(0,1; (@1>=2^31)?{break(i)}{@2+@1}, i=1++)\relax +\end{everbatim*} + +\begin{everbatim*} +Prime numbers are always cool +\xinttheiiexpr seq((seq((subs((x/:m)?{(m*m>x)?{1}{0}}{-1},m=2n+1)) + ??{break(0)}{omit}{break(1)},n=1++))?{x}{omit}, + x=10001..[2]..10200)\relax +\end{everbatim*} + +The syntax in this last example may look a bit involved. First |x/:m| computes +|x modulo m| (this is the modulo with respect to truncated division, which +here for positive arguments is like Euclidean division; in +|\xintexpr...\relax|, |a/:b| is such that |a = b*(a//b)+a/:b|, with |a//b| the +algebraic quotient |a/b| truncated to an integer.). The |(x)?{yes}{no}| +construct checks if |x| (which \emph{must} be within parentheses) is true or +false, i.e. non zero or zero. It then executes either the |yes| or the |no| +branch, the non chosen branch is \emph{not} evaluated. Thus if |m| divides |x| +we are in the second (``false'') branch. This gives a |-1|. This |-1| is the +argument to a |??| branch which is of the type |(y)??{y<0}{y=0}{y>0}|, thus here +the |y<0|, i.e., |break(0)| is chosen. This |0| is thus given to another |?| +which consequently chooses |omit|, hence the number is not kept in the list. +The numbers which survive are the prime numbers. + +% A006877 In the `3x+1' problem, these values for the starting value set new +% records for number of steps to reach 1. (Formerly M0748) 14 1, 2, 3, 6, 7, +% 9, 18, 25, 27, 54, 73, 97, 129, 171, 231, 313, 327, 649, 703, 871, 1161, +% 2223, 2463, 2919, 3711, 6171, 10971, 13255, 17647, 23529, 26623, 34239, +% 35655, 52527, 77031, 106239, 142587, 156159, 216367, 230631, 410011, 511935, +% 626331, 837799 + +\item The |iter| function is like |rrseq| but does not leave a trace of earlier items, + it starts with |K| initial values, then it iterates: either a fixed number of times, + or until aborting or breaking. And ultimately it prints |K| final values. +\begin{everbatim*} +The first Fibonacci number beyond the \TeX{} bound is +\xinttheiiexpr subs(iter(0,1;(@1>N)?{break(i)}{@1+@2},i=1++),N=2^31)\relax{} +and the previous number was its index. +\end{everbatim*}But this was a bit too easy, what is the smallest Fibonacci number not representable on 64 bits? +\begin{everbatim*} +The first Fibonacci number beyond |2^64| bound is +\xinttheiiexpr subs(iter(0,1;(@1>N)?{break(i)}{@1+@2},i=1++),N=2^64)\relax{} +and the previous number was its index. +\end{everbatim*} + +One more recursion: +\begin{everbatim*} +\def\syr #1{\xinttheiiexpr rseq(#1; (@<=1)?{break(i)}{odd(@)?{3@+1}{@//2}},i=0++)\relax} +The 3x+1 problem: \syr{231}\par +\end{everbatim*} + +Ok, a final one: +\begin{everbatim*} +\def\syrMax #1{\xinttheiiexpr iter(#1,#1;even(i)? + {(@2<=1)?{break(i/2)}{odd(@2)?{3@2+1}{@2//2}}} + {(@1>@2)?{@1}{@2}},i=0++)\relax } +With initial value 1161, the maximal number attained is \syrMax{1161} and that latter +number is the number of steps which was needed to reach 1.\par +\end{everbatim*} + +Well, one more: + +\begin{everbatim*} +\newcommand\GCD [2]{\xinttheiiexpr rrseq(#1,#2; (@1=0)?{abort}{@2/:@1}, i=1++)\relax } +\GCD {13^10*17^5*29^5}{2^5*3^6*17^2} +\end{everbatim*} + +and the ultimate: + +\begin{everbatim*} +\newcommand\Factors [1]{\xinttheiiexpr + subs(seq((i/:3=2)?{omit}{[L][i]},i=1..([L][0])), + L=rseq(#1;(p^2>[@][1])?{([@][1]>1)?{break(1,[@][1],1)}{abort}} + {(([@][1])/:p)?{omit} + {iter(([@][1])//p; (@/:p)?{break(@,p,e)}{@//p},e=1++)}},p=2++))\relax } +\Factors {41^4*59^2*29^3*13^5*17^8*29^2*59^4*37^6} +\end{everbatim*} + +This might look a bit scary, I admit. \xintexprname has minimal tools and +is obstinate about doing everything expandably! We are hampered by absence of a +notion of ``nuple''. The algorithm divides |N| by |2| until no more possible, +then by |3|, then by |4| (which is silly), then by |5|, then by |6| (silly +again), \dots. + +The variable |L=rseq(#1;...)| expands, if one follows the steps, to a comma +separated list starting with the initial (evaluated) |N=#1| and then +pseudo-triplets where the first item is |N| trimmed of small primes, the +second item is the last prime divisor found, and the third item is its +exponent in original |N|. + +The algorithm needs to keep handy the last computed quotient by prime powers, +hence all of them, but at the very end it will be cleaner to get rid of them +(this corresponds to the first line in the code above). This is achieved in a +cumbersome inefficient way; indeed each item extraction |[L][i]| is costly: it +is not like accessing an array stored in memory, due to expandability, nothing +can be stored in memory! Nevertheless, this step could be done here in a far +less inefficient manner if there was a variant of |seq| which, in the spirit +of \csbxint{iloopindex}, would know how many steps it had been through so far. +This is a feature to be added to |\xintexpr|! (as well as a |++| construct +allowing a non unit step). + +Notice that in |iter(([@][1])//p;| the |@| refers to the previous triplet (or +in the first step to |N|), but the latter |@| showing up in |(@/:p)?| refers +to the previous value computed by |iter|. + +\begin{snugframed} + Parentheses are essential in |..([y][0])| else the parser will see |..[| and + end up in ultimate confusion, and also in |([@][1])/:p| else the parser will + see the itemwise operator |]/| on lists and again be very confused (I could + implement a |]/:| on lists, but in this situation this would also be very + confusing to the parser.) +\end{snugframed} + +For comparison, here is an \fexpan dable macro expanding to the same result, +but coded directly with the \xintname macros. Here |#1| can not be itself an +expression, naturally. But at least we let |\Factorize| \fexpan d its +argument. +\begin{everbatim} +\makeatletter +\newcommand\Factorize [1] + {\romannumeral0\expandafter\factorize\expandafter{\romannumeral-`0#1}}% +\newcommand\factorize [1]{\xintiiifOne{#1}{ 1}{\factors@a #1.{#1};}}% +\def\factors@a #1.{\xintiiifOdd{#1} + {\factors@c 3.#1.}% + {\expandafter\factors@b \expandafter1\expandafter.\romannumeral0\xinthalf{#1}.}}% +\def\factors@b #1.#2.{\xintiiifOne{#2} + {\factors@end {2, #1}}% + {\xintiiifOdd{#2}{\factors@c 3.#2.{2, #1}}% + {\expandafter\factors@b \the\numexpr #1+\@ne\expandafter.% + \romannumeral0\xinthalf{#2}.}}% +}% +\def\factors@c #1.#2.{% + \expandafter\factors@d\romannumeral0\xintiidivision {#2}{#1}{#1}{#2}% +}% +\def\factors@d #1#2#3#4{\xintiiifNotZero{#2} + {\xintiiifGt{#3}{#1} + {\factors@end {#4, 1}}% ultimate quotient is a prime with power 1 + {\expandafter\factors@c\the\numexpr #3+\tw@.#4.}}% + {\factors@e 1.#3.#1.}% +}% +\def\factors@e #1.#2.#3.{\xintiiifOne{#3} + {\factors@end {#2, #1}}% + {\expandafter\factors@f\romannumeral0\xintiidivision {#3}{#2}{#1}{#2}{#3}}% +}% +\def\factors@f #1#2#3#4#5{\xintiiifNotZero{#2} + {\expandafter\factors@c\the\numexpr #4+\tw@.#5.{#4, #3}}% + {\expandafter\factors@e\the\numexpr #3+\@ne.#4.#1.}% +}% +\def\factors@end #1;{\xintlistwithsep{, }{\xintRevWithBraces {#1}}}% +\makeatother +\end{everbatim} + +The macro |\Factorize| puts a little stress on the input save stack in order +not be bothered with previously gathered things. I timed it to be about eight +times faster than |\Factors| in test cases such as +|16246355912554185673266068721806243461403654781833| and others. Among the +various things explaining the speed-up, there is fact that we step by +increments of two, not one, and also that we divide only once, obtaining +quotient and remainder in one go. These two things already make for a speed-up +factor of about four. Thus, our earlier |\Factors| was not completely +inefficient, and was quite easier to come up with than |\Factorize|. + +If we only considered small integers, we could write pure |\numexpr| methods +which would be very much faster (especially if we had a table of small primes +prepared first) but still ridiculously slow compared to any non expandable +implementation, not to mention use of programming languages directly accessing +the CPU registers\dots +\end{itemize} + +%\phantomsection +\phantomsection\label{sec:expr11coords} + +To conclude with this overview of the new features in \xintexprname |1.1|, I +will mention {\bfseries |\xintthecoords|} which converts a comma separated +list as produced by |\xintfloatexpr| or |\xintiexpr [d]| to the format +expected by the |TikZ| |coordinates| syntax. +\begin{everbatim*} +{\centering\begin{tikzpicture}[scale=10]\xintDigits:=8; + \clip (-1.1,-.25) rectangle (.3,.25); + \draw [blue] (-1.1,0)--(1,0); + \draw [blue] (0,-1)--(0,+1); + \draw [red] plot[smooth] coordinates {\xintthecoords + % converts into (x1, y1) (x2, y2)... format + \xintfloatexpr seq((x^2-1,mul(x-t,t=-1+[0..4]/2)),x=-1.2..[0.1]..+1.2) \relax }; +\end{tikzpicture}\par } +\end{everbatim*} + +% Notice: if x goes no take exactly value 1 or -1, the origin appears slightly +% off the curve, not MY fault!!! + +\csbxint{thecoords} should be followed immediately by \csbxint{floatexpr} or +\csbxint{iexpr} or \csbxint{iiexpr}, but not |\xintthefloatexpr|, etc\dots + +Besides, as |TikZ| will not understand the |A/B[N]| format which is used on +output by |\xintexpr|, |\xintexpr| is not really usable with |\xintthecoords| +for a |TikZ| picture, but one may use it on its own, and the reason for the +spaces in and between coordinate pairs is to allow if necessary to print on +the page for examination with about correct line-breaks. + +\begin{everbatim*} +\edef\x{\xintthecoords \xintexpr rrseq(1/2,1/3; @1+@2, x=1..20)\relax } +\meaning\x +++ +\end{everbatim*} \subsection{The syntax}\label{ssec:syntax} @@ -10001,12 +10227,13 @@ two |t|'s. |\xintexpr|-essions and |\xinttheexpr|-essions are completely expandable, in two steps. \begin{itemize}[parsep=0pt, labelwidth=\leftmarginii, - itemindent=\leftmarginii, leftmargin=0em] + 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. + output each comma will be followed by a space. A decimal number must have + digits either before or after the decimal mark.\MyMarginNote{Changed!} \item as everything gets expanded, the characters |.|, |+|, |-|, |*|, |/|, |^|, |!|, |&|, \verb+|+, |?|, |:|, |<|, |>|, |=|, |(|, |)|, |"|, |]|, |[|, |@| @@ -10031,7 +10258,8 @@ two |t|'s. \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). + post-fix operator which does the factorial. In \csbxint{floatexpr} it is + mapped to \csbxint{FloatFac}, else it computes the exact factorial. \item The |?| may serve either as a function (the truth value) requiring an argument within parentheses), or as two-way post-fix branching operator @@ -10264,10 +10492,10 @@ operators and functions. |?| and |!| (as prefix) require parentheses around their arguments. \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} + \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} |quo|, |rem|, |even|, |odd|, |gcd| and |lcm| will first truncate their arguments to integers; the latter two require package \xintgcdname; @@ -10275,8 +10503,11 @@ operators and functions. |`*`|, |max| and |min| are functions with arbitrarily many comma separated arguments. - |bool| and |togl| use delimited macros to fetch their argument whose - closing parenthesis thus must be explicit, not arising from expansion. + |bool|, |togl| use delimited macros to fetch their argument and the + closing parenthesis which thus must be explicit, not arising from + expansion. + + The same holds for |qint|, |qfrac|, |qfloat|.\NewWith{1.2} Similarly |add|, |mul|, |subs|, |seq|, |rseq|, |rrseq|, |iter| use at some stages delimited macros. They work with \emph{dummy variables}, @@ -10298,11 +10529,34 @@ operators and functions. \item[functions with a single (numeric) argument] \noindent\par \begin{description} - \item[num] truncates to the nearest integer (truncation towards zero) + \item[num] truncates to the nearest integer (truncation towards zero). \begin{everbatim*} \xinttheexpr num(3.1415^20)\relax \end{everbatim*} + \item[qint] skips the token by token parsing of the input. The ending + parenthesis must be physically present rather than arising from + expansion.\NewWith{1.2} The |q| stands for ``quick''. This ``function'' + handles the input exactly like do the |i| macros of \xintcorename, via + \csbxint{iNum}. Hence leading signs and the leading zeroes (coming next) + will be handled appropriately but spaces will not be systematically + stripped. They should cause no harm and will be removed as soon as the + number is used with one of the basic operators. This input form \emph{does + not accept decimal part or scientific part}. +\begin{everbatim} +\def\x{....many many many ... digits}\def\y{....also many many many digits...} +\xinttheiiexpr qint(\x)*qint(\y)+qint(\y)^2\relax +\end{everbatim} + + \item[qfrac] does the same as \dtt{qint} excepts that it accepts fractions, + decimal numbers, scientific numbers as they are understood by the macros of + package\NewWith{1.2} \xintfracname. Not to be used within an + |\xintiiexpr|-ession, except if hidden inside functions such as + \dtt{round} or \dtt{trunc} which produce integers from fractions. + + \item[qfloat] does the same as \dtt{qfrac} and converts to a float with the + precision given by the setting of |\xintDigits|. + \item[reduce] reduces a fraction to smallest terms \begin{everbatim*} \xinttheexpr reduce(50!/20!/20!/10!)\relax @@ -10567,7 +10821,6 @@ Refer to \autoref{sec:expr11} for more examples. \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|. \item[{\color[named]{DarkOrchid}?}] is used as |(cond)?{yes}{no}|. It evaluates the (numerical) condition (any non-zero value counts as @@ -10610,13 +10863,16 @@ Refer to \autoref{sec:expr11} for more examples. optional and unique component of a being formed number. One can do things such as % - \leftedline{\restoreMicroFont|\xinttheexpr .^2+2^.\relax|} + \leftedline{\restoreMicroFont|\xinttheexpr 0.^2+2^.0\relax|} % - which is |0^2+2^0| and produces \dtt{\xinttheexpr .^2+2^.\relax}. + which is |0^2+2^0| and produces \dtt{\xinttheexpr 0.^2+2^.0\relax}. + + However a single dot |"."| as in |\xinttheexpr .^2\relax| is now illegal + input.\MyMarginNote{Changed!} \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. + 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 @@ -10726,22 +10982,39 @@ one obtains as output \xinttheexpr 2^3,3^4,5^6\relax{}. dimexpr} expressions, count and dimension registers and variables} \label{ssec:countinexpr} -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. - -\LaTeX{} lengths are skip control sequences and \LaTeX{} counters should be -inserted using |\value|. +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*} -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. +Control sequences however (such as |\parindent|) are picked up as a whole by +|\xintexpr|, and the numbers they define cannot be extended extra digits, a +syntax error is raised if the parser finds digits rather than a legal +operation after such a control sequence. A token list variable must be prefixed by |\the|, it will not be unpacked automatically (the parser will actually try |\number|, and thus fail). Do not @@ -10750,17 +11023,8 @@ 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|. -% 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}. +see also \autoref{sec:Dimensions}. \subsection{Catcodes and spaces} @@ -10801,10 +11065,15 @@ The characters |+|, |-|, |*|, |/|, |^|, |!|, |&|, \verb+|+, |?|, |:|, |<|, |>|, in the expression, as everything is expanded along the way. If one of them is active, it should be prefixed with |\string|. -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. +The exclamation mark should have its standard catcode, because it is used for +internal purposes with a different one. + +% 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. 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''. @@ -11010,7 +11279,7 @@ And this works: \item \FA{1}{3}{90}{-40}{-15} \item \FA{1.234}{-0.123}{-10}{3}{7} \end{itemize} -\oodef\test {\FA {0}{10}{100}{3}{6}}\meaning\test +++ +\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 @@ -11157,30 +11426,34 @@ 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 |/| 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}. +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{}, -but \xinttheiiexpr 5/3, round(protect(5/3),3), trunc(protect(5/3),3), floor(protect(5/3)), -ceil(protect(5/3))\relax{} works! -\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. +\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. -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! +\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*} @@ -11193,8 +11466,8 @@ 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, +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 @@ -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{} bound. The initial term \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{} bound. The initial term \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 |f<x<g| or |f>x>g| +two given fractions |f| and |g|. Notice that any real number |f<x<g| or |f>x>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 <multiple times> -% 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 <multiple times> 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<space>\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.| @@ -15160,17 +15526,24 @@ $1$ or $-1$. % % \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. +% 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} % -% 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. +% 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} % @@ -15229,246 +15602,278 @@ $1$ or $-1$. % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintcore}% - [2015/09/12 v1.1c Expandable arithmetic on big integers (jfB)]% + [2015/10/10 v1.2 Expandable arithmetic on big integers (jfB)]% % \end{macrocode} -% \subsection{More token management, constants} +% \subsection{Counts for holding needed constants} % \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 +\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} -% \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 {}<le truc à renverser>\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{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). +% +% Note (10/2015): I should take time to revisit this.| % \begin{macrocode} -\def\XINT_RQ #1#2#3#4#5#6#7#8#9% +\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_gob_til_R #9\XINT_RQ_end_a\R\XINT_RQ {#9#8#7#6#5#4#3#2#1}% + \XINT_num_loop #1\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\Z }% -\def\XINT_RQ_end_a\R\XINT_RQ #1#2\Z +\def\XINT_num_loop #1#2#3#4#5#6#7#8% {% - \XINT_RQ_end_b #1\Z + \xint_gob_til_xint_relax #8\XINT_num_end\xint_relax + \XINT_num_NumEight #1#2#3#4#5#6#7#8% }% -\def\XINT_RQ_end_b #1#2#3#4#5#6#7#8% +\edef\XINT_num_end\xint_relax\XINT_num_NumEight #1\xint_relax #2\Z {% - \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% + \noexpand\expandafter\space\noexpand\the\numexpr #1+\xint_c_\relax }% -\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}% +\def\XINT_num_NumEight #1#2#3#4#5#6#7#8% +{% + \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_num_keepsign_a #1% +{% + \xint_gob_til_one#1\XINT_num_gobacktoloop 1\XINT_num_keepsign_b +}% +\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{XINT_OQ}} +% \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_OQ #1#2#3#4#5#6#7#8#9% +\edef\XINT_cuz_small #1#2#3#4#5#6#7#8% {% - \xint_gob_til_R #9\XINT_OQ_end_a\R\XINT_OQ {#9#8#7#6#5#4#3#2#1}% + \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5#6#7#8\relax }% -\def\XINT_OQ_end_a\R\XINT_OQ #1#2\Z +%%%%%%%%%%%% +\def\XINT_cuz #1#2#3#4#5#6#7#8#9% {% - \XINT_OQ_end_b #1\Z + \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_OQ_end_b #1#2#3#4#5#6#7#8% +\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_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% + \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_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}% +\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{\csh{XINT_SQ}} +% \subsection{Blocks of eight digits} +% \lverb|Lingua of release 1.2.| % \begin{macrocode} -\def\XINT_SQ #1#2#3#4#5#6#7#8% +\def\XINT_zeroes_forviii #1#2#3#4#5#6#7#8% {% - \xint_gob_til_R #8\XINT_SQ_end_a\R\XINT_SQ {#8#7#6#5#4#3#2#1}% + \xint_gob_til_R #8\XINT_zeroes_forviii_end\R\XINT_zeroes_forviii }% -\def\XINT_SQ_end_a\R\XINT_SQ #1#2\Z +\edef\XINT_zeroes_forviii_end\R\XINT_zeroes_forviii #1#2#3#4#5#6#7#8#9\W {% - \XINT_SQ_end_b #1\Z + \noexpand\expandafter\space\noexpand\xint_gob_til_one #2#3#4#5#6#7#8% }% -\def\XINT_SQ_end_b #1#2#3#4#5#6#7% +%%%%%%%%%%%% +\def\XINT_rsepbyviii #1#2#3#4#5#6#7#8% {% - \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% + \XINT_rsepbyviii_b {#1#2#3#4#5#6#7#8}% +}% +\def\XINT_rsepbyviii_b #1#2#3#4#5#6#7#8#9% {% - \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4\relax + #2#3#4#5#6#7#8#9\expandafter!\the\numexpr + 1#1\expandafter.\the\numexpr 1\XINT_rsepbyviii }% -\def\xint_cleanupzeros_nostop #1#2#3#4% +\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 {% - \the\numexpr #1#2#3#4\relax + \expandafter\XINT_sepandrev_a\the\numexpr 1\XINT_rsepbyviii }% -\def\XINT_rev_andcuz #1% +\def\XINT_sepandrev_a {\XINT_sepandrev_b {}}% +\def\XINT_sepandrev_b #1#2.#3.#4.#5.#6.#7.#8.#9.% {% - \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 + \xint_gob_til_R #9\XINT_sepandrev_end\R + \XINT_sepandrev_b {#9!#8!#7!#6!#5!#4!#3!#2!#1}% +}% +\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_sepandrev_andcount_a\the\numexpr 1\XINT_rsepbyviii +}% +\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_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_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} -% \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{Blocks of eight, for needs of v1.2 \csh{xintiiDivision}.} % \begin{macrocode} -\def\XINT_cuz #1% +\def\XINT_sepbyviii_andcount {% - \XINT_cuz_loop #1\W\W\W\W\W\W\W\Z% + \expandafter\XINT_sepbyviii_andcount_a\the\numexpr\XINT_sepbyviii }% -\def\XINT_cuz_loop #1#2#3#4#5#6#7#8% +\def\XINT_sepbyviii #1#2#3#4#5#6#7#8% {% - \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}% + 1#1#2#3#4#5#6#7#8\expandafter!\the\numexpr\XINT_sepbyviii }% -\def\xint_cuz_end_a #1\XINT_cuz_check_a #2% +\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_cuz_end_b #2% + #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.% }% -\edef\xint_cuz_end_b #1#2#3#4#5\Z +\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!% {% - \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4\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_cuz_end_A \Z\XINT_cuz_check_a #1{ 0}% -\def\XINT_cuz_check_a #1% +\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% {% - \expandafter\XINT_cuz_check_b\the\numexpr #1\relax + 1#1#2#3#4#5#6#7#8\expandafter!\the\numexpr\XINT_sepbyviii_Z }% -\def\XINT_cuz_check_b #1% +\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_zero #1\xint_cuz_backtoloop 0\XINT_cuz_stop #1% + \xint_gob_til_R #9\XINT_unsep_cuzsmall_end\R + \XINT_unsep_cuzsmall {#1#2#3#4#5#6#7#8#9}% }% -\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). -% -% Note (22/06/14): \xintiNum jamais utilisé sous ce nom, le supprimer? -% \XINT_num maintenant utilisé par le parseur de xintexpr.| -% \begin{macrocode} -\def\xintiNum {\romannumeral0\xintinum }% -\def\xintinum #1% +\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_num_loop - \romannumeral-`0#1\xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_relax\Z + \xint_gob_til_R #9\XINT_div_unsepQ_end\R + \XINT_div_unsepQ {#1#2#3#4#5#6#7#8#9}% }% -\let\xintNum\xintiNum \let\xintnum\xintinum -\def\XINT_num #1% +\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_num_loop #1\xint_relax\xint_relax\xint_relax\xint_relax - \xint_relax\xint_relax\xint_relax\xint_relax\Z + \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_num_loop #1#2#3#4#5#6#7#8% +\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!% {% - \xint_gob_til_xint_relax #8\XINT_num_end\xint_relax - \XINT_num_NumEight #1#2#3#4#5#6#7#8% + \xint_gob_til_R #9\XINT_div_unsepR_end\R + \XINT_div_unsepR {#1#2#3#4#5#6#7#8#9}% }% -\edef\XINT_num_end\xint_relax\XINT_num_NumEight #1\xint_relax #2\Z +\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!% {% - \noexpand\expandafter\space\noexpand\the\numexpr #1+\xint_c_\relax + \xint_gob_til_R #9\XINT_unrevbyviii_a\R + \XINT_unrevbyviii {#9#8#7#6#5#4#3#2#1}% }% -\def\XINT_num_NumEight #1#2#3#4#5#6#7#8% +\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% {% - \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 + \expandafter\XINT_cuz_small\xint_gob_til_Z #8#7#6#5#4#3#2#1% }% -\def\XINT_num_keepsign_a #1% +% \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_gob_til_one#1\XINT_num_gobacktoloop 1\XINT_num_keepsign_b + 1#8#7#6#5#4#3#2#1\expandafter!\the\numexpr\XINT_microrevsep }% -\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}% +\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_UDsignfork + #1{\expandafter\xint_minus_thenstop\romannumeral0\XINT_reversedigits_a}% + -{\XINT_reversedigits_a #1}% + \krof +}% +\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_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_R #9\XINT_revdigits_end\R + \XINT_revdigits_b {#9#8#7#6#5#4#3#2#1}% +}% +\edef\XINT_revdigits_end\R\XINT_revdigits_b #1#2\W + {\noexpand\expandafter\space\noexpand\xint_gob_til_Z #1}% % \end{macrocode} % \subsection{\csh{xintSgn}, \csh{xintiiSgn}, \csh{XINT_Sgn}, \csh{XINT_cntSgn}} % \lverb|& @@ -15510,13 +15915,12 @@ $1$ or $-1$. {% \xint_UDzerominusfork #1-\xint_c_ - 0#1\m@ne % I will not allocate a count only for -1? + 0#1\xint_c_mone 0-\xint_c_i \krof }% % \end{macrocode} -% \subsection{\csh{xintiOpp}} -% \lverb|\xintnum added in 1.09a| +% \subsection{\csh{xintiOpp}, \csh{xintiiOpp}} % \begin{macrocode} \def\xintiiOpp {\romannumeral0\xintiiopp }% \def\xintiiopp #1% @@ -15528,7 +15932,6 @@ $1$ or $-1$. {% \expandafter\XINT_opp \romannumeral0\xintnum{#1}% }% -\let\xintOpp\xintiOpp \let\xintopp\xintiopp \def\XINT_Opp #1{\romannumeral0\XINT_opp #1}% \def\XINT_opp #1% {% @@ -15556,7 +15959,6 @@ $1$ or $-1$. {% \expandafter\XINT_abs \romannumeral0\xintnum{#1}% }% -\let\xintAbs\xintiAbs \let\xintabs\xintiabs \def\XINT_Abs #1{\romannumeral0\XINT_abs #1}% \def\XINT_abs #1% {% @@ -15600,33 +16002,34 @@ $1$ or $-1$. % 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| +% 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% {% - \expandafter\XINT_ldg\expandafter {\romannumeral-`0#1}% -}% -\def\xintLDg {\romannumeral0\xintldg }% -\def\xintldg #1% -{% - \expandafter\XINT_ldg\expandafter {\romannumeral0\xintnum{#1}}% -}% -\def\XINT_LDg #1{\romannumeral0\XINT_ldg {#1}}% -\def\XINT_ldg #1% -{% - \expandafter\XINT_ldg_\romannumeral0\xintreverseorder {#1}\Z + \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_ldg_ #1#2\Z{ #1}% +\def\XINT_ldg_done #1#2\Z { #1}% % \end{macrocode} % \subsection{\csh{xintDouble}} -% \lverb|v1.08| +% \lverb|v1.08. Rewritten for v1.2.| % \begin{macrocode} \def\xintDouble {\romannumeral0\xintdouble }% \def\xintdouble #1% {% - \expandafter\XINT_dbl\romannumeral-`0#1% - \R\R\R\R\R\R\R\Z \W\W\W\W\W\W\W + \expandafter\XINT_dbl\romannumeral-`0#1\Z }% \def\XINT_dbl #1% {% @@ -15636,44 +16039,31 @@ $1$ or $-1$. 0-{\XINT_dbl_pos #1}% \krof }% -\def\XINT_dbl_zero #1\Z \W\W\W\W\W\W\W { 0}% +\def\XINT_dbl_zero #1\Z { 0}% \def\XINT_dbl_neg {\expandafter\xint_minus_thenstop\romannumeral0\XINT_dbl_pos }% -\def\XINT_dbl_pos -{% - \expandafter\XINT_dbl_a \expandafter{\expandafter}\expandafter 0% - \romannumeral0\XINT_SQ {}% -}% -\def\XINT_dbl_a #1#2#3#4#5#6#7#8#9% -{% - \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}% -}% -\def\XINT_dbl_b 1#1#2#3#4#5#6#7#8#9% +\def\XINT_dbl_pos #1\Z {% - \XINT_dbl_a {#2#3#4#5#6#7#8#9}{#1}% + \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_dbl_end_a #1+#2+#3\relax #4% +\def\XINT_dbl_pos_aa {% - \expandafter\XINT_dbl_end_b #2#4% -}% -\edef\XINT_dbl_end_b #1#2#3#4#5#6#7#8% -{% - \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5#6#7#8\relax + \expandafter\XINT_mul_out\the\numexpr\XINT_verysmallmul 0.2!% }% % \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.| +% \lverb|v1.08. Rewritten for v1.2.| % \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 + \expandafter\XINT_half\romannumeral-`0#1\Z }% \def\XINT_half #1% {% @@ -15683,52 +16073,38 @@ $1$ or $-1$. 0-{\XINT_half_pos #1}% \krof }% -\def\XINT_half_zero #1\Z \W\W\W\W\W\W\W { 0}% +\def\XINT_half_zero #1\Z { 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% -{% - \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% -}% -\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 -{% - \noexpand\expandafter\space - \noexpand\the\numexpr (#1#2#3#4#5#6#7+\xint_c_i)/\xint_c_ii-\xint_c_i \relax -}% -\def\XINT_half_b 1#1#2#3#4#5#6#7#8% -{% - \XINT_half_c {#2#3#4#5#6#7}{#1}% -}% -\def\XINT_half_c #1#2#3#4#5#6#7#8#9% -{% - \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}% -}% -\def\XINT_half_d 1#1#2#3#4#5#6#7#8#9% +\def\XINT_half_pos #1\Z {% - \XINT_half_c {#2#3#4#5#6#7#8#9}{#1}% + \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_half_end_a #1\W #2\relax #3% +\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_gob_til_zero #1\XINT_half_end_b 0\space #1#3% + \xint_gob_til_Z #9\XINT_half_small \Z + \XINT_mul_out 1#1#2#3#4#5#6#7!1#9% }% -\edef\XINT_half_end_b 0\space 0#1#2#3#4#5#6#7% +\edef\XINT_half_small \Z\XINT_mul_out 1#1!#2\W {% - \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5#6#7\relax + \noexpand\expandafter\space\noexpand\the\numexpr #1\relax }% % \end{macrocode} % \subsection{\csh{xintDec}} -% \lverb!v1.08! +% \lverb|v1.08. Rewritten for v1.2.| % \begin{macrocode} \def\xintDec {\romannumeral0\xintdec }% \def\xintdec #1% {% - \expandafter\XINT_dec\romannumeral-`0#1% - \R\R\R\R\R\R\R\R\Z \W\W\W\W\W\W\W\W + \expandafter\XINT_dec\romannumeral-`0#1\Z }% \def\XINT_dec #1% {% @@ -15738,47 +16114,28 @@ $1$ or $-1$. 0-{\XINT_dec_pos #1}% \krof }% -\def\XINT_dec_zero #1\W\W\W\W\W\W\W\W { -1}% +\def\XINT_dec_zero #1\Z { -1}% \def\XINT_dec_neg {\expandafter\xint_minus_thenstop\romannumeral0\XINT_inc_pos }% -\def\XINT_dec_pos -{% - \expandafter\XINT_dec_a \expandafter{\expandafter}% - \romannumeral0\XINT_OQ {}% -}% -\def\XINT_dec_a #1#2#3#4#5#6#7#8#9% +\def\XINT_dec_pos #1\Z {% - \expandafter\XINT_dec_b - \the\numexpr 11#9#8#7#6#5#4#3#2-\xint_c_i\relax {#1}% -}% -\def\XINT_dec_b 1#1% -{% - \xint_gob_til_one #1\XINT_dec_A 1\XINT_dec_c -}% -\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 -{% - \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% + \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 }% -\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 }% +\def\XINT_dec_pos_aa {\XINT_sub_aa 100000001!\Z!\Z!\Z!\Z!\Z!\W }% % \end{macrocode} % \subsection{\csh{xintInc}} -% \lverb!v1.08! +% \lverb!v1.08. Rewritten for v1.2.! % \begin{macrocode} \def\xintInc {\romannumeral0\xintinc }% \def\xintinc #1% {% - \expandafter\XINT_inc\romannumeral-`0#1% - \R\R\R\R\R\R\R\R\Z \W\W\W\W\W\W\W\W + \expandafter\XINT_inc\romannumeral-`0#1\Z }% \def\XINT_inc #1% {% @@ -15788,520 +16145,231 @@ $1$ or $-1$. 0-{\XINT_inc_pos #1}% \krof }% -\def\XINT_inc_zero #1\W\W\W\W\W\W\W\W { 1}% +\def\XINT_inc_zero #1\Z { 1}% \def\XINT_inc_neg {\expandafter\XINT_opp\romannumeral0\XINT_dec_pos }% -\def\XINT_inc_pos -{% - \expandafter\XINT_inc_a \expandafter{\expandafter}% - \romannumeral0\XINT_OQ {}% -}% -\def\XINT_inc_a #1#2#3#4#5#6#7#8#9% -{% - \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_inc_b 1#1% -{% - \xint_gob_til_zero #1\XINT_inc_A 0\XINT_inc_c -}% -\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}% -% \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. -% -% Addition and multiplication each have multiple implementations corresponding -% to slightly differing formats on input and on output.| -% -% \subsubsection{Addition vI: \csh{XINT_add_A}} -% \lverb|& -% INPUT:$\ -% \romannumeral0\XINT_add_A 0{}<N1>\W\X\Y\Z <N2>\W\X\Y\Z$\ -% 1. <N1> et <N2> 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. -% -% OUTPUT: la somme <N1>+<N2>, ordre normal, plus sur 4n, pas de leading zeros -% La procédure est plus rapide lorsque <N1> 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}% -}% -% \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| -% \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 -}% -% \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| -% \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}% -% \end{macrocode} -% \subsubsection{Addition vII: \csh{XINT_addr_A}} -% \lverb|& -% INPUT: \romannumeral0\XINT_addr_A 0{}<N1>\W\X\Y\Z <N2>\W\X\Y\Z -% -% 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. <N1> et <N2> 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 <N1>+<N2>, *aussi renversée* et *sur 4n*| -% \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% -{% - \XINT_addr_A #2{#7#6#5#4#3}% -}% -\def\xint_addr_bz\W\XINT_addr_E #1#2#3#4#5#6% -{% - \expandafter\XINT_addr_CC\the\numexpr #1+10#5#4#3#2\relax -}% -\def\XINT_addr_CC #1#2#3#4#5#6#7% -{% - \XINT_addr_AC_checkcarry #2{#7#6#5#4#3}% -}% -\def\XINT_addr_AC_checkcarry #1% -{% - \xint_gob_til_zero #1\xint_addr_AC_nocarry 0\XINT_addr_C -}% -\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% -{% - \xint_gob_til_W #2\xint_addr_cz\W - \XINT_addr_D {#5#4#3#2}{#1}% -}% -\def\XINT_addr_D #1% -{% - \expandafter\XINT_addr_CC\the\numexpr 1+10#1\relax -}% -\def\xint_addr_cz\W\XINT_addr_D #1#2{ #21000}% -% \end{macrocode} -% \subsubsection{Addition vIII: \csh{XINT_addm_A}} -% \lverb|& -% INPUT:\romannumeral0\XINT_addm_A 0{}<N1>\W\X\Y\Z <N2>\W\X\Y\Z$\ -% 1. <N1> et <N2> renversés$\ -% 2. <N1> de longueur 4n ; <N2> non$\ -% 3. <N2> est *garanti au moins aussi long* que <N1>$\ -% OUTPUT: la somme <N1>+<N2>, ordre normal, pas sur 4n, leading zeros retirés. -% Utilisé par la multiplication.| -% \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_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_addm_CD #1% -{% - \expandafter\XINT_addm_CC\the\numexpr 1+10#1.% -}% -\def\XINT_addm_CC #1#2#3.#4% -{% - \XINT_addm_AC_checkcarry #2{#3#4}% -}% -\def\xint_addm_cw - #1\xint_addm_cx - #2\xint_addm_cy - #3\xint_addm_cz - \W\XINT_addm_CD -{% - \expandafter\XINT_addm_CDw\the\numexpr 1+#1#2#3.% -}% -\def\XINT_addm_CDw #1.#2#3\X\Y\Z -{% - \XINT_addm_end #1#3% -}% -\def\xint_addm_cx - #1\xint_addm_cy - #2\xint_addm_cz - \W\XINT_addm_CD -{% - \expandafter\XINT_addm_CDx\the\numexpr 1+#1#2.% -}% -\def\XINT_addm_CDx #1.#2#3\Y\Z -{% - \XINT_addm_end #1#3% -}% -\def\xint_addm_cy - #1\xint_addm_cz - \W\XINT_addm_CD -{% - \expandafter\XINT_addm_CDy\the\numexpr 1+#1.% -}% -\def\XINT_addm_CDy #1.#2#3\Z -{% - \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} -% \subsubsection{Addition vIV: \csh{XINT_addp_A}} -% \lverb|& -% INPUT: -% \romannumeral0\XINT_addp_A 0{}<N1>\W\X\Y\Z <N2>\W\X\Y\Z$\ -% 1. <N1> et <N2> renversés$\ -% 2. <N1> de longueur 4n ; <N2> non$\ -% 3. <N2> est *garanti au moins aussi long* que <N1>$\ -% OUTPUT: la somme <N1>+<N2>, 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.| +\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\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% +\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_addp_AC_checkcarry #1% + \expandafter\XINT_add_nfork\expandafter #1\romannumeral-`0#3\Z #2\Z }% -\def\XINT_addp_AC_checkcarry #1% +\def\XINT_iadd #1#2\Z #3% {% - \xint_gob_til_zero #1\xint_addp_AC_nocarry 0\XINT_addp_C + \expandafter\XINT_add_nfork\expandafter #1\romannumeral0\xintnum{#3}\Z #2\Z }% -\def\xint_addp_AC_nocarry 0\XINT_addp_C +\def\XINT_add_fork #1#2\Z #3\Z {\XINT_add_nfork #1#3\Z #2\Z}% +\def\XINT_add_nfork #1#2% {% - \XINT_addp_F -}% -\def\XINT_addp_AB #1#2#3#4\W\X\Y\Z #5#6#7#8% -{% - \XINT_addp_ABE #1#2{#8#7#6#5}{#3}#4\W\X\Y\Z + \xint_UDzerofork + #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_addp_ABE #1#2#3#4#5#6% -{% - \expandafter\XINT_addp_ABEA\the\numexpr #1+10#5#4#3#2+#6\relax +\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_addp_ABEA #1#2#3#4#5#6#7% +\def\XINT_add_exchange #1.#2.#3\Z!\Z!\Z!\Z!\Z!\W #4\Z {% - \XINT_addp_A #2{#7#6#5#4#3}%<-- attention on met donc \`a droite + \XINT_add_A #2.#1.#4\Z!\Z!\Z!\Z!\Z!\W #3\Z }% -\def\XINT_addp_C #1#2#3#4#5% +\def\XINT_add_A #1.#2.% {% - \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}% + \ifnum #1>\xint_c_vi % + \expandafter\XINT_add_aa + \else \expandafter\XINT_add_aa_small + \fi }% -\def\XINT_addp_CD #1% +%%%%%%%%%%%% +\def\XINT_add_out #1\Z #2\W% {% - \expandafter\XINT_addp_CC\the\numexpr 1+10#1\relax + \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_addp_CC #1#2#3#4#5#6#7% +\def\XINT_add_out_small #1\Z #2\W% {% - \XINT_addp_AC_checkcarry #2{#7#6#5#4#3}% + \XINT_smallunrevbyviii #11\Z!1\R!1\R!1\R!1\R!1\R!1\R!\W }% -\def\xint_addp_cw - #1\xint_addp_cx - #2\xint_addp_cy - #3\xint_addp_cz - \W\XINT_addp_CD +%%%%%%%%%%%% +\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_addp_CDw\the\numexpr \xint_c_i+10#1#2#3\relax + \XINT_add_b #1!#6!#2!#7!#3!#8!#4!#9!#5\W }% -\def\XINT_addp_CDw #1#2#3#4#5#6% +\def\XINT_add_b #1#2!#3!% {% - \xint_gob_til_zeros_iv #2#3#4#5\XINT_addp_endDw_zeros - 0000\XINT_addp_endDw #2#3#4#5% + \xint_gob_til_Z #2\XINT_add_bi \Z + \expandafter\XINT_add_c\the\numexpr#1+#2+#3-\xint_c_ii.% }% -\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_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_addp_CDx\the\numexpr \xint_c_i+100#1#2\relax + \XINT_add_k #1#3!#5!#7!#9!% }% -\def\XINT_addp_CDx #1#2#3#4#5#6% +\def\XINT_add_c #1#2.% {% - \xint_gob_til_zeros_iv #2#3#4#5\XINT_addp_endDx_zeros - 0000\XINT_addp_endDx #2#3#4#5% + 1#2\expandafter!\the\numexpr\XINT_add_d #1% }% -\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_add_d #1#2!#3!% {% - \expandafter\XINT_addp_CDy\the\numexpr \xint_c_i+1000#1\relax + \xint_gob_til_Z #2\XINT_add_di \Z + \expandafter\XINT_add_e\the\numexpr#1+#2+#3-\xint_c_ii.% }% -\def\XINT_addp_CDy #1#2#3#4#5#6% +\def\XINT_add_di\Z\expandafter\XINT_add_e + \the\numexpr#1+#2+#3-\xint_c_ii.#4!#5!#6!#7!#8\W {% - \xint_gob_til_zeros_iv #2#3#4#5\XINT_addp_endDy_zeros - 0000\XINT_addp_endDy #2#3#4#5% + \XINT_add_k #1#3!#5!#7!% }% -\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% +\def\XINT_add_e #1#2.% {% - \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}% + 1#2\expandafter!\the\numexpr\XINT_add_f #1% }% -\def\XINT_addp_G #1#2% +\def\XINT_add_f #1#2!#3!% {% - \XINT_addp_F {#2#1}% + \xint_gob_til_Z #2\XINT_add_fi \Z + \expandafter\XINT_add_g\the\numexpr#1+#2+#3-\xint_c_ii.% }% -\def\xint_addp_Gw - #1\xint_addp_Gx - #2\xint_addp_Gy - #3\xint_addp_Gz - \W\XINT_addp_G #4% +\def\XINT_add_fi\Z\expandafter\XINT_add_g + \the\numexpr#1+#2+#3-\xint_c_ii.#4!#5!#6\W {% - \xint_gob_til_zeros_iv #3#2#10\XINT_addp_endGw_zeros - 0000\XINT_addp_endGw #3#2#10% + \XINT_add_k #1#3!#5!% }% -\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% +\def\XINT_add_g #1#2.% {% - \xint_gob_til_zeros_iv #2#100\XINT_addp_endGx_zeros - 0000\XINT_addp_endGx #2#100% + 1#2\expandafter!\the\numexpr\XINT_add_h #1% }% -\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_add_h #1#2!#3!% {% - \xint_gob_til_zeros_iv #1000\XINT_addp_endGy_zeros - 0000\XINT_addp_endGy #1000% + \xint_gob_til_Z #2\XINT_add_hi \Z + \expandafter\XINT_add_i\the\numexpr#1+#2+#3-\xint_c_ii.% }% -\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}% -% \end{macrocode} -% \subsection{\csh{xintiAdd}, \csh{xintiiAdd}} -% \lverb|ADDITION -% [algo plus efficace lorsque le premier argument plus long que le second] -% -% Note (octobre 2014, pendant la préparation de la sortie de 1.1) -% -% 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.| -% \begin{macrocode} -\def\xintiiAdd {\romannumeral0\xintiiadd }% -\def\xintiiadd #1{\expandafter\xint_iiadd\romannumeral-`0#1\Z }% -\def\xint_iiadd #1#2\Z #3% +\def\XINT_add_hi\Z + \expandafter\XINT_add_i\the\numexpr#1+#2+#3-\xint_c_ii.#4\W {% - \expandafter\XINT_add_fork\expandafter #1\romannumeral-`0#3\Z #2\Z + \XINT_add_k #1#3!% }% -\def\xintiAdd {\romannumeral0\xintiadd }% -\def\xintiadd #1% +\def\XINT_add_i #1#2.% {% - \expandafter\xint_add\romannumeral0\xintnum{#1}\Z + 1#2\expandafter!\the\numexpr\XINT_add_a #1% }% -\def\xint_add #1#2\Z #3% +%%%%%%%%%%%% +\def\XINT_add_k #1% + {\if #12\expandafter\XINT_add_ke\else\expandafter\XINT_add_l \fi}% +\def\XINT_add_ke #1% {% - \expandafter\XINT_add_fork\expandafter #1\romannumeral0\xintnum{#3}\Z #2\Z + \xint_gob_til_Z #1\XINT_add_kf\Z 1% }% -\let\xintAdd\xintiAdd \let\xintadd\xintiadd -\def\XINT_add_fork #1#2% +\def\XINT_add_kf\Z 1{1}% +\def\XINT_add_l #1% {% - \xint_UDzerofork - #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% + \xint_gob_til_Z #1\XINT_add_lf\Z \XINT_add_m 1% }% -\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_add_lf\Z\XINT_add_m 1{100000001}% +\def\XINT_add_m #1!% {% - \expandafter\XINT_add_pre_b\expandafter - {\romannumeral0\XINT_RQ {}#1\R\R\R\R\R\R\R\R\Z }% + \expandafter\XINT_add_n\the\numexpr\xint_c_i+#1.% }% -\def\XINT_add_pre_b #1#2% +\def\XINT_add_n #1#2.% {% - \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 + 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} % \subsection{\csh{xintiSub}, \csh{xintiiSub}} -% \lverb|Release 1.09a has \xintnum added into \xintiSub.| +% \lverb|Entirely rewritten for v1.2.| % \begin{macrocode} \def\xintiiSub {\romannumeral0\xintiisub }% -\def\xintiisub #1{\expandafter\xint_iisub\romannumeral-`0#1\Z }% -\def\xint_iisub #1#2\Z #3% +\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 + \expandafter\XINT_sub_nfork\expandafter #1\romannumeral-`0#3\Z #2\Z }% -\def\xintiSub {\romannumeral0\xintisub }% -\def\xintisub #1% +\def\xintiSub {\romannumeral0\xintisub }% +\def\xintisub #1{\expandafter\XINT_isub\romannumeral0\xintnum{#1}\Z }% +\def\XINT_isub #1#2\Z #3% {% - \expandafter\xint_sub\romannumeral0\xintnum{#1}\Z + \expandafter\XINT_sub_nfork\expandafter #1\romannumeral0\xintnum{#3}\Z #2\Z }% -\def\xint_sub #1#2\Z #3% -{% - \expandafter\XINT_sub_fork\expandafter #1\romannumeral0\xintnum{#3}\Z #2\Z -}% -\let\xintSub\xintiSub \let\xintsub\xintisub -\def\XINT_sub_fork #1#2% +\def\XINT_sub_nfork #1#2% {% \xint_UDzerofork #1\XINT_sub_firstiszero @@ -16315,756 +16383,437 @@ $1$ or $-1$. --\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| -% \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% -{% - \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 -}% -% \end{macrocode} -% \lverb|& -% \romannumeral0\XINT_sub_A 1{}<N1>\W\X\Y\Z<N2>\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% -{% - \xint_gob_til_W - #4\xint_sub_az - \W\XINT_sub_B #1{#4#5#6#7}{#2}#3\W\X\Y\Z -}% -\def\XINT_sub_B #1#2#3#4#5#6#7% +\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.% {% - \xint_gob_til_W - #4\xint_sub_bz - \W\XINT_sub_onestep #1#2{#7#6#5#4}{#3}% -}% -% \end{macrocode} -% \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.| -% \begin{macrocode} -\def\XINT_sub_onestep #1#2#3#4#5#6% -{% - \expandafter\XINT_sub_backtoA\the\numexpr 11#5#4#3#2-#6+#1-\xint_c_i.% + \ifnum #2>#1 + \expandafter\XINT_sub_exchange + \else + \expandafter\XINT_sub_aa + \fi }% -% \end{macrocode} -% \lverb|ON PRODUIT LE RÉSULTAT DANS LE BON ORDRE| -% \begin{macrocode} -\def\XINT_sub_backtoA #1#2#3.#4% +\def\XINT_sub_exchange #1\Z!\Z!\Z!\Z!\Z!\W #2\Z {% - \XINT_sub_A #2{#3#4}% + \expandafter\XINT_opp\romannumeral0\XINT_sub_aa + #2\Z!\Z!\Z!\Z!\Z!\W #1\Z }% -\def\xint_sub_bz - \W\XINT_sub_onestep #1#2#3#4#5#6#7% +%%%%%%%%%%%% +\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 {% - \xint_UDzerofork - #1\XINT_sub_C % une retenue - 0\XINT_sub_D % pas de retenue - \krof - {#7}#2#3#4#5% + \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_sub_D #1#2\W\X\Y\Z +\def\XINT_sub_startrescue\expandafter\XINT_cuz_small + \romannumeral0\XINT_unrevbyviii #1#2\Z!#3\W {% - \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% + \expandafter\XINT_sub_rescue_finish + \the\numexpr\XINT_sub_rescue_a #2!% + 1\Z!1\R!1\R!1\R!1\R!1\R!1\R!1\R!1\R!\W \R }% -\def\XINT_sub_C #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_W - #2\xint_sub_cz - \W\XINT_sub_AC_onestep {#5#4#3#2}{#1}% + \expandafter\XINT_sub_rescue_c\the\numexpr \xint_c_xii_e_viii-#1.% }% -\def\XINT_sub_AC_onestep #1% +\def\XINT_sub_rescue_c 1#1#2.% {% - \expandafter\XINT_sub_backtoC\the\numexpr 11#1-\xint_c_i.% + 1#2\expandafter!\the\numexpr\XINT_sub_rescue_d #1% }% -\def\XINT_sub_backtoC #1#2#3.#4% +\def\XINT_sub_rescue_d #1#2#3!% {% - \XINT_sub_AC_checkcarry #2{#3#4}% la retenue va \^etre examin\'ee + \xint_gob_til_minus #2\XINT_sub_rescue_z -% + \expandafter\XINT_sub_rescue_c\the\numexpr \xint_c_xii_e_viii_mone-#2#3+#1.% }% -\def\XINT_sub_AC_checkcarry #1% +\def\XINT_sub_rescue_z #1.{1!}% +%%%%%%%%%%%% +\def\XINT_sub_a #1!#2!#3!#4!#5\W #6!#7!#8!#9!% {% - \xint_gob_til_one #1\xint_sub_AC_nocarry 1\XINT_sub_C + \XINT_sub_b #1!#6!#2!#7!#3!#8!#4!#9!#5\W }% -\def\xint_sub_AC_nocarry 1\XINT_sub_C #1#2\W\X\Y\Z +\def\XINT_sub_b #1#2#3!#4!% {% - \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_gob_til_Z #2\XINT_sub_bi \Z + \expandafter\XINT_sub_c\the\numexpr#1+1#4-#3-\xint_c_i.% }% -\def\xint_sub_cz\W\XINT_sub_AC_onestep #1% +\def\XINT_sub_c 1#1#2.% {% - \XINT_cuz + 1#2\expandafter!\the\numexpr\XINT_sub_d #1% }% -\def\xint_sub_az\W\XINT_sub_B #1#2#3#4#5#6#7% +\def\XINT_sub_d #1#2#3!#4!% {% - \xint_gob_til_W - #4\xint_sub_ez - \W\XINT_sub_Eenter #1{#3}#4#5#6#7% + \xint_gob_til_Z #2\XINT_sub_di \Z + \expandafter\XINT_sub_e\the\numexpr#1+1#4-#3-\xint_c_i.% }% -% \end{macrocode} -% \lverb|le premier nombre continue, le résultat sera < 0.| -% \begin{macrocode} -\def\XINT_sub_Eenter #1#2% +\def\XINT_sub_e 1#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% + 1#2\expandafter!\the\numexpr\XINT_sub_f #1% }% -\def\XINT_sub_E #1#2#3#4#5#6% +\def\XINT_sub_f #1#2#3!#4!% {% - \xint_gob_til_W #3\xint_sub_F\W - \XINT_sub_Eonestep #1{#6#5#4#3}{#2}% + \xint_gob_til_Z #2\XINT_sub_fi \Z + \expandafter\XINT_sub_g\the\numexpr#1+1#4-#3-\xint_c_i.% }% -\def\XINT_sub_Eonestep #1#2% +\def\XINT_sub_g 1#1#2.% {% - \expandafter\XINT_sub_backtoE\the\numexpr 109999-#2+#1.% + 1#2\expandafter!\the\numexpr\XINT_sub_h #1% }% -\def\XINT_sub_backtoE #1#2#3.#4% +\def\XINT_sub_h #1#2#3!#4!% {% - \XINT_sub_E #2{#3#4}% + \xint_gob_til_Z #2\XINT_sub_hi \Z + \expandafter\XINT_sub_i\the\numexpr#1+1#4-#3-\xint_c_i.% }% -\def\xint_sub_F\W\XINT_sub_Eonestep #1#2#3#4% +\def\XINT_sub_i 1#1#2.% {% - \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}% + 1#2\expandafter!\the\numexpr\XINT_sub_a #1% }% -\def\XINT_sub_DD {\expandafter\xint_minus_thenstop\romannumeral0\XINT_sub_D }% -\def\XINT_sub_Fdec #1#2#3#4#5#6% +\def\XINT_sub_bi\Z + \expandafter\XINT_sub_c\the\numexpr#1+1#2-#3.#4!#5!#6!#7!#8!#9!\Z !\W {% - \xint_gob_til_W #3\xint_sub_Fdec_finish\W - \XINT_sub_Fdec_onestep #1{#6#5#4#3}{#2}% + \XINT_sub_k #1#2!#5!#7!#9!% }% -\def\XINT_sub_Fdec_onestep #1#2% +\def\XINT_sub_di\Z + \expandafter\XINT_sub_e\the\numexpr#1+1#2-#3.#4!#5!#6!#7!#8\W {% - \expandafter\XINT_sub_backtoFdec\the\numexpr 11#2+#1-\xint_c_i.% + \XINT_sub_k #1#2!#5!#7!% }% -\def\XINT_sub_backtoFdec #1#2#3.#4% +\def\XINT_sub_fi\Z + \expandafter\XINT_sub_g\the\numexpr#1+1#2-#3.#4!#5!#6\W {% - \XINT_sub_Fdec #2{#3#4}% + \XINT_sub_k #1#2!#5!% }% -\def\xint_sub_Fdec_finish\W\XINT_sub_Fdec_onestep #1#2% +\def\XINT_sub_hi\Z + \expandafter\XINT_sub_i\the\numexpr#1+1#2-#3.#4\W {% - \expandafter\xint_minus_thenstop\romannumeral0\XINT_cuz + \XINT_sub_k #1#2!% }% -\def\XINT_sub_Finc #1#2#3#4#5#6% +%%%%%%%%%%%% +\def\XINT_sub_k #1#2% {% - \xint_gob_til_W #3\xint_sub_Finc_finish\W - \XINT_sub_Finc_onestep #1{#6#5#4#3}{#2}% + \xint_gob_til_Z #2\XINT_sub_p\Z \XINT_sub_l #1#2% }% -\def\XINT_sub_Finc_onestep #1#2% +\def\XINT_sub_l #1% {% - \expandafter\XINT_sub_backtoFinc\the\numexpr 10#2+#1.% + \xint_UDzerofork + #1\XINT_sub_m + 0{}% + \krof }% -\def\XINT_sub_backtoFinc #1#2#3.#4% +\def\XINT_sub_m #1!% {% - \XINT_sub_Finc #2{#3#4}% + \expandafter\XINT_sub_n\the\numexpr 1#1-\xint_c_i!% }% -\def\xint_sub_Finc_finish\W\XINT_sub_Finc_onestep #1#2#3% +\def\XINT_sub_n 1#1% {% \xint_UDzerofork - #1{\expandafter\expandafter\expandafter - \xint_minus_thenstop\xint_cleanupzeros_nostop}% - 0{ -1}% + #1{\XINT_sub_o}% + 0{\XINT_sub_n_checkzero}% \krof - #3% }% -\def\xint_sub_ez\W\XINT_sub_Eenter #1% +\def\XINT_sub_o #1!{1#1\expandafter!\the\numexpr\XINT_sub_m }% +\def\XINT_sub_n_checkzero #1!% {% - \xint_UDzerofork - #1\XINT_sub_K % il y a une retenue - 0\XINT_sub_L % pas de retenue - \krof + \xint_gob_til_eightzeroes #1\XINT_sub_n_prepare_cuz 00000000% + 1#1!% }% -\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% +\def\XINT_sub_n_prepare_cuz 00000000100000000{1\XINT_sub_prepare_cuz}% +\def\XINT_sub_p\Z\XINT_sub_l #1\Z!% {% - \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_sub_KK_onestep #1#2% -{% - \expandafter\XINT_sub_backtoKK\the\numexpr 109999-#2+#1.% -}% -\def\XINT_sub_backtoKK #1#2#3.#4% -{% - \XINT_sub_KK #2{#3#4}% -}% -\def\xint_sub_KK_finish\W\XINT_sub_KK_onestep #1#2#3% -{% - \expandafter\xint_minus_thenstop - \romannumeral0\XINT_cuz_loop #3\W\W\W\W\W\W\W\Z + \xint_UDzerofork + #1{-1\XINT_sub_prepare_rescue}% + 0{1\XINT_sub_prepare_cuz }% + \krof }% % \end{macrocode} % \subsection{\csh{xintiMul}, \csh{xintiiMul}} -% \lverb|1.09a adds \xintnum| +% \lverb|Completely rewritten for v1.2.| % \begin{macrocode} -\def\xintiiMul {\romannumeral0\xintiimul }% -\def\xintiimul #1% +\def\xintiMul {\romannumeral0\xintimul }% +\def\xintimul #1% {% - \expandafter\xint_iimul\expandafter {\romannumeral-`0#1}% + \expandafter\XINT_imul\romannumeral0\xintnum{#1}\Z }% -\def\xint_iimul #1#2% +\def\XINT_imul #1#2\Z #3% {% - \expandafter\XINT_mul_fork \romannumeral-`0#2\Z #1\Z + \expandafter\XINT_mul_nfork\expandafter #1\romannumeral0\xintnum{#3}\Z #2\Z }% -\def\xintiMul {\romannumeral0\xintimul }% -\def\xintimul #1% +\def\xintiiMul {\romannumeral0\xintiimul }% +\def\xintiimul #1% {% - \expandafter\xint_mul\expandafter {\romannumeral0\xintnum{#1}}% + \expandafter\XINT_iimul\romannumeral-`0#1\Z }% -\def\xint_mul #1#2% +\def\XINT_iimul #1#2\Z #3% {% - \expandafter\XINT_mul_fork \romannumeral0\xintnum{#2}\Z #1\Z + \expandafter\XINT_mul_nfork\expandafter #1\romannumeral-`0#3\Z #2\Z }% -\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 +% \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_UDzerofork #1\XINT_mul_zero - #3\XINT_mul_zero + #2\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}% -}% -\def\XINT_mul_zero #1\krof #2#3{ 0}% -\def\XINT_mul_minusminus #1#2% -{% - \expandafter\XINT_mul_choice_a - \expandafter{\romannumeral0\xintlength {#2}}% - {\romannumeral0\xintlength {#1}}{#1}{#2}% -}% -\def\XINT_mul_minusplus #1#2#3% -{% - \expandafter\xint_minus_thenstop\romannumeral0\expandafter - \XINT_mul_choice_a - \expandafter{\romannumeral0\xintlength {#1#3}}% - {\romannumeral0\xintlength {#2}}{#2}{#1#3}% -}% -\def\XINT_mul_plusminus #1#2#3% -{% - \expandafter\xint_minus_thenstop\romannumeral0\expandafter - \XINT_mul_choice_a - \expandafter{\romannumeral0\xintlength {#3}}% - {\romannumeral0\xintlength {#1#2}}{#1#2}{#3}% -}% -\def\XINT_mul_plusplus #1#2#3#4% -{% - \expandafter\XINT_mul_choice_a - \expandafter{\romannumeral0\xintlength {#2#4}}% - {\romannumeral0\xintlength {#1#3}}{#1#3}{#2#4}% -}% -\def\XINT_mul_choice_a #1#2% -{% - \expandafter\XINT_mul_choice_b\expandafter{#2}{#1}% -}% -\def\XINT_mul_choice_b #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}% -}% -\def\XINT_mul_choice_littlebyfirst #1#2#3#4% -{% - \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 -}% -\def\XINT_mul_choice_littlebysecond #1#2#3#4% -{% - \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 + #1#2\XINT_mul_minusminus + #1-\XINT_mul_minusplus + #2-\XINT_mul_plusminus + --\XINT_mul_plusplus + \krof #1#2% }% -\def\XINT_mul_choice_compare #1#2% -{% - \ifnum #1>#2 - \expandafter \XINT_mul_choice_i +\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 - \expandafter \XINT_mul_choice_ii + \ifnum \numexpr (#1-\xint_c_i)*(#2-#1)>383 + \XINT_mul_exchange + \fi \fi - {#1}{#2}% -}% -\def\XINT_mul_choice_i #1#2% -{% - \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 -}% -\def\XINT_mul_choice_ii #1#2% -{% - \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 -}% -\def\XINT_mul_choice_same #1#2% -{% - \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 -}% -\def\XINT_mul_choice_permute #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 -}% -% \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.| -% \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% -{% - \expandafter\XINT_mul_ABEAr - \the\numexpr #1+10#2+#8#7#6#5.{#3}#4\W\X\Y\Z -}% -\def\XINT_mul_ABEAr #1#2#3#4#5#6.#7% -{% - \XINT_mul_Ar #2{#7#6#5#4#3}% -}% -% \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 {<n>}<N>\Z\Z\Z\Z$\ -% Fait la multiplication de <N> par <n>, qui est < 10000. -% <N> est présenté *à l'envers*, sur *4n*. Lorsque <n> vaut 0, donne 0000.| + \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_mul_Mr #1% +\def\XINT_minimulwc_a 1#1.#2.#3!#4#5#6#7#8.% {% - \expandafter\XINT_mul_Mr_checkifzeroorone\expandafter{\the\numexpr #1}% + \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_mul_Mr_checkifzeroorone #1% +\def\XINT_minimulwc_b 1#1#2#3#4#5#6.#7.% {% - \ifcase #1 - \expandafter\XINT_mul_Mr_zero - \or - \expandafter\XINT_mul_Mr_one - \else - \expandafter\XINT_mul_Nr - \fi - {0000}{}{#1}% + \expandafter\XINT_minimulwc_c + \the\numexpr \xint_c_x^ix+#1#2#3#4#5+#7.#6.% }% -\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_minimulwc_c 1#1#2#3#4#5#6.#7.#8.% {% - \xint_gob_til_Z #4\xint_mul_pr\Z\XINT_mul_Pr {#1}{#3}{#7#6#5#4}{#2}{#3}% + 1#6#7\expandafter!% + \the\numexpr\expandafter\XINT_smallmul_a + \the\numexpr \xint_c_x^viii+#1#2#3#4#5+#8.% }% -\def\XINT_mul_Pr #1#2#3% +\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_mul_Lr\the\numexpr \xint_c_x^viii+#1+#2*#3\relax + \xint_gob_til_Z #4\XINT_smallmul_e\Z + \XINT_minimulwc_a #1.#2.#3!#4.#2.#3!% }% -\def\XINT_mul_Lr 1#1#2#3#4#5#6#7#8#9% -{% - \XINT_mul_Nr {#1#2#3#4}{#9#8#7#6#5}% -}% -\def\xint_mul_pr\Z\XINT_mul_Pr #1#2#3#4#5% -{% - \xint_gob_til_zeros_iv #1\XINT_mul_Mr_end_nocarry 0000% - \XINT_mul_Mr_end_carry #1{#4}% -}% -\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}% +\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} -% \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 {<n>}<N>\Z\Z\Z\Z$\ -% Fait la multiplication de <N> par <n>, qui est < 10000. -% <N> est présenté *à l'envers*, sur *4n*. | +% \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_mul_M #1% -{% - \expandafter\XINT_mul_M_checkifzeroorone\expandafter{\the\numexpr #1}% -}% -\def\XINT_mul_M_checkifzeroorone #1% -{% - \ifcase #1 - \expandafter\XINT_mul_M_zero - \or - \expandafter\XINT_mul_M_one - \else - \expandafter\XINT_mul_N - \fi - {0000}{}{#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 -{% - \expandafter\xint_cleanupzeros_andstop\romannumeral0\xintreverseorder{#4}% -}% -\def\XINT_mul_N #1#2#3#4#5#6#7% -{% - \xint_gob_til_Z #4\xint_mul_p\Z\XINT_mul_P {#1}{#3}{#7#6#5#4}{#2}{#3}% -}% -\def\XINT_mul_P #1#2#3% -{% - \expandafter\XINT_mul_L\the\numexpr \xint_c_x^viii+#1+#2*#3\relax -}% -\def\XINT_mul_L 1#1#2#3#4#5#6#7#8#9% -{% - \XINT_mul_N {#1#2#3#4}{#5#6#7#8#9}% -}% -\def\xint_mul_p\Z\XINT_mul_P #1#2#3#4#5% -{% - \XINT_mul_M_end #1#4% -}% -\edef\XINT_mul_M_end #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} -% \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 <N1>\Z\Z\Z\Z <N2>\W\W\W\W$\ -% avec <N1> *renversé*, *longueur 4n* (zéros éventuellement ajoutés -% au-delà du chiffre le plus significatif) -% et <N2> 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_verysmallmul #1.#2!1#3!% {% - \xint_gob_til_W - #2\XINT_mul_exit_ci - #3\XINT_mul_exit_cii - \W\XINT_mul_exit_ciii #1#2#3#4% -}% -\def\XINT_mul_exit_ciii #1\W #2\Z\Z\Z\Z \W\W\W -{% - \XINT_mul_M {#1}#2\Z\Z\Z\Z -}% -\def\XINT_mul_exit_cii\W\XINT_mul_exit_ciii #1\W\W #2\Z\Z\Z\Z \W\W -{% - \XINT_mul_M {#1}#2\Z\Z\Z\Z -}% -\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 -{% - \XINT_mul_M {#1}#2\Z\Z\Z\Z -}% -\def\XINT_mul_start #1#2\Z\Z\Z\Z -{% - \expandafter\XINT_mul_main\expandafter - {\romannumeral0\XINT_mul_Mr {#1}#2\Z\Z\Z\Z}#2\Z\Z\Z\Z -}% -\def\XINT_mul_main #1#2\Z\Z\Z\Z #3#4#5#6% -{% - \xint_gob_til_W #6\XINT_mul_finish_a\W - \XINT_mul_compute {#3#4#5#6}{#1}#2\Z\Z\Z\Z + \xint_gob_til_Z #3\XINT_verysmallmul_e\Z + \expandafter\XINT_verysmallmul_a + \the\numexpr #2*#3+#1.#2!% }% -\def\XINT_mul_compute #1#2#3\Z\Z\Z\Z +\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.% {% - \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 + \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_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|& -% 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. | +% \lverb|Used by division and by squaring, not by multiplication itself.| % \begin{macrocode} -\def\XINT_mul_finish_a\W\XINT_mul_compute #1% -{% - \XINT_mul_finish_b #1% -}% -\def\XINT_mul_finish_b #1#2#3#4% -{% - \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% -}% -\def\XINT_mul_finish_ciii #1\W #2#3\Z\Z\Z\Z \W\W\W +\def\XINT_minimul_a #1.#2!#3#4#5#6#7!% {% - \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_minimul_b + \the\numexpr \xint_c_x^viii+#2*#7.#2*#3#4#5#6+#1*#7.#1*#3#4#5#6.% }% -\def\XINT_mul_finish_cii - \W\XINT_mul_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_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 + \expandafter\XINT_minimul_c + \the\numexpr \xint_c_x^ix+#1#2#3#4+#6.#5.% }% -\def\XINT_mul_finish_ci #1\XINT_mul_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_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 -}% -\def\XINT_mul_finish_c #1\XINT_mul_finish_ciii \W\W\W\W #2#3\Z\Z\Z\Z -{% - \expandafter\xint_cleanupzeros_andstop\romannumeral0\xintreverseorder{#2}% + 1#6#7\expandafter!\the\numexpr \xint_c_x^viii+#1#2#3#4#5+#8!% }% % \end{macrocode} -% \subsubsection{Variant: \csh{XINT_mulr_enter}} -% \lverb|& -% \romannumeral0\XINT_mulr_enter <N1>\Z\Z\Z\Z <N2>\W\W\W\W $\ -% Ici <N1> est à l'envers sur 4n, et <N2> 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{xintiSqr}, \csh{xintiiSqr}} +% \lverb|Rewritten for v1.2.| % \begin{macrocode} -\def\XINT_mulr_enter #1\Z\Z\Z\Z #2#3#4#5% -{% - \xint_gob_til_W #5\XINT_mulr_exit_a\W - \XINT_mulr_start {#2#3#4#5}#1\Z\Z\Z\Z -}% -\def\XINT_mulr_exit_a\W\XINT_mulr_start #1% -{% - \XINT_mulr_exit_b #1% -}% -\def\XINT_mulr_exit_b #1#2#3#4% -{% - \xint_gob_til_W - #2\XINT_mulr_exit_ci - #3\XINT_mulr_exit_cii - \W\XINT_mulr_exit_ciii #1#2#3#4% -}% -\def\XINT_mulr_exit_ciii #1\W #2\Z\Z\Z\Z \W\W\W -{% - \XINT_mul_Mr {#1}#2\Z\Z\Z\Z -}% -\def\XINT_mulr_exit_cii\W\XINT_mulr_exit_ciii #1\W\W #2\Z\Z\Z\Z \W\W -{% - \XINT_mul_Mr {#1}#2\Z\Z\Z\Z -}% -\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 -{% - \XINT_mul_Mr {#1}#2\Z\Z\Z\Z -}% -\def\XINT_mulr_start #1#2\Z\Z\Z\Z -{% - \expandafter\XINT_mulr_main\expandafter - {\romannumeral0\XINT_mul_Mr {#1}#2\Z\Z\Z\Z}#2\Z\Z\Z\Z -}% -\def\XINT_mulr_main #1#2\Z\Z\Z\Z #3#4#5#6% -{% - \xint_gob_til_W #6\XINT_mulr_finish_a\W - \XINT_mulr_compute {#3#4#5#6}{#1}#2\Z\Z\Z\Z -}% -\def\XINT_mulr_compute #1#2#3\Z\Z\Z\Z -{% - \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 -}% -\def\XINT_mulr_finish_a\W\XINT_mulr_compute #1% -{% - \XINT_mulr_finish_b #1% -}% -\def\XINT_mulr_finish_b #1#2#3#4% +\def\xintiiSqr {\romannumeral0\xintiisqr }% +\def\xintiisqr #1% {% - \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% + \expandafter\XINT_sqr\romannumeral0\xintiiabs{#1}\Z }% -\def\XINT_mulr_finish_ciii #1\W #2#3\Z\Z\Z\Z \W\W\W +\def\xintiSqr {\romannumeral0\xintisqr }% +\def\xintisqr #1% {% - \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_sqr\romannumeral0\xintiabs{#1}\Z }% -\def\XINT_mulr_finish_cii - \W\XINT_mulr_finish_ciii #1\W\W #2#3\Z\Z\Z\Z \W\W +\def\XINT_sqr #1\Z {% - \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_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_mulr_finish_ci #1\XINT_mulr_finish_ciii #2\W\W\W #3#4\Z\Z\Z\Z \W -{% - \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 +\def\XINT_sqr_a #1.% +{% + \ifnum #1=\xint_c_i \expandafter\XINT_sqr_small + \else\expandafter\XINT_sqr_start\fi }% -\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}} -% \begin{macrocode} -\def\xintiiSqr {\romannumeral0\xintiisqr }% -\def\xintiisqr #1% +\def\XINT_sqr_small 1#1#2#3#4#5!\Z {% - \expandafter\XINT_sqr\expandafter {\romannumeral0\xintiiabs{#1}}% + \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!% }% -\def\xintiSqr {\romannumeral0\xintisqr }% -\def\xintisqr #1% +\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!% {% - \expandafter\XINT_sqr\expandafter {\romannumeral0\xintiabs{#1}}% + \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 @@ -17140,7 +16888,7 @@ $1$ or $-1$. \ifcase\XINT_cntSgn #1\Z \expandafter\XINT_pow_BisZero \or - \expandafter\XINT_pow_checkBsize + \expandafter\XINT_pow_I_in \else \expandafter\XINT_pow_BisNegative \fi @@ -17150,117 +16898,233 @@ $1$ or $-1$. {\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% -{% - \ifnum #1>100000 - \expandafter\XINT_pow_BtooBig +% \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_loopI - \fi - {#1}% + \expandafter\XINT_pow_I_squareit + \fi #1.% }% -\edef\XINT_pow_BtooBig #1#2{\noexpand\xintError:ExponentTooBig\space 0}% -\def\XINT_pow_loopI #1% +\def\XINT_pow_I_exit \ifodd #1\fi #2.#3\W {\XINT_mul_out #3}% +\def\XINT_pow_I_squareit #1.#2\W% {% - \ifnum #1=\xint_c_i\XINT_pow_Iend\fi + \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_loopI_odd + \expandafter\XINT_pow_II_odda \else - \expandafter\XINT_pow_loopI_even - \fi - {#1}% + \expandafter\XINT_pow_II_even + \fi #1.% }% -\edef\XINT_pow_Iend\fi #1\fi #2#3{\noexpand\fi\space #3}% -\def\XINT_pow_loopI_even #1#2% +\def\XINT_pow_II_exit\ifodd #1\fi #2.#3\W #4\W {% - \expandafter\XINT_pow_loopI\expandafter - {\the\numexpr #1/\xint_c_ii\expandafter}\expandafter - {\romannumeral0\xintiisqr {#2}}% + \expandafter\XINT_mul_out + \the\numexpr\XINT_pow_mulbutcheckifsmall #4\W #3% }% -\def\XINT_pow_loopI_odd #1#2% +\def\XINT_pow_II_even #1.#2\W {% - \expandafter\XINT_pow_loopI_odda\expandafter - {\romannumeral0\XINT_RQ {}#2\R\R\R\R\R\R\R\R\Z }{#1}{#2}% + \expandafter\XINT_pow_II_loop + \the\numexpr #1/\xint_c_ii\expandafter.% + \the\numexpr\XINT_pow_mulbutcheckifsmall #2\W #2\W }% -\def\XINT_pow_loopI_odda #1#2#3% +\def\XINT_pow_II_odda #1.#2\W #3\W {% - \expandafter\XINT_pow_loopII\expandafter - {\the\numexpr #2/\xint_c_ii-\xint_c_i\expandafter}\expandafter - {\romannumeral0\xintiisqr {#3}}{#1}% + \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_loopII #1% +\def\XINT_pow_II_oddb #1.#2\W #3\W {% - \ifnum #1 = \xint_c_i\XINT_pow_IIend\fi - \ifodd #1 - \expandafter\XINT_pow_loopII_odd + \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 + \xint_afterfi{\expandafter\space\expandafter 1\xint_gobble_i }% + \or + \expandafter\XINT_fac_checksize \else - \expandafter\XINT_pow_loopII_even + \xint_afterfi{\expandafter\xintError:FactorialOfNegativeNumber + \expandafter\space\expandafter 1\xint_gobble_i }% \fi {#1}% }% -\def\XINT_pow_loopII_even #1#2% +\def\XINT_fac_checksize #1% {% - \expandafter\XINT_pow_loopII\expandafter - {\the\numexpr #1/\xint_c_ii\expandafter}\expandafter - {\romannumeral0\xintiisqr {#2}}% + \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 }% -\def\XINT_pow_loopII_odd #1#2#3% +\def\XINT_fac_bigloop_a #1.% {% - \expandafter\XINT_pow_loopII_odda\expandafter - {\romannumeral0\XINT_mulr_enter #3\Z\Z\Z\Z #2\W\W\W\W}{#1}{#2}% + \expandafter\XINT_fac_bigloop_b \the\numexpr + #1+\xint_c_i-\xint_c_ii*((#1-464)/\xint_c_ii).#1.% }% -\def\XINT_pow_loopII_odda #1#2#3% +\def\XINT_fac_bigloop_b #1.#2.% {% - \expandafter\XINT_pow_loopII\expandafter - {\the\numexpr #2/\xint_c_ii-\xint_c_i\expandafter}\expandafter - {\romannumeral0\xintiisqr {#3}}{#1}% + \expandafter\XINT_fac_medloop_a + \the\numexpr #1-\xint_c_i.{\XINT_fac_bigloop_loop #1.#2.}% +}% +\def\XINT_fac_bigloop_loop #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_fac_bigloop_exit #1!{\XINT_mul_out}% +\def\XINT_fac_bigloop_mul #1!% +{% + \expandafter\XINT_smallmul + \the\numexpr \xint_c_x^viii+#1*(#1+\xint_c_i)!% +}% +\def\XINT_fac_medloop_a #1.% +{% + \expandafter\XINT_fac_medloop_b + \the\numexpr #1+\xint_c_i-\xint_c_iii*((#1-100)/\xint_c_iii).#1.% +}% +\def\XINT_fac_medloop_b #1.#2.% +{% + \expandafter\XINT_fac_smallloop_a + \the\numexpr #1-\xint_c_i.{\XINT_fac_medloop_loop #1.#2.}% +}% +\def\XINT_fac_medloop_loop #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_fac_medloop_mul #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 {% - \expandafter\XINT_div_I_f \the\numexpr \xint_c_x^iv+#2+#5{#1}% + \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% +{% + 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<a1>!1<a2>!, 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.% +{% + 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_div_littleI_a {#1#2#3#4}#6{#7}{#5}% + \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_gob_til_W #3\xint_div_sub_cz\W - \XINT_div_sub_C_onestep #1{#6#5#4#3}{#2}% + \xint_UDzerofork + #1{-2\relax}% + 0\XINT_div_sub_r + \krof }% -\def\XINT_div_sub_C_onestep #1#2% +\def\XINT_div_sub_r #1!% {% - \expandafter\XINT_div_sub_backtoC \the\numexpr 11#2+#1-\xint_c_i.% + -\ifnum 0#1=\xint_c_ 1\else2\fi\relax }% -\def\XINT_div_sub_backtoC #1#2#3.#4% +%%%%%%%%%%%% +\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!% {% - \XINT_div_sub_C #2{#3#4}% + \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_c_x^viii+#1+#2\expandafter!\the\numexpr\XINT_smalldiv_k + #1!% +}% +\def\XINT_smalldiv_k #1!#2!#3.#4!% +{% + \expandafter\XINT_smalldiv_d\the\numexpr #2-#1*#4!#3.#4!% +}% +%%%%%%%%%%%% +\def\XINT_div_mini #1.#2!1#3!% +{% + \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{}<N1>\W\X\Y\Z<N2>\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}} +% \subsection{\csh{xintGeq}, \csh{xintiiGeq}} % \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% +\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\expandafter {\romannumeral0\xintnum{#1}}% + \expandafter\XINT_geq_fork\expandafter #1\romannumeral-`0#3\Z #2\Z }% -\def\xint_geq #1#2% +\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 \romannumeral0\xintnum{#2}\Z #1\Z + \expandafter\XINT_geq_fork\expandafter #1\romannumeral0\xintnum{#3}\Z #2\Z }% -\def\XINT_Geq #1#2{\romannumeral0\XINT_geq_fork #2\Z #1\Z }% -% \end{macrocode} -% \lverb|& -% PLUS GRAND OU ÉGAL -% ATTENTION, TESTE les VALEURS ABSOLUES| -% \begin{macrocode} -\def\XINT_geq_fork #1#2\Z #3#4\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_distinctlengths #1#2#3\W #4\W +{% + \ifnum #1>#2 + \expandafter\xint_firstoftwo + \else + \expandafter\xint_secondoftwo + \fi + { 1}{ 0}% }% -\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_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_pre_b\expandafter - {\romannumeral0\XINT_RQ {}#1\R\R\R\R\R\R\R\R\Z }% + \XINT_geq_b #1!#6!#2!#7!#3!#8!#4!#9!#5\W }% -\def\XINT_geq_pre_b #1#2% +\def\XINT_geq_b #1#2#3!#4!% {% - \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_gob_til_Z #2\XINT_geq_bi \Z + \expandafter\XINT_geq_c\the\numexpr#1+1#4-#3-\xint_c_i.% }% -% \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{}<N1>\W\X\Y\Z<N2>\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_c 1#1#2.% {% - \xint_gob_til_W #4\xint_geq_az\W - \XINT_geq_B #1{#4#5#6#7}{#2}#3\W\X\Y\Z + 1#2\expandafter!\the\numexpr\XINT_geq_d #1% }% -\def\XINT_geq_B #1#2#3#4#5#6#7% +\def\XINT_geq_d #1#2#3!#4!% {% - \xint_gob_til_W #4\xint_geq_bz\W - \XINT_geq_onestep #1#2{#7#6#5#4}{#3}% + \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_onestep #1#2#3#4#5#6% +\def\XINT_geq_e 1#1#2.% {% - \expandafter\XINT_geq_backtoA\the\numexpr 11#5#4#3#2-#6+#1-\xint_c_i.% + 1#2\expandafter!\the\numexpr\XINT_geq_f #1% }% -\def\XINT_geq_backtoA #1#2#3.#4% +\def\XINT_geq_f #1#2#3!#4!% {% - \XINT_geq_A #2{#3#4}% + \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_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_g 1#1#2.% {% - \xint_gob_til_W #4\xint_geq_ez\W - \XINT_geq_Eenter #1% + 1#2\expandafter!\the\numexpr\XINT_geq_h #1% }% -\def\XINT_geq_Eenter #1\W\X\Y\Z { 0}% -\def\xint_geq_ez\W\XINT_geq_Eenter #1% +\def\XINT_geq_h #1#2#3!#4!% {% - \xint_UDzerofork - #1{ 0} % il y a une retenue - 0{ 1} % pas de retenue - \krof + \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<N, donc rounded->#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<b - { #1}{\XINT_dec_pos #1\R\R\R\R\R\R\R\R\Z \W\W\W\W\W\W\W\W }}% -\def\xintisquareroot #1{\expandafter\XINT_sqrt_checkin\romannumeral0\xintnum{#1}\Z }% +\def\XINT_sqrtr_post #1#2{\xintiiifLt {#2}{#1}{ #1}{\XINT_dec_pos #1\Z}}% +\def\xintisquareroot #1% + {\expandafter\XINT_sqrt_checkin\romannumeral0\xintnum{#1}\Z }% \def\xintiisquareroot #1{\expandafter\XINT_sqrt_checkin\romannumeral-`0#1\Z }% \def\XINT_sqrt_checkin #1% {% @@ -19889,8 +19785,7 @@ $1$ or $-1$. \def\XINT_sqrt_big_g #1#2% {% \expandafter\XINT_sqrt_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}% + \romannumeral0\xintiidivision{#1}{\romannumeral0\XINT_dbl_pos #2\Z}{#2}% }% \def\XINT_sqrt_big_j #1% {% @@ -19920,6 +19815,19 @@ $1$ or $-1$. {\expandafter\XINT_iie\the\numexpr #2\expandafter.\expandafter{\romannumeral-`0#1}}% \def\XINT_iie #1.#2{\ifnum#1>\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% + #1[#2% }% -\def\XINT_infrac_A #1[\W]\T +\def\XINT_infrac_res_a #1% {% - \XINT_frac #1/\W\Z + \xint_gob_til_zero #1\XINT_infrac_res_zero 0\XINT_infrac_res_b #1% }% -\def\XINT_infrac_B #1% +\def\XINT_infrac_res_zero 0\XINT_infrac_res_b #1\XINT_T {{0}{0}{1}}% +\def\XINT_infrac_res_b #1/#2% {% - \xint_gob_til_zero #1\XINT_infrac_Zero0\XINT_infrac_BB #1% -}% -\def\XINT_infrac_BB #1[\W]\T {\XINT_infrac_BC #1/\W\Z }% -\def\XINT_infrac_BC #1/#2#3\Z -{% - \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~% }% -\edef\XINT_frac_Gdivisionbyzero #1\Z #2#3% +\def\XINT_frac_gen_Gdivbyzero_a #1~#2~% {% - \noexpand\xintError:DivisionByZero\space {0}{#2}{0}% + \xintError:DivisionByZero {#2}{#1}{0}% }% -\def\XINT_frac_Gneg #1\Z #2#3% +\def\XINT_frac_gen_G #1#2#3~#4~#5~% {% - \expandafter\XINT_frac_H \expandafter{\romannumeral0\XINT_opp #2}{#3}{#1}% + \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_H #1#2{ {#2}{#1}}% -\def\XINT_frac_Gpos #1\Z #2#3{ {#3}{#2}{#1}}% +\def\XINT_frac_gen_Ga #1#2~#3~% +{% + \xint_gob_til_zero #1\XINT_frac_gen_zero 0% + {#3}{#1#2}% +}% +\def\XINT_frac_gen_zero 0#1#2#3{{0}{0}{1}}% % \end{macrocode} % \subsection{\csh{XINT_factortens}, \csh{XINT_cuz_cnt}} % \begin{macrocode} @@ -21709,6 +21674,102 @@ $1$ or $-1$. \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_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_addm_CD #1% +{% + \expandafter\XINT_addm_CC\the\numexpr 1+10#1.% +}% +\def\XINT_addm_CC #1#2#3.#4% +{% + \XINT_addm_AC_checkcarry #2{#3#4}% +}% +\def\xint_addm_cw + #1\xint_addm_cx + #2\xint_addm_cy + #3\xint_addm_cz + \W\XINT_addm_CD +{% + \expandafter\XINT_addm_CDw\the\numexpr 1+#1#2#3.% +}% +\def\XINT_addm_CDw #1.#2#3\X\Y\Z +{% + \XINT_addm_end #1#3% +}% +\def\xint_addm_cx + #1\xint_addm_cy + #2\xint_addm_cz + \W\XINT_addm_CD +{% + \expandafter\XINT_addm_CDx\the\numexpr 1+#1#2.% +}% +\def\XINT_addm_CDx #1.#2#3\Y\Z +{% + \XINT_addm_end #1#3% +}% +\def\xint_addm_cy + #1\xint_addm_cz + \W\XINT_addm_CD +{% + \expandafter\XINT_addm_CDy\the\numexpr 1+#1.% +}% +\def\XINT_addm_CDy #1.#2#3\Z +{% + \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|& % 1.07: this macro simply prints in a user readable form the fraction after its @@ -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.=<digits>\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_gobz_scanint_b #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_aa #1% +\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 {% - \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% + \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_scanintpart_b #1#2% +\def\XINT_expr_gobz_scanint_d #1% {% - \expandafter #1\romannumeral-`0\expandafter - \XINT_expr_scanintpart_a\romannumeral-`0#2% + \expandafter\XINT_expr_gobz_scanint_b\romannumeral-`0#1% }% -\def\XINT_expr_scandec_transition .#1% +\def\XINT_expr_gobz_startdec_a .#1% {% - \expandafter\XINT_expr_scandec_trans_a\romannumeral-`0#1% + \expandafter\XINT_expr_gobz_scandec_a\romannumeral-`0#1% }% -\def\XINT_expr_scandec_trans_a #1% +\def\XINT_expr_gobz_scandec_a #1% {% - \if .#1\xint_dothis{!!..}\fi - \xint_orthat {\expandafter\XINT_expr_infracpart - \romannumeral-`0\XINT_expr_scanfracpart_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_scanfracpart_b #1#2% +\def\XINT_expr_scandec_c\string #1#2\the\numexpr#3-\xint_c_i.% {% - \expandafter #1\romannumeral-`0\expandafter - \XINT_expr_scanfracpart_a\romannumeral-`0#2% + \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_gobz_scandec_endbycs #1#2\xint_c_mone.{0[0]\endcsname #1}% +\def\XINT_expr_gobz_scandec_c\string #1#2\xint_c_mone.% +{% + \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 %% --------------------------------------------------------------- %% |