diff options
author | Karl Berry <karl@freefriends.org> | 2014-02-06 23:21:15 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2014-02-06 23:21:15 +0000 |
commit | ae325decb4680e2b5926cf27246bb47fee52e62d (patch) | |
tree | 9b836bc3bdb6478db3b574a8f639b02f3d336e5a /Master/texmf-dist/doc/generic/xint | |
parent | c7c965a288246cd94f7bdad3730cd86d01cca50f (diff) |
xint (6feb14)
git-svn-id: svn://tug.org/texlive/trunk@32883 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/doc/generic/xint')
-rw-r--r-- | Master/texmf-dist/doc/generic/xint/README | 161 | ||||
-rw-r--r-- | Master/texmf-dist/doc/generic/xint/xint.dtx | 24759 | ||||
-rw-r--r-- | Master/texmf-dist/doc/generic/xint/xint.pdf | bin | 996033 -> 998916 bytes |
3 files changed, 24759 insertions, 161 deletions
diff --git a/Master/texmf-dist/doc/generic/xint/README b/Master/texmf-dist/doc/generic/xint/README deleted file mode 100644 index 3124562d23a..00000000000 --- a/Master/texmf-dist/doc/generic/xint/README +++ /dev/null @@ -1,161 +0,0 @@ -The xint bundle -Release 1.09k (2014/01/21). Documentation date: 2014/01/21 - -Copyright (C) 2013-2014 by Jean-Francois Burnol -License: LaTeX Project Public License 1.3c or later. - -Contents: Abstract, Installation, License. - -Abstract -======== - -xinttools is loaded by xint (hence by all other packages of the -bundle, too): it provides utilities of independent interest such as -expandable and non-expandable loops. - -xint implements with expandable TEX macros additions, subtractions, -multiplications, divisions and powers with arbitrarily long numbers. - -xintfrac extends the scope of xint to decimal numbers, to numbers in -scientific notation and also to fractions with arbitrarily long such -numerators and denominators separated by a forward slash. - -xintexpr extends xintfrac with an expandable parser - \xintexpr . . . \relax -of expressions involving arithmetic operations in infix notation on -decimal numbers, fractions, numbers in scientific notation, with -parentheses, factorial symbol, function names, comparison operators, -logic operators, twofold and threefold way conditionals, -sub-expressions, macros expanding to the previous items. - -Further modules: - -xintbinhex is for conversions to and from binary and hexadecimal -bases. - -xintseries provides some basic functionality for computing in an -expandable manner partial sums of series and power series with -fractional coefficients. - -xintgcd implements the Euclidean algorithm and its typesetting. - -xintcfrac deals with the computation of continued fractions. - -Most macros, and all of those doing computations, work purely by -expansion without assignments, and may thus be used almost everywhere -in TeX. The packages may be used with any flavor of TeX supporting the -e-TeX extensions. LaTeX users will use \usepackage and others \input -to load the package components. - -Installation -============ - -A. Installation using xint.tds.zip: ------------------------------------ - -obtain xint.tds.zip from CTAN: - http://mirror.ctan.org/install/macros/generic/xint.tds.zip - -cd to the download repertory and issue - unzip xint.tds.zip -d <TEXMF> -for example: (assuming standard access rights, so sudo needed) - sudo unzip xint.tds.zip -d /usr/local/texlive/texmf-local - sudo mktexlsr - -On Mac OS X, installation into user home folder: - unzip xint.tds.zip -d ~/Library/texmf - -B. Installation after file extractions: ---------------------------------------- - -obtain xint.dtx, xint.ins and the README from CTAN: - http://www.ctan.org/pkg/xint - -- "tex xint.ins" generates the style files -(pre-existing files in the same repertory will be overwritten). - -- without xint.ins: "tex or latex or pdflatex or xelatex xint.dtx" -will also generate the style files (and xint.ins). - -xint.tex is also extracted, use it for the documentation: - -- with latex+dvipdfmx: latex xint.tex thrice then dvipdfmx xint.dvi -Ignore dvipdfmx warnings, but if the pdf file has problems with fonts -(possibly from an old dvipdfmx), use then rather pdflatex or xelatex. - -- with pdflatex or xelatex: run it directly thrice on xint.dtx, or run -it on xint.tex after having edited the suitable toggle therein. - -When compiling xint.tex, the documentation is by default produced -with the source code included. See instructions in the file for -changing this default. - -When compiling directly xint.dtx, the documentation is produced -without the source code (latex+dvips or pdflatex or xelatex). - -Finishing the installation: (on first installation the destination -repertories may need to be created) - - xinttools.sty | - xint.sty | - xintfrac.sty | - xintexpr.sty | --> TDS:tex/generic/xint/ - xintbinhex.sty | - xintgcd.sty | - xintseries.sty | - xintcfrac.sty | - - xint.dtx --> TDS:source/generic/xint/ - xint.ins --> TDS:source/generic/xint/ - xint.tex --> TDS:source/generic/xint/ - - xint.pdf --> TDS:doc/generic/xint/ - README --> TDS:doc/generic/xint/ - -Depending on the TDS destination and the TeX installation, it may be -necessary to refresh the TeX installation filename database (mktexlsr) - -C. Usage: ---------- - -Usage with LaTeX: \usepackage{xinttools} - \usepackage{xint} % (loads xinttools) - \usepackage{xintfrac} % (loads xint) - \usepackage{xintexpr} % (loads xintfrac) - - \usepackage{xintbinhex} % (loads xint) - \usepackage{xintgcd} % (loads xint) - \usepackage{xintseries} % (loads xintfrac) - \usepackage{xintcfrac} % (loads xintfrac) - -Usage with TeX: \input xinttools.sty\relax - \input xint.sty\relax % (loads xinttools) - \input xintfrac.sty\relax % (loads xint) - \input xintexpr.sty\relax % (loads xintfrac) - - \input xintbinhex.sty\relax % (loads xint) - \input xintgcd.sty\relax % (loads xint) - \input xintseries.sty\relax % (loads xintfrac) - \input xintcfrac.sty\relax % (loads xintfrac) - -License -======= - - This work may be distributed and/or modified under the - conditions of the LaTeX Project Public License, either - version 1.3c of this license or (at your option) any later - version. This version of this license is in - http://www.latex-project.org/lppl/lppl-1-3c.txt - and the latest version of this license is in - http://www.latex-project.org/lppl.txt - and version 1.3 or later is part of all distributions of - LaTeX version 2005/12/01 or later. - -This work consists of the source file xint.dtx and of its derived files: -xinttools.sty xint.sty, xintfrac.sty, xintexpr.sty, xintbinhex.sty, -xintgcd.sty, xintseries.sty, xintcfrac.sty, as well as xint.ins, xint.tex -and the documentation xint.pdf (or xint.dvi). - -The author of this work is Jean-Francois Burnol <jfbu at free dot fr>. -This work has the LPPL maintenance status `author-maintained'. - diff --git a/Master/texmf-dist/doc/generic/xint/xint.dtx b/Master/texmf-dist/doc/generic/xint/xint.dtx new file mode 100644 index 00000000000..6f868a9a451 --- /dev/null +++ b/Master/texmf-dist/doc/generic/xint/xint.dtx @@ -0,0 +1,24759 @@ +% -*- coding: iso-latin-1; time-stamp-format: "%02d-%02m-%:y %02H:%02M:%02S %Z" -*- +% File: xint.dtx, package: 1.09ka (2014/02/05), documentation: 2014/02/05 +% License: LaTeX Project Public License 1.3c or later. +% Copyright (C) 2013-2014 by Jean-Francois Burnol <jfbu at free dot fr> +%<*dtx> +\def\lasttimestamp{Time-stamp: <05-02-2014 21:53:23 CET>} +%</dtx> +%<*drv> +\def\xintdate {2014/02/05} +\def\xintversion {1.09ka} +%</drv> +%%---------------------------------------------------------------- +%% The xint bundle (version 1.09ka of February 5, 2014) +%<xinttools>%% xinttools: Expandable and non-expandable utilities +%<xint>%% xint: Expandable operations on long numbers +%<xintfrac>%% xintfrac: Expandable operations on fractions +%<xintexpr>%% xintexpr: Expandable expression parser +%<xintbinhex>%% xintbinhex: Expandable binary and hexadecimal conversions +%<xintgcd>%% xintgcd: Euclidean algorithm with xint package +%<xintseries>%% xintseries: Expandable partial sums with xint package +%<xintcfrac>%% xintcfrac: Expandable continued fractions with xint package +%% Copyright (C) 2013-2014 by Jean-Francois Burnol +%%---------------------------------------------------------------- +% Installation +% ============ +% +% A. Installation using xint.tds.zip: +% ----------------------------------- +% +% obtain xint.tds.zip from CTAN: +% http://mirror.ctan.org/install/macros/generic/xint.tds.zip +% +% cd to the download repertory and issue +% unzip xint.tds.zip -d <TEXMF> +% for example: (assuming standard access rights, so sudo needed) +% sudo unzip xint.tds.zip -d /usr/local/texlive/texmf-local +% sudo mktexlsr +% +% On Mac OS X, installation into user home folder: +% unzip xint.tds.zip -d ~/Library/texmf +% +% B. Installation after file extractions: +% --------------------------------------- +% +% obtain xint.dtx, xint.ins and the README from CTAN: +% http://www.ctan.org/pkg/xint +% +% - "tex xint.ins" generates the style files +% (pre-existing files in the same repertory will be overwritten). +% +% - without xint.ins: "tex or latex or pdflatex or xelatex xint.dtx" +% will also generate the style files (and xint.ins). +% +% xint.tex is also extracted, use it for the documentation: +% +% - with latex+dvipdfmx: latex xint.tex thrice then dvipdfmx xint.dvi +% Ignore dvipdfmx warnings, but if the pdf file has problems with fonts +% (possibly from an old dvipdfmx), use then rather pdflatex or xelatex. +% +% - with pdflatex or xelatex: run it directly thrice on xint.dtx, or run +% it on xint.tex after having edited the suitable toggle therein. +% +% When compiling xint.tex, the documentation is by default produced +% with the source code included. See instructions in the file for +% changing this default. +% +% When compiling directly xint.dtx, the documentation is produced +% without the source code (latex+dvips or pdflatex or xelatex). +% +% Finishing the installation: (on first installation the destination +% repertories may need to be created) +% +% xinttools.sty | +% xint.sty | +% xintfrac.sty | +% xintexpr.sty | --> TDS:tex/generic/xint/ +% xintbinhex.sty | +% xintgcd.sty | +% xintseries.sty | +% xintcfrac.sty | +% +% xint.dtx --> TDS:source/generic/xint/ +% xint.ins --> TDS:source/generic/xint/ +% xint.tex --> TDS:source/generic/xint/ +% +% xint.pdf --> TDS:doc/generic/xint/ +% README --> TDS:doc/generic/xint/ +% +% Depending on the TDS destination and the TeX installation, it may be +% necessary to refresh the TeX installation filename database (mktexlsr) +% +% C. Usage: +% --------- +% +% Usage with LaTeX: \usepackage{xinttools} +% \usepackage{xint} % (loads xinttools) +% \usepackage{xintfrac} % (loads xint) +% \usepackage{xintexpr} % (loads xintfrac) +% +% \usepackage{xintbinhex} % (loads xint) +% \usepackage{xintgcd} % (loads xint) +% \usepackage{xintseries} % (loads xintfrac) +% \usepackage{xintcfrac} % (loads xintfrac) +% +% Usage with TeX: \input xinttools.sty\relax +% \input xint.sty\relax % (loads xinttools) +% \input xintfrac.sty\relax % (loads xint) +% \input xintexpr.sty\relax % (loads xintfrac) +% +% \input xintbinhex.sty\relax % (loads xint) +% \input xintgcd.sty\relax % (loads xint) +% \input xintseries.sty\relax % (loads xintfrac) +% \input xintcfrac.sty\relax % (loads xintfrac) +% +% License +% ======= +% +% This work may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either +% version 1.3c of this license or (at your option) any later +% version. This version of this license is in +% http://www.latex-project.org/lppl/lppl-1-3c.txt +% and the latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3 or later is part of all distributions of +% LaTeX version 2005/12/01 or later. +% +% This work consists of the source file xint.dtx and of its derived files: +% xinttools.sty xint.sty, xintfrac.sty, xintexpr.sty, xintbinhex.sty, +% xintgcd.sty, xintseries.sty, xintcfrac.sty, as well as xint.ins, xint.tex +% and the documentation xint.pdf (or xint.dvi). +% +% The author of this work is Jean-Francois Burnol <jfbu at free dot fr>. +% This work has the LPPL maintenance status `author-maintained'. +% +%<*dtx> +\iffalse +%</dtx> +%<*drv>---------------------------------------------------------------------- +%% This is a generated file. Run latex thrice on this file xint.tex then +%% run dvipdfmx on xint.dvi to produce the documentation xint.pdf, with +%% source code included. (ignore the dvipdfmx warnings) +%% +%% Customize as desired the class options and the two toggles below. +%% +%% See xint.dtx for the copyright and the conditions for distribution +%% and/or modification of this work. +%% +\NeedsTeXFormat{LaTeX2e} +\ProvidesFile{xint.tex}% +[\xintdate\space v\xintversion\space driver file for xint documentation (jfB)]% +\PassOptionsToClass{a4paper,fontsize=11pt}{scrdoc} +\chardef\Withdvipdfmx 1 % replace 1<space> by 0<space> for using latex/pdflatex +\chardef\NoSourceCode 0 % replace 0<space> by 1<space> for no source code +\input xint.dtx +%%% Local Variables: +%%% mode: latex +%%% End: +%</drv>---------------------------------------------------------------------- +%<*ins>------------------------------------------------------------------------- +%% This is a generated file. +%% "tex xint.ins" extracts from xint.dtx: +%% xinttools.sty, xint.sty, xintfrac.sty, xintexpr.sty, xintbinhex.sty, +%% xintgcd.sty, xintseries.sty and xintcfrac.sty as well as xint.tex +%% (for typesetting the documentation). +%% +%% See xint.dtx for the copyright and the conditions for distribution +%% and/or modification of this work. +%% +\input docstrip.tex +\askforoverwritefalse +\generate{\nopreamble +\file{xint.tex}{\from{xint.dtx}{drv}} +\usepreamble\defaultpreamble +\file{xinttools.sty}{\from{xint.dtx}{xinttools}} +\file{xint.sty}{\from{xint.dtx}{xint}} +\file{xintbinhex.sty}{\from{xint.dtx}{xintbinhex}} +\file{xintgcd.sty}{\from{xint.dtx}{xintgcd}} +\file{xintfrac.sty}{\from{xint.dtx}{xintfrac}} +\file{xintseries.sty}{\from{xint.dtx}{xintseries}} +\file{xintcfrac.sty}{\from{xint.dtx}{xintcfrac}} +\file{xintexpr.sty}{\from{xint.dtx}{xintexpr}}} +\catcode32=13\relax% active space +\let =\space% +\Msg{************************************************************************} +\Msg{*} +\Msg{* To finish the installation you have to move the following} +\Msg{* files into a directory searched by TeX:} +\Msg{*} +\Msg{* xinttools.sty} +\Msg{* xint.sty} +\Msg{* xintbinhex.sty} +\Msg{* xintgcd.sty} +\Msg{* xintfrac.sty} +\Msg{* xintseries.sty} +\Msg{* xintcfrac.sty} +\Msg{* xintexpr.sty} +\Msg{*} +\Msg{* To produce the documentation run latex thrice on file xint.tex} +\Msg{* and then run dvipdfmx on file xint.dvi (ignore dvipdfmx warnings)} +\Msg{*} +\Msg{* Happy TeXing!} +\Msg{*} +\Msg{************************************************************************} +\endbatchfile +%</ins>------------------------------------------------------------------------- +%<*dtx> +\fi % end of \iffalse block +\def\striptimestamp #1 <#2 #3 #4>{#2 at #3 #4} +\def\getdocdate #1 <#2-#3-#4 #5>{#4/#3/#2} +\edef\docdate{\expandafter\getdocdate\lasttimestamp} +\edef\dtxtimestamp{\expandafter\striptimestamp\lasttimestamp} +\chardef\noetex 0 +\expandafter\ifx\csname numexpr\endcsname\relax \chardef\noetex 1 \fi +\ifnum\noetex=1 \chardef\extractfiles 0 % extract files, then stop +\else + \expandafter\ifx\csname ProvidesFile\endcsname\relax + \chardef\extractfiles 0 % etex etc.. on xint.dtx + \else % latex/pdflatex on xint.tex or on xint.dtx + \expandafter\ifx\csname Withdvipdfmx\endcsname\relax + % latex run is on etoc.dtx, we will extract all files + \chardef\extractfiles 1 % 1 = extract all and typeset doc + \chardef\Withdvipdfmx 0 % 0 = pdflatex or latex+dvips + \chardef\NoSourceCode 1 % + \NeedsTeXFormat{LaTeX2e}% + \PassOptionsToClass{a4paper,11pt}{scrdoc}% + \else % latex run is on etoc.tex, + \chardef\extractfiles 2 % no extractions + \fi + \ProvidesFile{xint.dtx}% + [bundle source (\xintversion, \xintdate) and documentation (\docdate)]% + \fi +\fi +\ifnum\extractfiles<2 % extract files +\def\MessageDeFin{\newlinechar10 \let\Msg\message +\Msg{^^J}% +\Msg{********************************************************************^^J}% +\Msg{*^^J}% +\Msg{* To finish the installation you have to move the following^^J}% +\Msg{* files into a directory searched by TeX:^^J}% +\Msg{*^^J}% +\Msg{*\space\space\space\space xinttools.sty^^J}% +\Msg{*\space\space\space\space xint.sty^^J}% +\Msg{*\space\space\space\space xintbinhex.sty^^J}% +\Msg{*\space\space\space\space xintgcd.sty^^J}% +\Msg{*\space\space\space\space xintfrac.sty^^J}% +\Msg{*\space\space\space\space xintseries.sty^^J}% +\Msg{*\space\space\space\space xintcfrac.sty^^J}% +\Msg{*\space\space\space\space xintexpr.sty^^J}% +\Msg{*^^J}% +\Msg{* To produce the documentation with source code included run latex^^J}% +\Msg{* thrice on file xint.tex and then dvipdfmx on xint.dvi^^J}% +\Msg{* \space\space\space\space(ignore the dvipdfmx warnings)^^J}% +\Msg{*^^J}% +\Msg{* Happy TeXing!^^J}% +\Msg{*^^J}% +\Msg{********************************************************************^^J}% +}% +\begingroup + \input docstrip.tex + \askforoverwritefalse + \generate{\nopreamble + \file{xint.ins}{\from{xint.dtx}{ins}} + \file{xint.tex}{\from{xint.dtx}{drv}} + \usepreamble\defaultpreamble + \file{xinttools.sty}{\from{xint.dtx}{xinttools}} + \file{xint.sty}{\from{xint.dtx}{xint}} + \file{xintbinhex.sty}{\from{xint.dtx}{xintbinhex}} + \file{xintgcd.sty}{\from{xint.dtx}{xintgcd}} + \file{xintfrac.sty}{\from{xint.dtx}{xintfrac}} + \file{xintseries.sty}{\from{xint.dtx}{xintseries}} + \file{xintcfrac.sty}{\from{xint.dtx}{xintcfrac}} + \file{xintexpr.sty}{\from{xint.dtx}{xintexpr}}} +\endgroup +\fi % end of file extraction +\ifnum\extractfiles=0 +% direct tex/etex/xetex/etc on xint.dtx, files now extracted, stop + \MessageDeFin\expandafter\end +\fi +% no use of docstrip to extract files if latex compilation was on etoc.tex +\ifdefined\MessageDeFin\AtEndDocument{\MessageDeFin}\fi +%------------------------------------------------------------------------------- +\documentclass {scrdoc} +\ifnum\NoSourceCode=1 \OnlyDescription\fi +\makeatletter +\ifnum\Withdvipdfmx=1 + \@for\@tempa:=hyperref,bookmark,graphicx,xcolor\do + {\PassOptionsToPackage{dvipdfmx}\@tempa} + % + \PassOptionsToPackage{dvipdfm}{geometry} + \PassOptionsToPackage{bookmarks=true}{hyperref} + \PassOptionsToPackage{dvipdfmx-outline-open}{hyperref} + \PassOptionsToPackage{dvipdfmx-outline-open}{bookmark} + % + \def\pgfsysdriver{pgfsys-dvipdfm.def} +\else + \PassOptionsToPackage{bookmarks=true}{hyperref} +\fi +\makeatother + +\pagestyle{headings} +\makeatletter +% January 4, 2014 +% took me a while to pinpoint yesterday evening the origin of the problem, if +% only I had visited +% http://www.komascript.de/release3.12 immediately! +% +% as I subscribe to c.t.tex and d.c.t.tex I thought a problem with KOMA scrartcl +% would have been mentioned there, if as crippling as is this one, so I +% initially thought something related to TOCs had changed in KOMA and that etoc +% was now incompatible, and thus I started examining this, until finally +% understanding this had nothing to do with the TOC but originated in a +% buggy \sectionmark, revealed with pagestyle headings. +% +% This morning I see this is fixed in the experimental archive +% http://www.komascript.de/~mkohm/texlive-KOMA/archive/ and appears in the +% CHANGELOG as r1584. It is a bit hard for me to understand why such a typo with +% big consequences is not yet fixed in the CTAN distributed version. I did waste +% 90 minutes on that, at a time I was concentrating on xint things. Bugs are +% unavoidable, especially typos like this originating from modifying earlier +% code, but this tiny typo is severely annoying to users (*) and in my humble +% opinion a CTAN update should have been done sooner. Ok, this was a +% turn-of-year time... +% +% (*) compiling old documents is broken, and one sometimes does not want to +% modify the source files. +% +\def\buggysectionmark #1{% KOMA 3.12 as released to CTAN December 2013 + \if@twoside\expandafter\markboth\else\expandafter\markright\fi + {\MakeMarkcase{\ifnumbered{section}{\sectionmarkformat\fi}{}#1}}{}} +\ifx\buggysectionmark\sectionmark +\def\sectionmark #1{% + \if@twoside\expandafter\markboth\else\expandafter\markright\fi + {\MakeMarkcase{\ifnumbered{section}{\sectionmarkformat}{}#1}}{}} +\fi +\makeatother + +\usepackage[T1]{fontenc} +\usepackage[latin1]{inputenc} + +%\usepackage{array} +\usepackage{multicol} + +%---- GEOMETRY WILL BE CHANGED FOR SOURCE CODE SECTIONS +\usepackage[hscale=0.66,vscale=0.75]{geometry} + +\usepackage{xintexpr} + +\usepackage{xintbinhex} +\usepackage{xintgcd} +\usepackage{xintseries} +\usepackage{xintcfrac} + +\usepackage{amsmath} % for \cfrac in the documentation +\usepackage{varioref} + +\usepackage{etoolbox} + +\usepackage{etoc}[2013/10/16] % I need \etocdepthtag.toc + +%---- USE OF ETOC FOR THE TABLES OF CONTENTS + +\def\gobbletodot #1.{} +\makeatletter +\let\savedsectionline\l@section +\makeatother + +\def\sectioncouleur{{cyan}} + +% attention à ce 22 hard codé. 23 maintenant,... 24; et 31 non 32... +% et ça continue de changer + +\etocsetstyle{section}{} + {} + {\ifnum\etocthenumber=23 \gdef\sectioncouleur{{joli}}\fi + \ifnum\etocthenumber=31 \gdef\sectioncouleur{[named]{RoyalPurple}}\fi + \savedsectionline{\numberline{\expandafter\textcolor\sectioncouleur + {\etocnumber}}\etocname} + {{\mdseries\etocpage}}% + }% cf l@section en classe scrartcl + {}% + +\def\MARGEPAGENO {1.5em} +\etocsetstyle{subsection} + {\begingroup + \setlength{\premulticols}{0pt} + \setlength{\multicolsep}{0pt} + \setlength{\columnsep}{1em} + \setlength{\columnseprule}{.4pt} + \raggedcolumns % only added for 1.08a, I should have done it long time ago! + \begin{multicols}{2} + \leftskip 2.3em + \rightskip \MARGEPAGENO plus 2em minus 1em % 18 octobre 2013 + \parfillskip -\MARGEPAGENO\relax + } + {} + {\noindent + \llap{\makebox[2.3em][l] + {\ttfamily\bfseries\etoclink + {.\expandafter\gobbletodot\etocthenumber}}}% + \strut + \etocname\nobreak\leaders\etoctoclineleaders\hfill\nobreak + \strut\makebox[1.5em][r]{\normalfont\small\etocpage}\endgraf } + {\end{multicols}\endgroup }% + +\makeatother + +\addtocontents{toc}{\protect\hypersetup{hidelinks}} +% je rends le @ actif... après begin document... (donc ok pour aux) +\addtocontents{toc}{\protect\makeatother} + +%--- TXFONTS: TXTT WILL BE MADE SMALLER AND WILL ALLOW HYPHENATION +\usepackage{txfonts} +\usepackage{pifont} + +% malheureusement, comme j'utilise des diacritiques dans mes +% parties commentées, imprimées verbatim, je ne pourrai pas +% utiliser dvipdfmx qui a un problème avec txtt + +\DeclareFontFamily{T1}{txtt}{} +\DeclareFontShape{T1}{txtt}{m}{n}{ %medium + <->s*[.96] t1xtt% +}{} +\DeclareFontShape{T1}{txtt}{m}{sc}{ %cap & small cap + <->s*[.96] t1xttsc% +}{} +\DeclareFontShape{T1}{txtt}{m}{sl}{ %slanted + <->s*[.96] t1xttsl% +}{} +\DeclareFontShape{T1}{txtt}{m}{it}{ %italic + <->ssub * txtt/m/sl% +}{} +\DeclareFontShape{T1}{txtt}{m}{ui}{ %unslanted italic + <->ssub * txtt/m/sl% +}{} +\DeclareFontShape{T1}{txtt}{bx}{n}{ %bold extended + <->t1xbtt% +}{} +\DeclareFontShape{T1}{txtt}{bx}{sc}{ %bold extended cap & small cap + <->t1xbttsc% +}{} +\DeclareFontShape{T1}{txtt}{bx}{sl}{ %bold extended slanted + <->t1xbttsl% +}{} +\DeclareFontShape{T1}{txtt}{bx}{it}{ %bold extended italic + <->ssub * txtt/bx/sl% +}{} +\DeclareFontShape{T1}{txtt}{bx}{ui}{ %bold extended unslanted italic + <->ssub * txtt/bx/sl% +}{} +\DeclareFontShape{T1}{txtt}{b}{n}{ %bold + <->ssub * txtt/bx/n% +}{} +\DeclareFontShape{T1}{txtt}{b}{sc}{ %bold cap & small cap + <->ssub * txtt/bx/sc% +}{} +\DeclareFontShape{T1}{txtt}{b}{sl}{ %bold slanted + <->ssub * txtt/bx/sl% +}{} +\DeclareFontShape{T1}{txtt}{b}{it}{ %bold italic + <->ssub * txtt/bx/it% +}{} +\DeclareFontShape{T1}{txtt}{b}{ui}{ %bold unslanted italic + <->ssub * txtt/bx/ui% +}{} + +\def\digitstt {\bgroup\fontfamily {lmtt}\selectfont\let\next=} + +\usepackage{xspace} +%\usepackage[dvipsnames]{color} +\usepackage[dvipsnames]{xcolor} +\usepackage{framed} + +\definecolor{joli}{RGB}{225,95,0} +\definecolor{JOLI}{RGB}{225,95,0} +\definecolor{BLUE}{RGB}{0,0,255} +\definecolor{niceone}{RGB}{38,128,192} + +% for the quick sort algorithm illustration +\definecolor{LEFT}{RGB}{216,195,88} +\definecolor{RIGHT}{RGB}{208,231,153} +\definecolor{INERT}{RGB}{199,200,194} +\definecolor{PIVOT}{RGB}{109,8,57} + +\usepackage[para]{footmisc} + +\usepackage[english]{babel} +\usepackage[autolanguage,np]{numprint} +\AtBeginDocument{\npthousandsep{,\hskip .5pt plus .1pt minus .1pt}} + + +\usepackage[pdfencoding=pdfdoc]{hyperref} +\hypersetup{% +linktoc=all,% +breaklinks=true,% +colorlinks=true,% +urlcolor=niceone,% +linkcolor=blue,% +pdfauthor={Jean-Fran\c cois Burnol},% +pdftitle={The xint bundle},% +pdfsubject={Arithmetic with TeX},% +pdfkeywords={Expansion, arithmetic, TeX},% +pdfstartview=FitH,% +pdfpagemode=UseOutlines} +\usepackage{bookmark} + +\usepackage{picture} % permet d'utiliser des unités dans les dimensions de la + % picture et dans \put +\usepackage{graphicx} +\usepackage{eso-pic} + + +%---- \MyMarginNote: a simple macro for some margin notes with no fuss +% je m'aperçois que je peux l'utiliser dans les footnotes... +\makeatletter +\def\MyMarginNote {\@ifnextchar[\@MyMarginNote{\@MyMarginNote[]}}% +% 18 janvier 2014, j'ai besoin d'un raccourci. +\let\inmarg\MyMarginNote +\def\@MyMarginNote [#1]#2{% + \vadjust{\vskip-\dp\strutbox + \smash{\hbox to 0pt + {\color[named]{PineGreen}\normalfont\small + \hsize 1.5cm\rightskip.5cm minus.5cm + \hss\vtop{\noindent #2}\ $\to$#1\ }}% + \vskip\dp\strutbox }\strut{}} +\def\MyMarginNoteWithBrace #1{% + \vadjust{\vskip-\dp\strutbox + \smash{\hbox to 0pt + {\color[named]{PineGreen}\normalfont\small + \hss #1\ $\Bigg\{$\ }}% + \vskip\dp\strutbox }\strut{}} +\def\IMPORTANT {\MyMarginNoteWithBrace {IMPORTANT!}} +% 26 novembre 2013: +\def\etype #1{% + \vadjust{\vskip-\dp\strutbox + \smash{\hbox to 0pt {\hss\color[named]{PineGreen}% + \itshape \xintListWithSep{\,}{#1}\ $\star$\quad }}% + \vskip\dp\strutbox }\strut{}} +\def\retype #1{% + \vadjust{\vskip-\dp\strutbox + \smash{\hbox to 0pt {\hss\color[named]{PineGreen}% + \itshape \xintListWithSep{\,}{#1}\ \ding{73}\quad }}% + \vskip\dp\strutbox }\strut{}} +\def\ntype #1{% + \vadjust{\vskip-\dp\strutbox + \smash{\hbox to 0pt {\hss\color[named]{PineGreen}% + \itshape \xintListWithSep{\,}{#1}\quad }}% + \vskip\dp\strutbox }\strut{}} +\def\Numf {{\vbox{\halign{\hfil##\hfil\cr \footnotesize + \upshape Num\cr + \noalign{\hrule height 0pt \vskip1pt\relax} + \itshape f\cr}}}} +\def\Ff {{\vbox{\halign{\hfil##\hfil\cr \footnotesize + \upshape Frac\cr + \noalign{\hrule height 0pt \vskip1pt\relax} + \itshape f\cr}}}} +\def\numx {{\vbox{\halign{\hfil##\hfil\cr \footnotesize + \upshape num\cr + \noalign{\hrule height 0pt \vskip1pt\relax} + \itshape x\cr}}}} +\makeatother + +%---- \centeredline: OUR OWN LITTLE MACRO FOR CENTERING LINES + +% 7 mars 2013 +% This macro allows to conveniently center a line inside a paragraph and still +% use therein \verb or other commands changing catcodes. +% A proposito, the \LaTeX \centerline uses \hsize and not \linewidth ! +% (which in my humble opinion is bad) + +% \ignorespaces ajouté le 9 juin. + +\makeatletter +\newcommand*\centeredline {% + \ifhmode \\\relax + \def\centeredline@{\hss\egroup\hskip\z@skip\ignorespaces }% + \else + \def\centeredline@{\hss\egroup }% + \fi + \afterassignment\@centeredline + \let\next=} +\def\@centeredline + {\hbox to \linewidth \bgroup \hss \bgroup \aftergroup\centeredline@ } +\makeatother + +%---- MODIFIED \verb, and verbatim like `environments' FITS BETTER OUR USE OF IT +% le \verb de doc.sty est très chiant car il a retiré \verbatim@font pour mettre +% un \ttfamily hard-coded à la place. [en fin de compte j'utilise dorénavant le +% vocable \MicroFont plutôt que \verbatim@font] +% +% à propos \do@noligs: +% macro:#1->\catcode `#1\active \begingroup \lccode `\~=`#1\relax \lowercase +% {\endgroup \def ~{\leavevmode \kern \z@ \char `#1}} +% ne manque-t-il pas un espace après le \char `#1? En effet! ça me pose des +% problèmes lorsque l'espace a catcode 10!! Ils ont voulu optimiser et gagner +% un token mais du coup ça en limite l'employabilité. +% +\def\MicroFont {\ttfamily\hyphenchar\font45 } +\def\MacroFont {\ttfamily\baselineskip12pt\relax} +\makeatletter + +% \makestarlowast ajouté le 8 juin 2013 + +% 18 octobre 2013, hyphénation dans les blocs verbatim +\def\dobackslash +{% + \catcode92 \active + \begingroup \lccode `\~=92\relax + \lowercase {\endgroup \def ~{\hskip \z@\@plus.1pt\@minus.1pt \char 92 }}% +}% +\def\dobraces +{% + \catcode123 \active + \begingroup \lccode `\~=123\relax + \lowercase {\endgroup \def ~{\hskip \z@\@plus.1pt\@minus.1pt + \char 123 }}% + \catcode125 \active + \begingroup \lccode `\~=125\relax + \lowercase {\endgroup \def ~{\char 125 \hskip \z@\@plus.1pt\@minus.1pt }}% +}% +% modif de \do@noligs: \char`#1} --> \char`#1 } +\def\do@noligs #1% +{% + \catcode `#1\active + \begingroup \lccode `\~=`#1\relax + \lowercase {\endgroup \def ~{\leavevmode \kern \z@ \char `#1 }}% +}% +% *** \verb utilise \MicroFont +\def\verb +{% + \relax \ifmmode\hbox\else\leavevmode\null\fi + \bgroup \MicroFont + \let\do\do@noligs \verbatim@nolig@list + \let\do\@makeother \dospecials \catcode32 10 + \dobackslash + \dobraces + \makestarlowast \@jfverb +}% +% +\long\def\lverb % pour utilisation dans la partie implémentation +% *** \lverb utilise \MacroFont (comme \verbatim) +{% + \relax\par\smallskip\noindent\null + \begingroup + \let\par\@@par\hbadness 100 \hfuzz 100pt\relax + \hsize .85\hsize + \MacroFont + \bgroup + \aftergroup\@@par \aftergroup\endgroup \aftergroup\medskip + \let\do\do@noligs \verbatim@nolig@list + \let\do\@makeother \dospecials + \catcode32 10 \catcode`\% 9 \catcode`\& 14 \catcode`\$ 0 + \@jfverb +} +% et voilà. Comme quoi, on peut aussi faire sans \trivlist si on veut. +% Voir aussi la re-définition de \MacroFont au moment du \StopEventually +% +% *** \dverb utilise \MacroFont (comme \verbatim) +% +% J'ai parfois besoin d'un caractère de contrôle, j'avais dans les premières +% versions de cette doc utilisé & ou $ mais ceci est devenu très peu commode +% lorsque j'ai commencé à insérer des tabular. Finalement j'ai fait sans, mais +% je prends aujourd'hui " qui par miracle est compatible aux emplois de \dverb +% dans la doc, et va me permettre par exemple d'en colorier des parties, via +% méthode sioux pour disposer des { et } temporairement. +% +\long\def\dverb % pour utilisation dans le manuel de l'utilisateur +{% + \relax\par\smallskip + \bgroup + \parindent0pt + \def\par{\@@par\leavevmode\null}% + \let\do\do@noligs \verbatim@nolig@list + \let\do\@makeother \dospecials + \def\"{\begingroup\catcode123 1 \catcode 125 2 \dverbescape}% + \catcode`\@ 14 \catcode`\" 0 \makestarlowast + \MacroFont \obeylines \@vobeyspaces + \@jfverb +} +\def\dverbescape #1;!{#1\endgroup } + +\def\@jfverb #1{\catcode`#1\active + \lccode`\~`#1\lowercase{\let~\egroup}}% +\makeatother + +\catcode`\_=11 + +\def\csa_aux #1{\ttfamily\hyphenchar\font45 \char`\\% + \scantokens{#1}\endgroup } +\def\csb_aux #1{\hyperref[\detokenize{xint#1}]{\ttfamily + \hyphenchar\font45 \char`\\\mbox{xint}\-% + \scantokens{#1}}\endgroup } + +\DeclareRobustCommand\csa {\begingroup\catcode`\_=11 + \everyeof{\noexpand}\endlinechar -1 + \makeatother + \makestarlowast + \csa_aux } +\DeclareRobustCommand\csbnolk {\begingroup\catcode`\_=11 + \everyeof{\noexpand}\endlinechar -1 + \makestarlowast + \makeatother + \color{blue}% + \csa_aux } +\DeclareRobustCommand\csbxint {\begingroup\catcode`\_=11 + \everyeof{\noexpand}\endlinechar -1 + \makestarlowast + \makeatother + \csb_aux } +\catcode`\_=8 + +\newcommand\csh[1]{\texorpdfstring{\csa{#1}}{\textbackslash #1}} +\newcommand\csbh[1]{\texorpdfstring{\csbnolk{#1}}{\textbackslash #1}} + +% emploi de \xintFor à partir de 1.09c +% There were some color leaks in 1.09i from dvipdfmx (not pdflatex) compilation, +% due to missing braces around use of \color, I have now added them. +\xintForpair #1#2 in +{(xinttools,tools),(xint,xint),(xintbinhex,binhex),(xintgcd,gcd),% + (xintfrac,frac),(xintseries,series),(xintcfrac,cfrac),(xintexpr,expr)} +\do +{% + \expandafter\def\csname #1name\endcsname + {\texorpdfstring + {\hyperref[sec:#2]% + {{\color{joli}\bfseries\ttfamily\hyphenchar\font45 #1}}} + {#1}% + \xspace }% + \expandafter\def\csname #1nameimp\endcsname + {\texorpdfstring + {\hyperref[sec:#2imp]% + {{\color[named]{RoyalPurple}% + \bfseries\ttfamily\hyphenchar\font45 #1}}} + {#1}% + \xspace }% +}% + +\frenchspacing +\renewcommand\familydefault\sfdefault + +%---- QUICK WAY TO PRINT LONG THINGS, IN PARTICULAR, BUT NOT EXCLUSIVELY, LONG +% NUMBERS +\def\allowsplits #1% +{% + \ifx #1\relax \else #1\hskip 0pt plus 1pt\relax + \expandafter\allowsplits\fi +}% +\def\printnumber #1% first ``fully'' expands its argument. +{\expandafter\allowsplits \romannumeral-`0#1\relax }% + + +%--- counts used in particular in the samples from the documentation of the +% xintseries.sty package +\newcount\cnta +\newcount\cntb +\newcount\cntc + +%--- printing (systematically) * in a lowered position in the various verbatim +% blocks using txtt. + +\def\lowast{\raisebox{-.25\height}{*}} +\begingroup + \catcode`* 13 + \gdef\makestarlowast {\let*\lowast\catcode`\*\active}% +\endgroup + +% 22 octobre 2013 +\newcommand\fexpan {\textit{f}-expan} + +% December 7, 2013. Expandably computing a big Fibonacci number +% with the help of TeX+\numexpr+\xintexpr, (c) Jean-François Burnol +\catcode`_ 11 +% +% ajouté 7 janvier 2014 au xint.dtx pour 1.07j. +% +% Le 17 janvier je me décide de simplifier l'algorithme car l'original ne tenait +% pas compte de la relation toujours vraie A=B+C dans les matrices symétriques +% utilisées en sous-main [[A,B],[B,C]]. +% +% la version ici est celle avec les * omis: car multiplication tacite devant les +% sous-expressions depuis 1.09j, et aussi devant les parenthèses depuis 1.09k. +% (pour tester) +\def\Fibonacci #1{% + \expandafter\Fibonacci_a\expandafter + {\the\numexpr #1\expandafter}\expandafter + {\romannumeral0\xintiieval 1\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval 1\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval 1\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval 0\relax}} +% +\def\Fibonacci_a #1{% + \ifcase #1 + \expandafter\Fibonacci_end_i + \or + \expandafter\Fibonacci_end_ii + \else + \ifodd #1 + \expandafter\expandafter\expandafter\Fibonacci_b_ii + \else + \expandafter\expandafter\expandafter\Fibonacci_b_i + \fi + \fi {#1}% +}% +\def\Fibonacci_b_i #1#2#3{\expandafter\Fibonacci_a\expandafter + {\the\numexpr #1/2\expandafter}\expandafter + {\romannumeral0\xintiieval sqr(#2)+sqr(#3)\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval (2#2-#3)#3\relax}% +}% end of Fibonacci_b_i +\def\Fibonacci_b_ii #1#2#3#4#5{\expandafter\Fibonacci_a\expandafter + {\the\numexpr (#1-1)/2\expandafter}\expandafter + {\romannumeral0\xintiieval sqr(#2)+sqr(#3)\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval (2#2-#3)#3\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval #2#4+#3#5\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval #2#5+#3(#4-#5)\relax}% +}% end of Fibonacci_b_ii +\def\Fibonacci_end_i #1#2#3#4#5{\xintthe#5} +\def\Fibonacci_end_ii #1#2#3#4#5{\xinttheiiexpr #2#5+#3(#4-#5)\relax} +\catcode`_ 8 + +\def\Fibo #1.{\Fibonacci {#1}} + +\begin{document}\thispagestyle{empty}\rmfamily +\pdfbookmark[1]{Title page}{TOP} +\makeatletter + +\begingroup\lccode`\~=`@ +\lowercase{\endgroup\def~}{\begingroup\fontfamily{lmtt}\selectfont + \let\do\@makeother\dospecials + \catcode`\@ \active + \jfendshrtverb } +\catcode`\@ \active +\def\jfendshrtverb #1@{#1\endgroup } + +% nice background added for 1.09j release, January 7, 2014. +% superbe, non? moi très content! +% bon je peaufine ce background le 17 janvier, c'est hard-coded mais je ne veux +% pas y passer plus de temps (ce qui est amusant c'est que j'ai constaté a +% posteriori qu'il y a 17 chiffres par lignes donc 1 chiffre avec son padding = +% 1cm... +% *\message{\xinttheexpr round(\dimexpr 8cm\relax/17,3)\relax} +% 877496.353 +\def\specialprintone #1% +{% + \ifx #1\relax \else \makebox[877496sp]{#1}\hskip 0pt plus 2sp\relax + \expandafter\specialprintone\fi +}% +\def\specialprintnumber #1% first ``fully'' expands its argument. +{\expandafter\specialprintone \romannumeral-`0#1\relax }% + +\AddToShipoutPicture*{% + \put(10.5cm,14.85cm) + {\makebox(0,0) + {\resizebox{17cm}{!}{\vbox + {\hsize 8cm\Huge\baselineskip.8\baselineskip\color{black!10}% + \digitstt{\specialprintnumber{F(1250)=}% + \specialprintnumber{\Fibonacci{1250}}}\par}}% + } + }% +} + +% Octobre 2013: le & est devenu assez pénible puisque j'en ai besoin dans mes +% exemples de \xintApplyInline/\xintFor avec des tabulars. Donc je décide +% (après avoir temporairement fait des choses un peu lourdes avec \lverb) de +% le remplacer par @ car il n'y en a quasi pas dans la partie user manual; +% idem pour \dverb. Cependant je dois faire attention avec un @ actif par +% exemple dans les tables de matières. Bon on va voir. + +{\normalfont\Large\parindent0pt \parfillskip 0pt\relax + \leftskip 2cm plus 1fil \rightskip 2cm plus 1fil + The \xintname bundle\par}% +{\centering + \textsc{Jean-François Burnol}\par + \footnotesize \ttfamily + jfbu (at) free (dot) fr\par + Package version: \xintversion\ (\xintdate)% + \let\thefootnote\empty + \footnote{Documentation generated from the + source file with timestamp ``\dtxtimestamp''.}\par +} +\setcounter{footnote}{0} + +\bigskip + +% comme \dverb ne fait pas un \par à la fin, il y a un problème avec le +% \baselineskip si on ne le spécifie pas en plus; il faudra que je voie si +% vraiment j'utilise \dverb sans terminer un paragraphe, il doit y avoir au plus +% quelque cas. +\begingroup\footnotesize\def\MacroFont {\ttfamily\baselineskip10pt\relax} +\baselineskip 10pt +\dverb|@ +\input xintexpr.sty +% December 7, 2013. Expandably computing a big Fibonacci number +% using TeX+\numexpr+\xintexpr, (c) Jean-François Burnol +% January 17, 2014: algorithm modified to be more economical in computations. + +\catcode`_ 11 + +\def\Fibonacci #1{% + \expandafter\Fibonacci_a\expandafter + {\the\numexpr #1\expandafter}\expandafter + {\romannumeral0\xintiieval 1\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval 1\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval 1\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval 0\relax}} + +\def\Fibonacci_a #1{% + \ifcase #1 + \expandafter\Fibonacci_end_i + \or + \expandafter\Fibonacci_end_ii + \else + \ifodd #1 + \expandafter\expandafter\expandafter\Fibonacci_b_ii + \else + \expandafter\expandafter\expandafter\Fibonacci_b_i + \fi + \fi {#1}% +}% + +\def\Fibonacci_b_i #1#2#3{\expandafter\Fibonacci_a\expandafter + {\the\numexpr #1/2\expandafter}\expandafter + {\romannumeral0\xintiieval sqr(#2)+sqr(#3)\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval (2*#2-#3)*#3\relax}% +}% end of Fibonacci_b_i + +\def\Fibonacci_b_ii #1#2#3#4#5{\expandafter\Fibonacci_a\expandafter + {\the\numexpr (#1-1)/2\expandafter}\expandafter + {\romannumeral0\xintiieval sqr(#2)+sqr(#3)\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval (2*#2-#3)*#3\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval #2*#4+#3*#5\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval #2*#5+#3*(#4-#5)\relax}% +}% end of Fibonacci_b_ii + +\def\Fibonacci_end_i #1#2#3#4#5{\xintthe#5} +\def\Fibonacci_end_ii #1#2#3#4#5{\xinttheiiexpr #2*#5+#3*(#4-#5)\relax} + +\catcode`_ 8 + +% This \Fibonacci macro is designed to compute *one* Fibonacci number, not a +% whole sequence of them. Let's reap the fruits of our work: + +\message{F(1250)=\Fibonacci {1250}} +\bye |\ttfamily\% see \autoref{ssec:fibonacci} for some explanations and +more.\par +\endgroup + +\clearpage + +% \pagebreak[3] + +\pdfbookmark[1]{Abstract}{ABSTRACT} + +\begin{addmargin}{1cm}\footnotesize + \begin{center} \bfseries\large Description of the packages\par\smallskip + \end{center}\medskip +\makeatletter +\renewenvironment{description} + {\list{}{\topsep\z@ \parsep\z@ \labelwidth\z@ \itemindent-\leftmargin + \let\makelabel\descriptionlabel}} + {\endlist} +\makeatother +\begin{description} +\item[\xinttoolsname] is loaded by \xintname (hence by all other packages of the + bundle, too): it provides utilities of independent interest such as expandable + and non-expandable loops. + +\item[\xintname] implements with expandable \TeX{} macros additions, + subtractions, multiplications, divisions and powers with arbitrarily long + numbers. + +\item[\xintfracname] extends the scope of \xintname to decimal numbers, to + numbers in scientific notation and also to fractions with arbitrarily + long such numerators and denominators separated by a forward slash. + +\item[\xintexprname] extends \xintfracname with an expandable parser |\xintexpr + . . . \relax| of expressions involving arithmetic operations in infix notation + on decimal numbers, fractions, numbers in scientific notation, with + parentheses, factorial symbol, function names, comparison operators, logic + operators, twofold and threefold way conditionals, sub-expressions, macros + expanding to the previous items. +\end{description} + +\noindent Further modules: +% +\begin{description} +\item[\xintbinhexname] is for conversions to and from binary and + hexadecimal bases. + +\item[\xintseriesname] provides some basic functionality for computing in an + expandable manner partial sums of series and power series with fractional + coefficients. + +\item[\xintgcdname] implements the Euclidean algorithm and its typesetting. + +\item[\xintcfracname] deals with the computation of continued fractions. +\end{description} + + Most macros, and all of those doing computations, work purely by expansion + without assignments, and may thus be used almost everywhere in \TeX{}. + + The packages may be used with any flavor of \TeX{} supporting the \eTeX{} + extensions. \LaTeX{} users will use |\usepackage| and others |\input| to + load the package components. + +\end{addmargin} + +\bigskip + +% \clearpage +% 18 octobre 2013, je remets la TOC ici. + +% je ne veux pas non plus que la main toc se liste elle-même donc je passe pour +% elle aussi à \section* + +\etocsetlevel{toctobookmark}{6} % 9 octobre 2013, je fais des petits tricks. + +% 18 novembre 2013, je n'inclus plus la TOC détaillée de xintexpr. Je +% reconfigure la TOC. + +\etocsettocdepth {subsection} + +\renewcommand*{\etocbelowtocskip}{0pt} +\renewcommand*{\etocinnertopsep}{0pt} +\renewcommand*{\etoctoclineleaders} + {\hbox{\normalfont\normalsize\hbox to 1ex {\hss.\hss}}} +\etocmulticolstyle [2]{% + \phantomsection\section* {Contents} + \etoctoccontentsline*{toctobookmark}{Contents}{1}% +} + + \etocsettagdepth {description}{section} + \etocsettagdepth {commandsA} {none} + \etocsettagdepth {xintexpr} {none} + \etocsettagdepth {commandsB} {none} + \etocsettagdepth {implementation}{none} +\tableofcontents +\etocmulticolstyle [2]{\raggedcolumns}{} + \etocsettagdepth {description}{none} + \etocsettagdepth {commandsA} {section} + \etocsettagdepth {xintexpr} {section} + \etocsettagdepth {commandsB} {section} + \etocsettagdepth {implementation}{section} +\tableofcontents +\medskip + +% pour la suite: +\etocignoredepthtags +\etocmulticolstyle [1]{% + \phantomsection\section* {Contents} + \etoctoccontentsline*{toctobookmark}{Contents}{2}% +} + +\etocdepthtag.toc {description} + +% \pdfbookmark[1]{Snapshot}{SNAPSHOT} + +\section{Read me first}\label{sec:quickintro} + +This section provides recommended reading on first discovering the package; +complete details are given later in the manual. + +{\etocdefaultlines\etocsettocstyle{}{}\localtableofcontents} + +\subsection{Presentation of the package} + +The components of the \xintname bundle provide macros dedicated to +\emph{expandable} computations on numbers exceeding the \TeX{} (and \eTeX{}) +limit of \digitstt{\number"7FFFFFFF}. + +The \eTeX{} extensions must be enabled; this is the case in modern +distributions by default, except if \TeX{} is invoked under the name +|tex| in command line (|etex| should be used then, or |pdftex| in |DVI| +output mode). All components may be used as regular \LaTeX{} packages +or, with any other format based on \TeX{}, loaded directly via +\string\input{} (e.g. |\input +xint.sty\relax|). +% +% {\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. + +The \xintname bundle consists of the three principal components \xintname, +\xintfracname (which loads \xintname), and \xintexprname (which loads +\xintfracname), and four additional modules. The macros of the \xintname bundle +not dealing directly with the manipulation of big numbers belong to a package +\xinttoolsname (automatically loaded by all others), which is of independent +interest. + +\subsection{User interface} + +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 |^| 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. + +In the latter case 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. In the former (macro) case 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 \csbxint{expr}|..\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 its 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 (1.)~\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.} (2.)~\emph{apply this \fexpan sion to each one of their + arguments.} 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}. + +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: +% +\centeredline{|\def\x{17} \def\y{35} \edef\z{\xintMul {\x}{\y}}|} +% +As a faster alternative to |\edef| (when hundreds of digits are involved), the +package provides |\oodef| which only expands twice its argument. + +The \xintexprname package has a private internal +representation for the evaluated computation result. With +% +\centeredline{|\oodef\z {\xintexpr 3.141^17\relax}|} +% +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 +% +\centeredline{|\xintexpr \z+1/\z\relax|} +% +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 example above produces a somewhat large output: +\digitstt{\oodef\z {\xintexpr 3.141^17\relax}% + \printnumber {\xinttheexpr \z+1/\z\relax }} + + \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. + \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 +% +\centeredline{|-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 +% +\centeredline{\digitstt{\xintRaw{-123.45602e78/+765.987e-123}}} +% +The optional forward slash |/| introducing a denominator is not an operation, +but a denomination for a fractional input. Reduction to the irreducible form +must be asked for explicitely via the \csbxint{Irr} macro or the |reduce| +function within |\xintexpr..\relax|. Elementary operations on fractions work +blindly (addition does not even check for equality of the denominators and +multiply them automatically) and do none of the simplifications which +could be obvious to (some) human beings. + + +\subsection{Space and time, floating point macros} + +The size of the manipulated numbers is limited by two +factors:\footnote{there is an intrinsic limit of + \digitstt{\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}. The most limiting factor is the second one, the time +needed (for multiplication and division, and even more for powers) +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, as it takes of the order of seconds (on my +laptop) for the package to multiply exactly two numbers each of @1000@ digits +and it would take hours for numbers each of @20000@ digits.\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.} + +To address this issue, floating +point macros are provided to work with a given arbitrary precision. The default +size for significands is @16@ digits. Working with significands of @24@, @32@, +@48@, @64@, or even @80@ digits is well within the reach of the package. But +routine multiplications and divisions will become too slow if the precision goes +into the hundreds, although the syntax to set it (|\xintDigits:=P;|) allows +values up to @32767@.\footnote{for a one-shot conversion of a fraction to float + format, or one addition, a precision exceeding \digitstt{32767} may be passed + as optional argument to the used macro.} The exponents may be as big as +\digitstt{$\pm$\number"7FFFFFFF}.\footnote{almost\dots{} as inner manipulations + may either add or subtract the precision value to the exponent, arithmetic + overflow may occur if the exponents are a bit to close to the \TeX{} bound + \digitstt{$\pm$\number"7FFFFFFF}.} + +Here is such a floating point computation: \centeredline{|\xintFloatPower [48] + {1.1547}{\xintiiPow {2}{35}}|} which thus computes +$(1.1547)^{2^{35}}=(1.1547)^{\xintiiPow {2}{35}}$ to be approximately +\centeredline{\digitstt{\np{\xintFloatPower [48] {1.1547}{\xintiiPow + {2}{35}}}}} +% +Notice that @2^35@ exceeds \TeX's bound, but \csa{xintFloatPower} allows it, +what counts is the exponent of the result which, while dangerously close to +@2^31@ is not quite there yet. The printing of the result was done via the +|\numprint| command from the \href{http://ctan.org/pkg/numprint}{numprint} +package\footnote{\url{http://ctan.org/pkg/numprint}}. + +The same computation can be done via the non-expandable assignment +|\xintDigits:=48;| and then \centeredline{|\xintthefloatexpr + 1.1547^(2^35)\relax|} Notice though that |2^35| will be evaluated as a +floating point number, and if the floating point precision had been too +low, this computation would have given an inexact value. It is safer, +and also more efficient to code this as: +% +\centeredline{|\xintthefloatexpr 1.1547^\xintiiexpr 2^35\relax\relax|} +% +The |\xintiiexpr| is a cousin of |\xintexpr| which is big integer-only and skips +the overhead of fraction management. Notice on this example that being +embedded inside the |floatexpr|-ession has nil influence on the +|iiexpr|-ession: expansion proceeds in exactly the same way as if it had +been at the `top' level. + + +\xintexprname provides \emph{no} implementation of the |IEEE| standard: +no |NaN|s, signed infinities, signed zeroes, error traps, \dots; what is +achieved though is exact rounding for the basic operations. The only +non-algebraic operation currently implemented is square root extraction. +The power functions (there are three of them: \csbxint{Pow} to which |^| +is mapped in |\xintexpr..\relax|, \csbxint{FloatPower} for |^| in +|\xintfloatexpr..relax|, and \csbxint{FloatPow} which is slighty faster +but limits the exponent to the \TeX{} bound) allow only integral +exponents. + + +\subsection{Printing big numbers on the page} + +When producing very long numbers there is the question of printing them on + the page, without going beyond the page limits. In this document, I have most + of the time made use of these macros (not provided by the package:) + +% +\begingroup\baselineskip11pt\def\MacroFont{\small\ttfamily\baselineskip11pt\relax }% +\dverb|@ +\def\allowsplits #1{\ifx #1\relax \else #1\hskip 0pt plus 1pt\relax + \expandafter\allowsplits\fi}% +\def\printnumber #1{\expandafter\allowsplits \romannumeral-`0#1\relax }% +% \printnumber thus first ``fully'' expands its argument.| +\par\endgroup +% +An alternative (\autoref{fn:np}) is to suitably configure the thousand separator +with the \href{http://ctan.org/pkg/numprint}{numprint} package (does not work in +math mode; I also tried \href{http://ctan.org/pkg/siunitx}{siunitx} but even in +text mode could not get it to break numbers accross lines). Recently I became +aware of the +\href{http://ctan.org/pkg/seqsplit}{seqsplit} +package\footnote{\url{http://ctan.org/pkg/seqsplit}} +which can be used to achieve this splitting accross lines, and does work +in inline math mode.\par + +\subsection{Expandable implementations of mathematical algorithms} + +Another use of the |\xintexpr|-essions is illustrated with the algorithm on the +title page: it shows how one may chain expandable evaluations, almost as if one +were using the |\numexpr| facilities.\footnote{The implementation uses the + (already once-expanded) integer only variant \csa{xintiiexpr} as \csa{romannumeral0}\csa{xintiieval..}\csa{relax}.} +Notice that the @47@th Fibonacci number is \digitstt{\Fibonacci {47}} thus +already too big for \TeX{} and \eTeX{}, a difficulty which our front page showed +how to overcome (see \autoref{ssec:fibonacci} for more). The |\Fibonacci| macro +is completely expandable hence can be used for example within |\message| to +write to the log and terminal. + +It is even \fexpan dable (although not in only two steps, this could be added +but does not matter here), thus if we are interested in knowing how many digits +@F(1250)@ has, suffices to use |\xintLen {\Fibonacci {1250}}| (which expands to +\digitstt{\xintLen {\Fibonacci {1250}}}), or if we want to check the formula +@gcd(F(1859),F(1573))=F(gcd(1859,1573))=F(143)@, we only need\footnote{The + \csa{xintGCD} macro is provided by the \xintgcdname package.} +\centeredline{|\xintGCD{\Fibonacci{1859}}{\Fibonacci{1573}}=\Fibonacci{\xintGCD{1859}{1573}}|} +\centeredline{\digitstt{\printnumber{\xintGCD{\Fibonacci{1859}}{\Fibonacci{1573}}}=\printnumber{\Fibonacci{\xintGCD{1859}{1573}}}}} + +The |\Fibonacci| macro expanded its |\xintGCD{1859}{1573}| argument via the +services of |\numexpr|: this step allows only things obeying the \TeX{} bound, +naturally! (but \digitstt{F(\xintiiPow2{31}}) would be rather big anyhow...). + + +\section{Recent changes} + +\footnotesize + +\noindent Release |1.09ka| (|[2014/02/05]|): +\begin{itemize} +\item bug fix (\xinttoolsname): \csbxint{BreakFor} and \csbxint{BreakForAndDo} + were buggy when used in the last iteration of an |\xintFor| loop. +\item bug fix (\xinttoolsname): \csbxint{Seq} from |1.09k| needed a |\chardef| + which was missing from |xinttools.sty|, it was in |xint.sty|. +\end{itemize} + +\noindent Release |1.09k| (|[2014/01/21]|): +\begin{itemize} +\item inside |\xintexpr..\relax| (and its variants) tacit multiplication + is implied when a number or operand is followed directly with an + opening parenthesis, +\item the |"| for denoting (arbitrarily big) hexadecimal numbers is recognized + by |\xintexpr| and its variants (package \xintbinhexname is required); a + fractional hexadecimal part introduced by a + dot |.| is allowed. +\item re-organization of the first sections of the user manual. +\item bug fix: forgotten loading time |"| catcode sanity check has been added. +\end{itemize} + +For a more detailed change history, see \autoref{sec:releases}. Main recent +additions: \smallskip + +\noindent Release |1.09j| (|[2014/01/09]|): +\begin{itemize} +\item the core division routines have been re-written for some (limited) + efficiency gain, more pronounced for small divisors. As a result the + \hyperlink{Machin1000}{computation of one thousand digits of $\pi$} + is close to three times faster than with earlier releases. +\item a new macro \csbxint{XTrunc} is designed to produce thousands or even tens + of thousands of digits of the decimal expansion of a fraction. +\item the tacit multiplication done in \csbxint{expr}|..\relax| on encountering + a count register or variable, or a |\numexpr|, while scanning a (decimal) + number, is extended to the case of a sub |\xintexpr|-ession. +\item \csbxint{expr} can now be used in an |\edef| with no |\xintthe| + prefix. +\end{itemize} + +\noindent Release |1.09i| (|[2013/12/18]|): +\begin{itemize} +\item \csbxint{iiexpr} is a variant of \csbxint{expr} which is optimized to deal + only with (long) integers, |/| does a euclidean quotient. +\item |\xintnumexpr|, |\xintthenumexpr|, |\xintNewNumExpr| are renamed, + respectively, \csbxint{iexpr}, \csbxint{theiexpr}, \csbxint{NewIExpr}. The + earlier denominations are kept but to be removed at some point. +\item it is now possible within |\xintexpr...\relax| and its variants to use + count, dimen, and skip registers or variables without explicit |\the/\number|: + the parser inserts automatically |\number| and a tacit multiplication is + implied when a register or variable immediately follows a number or fraction. +\item \xinttoolsname defines \hyperref[odef]{\ttfamily\char92odef}, + \hyperref[oodef]{\ttfamily\char92oodef}, + \hyperref[fdef]{\ttfamily\char92fdef}. These tools are provided for the case + one uses the package macros in a non-expandable context, particularly + \hyperref[oodef]{\ttfamily\char92oodef} which expands twice the macro + replacement text and is thus a faster alternative to |\edef|. This can be + significant when repeatedly making |\def|-initions expanding to hundreds of + digits. +\end{itemize} + + +\noindent Release |1.09h| (|[2013/11/28]|): +\begin{itemize} +\item all macros of \xinttoolsname for which it makes sense are now + declared |\long|. +\end{itemize} + +\noindent Release |1.09g| (|[2013/11/22]|): +\begin{itemize} +\item package \xinttoolsname is detached from \xintname, to make tools such as + \csbxint{For}, \csbxint{ApplyUnbraced}, and \csbxint{iloop} available without + the \xintname overhead. +\item new expandable nestable loops \csbxint{loop} and \csbxint{iloop}. +\end{itemize} + +\noindent Release |1.09f| (|[2013/11/04]|): +\begin{itemize} +\item new \csbxint{ZapFirstSpaces}, \csbxint{ZapLastSpaces}, + \csbxint{ZapSpaces}, \csbxint{ZapSpacesB}, for expandably stripping away + leading and/or ending spaces. +\item \csbxint{CSVtoList} by default uses \csbxint{ZapSpacesB} to strip away + spaces around commas (or at the start and end of the comma separated list). +\item also the \csbxint{For} loop will strip out all spaces around commas and at + the start and the end of its list argument; and similarly for + \csbxint{Forpair}, \csbxint{Forthree}, \csbxint{Forfour}. +\item \csbxint{For} \emph{et al.} accept all macro parameters + from |#1| to |#9|. +\end{itemize} + + +\noindent Release |1.09e| (|[2013/10/29]|): +\begin{itemize} +\item new \csbxint{integers}, \csbxint{dimensions}, \csbxint{rationals} for + infinite \csbxint{For} loops, interrupted with \csbxint{BreakFor} and + \csbxint{BreakForAndDo}. +\item new \csbxint{ifForFirst}, \csbxint{ifForLast} for the \csa{xintFor} and + \csa{xintFor*} loops, +\item the \csa{xintFor} and \csa{xintFor*} loops are now |\long|, the + replacement text and the items may contain explicit |\par|'s. +\item new conditionals \csbxint{ifCmp}, \csbxint{ifInt}, \csbxint{ifOdd}. +\item the documentation has been enriched with various additional examples, + such as the \hyperref[ssec:quicksort]{the quick sort algorithm illustrated} or + the computation of prime numbers (\autoref{ssec:primesI}, + \autoref{ssec:primesII}, \autoref{ssec:primesIII}). +\end{itemize} + +\noindent Release |1.09c| (|[2013/10/09]|): +\begin{itemize} +\item added \hyperlink{item:bool}{|bool|} and \hyperlink{item:bool}{|togl|} to + the + \csbxint{expr} syntax; also added \csbxint{boolexpr} and \csbxint{ifboolexpr}. +\item \csbxint{For} is a new type of loop, whose replacement text inserts the + comma separated values or list items via macro parameters, rather than + encapsulated in macros; the loops are nestable up to four levels (nine + levels since |1.09f|), + and their replacement texts are allowed to close groups as happens with the + tabulation in alignments, +\item \csbxint{ApplyInline} has been enhanced in order to be usable for + generating rows (partially or completely) in an alignment, +\item new command \csbxint{Seq} to generate (expandably) arithmetic sequences of + (short) integers, +\end{itemize} + + +\noindent Release |1.09a| (|[2013/09/24]|): +\begin{itemize} +\item \csbxint{expr}|..\relax| and + \csbxint{floatexpr}|..\relax| admit functions in their + syntax, with comma separated values as arguments, among them \texttt{reduce, + sqr, sqrt, abs, sgn, floor, ceil, quo, rem, round, trunc, float, gcd, lcm, + max, min, sum, prd, add, mul, not, all, any, xor}. +\item comparison (|<|, |>|, |=|) and logical (\verb$|$, |&|) operators. +\item \csbxint{NewExpr} now works with the standard macro parameter character + |#|. +\item both regular |\xintexpr|-essions and commands defined by |\xintNewExpr| + will work with comma separated lists of expressions, +\item new commands \csbxint{Floor}, \csbxint{Ceil}, \csbxint{Maxof}, + \csbxint{Minof} (package \xintfracname), \csbxint{GCDof}, \csbxint{LCM}, + \csbxint{LCMof} (package \xintgcdname), \csbxint{ifLt}, \csbxint{ifGt}, + \csbxint{ifSgn}, \csbxint{ANDof}, ... +\item The arithmetic macros from package \xintname now filter their operands via + \csbxint{Num} which means that they may use directly count registers and + |\numexpr|-essions without having to prefix them by |\the|. This is thus + similar to the situation holding previously but with \xintfracname loaded. +\end{itemize} + +See \autoref{sec:releases} for more. + +\normalsize + + + +\section{Some examples} + +The main initial goal is to allow computations with integers and fractions of +arbitrary sizes. + +Here are some examples. The first one uses only the base module \xintname, the +next two require the \xintfracname package, which deals with fractions. Then two +examples with the \xintgcdname package, one with the \xintseriesname package, +and finally a computation with a float. Some inputs are simplified by the use +of the \xintexprname package. + +{\color{magenta}@123456^99@: }\\ +{\color[named]{Purple}\csa{xintiPow}|{123456}{99}|}: \digitstt{\printnumber{\xintiPow {123456}{99}}} + +{\color{magenta}1234/56789 with 1500 digits after the decimal point: }\\ +{\color[named]{Purple}\csa{xintTrunc}|{1500}{1234/56789}\dots|}: +\digitstt{\printnumber {\xintTrunc {1500}{1234/56789}}\dots } + +{\color{magenta}@0.99^{-100}@ with 200 digits after the decimal point:}\\ +{\color[named]{Purple}\csa{xinttheexpr trunc}|(.99^-100,200)\relax\dots|}: +\digitstt{\printnumber{\xinttheexpr trunc(.99^-100,200)\relax}\dots } + + +{\color{magenta}% + Computation of a Bezout identity with |7^200-3^200| and |2^200-1|:}\par +{\color[named]{Purple} +\dverb|@ +\xintAssign \xintBezout {\xinttheiexpr 7^200-3^200\relax} + {\xinttheiexpr 2^200-1\relax}\to\A\B\U\V\D|% +\centeredline {|\U$\times$(7^200-3^200)+\xintiOpp\V$\times$(2^200-1)=\D|}}% +% +\xintAssign \xintBezout {\xinttheiexpr 7^200-3^200\relax} + {\xinttheiexpr 2^200-1\relax}\to\A\B\U\V\D +\digitstt +{\printnumber\U$\times$(@7^200-3^200@)+% + \printnumber{\xintiOpp\V}$\times$(@2^200-1@)=\printnumber\D} + +\textcolor{magenta}{The Euclide algorithm applied to +\np{22206980239027589097} and \np{8169486210102119256}:}% +\footnote{this example is computed tremendously faster than the + other ones, but we had to limit the space taken by the output.}\par +{\color[named]{Purple} +\noindent|\xintTypesetEuclideAlgorithm +{22206980239027589097}{8169486210102119256}|\endgraf} +\xintTypesetEuclideAlgorithm +{22206980239027589097}{8169486210102119256} \smallskip + +{\color{magenta}$\sum_{n=1}^{500} (4n^2 - 9)^{-2}$ with each term rounded to + twelve digits, and the sum to nine digits:} {\color[named]{Purple}% + |\def\coeff #1%|\\ + | {\xintiRound {12}{1/\xintiSqr{\the\numexpr 4*#1*#1-9\relax }[0]}}|\\ + |\xintRound {9}{\xintiSeries {1}{500}{\coeff}[-12]}|:} \def\coeff #1% +{\xintiRound {12}{1/\xintiSqr{\the\numexpr 4*#1*#1-9\relax }[0]}} +\digitstt{\xintRound {9}{\xintiSeries {1}{500}{\coeff}[-12]}}\endgraf + +The complete series, extended to +infinity, has value +$\frac{\pi^2}{144}-\frac1{162}={}$% +\digitstt{\np{0.06236607994583659534684445}\dots}\,% +\footnote{\label{fn:np}This number is typeset using the + \href{http://www.ctan.org/pkg/numprint}{numprint} package, with + \texttt{\detokenize{\npthousandsep{,\hskip 1pt plus .5pt minus .5pt}}}. + But the breaking across + lines works only in text mode. The number itself was (of course...) computed + initially with \xintname, with 30 digits of $\pi$ as input. + See + \hyperref[ssec:Machin]{{how {\xintname} may compute $\pi$ + from scratch}}.} I also used (this is a lengthier computation +than the one above) \xintseriesname to evaluate the sum with \np{100000} terms, +obtaining 16 +correct decimal digits for the complete sum. The +coefficient macro must be redefined to avoid a |\numexpr| overflow, as +|\numexpr| inputs must not exceed @2^31-1@; my choice +was: +{\color[named]{Purple}\dverb|@ +\def\coeff #1% +{\xintiRound {22}{1/\xintiSqr{\xintiMul{\the\numexpr 2*#1-3\relax} + {\the\numexpr 2*#1+3\relax}}[0]}} +|% +}% + + +{\color{magenta}Computation of $2^{\np{999999999}}$ with |24| significant + figures:}\\ +|\numprint{|{\color[named]{Purple}|\xintFloatPow [24] {2}{999999999}|}|}| expands to: +\centeredline{\digitstt{\np{\xintFloatPow [24] {2}{999999999}}}} where the +|\numprint| macro from the \hyperref[fn:np]{eponym package} was used. + +\edef\x{\xintQuo{\xintPow {2}{1000}}{\xintFac{100}}} +\edef\y{\xintLen{\x}} + +As an example of chaining package macros, let us consider the following +code snippet within a file with filename |myfile.tex|: +\dverb|@ +\newwrite\outstream +\immediate\openout\outstream \jobname-out\relax +\immediate\write\outstream {\xintQuo{\xintPow{2}{1000}}{\xintFac{100}}} +% \immediate\closeout\outstream +|% +The tex run creates a file |myfile-out.tex|, and then writes to it the quotient +from the euclidean division of @2^{1000}@ by @100!@. The number of digits is +|\xintLen{\xintQuo{\xintPow{2}{1000}}{\xintFac{100}}}| which expands (in two +steps) and tells us that @[2^{1000}/100!]@ has {\y} digits. This is not so many, +let us print them here: \digitstt{\printnumber\x}. + +For the sake of typesetting this documentation and not have big numbers +extend into the margin and go beyond the page physical limits, I use +these commands (not provided by the package): +\dverb|@ +\def\allowsplits #1{\ifx #1\relax \else #1\hskip 0pt plus 1pt \relax + \expandafter\allowsplits\fi}% +\def\printnumber #1% first ``fully'' expands its argument. +{\expandafter\allowsplits \romannumeral-`0#1\relax }| + +The |\printnumber| macro is not part of the package and would need additional +thinking for more general use.\footnote{as explained in \hyperref[fn:np]{a + previous footnote}, the |numprint| package may also be used, in text mode + only (as the thousand separator seemingly ends up typeset in a |\string\hbox| + when in math mode).} It may be used like this: +% +\centeredline{|\printnumber {\xintQuo{\xintPow {2}{1000}}{\xintFac{100}}}|} +or as |\printnumber\mynumber| or |\printnumber{\mynumber}| if +|\mynumber| was previously defined via a |\newcommand|, or a |\def|: +% +\centeredline{% + |\def\mynumber {\xintQuo {\xintPow {2}{1000}}{\xintFac{100}}}|}% + + +Just to show off (again), let's print 300 digits (after the decimal point) of +the decimal expansion of @0.7^{-25}@:\footnote{the |\string\np| typesetting + macro is from the |numprint| package.} +\centeredline{|\np {\xinttheexpr trunc(.7^-25,300)\relax}\dots|} + \digitstt{\np {\xinttheexpr trunc(.7^-25,300)\relax}\dots } + +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}. The fraction |.7^-25| is first evaluated \emph{exactly}; for +some more complex inputs, such as |.7123045678952^-243|, the exact evaluation +before truncation would be expensive, and (assuming one needs twenty digits) one +would rather use floating mode: \centeredline{|\xintDigits:=20; + \np{\xintthefloatexpr .7123045678952^-243\relax}|}% +\xintDigits:=20;% +\centeredline{|.7123045678952^-243|${}\approx{}$% + \digitstt{\np{\xintthefloatexpr .7123045678952^-243\relax }}} 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 + +\xintDigits:=16; + + +\section {Further illustrative examples within this document} +\label{sec:awesome} + + +The utilities provided by \xinttoolsname (\autoref{sec:tools}), some +completely expandable, others not, are of independent interest. Their +use is illustrated through various examples: among those, it is shown in +\autoref{ssec:quicksort} how to implement in a completely expandable way +the \hyperref[quicksort]{Quick Sort algorithm} and also how to +illustrate it graphically. Other examples include some dynamically +constructed alignments with automatically computed prime number cells: +one using a completely expandable prime test and \csbxint{ApplyUnbraced} +(\autoref{ssec:primesI}), another one with \csbxint{For*} +(\autoref{ssec:primesIII}). + +One has also a \hyperref[edefprimes]{computation of primes + within an \csa{edef}} (\autoref{xintiloop}), with the help of +\csbxint{iloop}. Also with \csbxint{iloop} an +\hyperref[ssec:factorizationtable]{automatically generated table of + factorizations} (\autoref{ssec:factorizationtable}). + +The title page fun with Fibonacci numbers is continued in +\autoref{ssec:fibonacci} with \csbxint{For*} joining the game. + +The computations of \hyperref[ssec:Machin]{ $\pi$ and $\log 2$} +(\autoref{ssec:Machin}) using \xintname and the computation of the +\hyperlink{e-convergents}{convergents of $e$} with the further help of +the \xintcfracname package are among further examples. +There is also an example of an \hyperref[xintXTrunc]{interactive + session}, where results are output to the log or to a file. + +Almost all of the computational results interspersed through the +documentation are not hard-coded in the source of the document but just written +there using the package macros, and were selected to not impact too much the +compilation time. + + +\section{General overview} + +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} + +`Arbitrarily big': this means with less than + |2^31-1|\digitstt{=\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 \digitstt{\number "7FFFFFFF} + in absolute value. + This is a distant irrelevant upper bound, as no such thing can fit + in \TeX's memory! And besides, +the true limitation is from the \emph{time} taken by the +expansion-compatible algorithms, as will be commented upon soon. + +As just recalled, ten-digits numbers starting with a @3@ already exceed the +\TeX{} bound on integers; 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. + +The \href{http://www.ctan.org/pkg/bigintcalc}{bigintcalc} package by +\textsc{Heiko Oberdiek} provided expandable operations (using some of |\numexpr| +possibilities, when available) on arbitrarily big integers, beyond the \TeX{} +bound. The present package does this again, using more of |\numexpr| (\xintname +requires the \eTeX{} extensions) for higher speed, and also on fractions, not +only integers. Arbitrary precision floating points operations are a derivative, +and not the initial design goal.\footnote{currently (|v1.08|), the only + non-elementary operation implemented for floating point numbers is the + square-root extraction; no signed infinities, signed zeroes, |NaN|'s, error + trapes\dots, have been + implemented, only the notion of `scientific notation with a given number of + significant figures'.}${}^{\text{,\,}}$\footnote{multiplication of two floats + with |P=\string\xinttheDigits| digits is first done exactly then rounded to + |P| digits, rather than using a specially tailored multiplication for floating + point numbers which would be more efficient (it is a waste to evaluate fully + the multiplication result with |2P| or |2P-1| digits.)} + +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 the \href{http://www.ctan.org/pkg/l3kernel}{l3fp} + (exactly represented) floating point numbers have their exponents limited to + $\pm$\digitstt{9999}.} + +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{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 do not cost much.} + +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. And 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{I could, naturally, be proven + wrong!}\,\footnote{The Lua\TeX{} project possibly makes endeavours + such as \xintname appear even more insane that they are, in truth.} + + +% \section{Missing things} + + +% `Arbitrary-precision' floating-point +% operations are currently limited to the basic four operations, the power +% function with integer exponent, and the extraction of square-roots. + + +\section{Origins of the package} + +Package |bigintcalc| by \textsc{Heiko Oberdiek} already +provides expandable arithmetic operations on ``big integers'', +exceeding the \TeX{} limits (of @2^{31}-1@), so why another\footnote{this section was written before the + \xintfracname package; the author is not aware of another package allowing + expandable computations with arbitrarily big fractions.} +one? + +I got started on this in early March 2013, via a thread on the +|c.t.tex| usenet group, where \textsc{Ulrich D\,i\,e\,z} used the +previously cited package together with a macro (|\ReverseOrder|) +which I had contributed to another thread.\footnote{the + \csa{ReverseOrder} could be avoided in that circumstance, but it + does play a crucial r\^ole here.} What I had learned in this +other thread thanks to interaction with \textsc{Ulrich D\,i\,e\,z} and +\textsc{GL} on expandable manipulations of tokens motivated me to +try my hands at addition and multiplication. + +I wrote macros \csa{bigMul} and \csa{bigAdd} which I posted to the +newsgroup; they appeared to work comparatively fast. These first +versions did not use the \eTeX{} \csa{numexpr} primitive, they worked +one digit at a time, having previously stored carry-arithmetic in +1200 macros. + +I noticed that the |bigintcalc| package used\csa{numexpr} +if available, but (as far as I could tell) not +to do computations many digits at a time. Using \csa{numexpr} for +one digit at a time for \csa{bigAdd} and \csa{bigMul} slowed them +a tiny bit but avoided cluttering \TeX{} memory with the 1200 +macros storing pre-computed digit arithmetic. I wondered if some speed +could be gained by using \csa{numexpr} to do four digits at a time +for elementary multiplications (as the maximal admissible number +for \csa{numexpr} has ten digits). + +The present package is the result of this initial questioning. + +% \begin{framed}\centering +% \xintname requires the \eTeX{} extensions. +% \end{framed} + + + +\section{Expansion matters} +\label{sec:expansions} + + +By convention in this manual \fexpan sion (``full expansion'' or ``full first +expansion'') is the process of expanding repeatedly the first token seen until +hitting against something not further expandable like an unexpandable +\TeX-primitive or an opening brace |{| or a character (inactive). For + those familiar with \LaTeX3 (which is not used by \xintname) this is what is + called in its documentation full expansion. Technically, macro arguments in + \xintname which are submitted to such a \fexpan sion are so via prefixing them + with |\romannumeral-`0|. An explicit or implicit space token stops such an + expansion and is gobbled. + +% +Most of the package macros, and all those dealing with computations, are +expandable in the strong sense that they expand to their final result via this +\fexpan sion. Again copied from \LaTeX3 documentation conventions, this will be +signaled in the description of the macro by a \etype{}star in the margin. +All\footnote{except \csbxint{loop} and \csbxint{iloop}.} +expandable macros of the \xintname packages completely expand in two steps. + +Furthermore the macros dealing with computations, as well as many utilities from +\xinttoolsname, apply this process of \fexpan sion to their arguments. Again +from \LaTeX3's conventions this will be signaled by a% +% +\ntype{{\setbox0 \hbox{\Ff}\hbox to \wd0 {\hss f\hss}}} +% +margin annotation. Some additional parsing +which is done by most macros of \xintname is indicated with a +variant\ntype{\Numf{\kern.5cm}}; and the extended fraction parsing done by most +macros of \xintfracname has its own symbol\ntype{\Ff}. When the argument has a +priori to obey the \TeX{} bound of \digitstt{\number"7FFFFFFF} it is +systematically fed to a |\numexpr..\relax| hence the expansion is then a +\emph{complete} one, signaled with an \ntype{\numx}\emph{x} in the margin. This +means not only complete expansion, but also that spaces are ignored, infix +algebra is possible, count registers are allowed, etc\dots + +The \csbxint{ApplyInline} and \csbxint{For*}\ntype{{\lowast f}} macros from +\xinttoolsname apply a special iterated \fexpan sion, which gobbles spaces, to +all those items which are found \emph{unbraced} from left to right in the list +argument; this is denoted specially as here in the margin. Some other macros +such as \csbxint{Sum}\ntype{f{$\to$}{\lowast\Ff}} from \xintfracname first do an +\fexpan sion, then treat each found (braced or not) item (skipping spaces +between such items) via the general fraction input parsing, this is signaled as +here in the margin where the signification of the \lowast{} is thus a bit +different from the previous case. + +A few macros from \xinttoolsname do not expand, or expand only once their +argument\ntype{n{{\color{black}\upshape, resp.}} o}. This is also +signaled in the margin with notations \`a la \LaTeX3. + +As the computations are done by \fexpan dable macros which \fexpan d their +argument they may be chained up to arbitrary depths and still produce expandable +macros. + +Conversely, wherever the package expects on input a ``big'' integers, or a +``fraction'', \fexpan sion of the argument \emph{must result in a complete + expansion} for this argument to be acceptable.\footnote{this is not quite as + stringent as claimed here, see \autoref{sec:useofcount} for more details.} +The +main exception is inside \csbxint{expr}|...\relax| where everything will be +expanded from left to right, completely. + +Summary of important expansion aspects: +\begin{enumerate} +\item the macros \fexpan d their arguments, this means that they expand + the first token seen (for each argument), then expand, etc..., until something + un-expandable + such as a\strut{} digit or a brace is hit against. This example + \centeredline{|\def\x{98765}\def\y{43210}|% + |\xintAdd {\x}{\x\y}|} is \emph{not} a legal construct, as the |\y| will + remain untouched by expansion and not get converted into the digits which + are expected by the sub-routines of |\xintAdd|. It is a |\numexpr| + which will expand it and an arithmetic overflow will arise as |9876543210| + exceeds the \TeX{} bounds. + + \begingroup\slshape + With \csbxint{theexpr} one could write |\xinttheexpr \x+\x\y\relax|, or + |\xintAdd\x{\xinttheexpr\x\y\relax}|.\hfill + \endgroup + +\item\label{fn:expansions} using |\if...\fi| constructs \emph{inside} the + package macro arguments requires suitably mastering \TeX niques + (|\expandafter|'s and/or swapping techniques) to ensure that the \fexpan sion + will indeed absorb the \csa{else} or closing \csa{fi}, else some error will + arise in further processing. Therefore it is highly recommended to use the + package provided conditionals such as \csbxint{ifEq}, \csbxint{ifGt}, + \csbxint{ifSgn}, \csbxint{ifOdd}\dots, or, for \LaTeX{} users and when dealing + with short integers the + \href{http://www.ctan.org/pkg/etoolbox}{etoolbox}\footnote{\url{http://www.ctan.org/pkg/etoolbox}} + expandable conditionals (for small integers only) such as \texttt{\char92 + ifnumequal}, \texttt{\char92 ifnumgreater}, \dots . Use of + \emph{non-expandable} things such as \csa{ifthenelse} is impossible inside the + arguments of \xintname macros. + + \begingroup\slshape + One can use naive |\if..\fi| things inside an \csbxint{theexpr}-ession + and cousins, as long as the test is + expandable, for example\upshape +\centeredline{|\xinttheiexpr\ifnum3>2 143\else 33\fi 0^2\relax|$\to$\digitstt{\xinttheiexpr \ifnum3>2 143\else 33\fi 0^2\relax =1430\char`\^2}} + \endgroup + +\item after the definition |\def\x {12}|, one can not use + {\color{blue}|-\x|} as input to one of the package macros: the \fexpan sion + will act only on the minus sign, hence do nothing. The only way is to use the + \csbxint{Opp} macro, or perhaps here rather \csbxint{iOpp} which does + maintains integer format on output, as they replace a number with + its opposite. + + \begingroup\slshape + Again, this is otherwise inside an \csbxint{theexpr}-ession or + \csbxint{thefloatexpr}-ession. There, the + minus sign may prefix macros which will expand to numbers (or parentheses + etc...) + \endgroup + +\def\x {12}% +\def\AplusBC #1#2#3{\xintAdd {#1}{\xintMul {#2}{#3}}}% + + +\item \label{item:xpxp} With the definition \centeredline{% + |\def\AplusBC #1#2#3{\xintAdd {#1}{\xintMul {#2}{#3}}}|} one obtains an + expandable macro producing the expected result, not in two, but rather in + three steps: a first expansion is consumed by the macro expanding to its + definition. As the package macros expand their arguments until no more is + possible (regarding what comes first), this |\AplusBC| may be used inside + them: {|\xintAdd {\AplusBC {1}{2}{3}}{4}|} does work and returns + \digitstt{\xintAdd {\AplusBC {1}{2}{3}}{4}}. + + If, for some reason, it is important to create a macro expanding in two steps + to its final value, one may either do: +\smallskip\centeredline {|\def\AplusBC + #1#2#3{|{\color{blue}|\romannumeral-`0\xintAdd |}|{#1}{\xintMul {#2}{#3}}}|}or use the \emph{lowercase} form of + \csa{xintAdd}: \smallskip\centeredline {|\def\AplusBC + #1#2#3{|{\color{blue}|\romannumeral0\xintadd |}|{#1}{\xintMul {#2}{#3}}}|} + + and then \csa{AplusBC} will share the same properties as do the + other \xintname `primitive' macros. + + +\end{enumerate} + +The |\romannumeral0| and |\romannumeral-`0| things above look like an invitation +to hacker's territory; if it is not important that the macro expands in two +steps only, there is no reason to follow these guidelines. Just chain +arbitrarily the package macros, and the new ones will be completely expandable +and usable one within the other. + +Since release |1.07| the \csbxint{NewExpr} command automatizes the creation of +such expandable macros: \centeredline{|\xintNewExpr\AplusBC[3]{#1+#2*#3}|} +creates the |\AplusBC| macro doing the above and expanding in two expansion +steps. + + +\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 disposals the general tools of +the \TeX{} language: |\def| or (in \LaTeX) |\newcommand|, and |\edef|. + +The \xinttoolsname package provides |\oodef| which expands twice the replacement +text, 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|. + +This section will explain the various inputs which are recognized by the package +macros and the format for their outputs. Inputs have mainly five possible +shapes: +\begin{enumerate} +\item expressions which will end up inside a |\numexpr..\relax|, +\item long integers in the strict format (no |+|, no leading zeroes, a count + register or variable must be prefixed by |\the| or |\number|) +\item long integers in the general format allowing both |-| and |+| signs, then + leading zeroes, and a count register or variable without prefix is allowed, +\item fractions with numerators and denominators as in the + previous item, or also decimal numbers, possibly in scientific notation (with + a lowercase |e|), and + also optionally the semi-private |A/B[N]| format, +\item and finally expandable material understood by the |\xintexpr| parser. +\end{enumerate} +Outputs are mostly of the following types: +\begin{enumerate} +\item long integers in the strict format, +\item fractions in the |A/B[N]| format where |A| and |B| are both strict long + integers, and |B| is positive, +\item numbers in scientific format (with a lowercase |e|), +\item the private |\xintexpr| format which needs the |\xintthe| prefix in order + to end up on the printed page (or get expanded in the log) + 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 +will be embedded in a |\numexpr..\relax| hence on input one may even use count +registers or variables and expressions with infix operators. Notice though that +|-(..stuff..)| is surprisingly not legal in the |\numexpr| syntax! + +But \xintname is mainly devoted to big numbers; +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. +\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 + digits:\centeredline{|\xintNum + {+-+-+----++-++----00000000009876543210}|\digitstt{=\xintNum + {+-+-+----++-++----0000000009876543210}}} The extended integer + format\ntype{\Numf} is thus for the arithmetic macros of \xintname which + automatically parse their arguments via this \csbxint{Num}.\footnote{A + \LaTeX{} \texttt{\char 92value\{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.} \centeredline{|\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}: + \centeredline{|\xintAdd{10.1e1}{101.010e3}|% + \digitstt{=\xintAdd{10.1e1}{101.010e3}}} + \centeredline{|\xintFloatAdd{10.1e1}{101.010e3}|% + \digitstt{=\xintFloatAdd{10.1e1}{101.010e3}}} + \centeredline{|\xintPow {2}{100}|% + \digitstt{=\xintPow {2}{100}}} + \centeredline{|\xintFloat{\xintPow {2}{100}}|% + \digitstt{=\xintFloat{\xintPow {2}{100}}}} + \centeredline{|\xintFloatPow {2}{100}|% + \digitstt{=\xintFloatPow {2}{100}}} +% +Produced fractions having a denominator equal to one are, as a general rule, +nevertheless printed as fractions. In math mode \csbxint{Frac} will remove such +dummy denominators, and in inline text mode one has \csbxint{PRaw} with the +similar effect. +% +\centeredline{|\xintPRaw{\xintAdd{10.1e1}{101.010e3}}|% + \digitstt{=\xintPRaw{\xintAdd{10.1e1}{101.010e3}}}} +\centeredline{|\xintRaw{1.234e5/6.789e3}|% + \digitstt{=\xintRaw{1.234e5/6.789e3}}}% +\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 its devoted section + (\autoref{sec:exprsummaryII}). +\end{enumerate} +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. + +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 accept +a fraction reducing to an integer. For example |\xintQuo {100/2}{12/3}| works, +because its arguments are, after simplification, integers. +% +% In this +% documentation, I often say ``numbers or fractions'', although at times the +% vocable ``numbers'' by itself may also include ``fractions''; and ``decimal +% numbers'' are counted among ``fractions''. + +With \xintfracname loaded, a number may be empty or start directly with a +decimal point: \centeredline{|\xintRaw{}=\xintRaw{.}|\digitstt{=\xintRaw{}}} +\centeredline{|\xintPow{-.3/.7}{11}|\digitstt{=\xintPow{-.3/+.7}{11}}} +\centeredline{|\xinttheexpr (-.3/.7)^11\relax|% + \digitstt{=\xinttheexpr (-.3/.7)^11\relax}} 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 |\string\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. \centeredline{|\xintRaw + {+--+1253.2782e++--3/---0087.123e---5}|\digitstt{=\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}} +\ntype{\Numf} in the margin. This symbol also means that these arguments may +contain to some extent infix algebra with count registers, see the section +\hyperref[sec:useofcount]{Use of count registers}. + + + With \xintfracname loaded the symbol \smash{\Numf} means that a fraction is + accepted if it is a whole number in disguise; and for macros accepting the + full fraction format with no restriction there is the corresponding symbol + in the margin\ntype{\Ff}. + + +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}, \csbxint{Sum}, \csbxint{Prd} are modified to allow +fractions on input,\footnote{the power function does not accept a fractional + exponent. Or rather, does not expect, and errors will result if one is + provided.}\,\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, if these fractions + reduce to integers, and then the output format is the original \xintname's + 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.} and 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|). +% +This represents |(A/B)| times |10^n|. The fraction |f| may be, and +generally is, reducible, and |A| and |B| may well end up with zeroes (\emph{i.e.} +|n| does not contain all powers of 10). Conversely, this format is accepted on +input (and is parsed more quickly than fractions containing decimal points; the +input may be a number without denominator).\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\string^\string{31\string}-9|.} + +Thus loading \xintfracname not only relaxes the format of the inputs; it +also modifies the format of the outputs: except when a fraction is +filtered on output by \csbxint{Irr} or \csbxint{RawWithZeros}, or +\csbxint{PRaw}, or by the truncation or rounding macros, or is given as +argument in math mode to \csbxint{Frac}, the output format is normally +of the \fbox{|A/B[n]|} form (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. + +A macro \csbxint{Frac} is provided for the typesetting (math-mode only) +of such a `raw' output. The command \csbxint{Frac} is not accepted as +input to the package macros, it is for typesetting only (in math mode). + +The macro \csbxint{Raw} prints the fraction +directly from its internal representation in |A/B[n]| form. The macro +\csbxint{PRaw} does the same but without printing the |[n]| if |n=0| and without +printing |/1| if |B=1|. + +% To convert the trailing |[n]| into explicit zeroes either at the +% numerator or the denominator, use \csbxint{RawWithZeros}. In both cases +% the |B| is printed even if it has value |1|. Conversely (sort of), the +% macro \csbxint{REZ} puts all powers of ten into the |[n]| (REZ stands +% for remove zeroes). Here also, the |B| is printed even if it has value +% |1|. + +The macro \csbxint{Irr} reduces the fraction to its irreducible form +|C/D| (without a trailing |[0]|), and it prints the |D| even if |D=1|. + +The macro \csbxint{Num} from package \xintname is extended: it now does +like \csbxint{Irr}, raises an error if the fraction did not reduce to an +integer, and outputs the numerator. This macro should be used when one +knows that necessarily the result of a computation is an integer, and +one wants to get rid of its denominator |/1| which would be left by +\csa{xintIrr} (or one can use \csbxint{PRaw} on top of \csbxint{Irr}). + + +% The macro \csbxint{Trunc}|{N}{f}| prints\footnote{`prints' does not at all mean +% that this macro is designed for typesetting; I am just using the verb here in +% analogy to the effect of the functioning of a computing software in console +% mode. The package does not provide any `printing' facility, besides its +% rudimentary \csbxint{Frac} and \csbxint{FwOver} math-mode only macros. To deal +% with really long numbers, some macros are necessary as \TeX{} by default will +% print a long number on a single line extending beyond the page limits. The +% \csa{printnumber} command used in this documentation is just one way to +% address this problem, some other method should be used if it is important that +% digits occupy the same width always.} the decimal expansion of |f| with |N| +% digits after the decimal point.\footnote{the current release does not provide a +% macro to get the period of the decimal expansion.} Currently, it does not +% verify that |N| is non-negative and strange things could happen with a negative +% |N|. A negative |f| is no problem, needless to say. When the original +% fraction is negative and its truncation has only zeroes, it is printed as +% |-0.0...0|, with |N| zeroes following the decimal point: +% \centeredline{|\xintTrunc {5}{\xintPow {-13}{-9}}|\digitstt{=\xintTrunc +% {5}{\xintPow {-13}{-9}}}}% +% \centeredline{|\xintTrunc {20}{\xintPow {-13}{-9}}|\digitstt{=\xintTrunc +% {20}{\xintPow {-13}{-9}}}} The output always contains a decimal point (even +% for |N=0|) followed by |N| digits, except when the original fraction was zero. +% In that case the output is |0|, with no decimal point. \centeredline{|\xintTrunc +% {10}{\xintSum {{1/2}{1/3}{1/5}{-31/30}}}|% +% \digitstt{=\xintTrunc {10}{\xintSum {{1/2}{1/3}{1/5}{-31/30}}}}} + +% \edef\z {\xintPow {1.01}{100}} + +% The macro \csbxint{iTrunc}|{N}{f}| is like \csa{xintTrunc}|{N}{f}| +% followed by multiplication by |10^N|. Thus, it outputs an integer +% in a format acceptable by the integer-only macros. +% To get the integer part of the decimal expansion of |f|, use +% |\xintiTrunc{0}{f}|: \centeredline{|\xintiTrunc {0}{\xintPow +% {1.01}{100}}|\digitstt{=\xintiTrunc {0}\z}}% +% \centeredline{|\xintiTrunc {0}{\xintPow{0.123}{-10}}|\digitstt{=\xintiTrunc +% {0}{\xintPow{0.123}{-10}}}} + +See also the documentations of \csbxint{Trunc}, \csbxint{iTrunc}, +\csbxint{XTrunc}, \csbxint{Round}, \csbxint{iRound} and +\csbxint{Float}. + +The \csbxint{iAdd}, \csbxint{iSub}, \csbxint{iMul}, \csbxint{iPow}, and +some others accept fractions on input under +the condition that they are (big) integers in disguise and then output a +(possibly big) integer, without fraction slash nor trailing |[n]|. + +The \csbxint{iiAdd}, \csbxint{iiSub}, \csbxint{iiMul}, \csbxint{iiPow}, and +some others with `\textcolor{blue}{ii}' in their names accept on input +only integers in strict format (skipping the overhead of the +\csbxint{Num} parsing) and output naturally a +(possibly big) integer, without fraction slash nor trailing |[n]|. + + +\subsection{Multiple outputs}\label{sec:multout} + +Some macros have an output consisting of more than one number or +fraction, each one is then returned within braces. Examples of +multiple-output macros are \csbxint{Division} which gives first the +quotient and then the remainder of euclidean division, \csbxint{Bezout} +from the \xintgcdname package which outputs five numbers, +\csbxint{FtoCv} from the \xintcfracname package which returns the list +of the convergents of a fraction, ... \autoref{sec:assign} and +\autoref{sec:utils} mention utilities, expandable or not, to cope with +such outputs. + +Another type of multiple outputs is when using commas inside +\csbxint{expr}|..\relax|: +\centeredline{|\xinttheiexpr 10!,2^20,lcm(1000,725)\relax|% + $\to$\digitstt{\xinttheiexpr 10!,2^20,lcm(1000,725)\relax}} + + +\section{Use of \TeX{} registers and variables} + +{\etocdefaultlines\etocsettocstyle{}{}\localtableofcontents} + +\subsection{Use of count registers}\label{sec:useofcount} + +Inside |\xintexpr..\relax| and its variants, a count register or count control +sequence is automatically unpacked using |\number|, with tacit multiplication: +|1.23\counta| is like |1.23*\number\counta|. There +is a subtle difference between count \emph{registers} and count +\emph{variables}. In |1.23*\counta| the unpacked |\counta| variable defines a +complete operand thus |1.23*\counta 7| is a syntax error. But |1.23*\count0| +just replaces |\count0| by |\number\count0| hence |1.23*\count0 7| is like +|1.23*57| if |\count0| contains the integer value |5|. + +Regarding now the package macros, there is first the case of arguments having to +be short integers: this means that they are fed to a |\numexpr...\relax|, hence +submitted to a \emph{complete expansion} which must deliver an integer, and +count registers and even algebraic expressions with them like +|\mycountA+\mycountB*17-\mycountC/12+\mycountD| are admissible arguments (the +slash stands here for the rounded integer division done by |\numexpr|). This +applies in particular to the number of digits to truncate or round with, to the +indices of a series partial sum, \dots + +The macros allowing the extended format for long numbers or dealing with +fractions will \emph{to some extent} allow the direct use of count +registers and even infix algebra inside their arguments: a count +register |\mycountA| or |\count 255| is admissible as numerator or also as +denominator, with no need to be prefixed by |\the| or |\number|. It is possible +to have as argument an algebraic expression as would be acceptable by a +|\numexpr...\relax|, under this condition: \emph{each of the numerator and + denominator is expressed with at most \emph{eight} + tokens}.\footnote{Attention! there is no problem with a \LaTeX{} + \csa{value}\texttt{\{countername\}} if if comes first, but if it comes later + in the input it will not get expanded, and braces around the name will be + removed and chaos\IMPORTANT{} will ensues inside a \csa{numexpr}. One should + enclose the whole input in \csa{the}\csa{numexpr}|...|\csa{relax} in such + cases.} The slash for rounded division in a |\numexpr| should be written with +braces |{/}| to not be confused with the \xintfracname delimiter between +numerator and denominator (braces will be removed internally). Example: +|\mycountA+\mycountB{/}17/1+\mycountA*\mycountB|, or |\count 0+\count +2{/}17/1+\count 0*\count 2|, but in the latter case the numerator has the +maximal allowed number of tokens (the braced slash counts for only one). +\centeredline{|\cnta 10 \cntb 35 \xintRaw + {\cnta+\cntb{/}17/1+\cnta*\cntb}|\digitstt{->\cnta 10 \cntb 35 \xintRaw + {\cnta+\cntb{/}17/1+\cnta*\cntb}}} For longer algebraic expressions using +count registers, there are two possibilities: +\begin{enumerate} +\item encompass each of the numerator and denominator in |\the\numexpr...\relax|, +\item encompass each of the numerator and denominator in |\numexpr {...}\relax|. +\end{enumerate} +\dverb|@ +\cnta 100 \cntb 10 \cntc 1 +\xintPRaw {\numexpr {\cnta*\cnta+\cntb*\cntb+\cntc*\cntc+ + 2*\cnta*\cntb+2*\cnta*\cntc+2*\cntb*\cntc}\relax/% + \numexpr {\cnta*\cnta+\cntb*\cntb+\cntc*\cntc}\relax }| +\cnta 100 \cntb 10 \cntc 1 +\centeredline{\digitstt{\xintPRaw {\numexpr + {\cnta*\cnta+\cntb*\cntb+\cntc*\cntc+ + 2*\cnta*\cntb+2*\cnta*\cntc+2*\cntb*\cntc}\relax/% + \numexpr {\cnta*\cnta+\cntb*\cntb+\cntc*\cntc}\relax }}} +The braces would not be accepted + as regular +|\numexpr|-syntax: and indeed, they + are removed at some point in the processing. + + +\subsection{Dimensions} +\label{sec:Dimensions} + +\meta{dimen} variables can be converted into (short) integers suitable for the +\xintname macros by prefixing them with |\number|. This transforms a dimension +into an explicit short integer which is its value in terms of the |sp| unit +(@1/65536@\,|pt|). +When |\number| is applied to a \meta{glue} variable, the stretch and shrink +components are lost. + +For \LaTeX{} users: a length is a \meta{glue} variable, prefixing a +length command defined by \csa{newlength} with \csa{number} will thus discard +the |plus| and |minus| glue components and return the dimension component as +described above, and usable in the \xintname bundle macros. + +This conversion is done automatically inside an +|\xintexpr|-essions, with tacit multiplication implied if prefixed by some +(integral or decimal) number. + +One may thus compute areas or volumes with no limitations, in units of |sp^2| +respectively |sp^3|, do arithmetic with them, compare them, etc..., and possibly +express some final result back in another unit, with the suitable conversion +factor and a rounding to a given number of decimal places. + +A \hyperref[tableofdimensions]{table of dimensions} illustrates that the +internal values used by \TeX{} do not correspond always to the closest rounding. +For example a millimeter exact value in terms of |sp| units is +\digitstt{72.27/10/2.54*65536=\xinttheexpr trunc(72.27/10/2.54*65536,3)\relax + ...} and \TeX{} uses internally \digitstt{\number\dimexpr 1mm\relax}|sp| (it +thus appears that \TeX{} truncates to get an integral multiple of the |sp| +unit). + + +% impossible avec le \ignorespaces mis par LaTeX de faire \number\dimexpr +% idem à la fin avec \unskip, si je veux xinttheexpr +\begin{figure*}[ht!] +\phantomsection\label{tableofdimensions} +\begingroup\let\ignorespaces\empty + \let\unskip\empty + \def\T{\expandafter\TT\number\dimexpr} + \def\TT#1!{\gdef\tempT{#1}} + \def\E{\expandafter\expandafter\expandafter + \EE\xintexpr reduce(} + \def\EE#1!{\gdef\tempE{#1}} +\centeredline{\begin{tabular}{% + >{\bfseries\strut}c% + c% + >{\E}c<{)\relax!}@{}% + >{\xintthe\tempE}r@{${}={}$}% + >{\xinttheexpr trunc(\tempE,3)\relax...}l% + >{\T}c<{!}@{}% + >{\tempT}r% + >{\xinttheexpr round(100*(\tempT-\tempE)/\tempE,4)\relax\%}c} + \hline + Unit&% + definition&% + \omit &% + \multicolumn{2}{c}{Exact value in \texttt{sp} units\strut}&% + \omit &% + \omit\parbox{2cm}{\centering\strut\TeX's value in \texttt{sp} units\strut}&% + \omit\parbox{2cm}{\centering\strut Relative error\strut}\\\hline + cm&0.01 m&72.27/2.54*65536&&&1cm&&\\ + mm&0.001 m&72.27/10/2.54*65536&&&1mm&&\\ + in&2.54 cm&72.27*65536&&&1in&&\\ + pc&12 pt&12*65536&&&1pc&&\\ + pt&1/72.27 in&65536&&&1pt&&\\ + bp&1/72 in&72.27*65536/72&&&1bp&&\\ + \omit\hfil\llap{3}bp\hfil&1/24 in&72.27*65536/24&&&3bp&&\\ + \omit\hfil\llap{12}bp\hfil&1/6 in&72.27*65536/6&&&12bp&&\\ + \omit\hfil\llap{72}bp\hfil&1 in&72.27*65536&&&72bp&&\\ + dd&1238/1157 pt&1238/1157*65536&&&1dd&&\\ + \omit\hfil\llap{11}dd\hfil&11*1238/1157 pt&11*1238/1157*65536&&&11dd&&\\ + \omit\hfil\llap{12}dd\hfil&12*1238/1157 pt&12*1238/1157*65536&&&12dd&&\\ + sp&1/65536 pt&1&&&1sp&&\\\hline + \multicolumn{8}{c}{\bfseries\large\TeX{} \strut dimensions}\\\hline +\end{tabular}} +\endgroup +\end{figure*} + +There is something quite amusing with the Didot point. According to the \TeX +Book, @1157@\,|dd|=@1238@\,|pt|. The actual internal value of @1@\,|dd| in \TeX{} is @70124@\,|sp|. We can use \xintcfracname to display the list of +centered convergents of the fraction @70124/65536@: +\centeredline{|\xintListWithSep{, }{\xintFtoCCv{70124/65536}}|} +% +\xintFor* #1 in {\xintFtoCCv{70124/65536}}\do {@#1@, }and we don't find +@1238/1157@ therein, but another approximant @1452/1357@! + +And indeed multiplying @70124/65536@ by @1157@, and respectively @1357@, we find +the approximations (wait for more, later): +\centeredline{``@1157@\,|dd|''\digitstt{=\xinttheexpr trunc(1157\dimexpr + 1dd\relax/\dimexpr 1pt\relax,12)\relax}\dots|pt|} +\centeredline{``@1357@\,|dd|''\digitstt{=\xinttheexpr trunc(1357\dimexpr + 1dd\relax/\dimexpr 1pt\relax,12)\relax}\dots|pt|} +and we seemingly discover that @1357@\,|dd|=@1452@\,|pt| is \emph{far more + accurate} than +the \TeX Book formula @1157@\,|dd|=@1238@\,|pt|~! +The formula to compute @N@\,|dd| was +% +\centeredline{|\xinttheexpr trunc(N\dimexpr 1dd\relax/\dimexpr + 1pt\relax,12)\relax}|} +% + +What's the catch? The catch is that \TeX{} \emph{does not} compute @1157@\,|dd| +like we just did: +\centeredline{@1157@\,|dd|=|\number\dimexpr 1157dd\relax/65536|% + \digitstt{=\xintTrunc{12}{\number\dimexpr 1157dd\relax/65536}}\dots|pt|} +\centeredline{@1357@\,|dd|=|\number\dimexpr 1357dd\relax/65536|% + \digitstt{=\xintTrunc{12}{\number\dimexpr 1357dd\relax/65536}}\dots|pt|} +We thus discover that \TeX{} (or rather here, e-\TeX{}, but one can check that +this works the same in \TeX82), uses indeed @1238/1157@ as a conversion factor, +and necessarily intermediate computations are done with more precision than is +possible with only integers less than @2^31@ (or @2^30@ for dimensions). Hence +the @1452/1357@ ratio is irrelevant, a misleading artefact of the necessary +rounding (or, as we see, truncating) for one |dd| as an integral number of +|sp|'s. + +Let us now +use |\xintexpr| to compute the value of the Didot point in millimeters, if +the above rule is exactly verified: \centeredline{|\xinttheexpr + trunc(1238/1157*25.4/72.27,12)\relax|% + \digitstt{=\xinttheexpr trunc(1238/1157*25.4/72.27,12)\relax}|...mm|} This +fits very well with the possible values of the Didot point as listed in the +\href{http://en.wikipedia.org/wiki/Point_%28typography%29#Didot}{Wikipedia Article}. +% +The value @0.376065@\,|mm| is said to be the \emph{the traditional value in + European printers' offices}. So the @1157@\,|dd|=@1238@\,|pt| rule refers to +this Didot point, or more precisely to the \emph{conversion factor} to be used +between this Didot and \TeX{} points. + +The actual value in millimeters of exactly one Didot point as implemented in +\TeX{} is +% +\centeredline +{|\xinttheexpr trunc(\dimexpr 1dd\relax/65536/72.27*25.4,12)\relax|} +\centeredline{% +\digitstt{=\xinttheexpr trunc(\dimexpr + 1dd\relax/65536/72.27*25.4,12)\relax}|...mm|} +The difference of circa @5@\AA\ is arguably tiny! + +% 543564351/508000000 + +By the way the \emph{European printers' offices \emph{(dixit Wikipedia)} Didot} is thus exactly +\centeredline{|\xinttheexpr reduce(.376065/(25.4/72.27))\relax|% + \digitstt{=\xinttheexpr reduce(.376065/(25.4/72.27))\relax}\,|pt|} +and the centered convergents of this fraction are \xintFor* #1 in +{\xintFtoCCv{543564351/508000000}}\do {@#1@\xintifForLast{.}{, }} We do recover +the @1238/1157@ therein! + +% As a final comment on the \hyperref[tableofdimensions]{table of dimensions}, we +% conclude that the ``Relative Error'' column is misleading as these relative +% errors by necessity decrease for integer multiples of the given dimension units. +% This was already indicated by the \textbf{72bp} row. + +% To conclude our comments on the +% \hyperref[tableofdimensions]{table of dimensions}, the big point, now known as +% \emph{Desktop Publishing Point} is less accurately implemented in \TeX{} than +% other units. Let us test for example the relation @1@\,|in|@=72@\,|bp|, the difference is +% % +% \centeredline{|\number\numexpr\dimexpr1in\relax-72*\dimexpr1bp\relax\relax|% +% \digitstt{=\number\numexpr\dimexpr1in\relax-72*\dimexpr1bp\relax\relax}\,|sp|} +% \centeredline{|\number\dimexpr1in-72bp\relax|% +% \digitstt{=\number\dimexpr1in-72bp\relax}\,|sp|} +% on the other hand +% \centeredline{|\xinttheexpr reduce(\dimexpr1in\relax-72.27*\dimexpr1pt\relax)\relax|} +% \centeredline +% \digitstt{=\xinttheexpr reduce(\dimexpr1in\relax-72.27*\dimexpr1pt\relax)\relax}\,|sp|=@-0.72@\,|sp|} +% \centeredline +% {\digitstt{=\number\dimexpr1in-72.27pt\relax}\,|sp|=@-0.72@\,|sp|} + + + +\section{\csh{ifcase}, \csh{ifnum}, ... constructs}\label{sec:ifcase} + +When using things such as |\ifcase \xintSgn{\A}| one has to make sure to leave +a space after the closing brace for \TeX{} to +stop its scanning for a number: once \TeX{} has finished expanding +|\xintSgn{\A}| and has so far obtained either |1|, |0|, or |-1|, a +space (or something `unexpandable') must stop it looking for more +digits. Using |\ifcase\xintSgn\A| without the braces is very dangerous, +because the blanks (including the end of line) following |\A| will be +skipped and not serve to stop the number which |\ifcase| is looking for. +With |\def\A{1}|: +\dverb|@ +\ifcase \xintSgn\A 0\or OK\else ERROR\fi ---> gives ERROR +\ifcase \xintSgn\A\space 0\or OK\else ERROR\fi ---> gives OK +\ifcase \xintSgn{\A} 0\or OK\else ERROR\fi ---> gives OK| +% \def\A{1} +% \ifcase \xintSgn\A 0\or OK\else ERROR\fi\ +% \ifcase \xintSgn{\A} 0\or OK\else ERROR\fi + +In order to use successfully |\if...\fi| constructions either as arguments to +the \xintname bundle expandable macros, or when building up a completely +expandable macro of one's own, one needs some \TeX nical expertise (see also +\autoref{fn:expansions} on page~\pageref{fn:expansions}). + +It is thus much to be recommended to opt rather for already existing expandable +branching macros, such as the ones which are provided by \xintname: +\csbxint{SgnFork}, \csbxint{ifSgn}, \csbxint{ifZero}, \csbxint{ifOne}, +\csbxint{ifNotZero}, \csbxint{ifTrueAelseB}, \csbxint{ifCmp}, \csbxint{ifGt}, +\csbxint{ifLt}, \csbxint{ifEq}, \csbxint{ifOdd}, and \csbxint{ifInt}. See their +respective documentations. All these conditionals always have either two or +three branches, and empty brace pairs |{}| for unused branches should not be +forgotten. + +If these tests are to be applied to standard \TeX{} short integers, it is more +efficient to use (under \LaTeX{}) the equivalent conditional tests from the +\href{http://www.ctan.org/pkg/etoolbox}{etoolbox}\footnote{\url{http://www.ctan.org/pkg/etoolbox}} +package. + + + +\section{Assignments}\label{sec:assign} + +\xintAssign \xintBezout{357}{323}\to\tmpA\tmpB\tmpU\tmpV\tmpD + +It might not be necessary to maintain at all times complete expandability. A +devoted syntax is provided to make these things more efficient, for example when +using the \csa{xintDivision} macro which computes both quotient and remainder at +the same time: +\centeredline{\csbxint{Assign}\csa{xintDivision}|{100}{3}|\csbnolk{to}|\A\B|} +\centeredline{\csbxint{Assign}\csa{xintDivision}% + |{\xintiPow {2}{1000}}{\xintFac{100}}|\csbnolk{to}|\A\B|} gives +\xintAssign\xintDivision{\xintiPow {2}{1000}}{\xintFac{100}}\to\A\B +|\meaning\A|\digitstt{: \expandafter\allowsplits\meaning\A\relax} and +|\meaning\B|\digitstt{: \expandafter\allowsplits\meaning\B\relax}. + +% +Another example (which uses \csbxint{Bezout} from the \xintgcdname package): +\centeredline{\csbxint{Assign}\csa{xintBezout}|{357}{323}|% +\csbnolk{to}|\A\B\U\V\D|} is equivalent to setting |\A| to \digitstt{\tmpA}, +|\B| to \digitstt{\tmpB}, |\U| to \digitstt{\tmpU}, |\V| to \digitstt{\tmpV}, +and |\D| to \digitstt{\tmpD}. And indeed +\digitstt{(\tmpU)$\times$\tmpA-(\tmpV)$\times$\tmpB$=$% +\xintiSub{\xintiMul\tmpU\tmpA}{\xintiMul\tmpV\tmpB}} is a Bezout Identity. + +Thus, what |\xintAssign| does is to first apply an +\hyperref[sec:expansions]{\fexpan sion} to what comes next; it then defines one +after the other (using |\def|; an optional argument allows to modify the +expansion type, see \autoref{xintAssign} for details), the macros found after +|\to| to correspond to the successive braced contents (or single tokens) located +prior to |\to|. + +\xintAssign +\xintBezout{3570902836026}{200467139463}\to\tmpA\tmpB\tmpU\tmpV\tmpD + +\centeredline{\csbxint{Assign}\csa{xintBezout}|{3570902836026}{200467139463}|% + \csbnolk{to}|\A\B\U\V\D|} +\noindent +gives then |\U|\digitstt{: + \expandafter\allowsplits\meaning\tmpU\relax}, + |\V|\digitstt{: + \expandafter\allowsplits\meaning\tmpV\relax} and |\D|\digitstt{=\tmpD}. + +% +In situations when one does not know in advance the number of items, one has +\csbxint{AssignArray} or its synonym \csbxint{DigitsOf}: +\centeredline{\csbxint{DigitsOf}\csa{xintiPow}|{2}{100}|\csbnolk{to}\csa{DIGITS}} +This defines \csa{DIGITS} to be macro with one parameter, \csa{DIGITS}|{0}| +gives the size |N| of the array and \csa{DIGITS}|{n}|, for |n| from |1| to |N| +then gives the |n|th element of the array, here the |n|th digit of @2^{100}@, +from the most significant to the least significant. As usual, the generated +macro \csa{DIGITS} is completely expandable (in two steps). As it wouldn't make +much sense to allow indices exceeding the \TeX{} bounds, the macros created by +\csbxint{AssignArray} put their argument inside a \csa{numexpr}, so it is +completely expanded and may be a count register, not necessarily prefixed by +|\the| or |\number|. Consider the following code snippet: +% +\dverb+@ +\newcount\cnta +\newcount\cntb +\begingroup +\xintDigitsOf\xintiPow{2}{100}\to\DIGITS +\cnta = 1 +\cntb = 0 +\loop +\advance \cntb \xintiSqr{\DIGITS{\cnta}} +\ifnum \cnta < \DIGITS{0} +\advance\cnta 1 +\repeat + +|2^{100}| (=\xintiPow {2}{100}) has \DIGITS{0} digits and the sum of +their squares is \the\cntb. These digits are, from the least to +the most significant: \cnta = \DIGITS{0} +\loop \DIGITS{\cnta}\ifnum \cnta > 1 \advance\cnta -1 , \repeat. +\endgroup ++ + +\edef\z{\xintiPow {2}{100}} + +\begingroup +\xintDigitsOf\z\to\DIGITS +\cnta = 1 +\cntb = 0 +\loop +\advance \cntb \xintiSqr{\DIGITS{\cnta}} +\ifnum \cnta < \DIGITS{0} +\advance\cnta 1 +\repeat + +@2^{100}@ (=\z) has \DIGITS{0} digits and the sum of +their squares is \the\cntb. These digits are, from the least to +the most significant: \cnta = \DIGITS{0} +\loop \DIGITS{\cnta}\ifnum \cnta > 1 \advance\cnta -1 , \repeat. +\endgroup + +% We used a group in order to release the memory taken by the +% \csa{DIGITS} array: indeed internally, besides \csa{DIGITS} itself, +% additional macros are defined which are \csa{DIGITS0}, \csa{DIGITS00}, +% \csa{DIGITS1}, \csa{DIGITS2}, ..., \csa{DIGITSN}, where |N| is the size of +% the array (which is the value returned by |\DIGITS{0}|; the digits +% are parts of the names not arguments). + +% The command \csbxint{RelaxArray}\csa{DIGITS} sets all these macros to +% \csa{relax}, but it was simpler to put everything withing a group. + +Warning: \csbxint{Assign}, \csbxint{AssignArray} and \csbxint{DigitsOf} +\emph{do not do any check} on whether the macros they define are already +defined. + +% In the example above, we deliberately broke all rules of complete expandability, +% but had we wanted to compute the sum of the digits, not the sum of the squares, +% we could just have written: \csbxint{iiSum}|{\xintiPow{2}{100}}|\digitstt{=% +% \xintiiSum\z}. Indeed, \csa{xintiiSum} is usually used on braced items as in +% \centeredline{% +% \csbxint{iiSum}|{{123}{-345}{\xintFac{7}}{\xintiOpp{\xintRem{3347}{591}}}}|% +% \digitstt{=% +% \xintiiSum{{123}{-345}{\xintFac{7}}{\xintiOpp{\xintRem{3347}{591}}}}}} but +% in the previous example each digit of @2^{100}@ was treated as one item due to +% the rules of \TeX{} for parsing macro arguments. + +% Note: |{-\xintRem{3347}{591}}| would not be a valid input, because +% the expansion will apply only to the minus sign and leave +% unaffected the |\xintRem|. So we used \csa{xint}\-|iOpp| which replaces +% a number with its opposite. + + +% As a last example with \csa{xintAssignArray} here is one line +% extracted from the source code of the \xintgcdname macro +% \csbxint{TypesetEuclideAlgorithm}: +% \centeredline{|\xintAssignArray\xintEuclideAlgorithm +% {#1}{#2}\to\U|} +% This is done inside a group. After this command |\U{1}| contains +% the number |N| of steps of the algorithm (not to be confused with +% |\U{0}=2N+4| which is the number of elements in the |\U| array), +% and the GCD is to be found in |\U{3}|, a convenient location +% between |\U{2}| and |\U{4}| which are (absolute values of the +% expansion of) the +% initial inputs. Then follow |N| quotients and remainders +% from the first to the last step of the algorithm. The +% \csa{xintTypesetEuclideAlgorithm} macro organizes this data +% for typesetting: this is just an example of one way to do it. + +\section{Utilities for expandable manipulations}\label{sec:utils} + +The package now has more utilities to deal expandably with `lists of things', +which were treated un-expandably in the previous section with \csa{xintAssign} +and \csa{xintAssignArray}: \csbxint{ReverseOrder} and \csbxint{Length} since the +first release, \csbxint{Apply} and \csbxint{ListWithSep} since |1.04|, +\csbxint{RevWithBraces}, \csbxint{CSVtoList}, \csbxint{NthElt} since |1.06|, +\csbxint{ApplyUnbraced}, since |1.06b|, \csbxint{loop} and \csbxint{iloop} since +|1.09g|.\footnote{All these utilities, as well as \csbxint{Assign}, + \csbxint{AssignArray} and the \csbxint{For} loops are now available from the + \xinttoolsname package, independently of the big integers facilities of + \xintname.} + +\edef\z{\xintiPow {2}{100}} + +As an example the following code uses only expandable operations: +\dverb+@ +|2^{100}| (=\xintiPow {2}{100}) has \xintLen{\xintiPow {2}{100}}} digits +and the sum of their squares is +\xintiiSum{\xintApply {\xintiSqr}{\xintiPow {2}{100}}}. +These digits are, from the least to the most significant: +\xintListWithSep {, }{\xintRev{\xintiPow {2}{100}}}. The thirteenth most +significant digit is \xintNthElt{13}{\xintiPow {2}{100}}. The seventh +least significant one is \xintNthElt{7}{\xintRev{\xintiPow {2}{100}}}. ++ +|2^{100}| (=\z) has \xintLen{\z} digits and the sum of +their squares is \xintiiSum{\xintApply\xintiSqr\z}. These digits are, from the +least to the most significant: \xintListWithSep {, }{\xintRev\z}. The +thirteenth most +significant digit is \xintNthElt{13}{\z}. The seventh +least significant one is \xintNthElt{7}{\xintRev\z}. + +It would be more efficient to do once and for all +|\oodef\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}. + + +\section{A new kind of for loop} + +As part of the \hyperref[sec:tools]{utilities} coming with the \xinttoolsname +package, there is a new kind of for loop, \csbxint{For}. Check it out +(\autoref{xintFor}). + +\section{A new kind of expandable loop} + +Also included in \xinttoolsname, \csbxint{iloop} is an expandable loop giving +access to an iteration index, without using count registers which would break +expandability. Check it out (\autoref{xintiloop}). + +\section{Exceptions (error messages)} + +In situations such as division by zero, the package will insert in the +\TeX{} processing an undefined control sequence (we copy this method +from the |bigintcalc| package). This will trigger the writing to the log +of a message signaling an undefined control sequence. The name of the +control sequence is the message. The error is raised \emph{before} the +end of the expansion so as to not disturb further processing of the +token stream, after completion of the operation. Generally the problematic +operation will output a zero. Possible such error message control +sequences: +\dverb|@ +\xintError:ArrayIndexIsNegative +\xintError:ArrayIndexBeyondLimit +\xintError:FactorialOfNegativeNumber +\xintError:FactorialOfTooBigNumber +\xintError:DivisionByZero +\xintError:NaN +\xintError:FractionRoundedToZero +\xintError:NotAnInteger +\xintError:ExponentTooBig +\xintError:TooBigDecimalShift +\xintError:TooBigDecimalSplit +\xintError:RootOfNegative +\xintError:NoBezoutForZeros +\xintError:ignored +\xintError:removed +\xintError:inserted +\xintError:bigtroubleahead +\xintError:unknownfunction| + +\section{Common input errors when using the package macros} + +\edef\x{\xintMul {3}{5}/\xintMul{7}{9}} + +Here is a list of common input errors. Some will cause compilation errors, +others are more annoying as they may pass through unsignaled. +\begin{itemize} +\item using |-| to prefix some macro: |-\xintiSqr{35}/271|.\footnote{to the + contrary, this \emph{is} + allowed inside an |\string\xintexpr|-ession.} +\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 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}|\digitstt{=\xintRaw{1.5/-3.5e-2}}, + |\xintRaw{-1.5e2/3.5}|\digitstt{=\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 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 \digitstt{\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| (but |/| therein is euclidean + quotient, which on positive operands is like truncating to the integer part, + not rounding). +\end{itemize} + + +\section{Package namespace} + +Inner macros of \xinttoolsname, \xintname, \xintfracname, \xintexprname, +\xintbinhexname, \xintgcdname, \xintseriesname, and \xintcfracname{} all begin +either with |\XINT_| or with |\xint_|.\footnote{starting with release |1.06b| + the style files use for macro names a more modern underscore |\_| rather than + the \texttt{\char`\@} sign. A handful of private macros starting with + |\string\XINT| do not have the underscore for technical reasons: + \csa{XINTsetupcatcodes}, \csa{XINTdigits} and macros with names starting with + |XINTinFloat| or |XINTinfloat|.} The package public commands all start with +|\xint|. Some other control sequences are used only as delimiters, and left +undefined, they may have been defined elsewhere, their meaning doesn't matter +and is not touched. + +\xinttoolsname defines \hyperref[odef]{\ttfamily\char92odef}, +\hyperref[oodef]{\ttfamily\char92oodef}, \hyperref[fdef]{\ttfamily\char92fdef}, +but only if macros with these names do not already exist (|\xintoodef| etc... +are defined anyhow for use in \csbxint{Assign} and \csbxint{AssignArray}). + +{\makeatother The \xintname packages presuppose that the \csa{space}, +\csa{empty}, |\m@ne|, |\z@| and |\@ne| control sequences +have their meanings as in Plain \TeX{} or \LaTeX2e.} + + +\section{Loading and usage} + +\dverb|@ +Usage with LaTeX: \usepackage{xinttools} + \usepackage{xint} % (loads xinttools) + \usepackage{xintfrac} % (loads xint) + \usepackage{xintexpr} % (loads xintfrac) + + \usepackage{xintbinhex} % (loads xint) + \usepackage{xintgcd} % (loads xint) + \usepackage{xintseries} % (loads xintfrac) + \usepackage{xintcfrac} % (loads xintfrac) + +Usage with TeX: \input xinttools.sty\relax + \input xint.sty\relax % (loads xinttools) + \input xintfrac.sty\relax % (loads xint) + \input xintexpr.sty\relax % (loads xintfrac) + + \input xintbinhex.sty\relax % (loads xint) + \input xintgcd.sty\relax % (loads xint) + \input xintseries.sty\relax % (loads xintfrac) + \input xintcfrac.sty\relax % (loads xintfrac) +| + +We have added, directly copied from packages by \textsc{Heiko Oberdiek}, a +mechanism of re-load and \eTeX{} detection, especially for Plain \TeX{}. As +\eTeX{} is required, the executable |tex| can not be used, |etex| or |pdftex| +(version |1.40| or later) or ..., must be invoked. Each package refuses to be +loaded twice and automatically loads the other components on which it has +dependencies.\footnote{exception: \xintexprname needs the user to explicitely + load \xintgcdname, resp. \xintbinhexname, if use is to be made in + \csa{xintexpr} of the \texttt{lcm} and \texttt{gcd} functions, and, resp., + hexadecimal numbers.} + +Also initially inspired from the \textsc{Heiko Oberdiek} packages we have +included a complete catcode protection mecanism. The packages may be loaded in +any catcode configuration satisfying these requirements: the percent is of +category code comment character, the backslash is of category code escape +character, digits have category code other and letters have category code +letter. Nothing else is assumed, and the previous configuration is restored +after the loading of each one of the packages. + +This is for the loading of the packages. + +For the input of numbers as macro arguments the minus sign must have its +standard category code (``\emph{other}''). Similarly the slash used for +fractions must have its standard category code. And the square brackets, if made +use of in the input, also must be of category code \emph{other}. The `e' of the +scientific notation must be of category code \emph{letter}. + +All these requirements (which are anyhow satisfied by default) are +relaxed for the contents of an |\xintexpr|-ession: spaces are gobbled, +catcodes mostly do not matter, the |e| of scientific notation may be |E| +(on input) \dots{} + + +\section{Installation}\label{sec:install} + +\begingroup +\def\MacroFont {\ttfamily\small\baselineskip11pt\relax\catcode`\"=12 } +\dverb!@ +A. Installation using xint.tds.zip: +----------------------------------- + +obtain xint.tds.zip from CTAN: + http://mirror.ctan.org/install/macros/generic/xint.tds.zip + +cd to the download repertory and issue + unzip xint.tds.zip -d <TEXMF> +for example: (assuming standard access rights, so sudo needed) + sudo unzip xint.tds.zip -d /usr/local/texlive/texmf-local + sudo mktexlsr + +On Mac OS X, installation into user home folder: + unzip xint.tds.zip -d ~/Library/texmf + +B. Installation after file extractions: +--------------------------------------- + +obtain xint.dtx, xint.ins and the README from CTAN: + http://www.ctan.org/pkg/xint + +- "tex xint.ins" generates the style files +(pre-existing files in the same repertory will be overwritten). + +- without xint.ins: "tex or latex or pdflatex or xelatex xint.dtx" +will also generate the style files (and xint.ins). + +xint.tex is also extracted, use it for the documentation: + +- with latex+dvipdfmx: latex xint.tex thrice then dvipdfmx xint.dvi +Ignore dvipdfmx warnings, but if the pdf file has problems with fonts +(possibly from an old dvipdfmx), use then rather pdflatex or xelatex. + +- with pdflatex or xelatex: run it directly thrice on xint.dtx, or run +it on xint.tex after having edited the suitable toggle therein. + +When compiling xint.tex, the documentation is by default produced +with the source code included. See instructions in the file for +changing this default. + +When compiling directly xint.dtx, the documentation is produced +without the source code (latex+dvips or pdflatex or xelatex). + +Finishing the installation: (on first installation the destination +repertories may need to be created) + + xinttools.sty | + xint.sty | + xintfrac.sty | + xintexpr.sty | --> TDS:tex/generic/xint/ + xintbinhex.sty | + xintgcd.sty | + xintseries.sty | + xintcfrac.sty | + + xint.dtx --> TDS:source/generic/xint/ + xint.ins --> TDS:source/generic/xint/ + xint.tex --> TDS:source/generic/xint/ + + xint.pdf --> TDS:doc/generic/xint/ + README --> TDS:doc/generic/xint/ + +Depending on the TDS destination and the TeX installation, it may be +necessary to refresh the TeX installation filename database (mktexlsr)! +\endgroup + +\section{The \csh{xintexpr} math parser (I)} +\label{sec:exprsummary} + +% 27 octobre 2013 plus de problème avec &... il n'est plus actif (ouf) +\xintexprSafeCatcodes +\newcommand\formula[3]{\xinttheexpr round((#1 & (#2 | #3)) * (355/113*#3 - + (#1 - #2/2)^2), 8)\relax } +\xintexprRestoreCatcodes + + +Here is some random formula, defining a \LaTeX{} command with three parameters, +\centeredline{\verb$\newcommand\formula[3]$} +\centeredline{\verb${\xinttheexpr round((#1 & (#2 | #3)) * (355/113*#3 - (#1 - + #2/2)^2), 8) \relax}$} + +\smallskip + +Let |a=#1|, |b=#2|, |c=#3| be the parameters. The first term is the logical +operation |a and (b or c)| where a number or fraction has truth value @1@ if it +is non-zero, and @0@ otherwise. So here it means that |a| must be non-zero as +well as |b| or |c|, for this first operand to be @1@, else the formula returns +@0@. This multiplies a second term which is algebraic. Finally the result (where +all intermediate computations are done \emph{exactly}) is rounded to a value +with @8@ digits after the decimal mark, and printed. +\centeredline{|\formula + {771.3/9.1}{1.51e2}{37.73}| expands to + \digitstt{\formula {771.3/9.1}{1.51e2}{37.73}}} +Note that |#1|, |#2|, and |#3| are not protected by parentheses in the +definition of |\formula|, this is something to keep in mind if for example we +want to use |2+5| as third argument: it should be |(2+5)| then. + + +\begingroup % 9 octobre pour une meilleure gestion de l'indentation +\leftmargini 0pt +\list\labelitemi{\def\makelabel#1{\hss\llap{#1}}\listparindent\parindent + \labelwidth\parindent + \itemindent\labelwidth}% +% +\item as everything gets expanded, the characters + \verb$+,-,*,/,^,!,&,|,?,:,<,>,=,(,),"$ and the comma, which may appear + in the |infix| syntax, should not (if actually used in the expression) be + active (for example from serving as + shorthands for some language in the |Babel| system). + The command \csbxint{exprSafeCatcodes} resets these characters to their + standard catcodes and \csbxint{exprRestoreCatcodes} restores the status + prevailing at the time of the previous \csa{xintexprSafeCatcodes}. +\item many expressions have equivalent macro formulations written without + |\xinttheexpr|.\footnote{Not everything allows a straightforward reformulation + because the package macros only \fexpan d their arguments while + \csa{xintexpr} expands everything from left to right.} Here for |\formula| + we could have used: \centeredline {|\xintRound {8}{\xintMul {\xintAND + {#1}{\xintOR {#2}{#3}}}{\xintSub |} \centeredline {| {\xintMul + {355/113}{#3}}{\xintPow {\xintSub {#1}{\xintDiv {#2}{2}}}{2}}}}|} with + the inherent difficulty of keeping up with braces and everything... +\item if such a formula is used thousands of times in a document (for plots?), + this could impact some parts of the \TeX{} program memory (for technical + reasons explained in \autoref{sec:expr}). So, a utility \csbxint{NewExpr} + is provided to do the work of translating an |\xintexpr|-ession with + parameters into a chain of macro evaluations.\footnote{As its makes some macro + definitions, it is not an expandable command. It does not need protection + against active characters as it does it itself.} With + \centeredline{|\xintNewExpr\formula[3]|} + \centeredline{\verb${ round((#1 & (#2 | #3)) * (355/113*#3 - (#1 - #2/2)^2), + 8) }$} + one gets a command |\formula| with three parameters and meaning: + +\xintNewExpr\formula[3] +{ round((#1 & (#2 | #3)) * (355/113*#3 - (#1 - #2/2)^2), + 8) } + +{\centering\ttfamily + +\meaning\formula + +}This does the same thing as the hand-written version from the previous item +(but expands in only two steps).\footnote{But the hand-written version as well + as the \csa{xintNewExpr} generated one differ from the original \csa{formula} + command which allowed each of its argument to use all the operators and + functions recognized by \csa{xintexpr}, and this aspect is lost. To recover it + the arguments themselves should be passed as \csa{xinttheexpr..\char92relax} + to the defined macro.} The use +even thousands of times of such an |\xintNewExpr|-generated |\formula| has no +memory impact. +\item count registers and |\numexpr|-essions are accepted (LaTeX{}'s counters + can be inserted using |\value|) without needing |\the| or |\number| as prefix. + Also dimen registers and control sequences, skip registers and control + sequences (\LaTeX{}'s lengths), |\dimexpr|-essions, |\glueexpr|-essions are + automatically unpacked using |\number|, discarding the stretch and shrink + components and giving the dimension value in |sp| units (@1/65536@th of a + \TeX{} point). Furthermore, tacit multiplication is implied, when the + register, variable, or expression if immediately prefixed by a (decimal) + number. +\item tacit multiplication (the parser inserts a |*|) applies when the parser is + currently scanning the digits of a number (or its decimal part), or is looking + for an infix operator, and: (1.)\inmarg{v1.09i}~\emph{encounters a register, + variable or \eTeX{} expression (as described in the previous item)}, + (2.)\inmarg{v1.09j}~\emph{encounters a sub-\csa{xintexpr}-ession}, or + (3.)\inmarg{\\ v1.09k}~\emph{encounters an opening parenthesis.} +\item so far only |\xinttheexpr| was mentioned: there is also |\xintexpr| which, + like a |\numexpr|, needs a prefix which is called \csbxint{the}. Thus + \csbxint{theexpr} as was done in the definition of |\formula| is equivalent to + \csbxint{the}|\xintexpr|. +\item This latter form is convenient when one has defined for + example: +% +\centeredline{|\def\x {\xintexpr \a + \b \relax}| or |\edef\x {\xintexpr \a+\b\relax}|} +% +One may then do |\xintthe\x|, either for printing the result +on the page or use it in some other package macros. The |\edef| does the +computation but keeps it in an internal private format. +Naturally, the |\edef| is only possible if |\a| and |\b| are already defined. +\item in both cases (the `yet-to-be computed' and the +`already computed') |\x| can then be inserted in other expressions, as +for example +% +\centeredline {|\edef\y {\xintexpr \x^3\relax}|} +% +This would have worked also with |\x| defined as |\def\x {(\a+\b)}| but +|\edef\x| would not have been an option then, and |\x| could have been used only +inside an |\xintexpr|-ession, whereas the previous |\x| can also be used as +|\xintthe\x| in any context triggering the expansion of |\xintthe|. +\item sometimes one needs an integer, not a fraction or decimal number. The + |round| function rounds to the nearest integer, and |\xintexpr + round(...)\relax| has an alternative and equivalent syntax as \csbxint{iexpr}| + ... \relax|. There is also \csbxint{theiexpr}. The rounding is applied to the + final result only, intermediate computations are not rounded. +\item \csbxint{iiexpr}|..\relax| and \csbxint{theiiexpr}|..\relax| deal only + with (long) integers and skip the overhead of the fraction internal format. + The infix operator |/| does euclidean division, thus |2+5/3| will not be + treated exactly but be like |2+1|. +\item there is also \csbxint{boolexpr}| ... \relax| and \csbxint{theboolexpr}| + ... \relax|. Same as |\xintexpr| with the final result converted to + @1@ + if it is not zero. See also \csbxint{ifboolexpr} + (\autoref{xintifboolexpr}) and the \hyperlink{item:bool}{discussion} + of the |bool| and |togl| functions in \autoref{sec:exprsummary}. Here is an + example: +\begingroup +\def\MacroFont {\ttfamily\parskip0pt \parindent 15pt \baselineskip 12pt \relax } +\dverb!@ +\xintNewBoolExpr \AssertionA[3]{ #1 & (#2|#3) } +\xintNewBoolExpr \AssertionB[3]{ #1 | (#2) } +\xintNewBoolExpr \AssertionC[3]{ xor(#1,#2,#3) } +\xintFor #1 in {0,1} \do {% + \xintFor #2 in {0,1} \do {% + \xintFor #3 in {0,1} \do {% + \centerline{#1 AND (#2 OR #3) is \AssertionA {#1}{#2}{#3}\hfil + #1 OR (#2 AND #3) is \AssertionB {#1}{#2}{#3}\hfil + #1 XOR #2 XOR #3 is \AssertionC {#1}{#2}{#3}}}}} +!% +\endgroup +\xintNewBoolExpr \AssertionA[3]{ #1 & (#2|#3) } +\xintNewBoolExpr \AssertionB[3]{ #1 | (#2) } +\xintNewBoolExpr \AssertionC[3]{ xor(#1,#2,#3) } +\xintFor #1 in {0,1} \do {% + \xintFor #2 in {0,1} \do {% + \xintFor #3 in {0,1} \do {% + \centeredline{#1 AND (#2 OR #3) is \AssertionA {#1}{#2}{#3}\hfil + #1 OR (#2 AND #3) is \AssertionB {#1}{#2}{#3}\hfil + #1 XOR #2 XOR #3 is \AssertionC {#1}{#2}{#3}}}}} + +% +\item there is also \csbxint{floatexpr}| ... \relax| where the algebra is done + in floating point approximation (also for each intermediate result). Use the + syntax |\xintDigits:=N;| to set the precision. Default: @16@ digits. + \centeredline{|\xintthefloatexpr 2^100000\relax:| \digitstt{\xintthefloatexpr + 2^100000\relax }} The square-root operation can be used in |\xintexpr|, it + is computed as a float with the precision set by |\xintDigits| or by the + optional second argument: \centeredline{|\xinttheexpr sqrt(2,60)\relax|:} + \centeredline{\digitstt{\xinttheexpr sqrt(2,60)\relax }} Notice the |a/b[n]| + notation: usually the denominator |b| even if |1| gets printed; it does not + show here because the square root is computed by a version of + \csbxint{FloatSqrt} which for efficiency when used in such expressions outputs + the result in a format |d_1 d_2 .... d_P [N]| equivalent to the usual float + output format |d_1.d_2...d_P e<expon.>|. To get a float + format, it is easier to use an |\xintfloatexpr|, but the precision must be set + using the non expandable |\xintDigits:=60;| assignment, there is no optional + parameter possible currently to |\xintfloatexpr|: +% +\centeredline{|\xintDigits:=60;\xintthefloatexpr sqrt(2)\relax|} +\centeredline{\digitstt{\xintDigits:=60;\xintthefloatexpr sqrt(2)\relax}} +% +Or, without manipulating |\xintDigits|, another option to convert to float a +computation done by an |\xintexpr|: +\centeredline{|\xintFloat[60]{\xinttheexpr sqrt(2,60)\relax}|} +\centeredline{\digitstt{\xintFloat[60]{\xinttheexpr sqrt(2,60)\relax}}} +% +Floats + are quickly indispensable when using the power function (which can only have + an integer exponent), as exact results will easily have hundreds, if not + thousands, of digits. +% +\centeredline{|\xintDigits:=48; + \xintthefloatexpr 2^100000\relax|: } +\centeredline{\xintDigits:=48;\digitstt{\xintthefloatexpr 2^100000\relax}} +% +\item hexadecimal \TeX{} number\inmarg{New with 1.09k!} denotations + (\emph{i.e.}, with a |"| prefix) are recognized by the |\xintexpr| parser and + its variants. Except in |\xintiiexpr|, a (possibly empty) fractional part + with the dot |.| as ``hexadecimal'' mark is allowed. +% +\centeredline{|\xinttheexpr "FEDCBA9876543210\relax|$\to$\digitstt{\xinttheexpr + "FEDCBA9876543210\relax}} +\centeredline{|\xinttheiexpr 16^5-("F75DE.0A8B9+"8A21.F5746+16^-5)\relax|$\to$\digitstt{\xinttheiexpr 16^5-("F75DE.0A8B9+"8A21.F5746+16^-5)\relax}} +% +Letters must be uppercased, as with standard + \TeX{} hexadecimal denotations. Loading the \xintbinhexname package is required + for this functionality. +\endlist +\endgroup + +\section{The \csh{xintexpr} math parser (II)} +\label{sec:exprsummaryII} + +An expression is built with infix operators (including comparison and boolean +operators), parentheses, functions, and the two branching operators |?| and |:|. +The parser expands everything from the left to the right and everything may thus +be revealed step by step by expansion of macros. Spaces anywhere are allowed. + +Note that |2^-10| is perfectly accepted input, no need for parentheses; +operators of power |^|, division |/|, and subtraction |-| are all +left-associative: |2^4^8| is evaluated as |(2^4)^8|. The minus sign as prefix +has various precedence levels: |\xintexpr -3-4*-5^-7\relax| evaluates as +|(-3)-(4*(-(5^(-7))))| and |-3^-4*-5-7| as |(-((3^(-4))*(-5)))-7|. + +If one uses directly macros within |\xintexpr..\relax|, rather than the +operators or the functions which are described next, one should take into +account that: +\begin{enumerate} +\item the parser will not see the macro arguments, (but they may themselves be + set-up as |\xinttheexpr...\relax|), +\item the output format of most \xintfracname macros is |A/B[N]|, and square + brackets are \emph{not understood by the parser}. One \emph{must} enclose the + macro and its arguments inside a brace pair |{..}|, which will be recognized + and treated specially, +\item a macro outputting numbers in scientific notation |x.yEz| (either with a + lowercase |e| or uppercase |E|), must \emph{not} be enclosed + in a brace pair, this is the exact opposite of the |A/B[N]| case; scientific + numbers, explicit or implicit, should just be inserted directly in the + expression. +\end{enumerate} + +One may insert a sub-|\xintexpr|-expression within a larger one. Each one of +|\xintexpr|, |\xintiexpr|, |\xintfloatexpr|, |\xintboolexpr| may be inserted in +another one. On the other hand the integer only |\xintiiexpr| will generally +choke on a sub-|\xintexpr| as the latter (except if it did not do any operation +or had an overall top level |round| or |trunc| or |?(..)| or\dots) produces (in +internal format) an |A/B[N]| which the strictly integer only \csbxint{iiexpr} +does not understand. See \autoref{xintiiexpr} for more information. + +Here is, listed from the highest priority to the lowest, the complete list of +operators and functions. Functions are at the top level of priority. Next are +the postfix operators: |!| for the factorial, |?| and |:| are two-fold way and +three-fold way branching constructs. Also at the top level of priority the |e| +and |E| of the scientific notation and the |"|\inmarg{\string" is new in 1.09k} +for hexadecimal numbers, then power, multiplication/division, +addition/subtraction, comparison, and logical operators. At the lowest level: +commas then parentheses. + + +The |\relax| at the end of an expression is \emph{mandatory}. + + % 1.09c ajoute bool et togl + % 1.09a: + % reduce, + % sqr, sqrt, abs, sgn, floor, ceil, quo, rem, round, trunc, float, gcd, lcm, + % max, min, sum, prd, add, mul, not, all, any, xor + % ?, !, if, ifsgn, ?, :. + +\newcommand\ctexttt [1]{\begingroup\color[named]{DarkOrchid}\ttfamily\bfseries + #1\endgroup} + +\begingroup % 9 octobre pour la gestion de l'indentation et couleurs +\leftmargini 0pt +\leftmarginii .5\parindent +\list\labelitemi{\def\makelabel#1{\hss\llap{#1}}\listparindent\parindent + \labelwidth\parindent + \itemindent\labelwidth}% +\item + Functions are at the same top level of priority. All functions even + |?| and |!| (as prefix) require parentheses around their argument + (possibly a comma separated list). + \begin{framed} + \ctexttt{floor, ceil, frac, reduce, sqr, abs, sgn, ?, !, not, bool, + togl, round, trunc, float, sqrt, quo, rem, if, ifsgn, all, any, + xor, add (=sum), mul (=prd), max, min, gcd, lcm.} + + |quo| and |rem| + operate only on integers; |gcd| and |lcm| also and require + \xintgcdname loaded; |togl| requires the |etoolbox| package; |all|, |any|, + |xor|, |add|, |mul|, |max| and |min| are functions with arbitrarily many + comma separated arguments. + \end{framed} + \begin{description} + \item[functions with one (numeric) argument] (numeric: any expression leading + to an integer, decimal number, fraction, or floating number in scientific + notation) \ctexttt{floor, ceil, frac, reduce, sqr, abs, sgn, ?, !, not}. The + |?(x)| function returns the truth value, @1@ if |x<>0|, @0@ if |x=0|. The + |!(x)| is the logical not. The |reduce| function puts the fraction in + irreducible form. The |frac| function is fractional part, + same sign as the number:\newline + \null\quad\quad|\xinttheexpr + frac(-3.57)\relax|$\to$\digitstt{\xinttheexpr frac(-3.57)\relax}\newline + \null\quad\quad|\xinttheexpr + trunc(frac(-3.57),2)\relax|$\to$\digitstt{\xinttheexpr + trunc(frac(-3.57),2)\relax}\newline + \null\quad\quad|\xintthefloatexpr + frac(-3.57)\relax|$\to$\digitstt{\xintthefloatexpr + frac(-3.57)\relax}.\newline + Like + the other functions |!| and |?| \emph{must} use parentheses. + + \item[functions with one (alphabetical) argument] \hypertarget{item:bool} + {\ctexttt{bool,togl}}. + |bool(name)| returns @1@ if the \TeX{} conditional |\ifname| would + act as |\iftrue| and @0@ otherwise. This works with conditionals + defined by |\newif| (in \TeX{} or \LaTeX{}) or with primitive + conditionals such as |\ifmmode|. For example: + \centeredline{|\xintifboolexpr{25*4-if(bool(mmode),100,75)}{YES}{NO}|} + will return $\xintifboolexpr{25*4-if(bool(mmode),100,75)}{YES}{NO}$ + if executed in math mode (the computation is then $100-100=0$) and + \xintifboolexpr{25*4-if(bool(mmode),100,75)}{YES}{NO} if not (the + \ctexttt{if} conditional is described below; the + \csbxint{ifboolexpr} test automatically encapsulates its first + argument in an |\xintexpr| and follows the first branch if the + result is non-zero (see \autoref{xintifboolexpr})). + + The alternative syntax |25*4-\ifmmode100\else75\fi| could have been used + here, the usefulness of |bool(name)| lies in the availability in the + |\xintexpr| syntax of the logic operators of conjunction |&|, inclusive + disjunction \verb+|+, negation |!| (or |not|), of the multi-operands + functions |all|, |any|, |xor|, of the two branching operators |if| and + |ifsgn| (see also |?| and |:|), which allow arbitrarily complicated + combinations of various |bool(name)|. + + Similarly |togl(name)| returns @1@ + if the \LaTeX{} package + \href{http://www.ctan.org/pkg/etoolbox}{etoolbox}\footnote{\url{http://www.ctan.org/pkg/etoolbox}} + has been used to define a toggle named |name|, and this toggle is + currently set to |true|. Using |togl| in an |\xintexpr..\relax| + without having loaded + \href{http://www.ctan.org/pkg/etoolbox}{etoolbox} will result in an + error from |\iftoggle| being a non-defined macro. If |etoolbox| is + loaded but |togl| is used on a name not recognized by |etoolbox| the + error message will be of the type ``ERROR: Missing |\endcsname| + inserted.'', with further information saying that |\protect| should + have not been encountered (this |\protect| comes from the expansion + of the non-expandable |etoolbox| error message). + + When |bool| or |togl| is encountered by the |\xintexpr| parser, the argument + enclosed in a parenthesis pair is expanded as usual from left to right, + token by token, until the closing parenthesis is found, but everything is + taken literally, no computations are performed. For example |togl(2+3)| will + test the value of a toggle declared to |etoolbox| with name |2+3|, and not + |5|. Spaces are gobbled in this process. It is impossible to use |togl| on + such names containing spaces, but |\iftoggle{name with spaces}{1}{0}| will + work, naturally, as its expansion will pre-empt the |\xintexpr| scanner. + + There isn't in |\xintexpr...| a |test| function available analogous to the + |test{\ifsometest}| construct from the |etoolbox| package; but any + \emph{expandable} |\ifsometest| can be inserted directly in an + |\xintexpr|-ession as |\ifsometest10| (or |\ifsometest{1}{0}|), for example + |if(\ifsometest{1}{0},YES,NO)| (see the |if| operator below) works. + + A straight |\ifsometest{YES}{NO}| would do the same more + efficiently, the point + of |\ifsometest10| is to allow arbitrary boolean combinations using + the (described later) \verb+&+ and \verb+|+ logic operators: + \verb+\ifsometest10 & \ifsomeothertest10 | \ifsomethirdtest10+, etc... |YES| + or |NO| above stand for material compatible with the + |\xintexpr| parser syntax. + + See also \csbxint{ifboolexpr}, in this context. + \item[functions with one mandatory and a second optional argument] + \ctexttt{round, trunc,\\ float, sqrt}. For + example |round(2^9/3^5,12)=|\digitstt{\xinttheexpr round(2^9/3^5,12)\relax.} + The |sqrt| is available also in |\xintexpr|, not only in |\xintfloatexpr|. + The second optional argument is the required float precision. + \item[functions with two arguments] + \ctexttt{quo, rem}. These functions are integer only, they give the quotient + and remainder in Euclidean division (more generally one can use + the |floor| function; related: the |frac| function). + \item[the if conditional (twofold way)] \ctexttt{if}|(cond,yes,no)| checks if + |cond| is true or false and takes the corresponding branch. Any non zero + number or fraction is logical true. The zero value is logical false. Both + ``branches'' are evaluated (they are not really branches but just numbers). + See also the |?| operator. + \item[the ifsgn conditional (threefold way)] + \ctexttt{ifsgn}|(cond,<0,=0,>0)| checks the sign of |cond| and + proceeds correspondingly. All three are evaluated. See also the |:| + operator. + \item[functions with an arbitrary number of arguments] \ctexttt{all, any, + xor, add (=sum), mul (=prd), max, min, gcd, lcm}: |gcd| and |lcm| are + integer-only and require the \xintgcdname package. Currently, the |and| and + |or| keywords are left undefined by the package, which uses rather |all| + and |any|. They must have at least one argument. + \end{description} +\item The three postfix operators \ctexttt{!, ?, :}. + \begin{description} + \item[{\color[named]{DarkOrchid}!}] computes the factorial of an integer. |sqrt(36)!| evaluates to |6!| + (\digitstt{=\np{\xinttheexpr sqrt(36)!\relax}}) and not to the square root of + |36!| (\digitstt{$\approx$\np{\xintthefloatexpr sqrt(36!)\relax}}). 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 |true|, zero counts as |false|). It then acts as + a macro with two mandatory arguments within braces (hence this escapes from + the parser scope, the braces can not be hidden in a macro), chooses the + correct branch \emph{without evaluating the wrong one}. Once the braces are + removed, the parser scans and expands the uncovered material so for example + \centeredline{|\xinttheiexpr (3>2)?{5+6}{7-1}2^3\relax|} is legal and + computes |5+62^3=|\digitstt{\xinttheiexpr(3>2)?{5+(6}{7-(1}2^3)\relax}. Note + though that it would be better practice to include here the |2^3| inside the + branches. The contents of the branches may be arbitrary as long as once glued + to what is next the syntax is respected: {|\xintexpr + (3>2)?{5+(6}{7-(1}2^3)\relax| also works.} Differs thus from the |if| + conditional in two ways: the false branch is not at all computed, and the + number scanner is still active on exit, more digits may follow. +\item[{\color[named]{DarkOrchid}:}] is used as |(cond):{<0}{=0}{>0}|. |cond| is anything, its sign is + evaluated (it is not necessary to use |sgn(cond):{<}{=}{>}|) and depending on + the sign the correct branch is un-braced, the two others are swallowed. The + un-braced branch will then be parsed as usual. Differs from the |ifsgn| + conditional as the two false branches are not evaluated and furthermore the + number scanner is still active on exit. + \centeredline{|\def\x{0.33}\def\y{1/3}|} \centeredline{|\xinttheexpr + (\x-\y):{sqrt}{0}{1/}(\y-\x)\relax|% + \digitstt{=\def\x{0.33}\def\y{1/3}\xinttheexpr + (\x-\y):{sqrt}{0}{1/}(\y-\x)\relax }} + \end{description} +\item \def\MicroFont{\color[named]{DarkOrchid}\ttfamily\bfseries} + The |.| as decimal mark; the number scanner treats it as an inherent, + optional and unique component of a being formed number. One can do things + such as {\def\MicroFont{\ttfamily}|\xinttheexpr + .^2+2^.\relax|$\to$\digitstt{\xinttheexpr .^2+2^.\relax} (which is + |0^2+2^0|)}. +\item The |"| for hexadecimal numbers: it is treated with highest priority, + allowed only at locations where the parser expects to start forming a numeric + operand, once encountered it triggers the hexadecimal scanner which looks for + successive hexadecimal digits (as usual skipping spaces and expanding forward + everything) possibly a unique optional dot (allowed directly in front) and + then an optional (possibly empty) fractional part. The dot and fractional part + are not allowed in {\def\MicroFont{\ttfamily}|\xintiiexpr..\relax|}. The |"| + functionality requires that the user loaded \xintbinhexname (there is no + warning, but an ``undefined control sequence'' error will naturally results if + the package has not been loaded). +\item + % + The |e| and |E| for scientific notation. They are treated as infix operators + of highest priority: this means that they serve as an end marker (possibly + arising from macro expansion) for the scanned number, and then will pre-empt + the number coming next, either explicit, or arising from expansion, from + parenthesized material, from a sub-expression etc..., to serve as exponent. + \begingroup + \def\MicroFont{\ttfamily}% + From + the rules above, inside |\xintexpr|, |1e3-1| + is \digitstt{\xinttheexpr 1e3-1\relax}, |1e3^2| is \digitstt{\xinttheexpr + 1e3^2\relax}, and |"Ae("A+"F)^"A| + is \digitstt{\xinttheexpr "Ae("A+"F)^"A\relax}.\endgroup +\item The power operator |^|. It is left associative: +\begingroup\def\MicroFont{\ttfamily}% +|\xinttheiexpr 2^2^3\relax| evaluates to \xinttheiexpr 2^2^3\relax, not +\xinttheiexpr 2^(2^3)\relax. Note that if the float precision is too low, +iterated powers withing |\xintfloatexpr..\relax| may fail: for example with the +default setting |(1+1e-8)^(12^16)| will be computed with |12^16| approximated +from its @16@ most significant digits but it has @18@ digits +(\digitstt{={\xintiiPow{12}{16}}}), hence the result is wrong: +% +\centeredline{$\np{\xintthefloatexpr (1+1e-8)^(12^16)\relax }$} +% +One should code +% +\centeredline{|\xintthe\xintfloatexpr (1+1e-8)^\xintiiexpr 12^20\relax \relax|} +% +to obtain the correct floating point evaluation +% +\centeredline{$\np{1.00000001}^{12^{16}}\approx\np{\xintthefloatexpr + (1+1e-8)^\xintiiexpr 12^16\relax\relax }$}% +% +\endgroup +\item Multiplication and division \raisebox{-.3\height}{|*|}, |/|. The division + is left associative, too: \begingroup\def\MicroFont{\ttfamily}% + |\xinttheiexpr 100/50/2\relax| evaluates to + \xinttheiexpr 100/50/2\relax, not \xinttheiexpr 100/(50/2)\relax.\endgroup +\item Addition and subtraction |+|, |-|. Again, |-| is left + associative: \begingroup\def\MicroFont{\ttfamily}% + |\xinttheiexpr 100-50-2\relax| evaluates to + \xinttheiexpr 100-50-2\relax, not \xinttheiexpr 100-(50-2)\relax.\endgroup +\item Comparison operators |<|, |>|, |=| (currently, no @<=@, @>=@, + \dots ). +\item Conjunction (logical and): |&|. (no @&&@) +\item Inclusive disjunction (logical or): \verb$|$. (no @||@) +\item The comma |,|. \def\MicroFont{\ttfamily}% + With |\xinttheiexpr 2^3, 3^4, 5^6\relax| one obtains as output + \xinttheiexpr 2^3,3^4,5^6\relax{} (no space after the commas on output). +\item The parentheses. +\endlist +\endgroup + +See \autoref{ssec:countinexpr} for count and dimen registers and variables. + + +\section{Change log for earlier releases} +\label{sec:releases} + +% peut-être je devrais mettre ici le dernier aussi? + +\footnotesize + +\noindent Release |1.09j| (|[2014/01/09]|): +\begin{itemize} +\item the core division routines have been re-written for some (limited) + efficiency gain, more pronounced for small divisors. As a result the + \hyperlink{Machin1000}{computation of one thousand digits of $\pi$} + is close to three times faster than with earlier releases. +\item some various other small improvements, particularly in the power routines. +\item a new macro \csbxint{XTrunc} is designed to produce thousands or even tens + of thousands of digits of the decimal expansion of a fraction. Although + completely expandable it has its use limited to inside an |\edef|, |\write|, + |\message|, \dots. It + can thus not be nested as argument to another package macro. +\item the tacit multiplication done in \csbxint{expr}|..\relax| on encountering + a count register or variable, or a |\numexpr|, while scanning a (decimal) + number, is extended to the case of a sub |\xintexpr|-ession. +\item \csbxint{expr} can now be used in an |\edef| with no |\xintthe| + prefix; it will execute completely the computation, and the error + message about a missing |\xintthe| will be inhibited. Previously, in + the absence of |\xintthe|, expansion could only be a full one (with + |\romannumeral-`0|), not a complete one (with |\edef|). Note that this + differs from the behavior of the non-expandable |\numexpr|: |\the| or + |\number| are needed not only to print but also to trigger the + computation, whereas |\xintthe| is mandatory only for the printing step. +\item the default behavior of \csbxint {Assign} is changed, it now does not do + any further expansion beyond the initial full-expansion which provided the + list of items to be assigned to macros. +\item bug-fix: |1.09i| did an unexplainable change to |\XINT_infloat_zero| which + broke the floating point routines for vanishing operands =:((( +\item dtx bug-fix: the |1.09i .ins| file produced a buggy |.tex| file. +\end{itemize} + +\noindent Release |1.09i| (|[2013/12/18]|): +\begin{itemize} +\item \csbxint{iiexpr} is a variant of \csbxint{expr} which is optimized to deal + only with (long) integers, |/| does a euclidean quotient. +\item |\xintnumexpr|, |\xintthenumexpr|, |\xintNewNumExpr| are renamed, + respectively, \csbxint{iexpr}, \csbxint{theiexpr}, \csbxint{NewIExpr}. The + earlier denominations are kept but to be removed at some point. +\item it is now possible within |\xintexpr...\relax| and its variants to use + count, dimen, and skip registers or variables without explicit |\the/\number|: + the parser inserts automatically |\number| and a tacit multiplication is + implied when a register or variable immediately follows a number or fraction. + Regarding dimensions and |\number|, see the further discussion in + \autoref{sec:Dimensions}. +\item new conditional \csbxint{ifOne}; |\xintifTrueFalse| renamed to + \csbxint{ifTrueAelseB}; new macros \csbxint{TFrac} (`fractional part', mapped + to function |frac| in |\xintexpr|-essions), \csbxint{FloatE}. +\item \csbxint{Assign} admits an optional argument to specify the expansion + type to be used: |[]| (none, default), |[o]| (once), |[oo]| (twice), |[f]| + (full), |[e]| (|\edef|),... to define the macros +\item related to the previous item, \xinttoolsname defines + \hyperref[odef]{\ttfamily\char92odef}, + \hyperref[oodef]{\ttfamily\char92oodef}, + \hyperref[fdef]{\ttfamily\char92fdef} (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 + \hyperref[oodef]{\ttfamily\char92oodef} which expands twice the macro + replacement text and is thus a faster alternative to |\edef| taking into + account that the \xintname bundle macros expand already completely in only + two steps. This can be significant when repeatedly making |\def|-initions + expanding to hundreds of digits. +\item some across the board slight efficiency improvement as a result of + modifications of various types to ``fork'' macros and ``branching + conditionals'' which are used internally. +\item bug-fix: |\xintAND| and |\xintOR| inserted a space token in some cases and + did not expand as promised in two steps (bug dating back to |1.09a| I think; + this bug was without consequences when using |&| and \verb+|+ in + \csa{xintexpr-}essions, it affected only the macro form) + |:-((|. +\item bug-fix: \csbxint{FtoCCv} still ended fractions with the |[0]|'s which + were supposed to have been removed since release |1.09b|. +\end{itemize} + +\noindent Release |1.09h| (|[2013/11/28]|): +\begin{itemize} +\item parts of the documentation have been re-written or re-organized, + particularly the discussion of expansion issues and of input and + output formats. +\item the expansion types of macro arguments are documented in the margin of the + macro descriptions, with conventions mainly taken over from those in the + \LaTeX3 documentation. +\item a dependency of \xinttoolsname on \xintname (inside \csbxint{Seq}) has + been removed. +\item \csbxint{TypesetEuclideAlgorithm} and \csbxint{TypesetBezoutAlgorithm} + have been slightly modified (regarding indentation). +\item macros \csa{xintiSum} and \csa{xintiPrd} are renamed to \csbxint{iiSum} + and \csbxint{iiPrd}. +\item a count register used in |1.09g| in the \csbxint{For} loops for parsing + purposes has been removed and replaced by use of a |\numexpr|. +\item the few uses of |\loop| have been replaced by |\xintloop/\xintiloop|. +\item all macros of \xinttoolsname for which it makes sense are now + declared |\long|. +\end{itemize} + +\noindent Release |1.09g| (|[2013/11/22]|): +\begin{itemize} +\item package \xinttoolsname is detached from \xintname, to make tools such as + \csbxint{For}, \csbxint{ApplyUnbraced}, and \csbxint{iloop} available without + the \xintname overhead. +\item new expandable nestable loops \csbxint{loop} and \csbxint{iloop}. +\item bugfix: \csbxint{For} and \csbxint{For*} do not modify anymore the value + of |\count 255|. +\end{itemize} + +\noindent Release |1.09f| (|[2013/11/04]|): +\begin{itemize} +\item new \csbxint{ZapFirstSpaces}, \csbxint{ZapLastSpaces}, + \csbxint{ZapSpaces}, \csbxint{ZapSpacesB}, for expandably stripping away + leading and/or ending spaces. +\item \csbxint{CSVtoList} by default uses \csbxint{ZapSpacesB} to strip away + spaces around commas (or at the start and end of the comma separated list). +\item also the \csbxint{For} loop will strip out all spaces around commas and at + the start and the end of its list argument; and similarly for + \csbxint{Forpair}, \csbxint{Forthree}, \csbxint{Forfour}. +\item \csbxint{For} \emph{et al.} accept all macro parameters + from + |#1| to |#9|. +\item for reasons of inner coherence some macros previously with one extra `|i|' + in their names (e.g. \csa{xint\-iMON}) now have a doubled `|ii|' + (\csbxint{iiMON}) to indicate that they skip the overhead of parsing their + inputs via \csbxint{Num}. Macros with a \emph{single} `|i|' such as + \csbxint{iAdd} are those which maintain the non-\xintfracname output format + for big integers, but do parse their inputs via \csbxint{Num} (since release + |1.09a|). They too may have doubled-|i| variants for matters of programming + optimization when working only with (big) integers and not fractions or + decimal numbers. +\end{itemize} + + +\noindent Release |1.09e| (|[2013/10/29]|): +\begin{itemize} +\item new \csbxint{integers}, \csbxint{dimensions}, \csbxint{rationals} for + infinite \csbxint{For} loops, interrupted with \csbxint{BreakFor} and + \csbxint{BreakForAndDo}. +\item new \csbxint{ifForFirst}, \csbxint{ifForLast} for the \csa{xintFor} and + \csa{xintFor*} loops, +\item the \csa{xintFor} and \csa{xintFor*} loops are now |\long|, the + replacement text and the items may contain explicit |\par|'s. +\item bug fix, the \csbxint{For} loop (not \csbxint{For*}) did not correctly + detect an + empty list. +\item new conditionals \csbxint{ifCmp}, \csbxint{ifInt}, \csbxint{ifOdd}. +\item bug fix, |\xintiSqrt {0}| crashed. |:-((| +\item the documentation has been enriched with various additional examples, + such as the \hyperref[ssec:quicksort]{the quick sort algorithm illustrated} or + the computation of prime numbers (\autoref{ssec:primesI}, + \autoref{ssec:primesII}, \autoref{ssec:primesIII}). +\item the documentation explains with more details various expansion related + issues, particularly in relation to conditionals. +\end{itemize} + +\noindent Release |1.09d| (|[2013/10/22]|):\nobreak +\begin{itemize} +\item \csbxint{For*} is modified to gracefully handle a space token (or + more than one) located at the + very end of its list argument (as in for example |\xintFor* #1 in + {{a}{b}{c}<space>} \do {stuff}|; + spaces at other locations were already harmless). Furthermore this new +version \fexpan ds the un-braced list items. After +|\def\x{{1}{2}}| and |\def\y{{a}\x {b}{c}\x }|, |\y| will appear to +\csbxint{For*} exactly as if it had been defined as +|\def\y{{a}{1}{2}{b}{c}{1}{2}}|. +\item same bug fix in \csbxint{ApplyInline}. +\end{itemize} + +\noindent Release |1.09c| (|[2013/10/09]|): +\begin{itemize} +\item added \hyperlink{item:bool}{|bool|} and \hyperlink{item:bool}{|togl|} to + the + \csbxint{expr} syntax; also added \csbxint{boolexpr} and \csbxint{ifboolexpr}. +\item added |\xintNewNumExpr| (now \csbxint{NewIExpr} and \csbxint{NewBoolExpr}, +\item \csbxint{For} is a new type of loop, whose replacement text inserts the + comma separated values or list items via macro parameters, rather than + encapsulated in macros; the loops are nestable up to four levels (nine + levels since |1.09f|) and their replacement texts are allowed to close + groups as happens with the tabulation in alignments, +\item \csbxint{Forpair}, \csbxint{Forthree}, \csbxint{Forfour} are experimental + variants of \csbxint{For}, +\item \csbxint{ApplyInline} has been enhanced in order to be usable for + generating rows (partially or completely) in an alignment, +\item new command \csbxint{Seq} to generate (expandably) arithmetic sequences of + (short) integers, +\item the factorial |!| and branching |?|, |:|, operators (in + \csbxint{expr}|...\relax|) have now less precedence than a function name + located just before: |func(x)!| is the factorial of |func(x)|, not |func(x!)|, +\item again various improvements and changes in the documentation. +\end{itemize} + +\noindent Release |1.09b| (|[2013/10/03]|): +\begin{itemize} +\item various improvements in the documentation, +\item more economical catcode management and re-loading handling, +\item removal of all those |[0]|'s previously forcefully added at the end of + fractions by various macros of \xintcfracname, +\item \csbxint{NthElt} with a negative index returns from the tail of the list, +\item new macro \csbxint{PRaw} to have something like what |\xintFrac| does in + math + mode; i.e. a |\xintRaw| which does not print the denominator if it is one. +\end{itemize} + +\noindent Release |1.09a| (|[2013/09/24]|): +\begin{itemize} +\item \csbxint{expr}|..\relax| and + \csbxint{floatexpr}|..\relax| admit functions in their + syntax, with comma separated values as arguments, among them \texttt{reduce, + sqr, sqrt, abs, sgn, floor, ceil, quo, rem, round, trunc, float, gcd, lcm, + max, min, sum, prd, add, mul, not, all, any, xor}. +\item comparison (|<|, |>|, |=|) and logical (\verb$|$, |&|) operators. +\item the command |\xintthe| which converts |\xintexpr|essions into printable + format (like |\the| with |\numexpr|) is more efficient, for example one can do + |\xintthe\x| if |\x| was def'ined to be an |\xintexpr..\relax|: +\centeredline{|\def\x{\xintexpr 3^57\relax}\def\y{\xintexpr \x^(-2)\relax}|} +\centeredline{|\def\z{\xintexpr + \y-3^-114\relax}|\hspace{1cm}|\xintthe\z=|\begingroup +\def\x{\xintexpr 3^57\relax}\def\y{\xintexpr \x^(-2)\relax}% +\def\z{\xintexpr \y-3^-114\relax}\digitstt{\xintthe\z}\endgroup} +\item |\xintnumexpr .. \relax| (now renamed \csbxint{iexpr}) is |\xintexpr + round( .. ) \relax|. +\item \csbxint{NewExpr} now works with the standard macro parameter character + |#|. +\item both regular |\xintexpr|-essions and commands defined by |\xintNewExpr| + will work with comma separated lists of expressions, +\item new commands \csbxint{Floor}, \csbxint{Ceil}, \csbxint{Maxof}, + \csbxint{Minof} (package \xintfracname), \csbxint{GCDof}, \csbxint{LCM}, + \csbxint{LCMof} (package \xintgcdname), \csbxint{ifLt}, \csbxint{ifGt}, + \csbxint{ifSgn}, \csbxint{ANDof}, ... +\item The arithmetic macros from package \xintname now filter their operands via + \csbxint{Num} which means that they may use directly count registers and + |\numexpr|-essions without having to prefix them by |\the|. This is thus + similar to the situation holding previously but with \xintfracname loaded. +\item a bug introduced in |1.08b| made \csbxint{Cmp} crash when one of its + arguments was zero. |:-((| +\end{itemize} + + +\noindent Release |1.08b| (|[2013/06/14]|): +\begin{itemize} +\item Correction of a problem with spaces inside |\xintexpr|-essions. +\item Additional improvements to the handling of floating point numbers. +\item The macros of \xintfracname allow to use count registers in their + arguments in ways which were not previously documented. See + \hyperref[sec:useofcount]{Use of count registers}. +\end{itemize} + +\noindent Release |1.08a| (|[2013/06/11]|): +\begin{itemize} +\item Improved efficiency of the basic conversion from exact + fractions to floating point numbers, + with ensuing speed gains especially for the power function macros + \csbxint{FloatPow} and \csbxint{FloatPower}, +\item Better management by the \xintfracname macros \csbxint{Cmp}, + \csbxint{Max}, \csbxint{Min} and \csbxint{Geq} of inputs having big powers + of ten in them. +\item Macros for floating point numbers added to the \xintseriesname package. +\end{itemize} + +\noindent Release |1.08| (|[2013/06/07]|): +\begin{itemize} +\item Extraction of square roots, for floating point numbers + (\csbxint{FloatSqrt}), and also in + a version adapted to integers (\csbxint{iSqrt}). +\item New package \xintbinhexname providing \hyperref[sec:binhex]{conversion + routines} to and from binary and hexadecimal bases. +\end{itemize} + +\noindent Release |1.07| (|[2013/05/25)]|): +\begin{itemize} +\item The \xintfracname macros accept numbers written in scientific notation, + the \csbxint{Float} command serves to output its argument with a given number + |D| of significant figures. The value of |D| is either given as optional + argument to \csbxint{Float} or set with |\xintDigits := D;|. The default value + is |16|. +\item The \xintexprname package is a new core constituent (which loads + automatically \xintfracname and \xintname) and implements the expandable + expanding parsers \centeredline{\csbxint{expr}| . . . \relax|, + and its variant + \csbxint{floatexpr}| . . . \relax|} allowing on input formulas using the + standard form with infix + operators |+|, |-|, |*|, |/|, and |^|, and arbitrary levels of + parenthesizing. Within a float expression the operations are executed + according to the current value of \csbxint{Digits}. Within an + |\xintexpr|-ession the binary operators are computed exactly. +\item The floating point precision |D| is set (this is a +local assignment to a |\mathchar| variable) with |\xintDigits := D;| and queried +with |\xinttheDigits|. It may be set to anything up to |32767|.\footnote{but + values higher than 100 or 200 will presumably give too slow evaluations.} The +macro incarnations of the binary operations admit an optional argument which +will replace pointwise |D|; this argument may exceed the |32767| bound. +\item To write the |\xintexpr| parser I benefited from the commented source of + the +\LaTeX3 parser; the |\xintexpr| parser has its own features and peculiarities. +See \hyperref[sec:expr]{its documentation}. +\end{itemize} + +Initial release |1.0| was on |2013/03/28|. + + +% \noindent Historians debate the early history of the \xintname bundle, whose +% details will need patient reconstruction from the scattered archeological +% remnants. It has been established that the initial release |1.0| was on +% |2013/03/28|, although only closer scrutiny of the CTAN logs could help +% completely exclude possibility of an earlier |0.9|. + + + +\normalsize + + +\etocdepthtag.toc {commandsA} + +\section{Commands of the \xinttoolsname package} +\label{sec:tools} + +\def\n{\string{N\string}} +\def\m{\string{M\string}} +\def\x{\string{x\string}} + +These utilities used to be provided within the \xintname package; since |1.09g| +they have been moved to an independently usable package \xinttoolsname, which +has none of the \xintname facilities regarding big numbers. Whenever relevant +release |1.09h| has made the macros |\long| so they accept |\par| tokens on +input. + +First the completely expandable utilities up to \csbxint{iloop}, then the non +expandable utilities. + +This section contains various concrete examples and ends with a +\hyperref[ssec:quicksort]{completely expandable implementation of the Quick Sort + algorithm} together with a graphical illustration of its action. + +\clearpage + +\localtableofcontents + + +\subsection{\csbh{xintReverseOrder}}\label{xintReverseOrder} + +\csa{xintReverseOrder}\marg{list}\etype{n} does not do any expansion of its +argument and just reverses the order of the tokens in the \meta{list}. Braces +are removed once and the enclosed material, now unbraced, does not get +reverted. Unprotected spaces (of any character code) are gobbled. +\centeredline{|\xintReverseOrder{\xintDigitsOf\xintiPow {2}{100}\to\Stuff}|} +\centeredline{gives: + \ttfamily{\string\Stuff\string\to1002\string\xintiPow\string\xintDigitsOf}} + +\subsection{\csbh{xintRevWithBraces}}\label{xintRevWithBraces} + +%{\small New in release |1.06|.\par} + +\edef\X{\xintRevWithBraces{12345}} +\edef\y{\xintRevWithBraces\X} +\expandafter\def\expandafter\w\expandafter + {\romannumeral0\xintrevwithbraces{{\A}{\B}{\C}{\D}{\E}}} + +% +\csa{xintRevWithBraces}\marg{list}\etype{f} first does the \fexpan sion of its +argument then it reverses the order of the tokens, or braced material, it +encounters, adding a pair of braces to each (thus, maintaining brace pairs +already existing). Spaces (in-between external brace pairs) are gobbled. This +macro is mainly thought out for use on a \meta{list} of such braced material; +with such a list as argument the \fexpan sion will only hit against the first +opening brace, hence do nothing, and the braced stuff may thus be macros one +does not want to expand. \centeredline{|\edef\x{\xintRevWithBraces{12345}}|} +\centeredline{|\meaning\x:|\ttfamily{\meaning\X}} +\centeredline{|\edef\y{\xintRevWithBraces\x}|}% +\centeredline{|\meaning\y:|\ttfamily{\meaning\y}} The examples above could be +defined with |\edef|'s because the braced material did not contain macros. +Alternatively: \centeredline{|\expandafter\def\expandafter\w\expandafter|}% +\centeredline{|{\romannumeral0\xintrevwithbraces{{\A}{\B}{\C}{\D}{\E}}}|} +\centeredline{|\meaning\w:|\ttfamily{\meaning\w}} The macro +\csa{xintReverseWithBracesNoExpand}\etype{n} does the same job without the +initial +expansion of its argument. + +\subsection{\csbh{xintLength}}\label{xintLength} + +\csa{xintLength}\marg{list}\etype{n} does not do \emph{any} expansion of its +argument and just counts how many tokens there are (possibly none). So to use it +to count things in the replacement text of a macro one should do +|\expandafter\xintLength\expandafter{\x}|. One may also use it inside macros as +|\xintLength{#1}|. Things enclosed in braces count as one. Blanks between tokens +are not counted. See \csbxint{NthElt}|{0}| for a variant which first \fexpan ds +its argument. \centeredline{|\xintLength {\xintiPow + {2}{100}}|\digitstt{=\xintLength {\xintiPow{2}{100}}}} +\centeredline{${}\neq{}$|\xintLen {\xintiPow {2}{100}}|\digitstt{=\xintLen + {\xintiPow{2}{100}}}} + +\subsection{\csbh{xintZapFirstSpaces}, \csbh{xintZapLastSpaces}, \csbh{xintZapSpaces}, \csbh{xintZapSpacesB}} +\label{xintZapFirstSpaces} +\label{xintZapLastSpaces} +\label{xintZapSpaces} +\label{xintZapSpacesB} +%{\small New with release |1.09f|.\par} + +\csa{xintZapFirstSpaces}\marg{stuff}\etype{n} does not do \emph{any} expansion +of its +argument, nor brace removal of any sort, nor does it alter \meta{stuff} in +anyway apart from stripping away all \emph{leading} spaces. + +This macro will be mostly of interest to programmers who will know what I will +now be talking about. \emph{The essential points, naturally, are the complete + expandability and the fact that no brace removal nor any other alteration is + done to the input.} + +\TeX's input scanner already converts consecutive blanks into single space +tokens, but \csa{xintZapFirstSpaces} handles successfully also inputs with +consecutive multiple space tokens. +However, it is assumed that \meta{stuff} does not contain (except inside braced +sub-material) space tokens of character code distinct from @32@. + +It expands in two steps, and if the goal is to apply it to the +expansion text of |\x| to define |\y|, then one should do: +|\expandafter\def\expandafter\y\expandafter + {\romannumeral0\expandafter\xintzapfirstspaces\expandafter{\x}}|. + +Other use case: inside a macro as |\edef\x{\xintZapFirstSpaces {#1}}| assuming +naturally that |#1| is compatible with such an |\edef| once the leading spaces +have been stripped. + +\begingroup +\def\x { \a { \X } { \b \Y } } +\centeredline{|\xintZapFirstSpaces { \a { \X } { \b \Y } }->|% +\digitstt{\color{magenta}{}\expandafter\detokenize\expandafter +{\romannumeral0\expandafter\xintzapfirstspaces\expandafter{\x}}}+++} +\endgroup + +\medskip + +\noindent\csbxint{ZapLastSpaces}\marg{stuff}\etype{n} does not do \emph{any} expansion of +its argument, nor brace removal of any sort, nor does it alter \meta{stuff} in +anyway apart from stripping away all \emph{ending} spaces. The same remarks as +for \csbxint{ZapFirstSpaces} apply. + +% ATTENTION à l'\ignorespaces fait par \color! +\begingroup +\def\x { \a { \X } { \b \Y } } +\centeredline{|\xintZapLastSpaces { \a { \X } { \b \Y } }->|% +\digitstt{\color{magenta}{}\expandafter\detokenize\expandafter +{\romannumeral0\expandafter\xintzaplastspaces\expandafter{\x}}}+++} +\endgroup + +\medskip + +\noindent\csbxint{ZapSpaces}\marg{stuff}\etype{n} does not do \emph{any} +expansion of its +argument, nor brace removal of any sort, nor does it alter \meta{stuff} in +anyway apart from stripping away all \emph{leading} and all \emph{ending} +spaces. The same remarks as for \csbxint{ZapFirstSpaces} apply. + +\begingroup +\def\x { \a { \X } { \b \Y } } +\centeredline{|\xintZapSpaces { \a { \X } { \b \Y } }->|% +\digitstt{\color{magenta}{}\expandafter\detokenize\expandafter +{\romannumeral0\expandafter\xintzapspaces\expandafter{\x}}}+++} +\endgroup + +\medskip + +\noindent\csbxint{ZapSpacesB}\marg{stuff}\etype{n} does not do \emph{any} +expansion of +its argument, nor does it alter \meta{stuff} in anyway apart from stripping away +all leading and all ending spaces and possibly removing one level of braces if +\meta{stuff} had the shape |<spaces>{braced}<spaces>|. The same remarks as for +\csbxint{ZapFirstSpaces} apply. + +\begingroup +\def\x { \a { \X } { \b \Y } } +\centeredline{|\xintZapSpacesB { \a { \X } { \b \Y } }->|% +\digitstt{\color{magenta}{}\expandafter\detokenize\expandafter +{\romannumeral0\expandafter\xintzapspacesb\expandafter{\x}}}+++} +\def\x { { \a { \X } { \b \Y } } } +\centeredline{|\xintZapSpacesB { { \a { \X } { \b \Y } } }->|% +\digitstt{\color{magenta}{}\expandafter\detokenize\expandafter +{\romannumeral0\expandafter\xintzapspacesb\expandafter{\x}}}+++} +\endgroup + The spaces here at the start and end of the output come from the braced + material, and are not removed (one would need a second application for that; + recall though that the \xintname zapping macros do not expand their argument). + +\subsection{\csbh{xintCSVtoList}} +\label{xintCSVtoList} +\label{xintCSVtoListNoExpand} + +% {\small New with release |1.06|. Starting with |1.09f|, \fbox{\emph{removes +% spaces around commas}!}\par} + +\csa{xintCSVtoList}|{a,b,c...,z}|\etype{f} returns |{a}{b}{c}...{z}|. A +\emph{list} is by +convention in this manual simply a succession of tokens, where each braced thing +will count as one item (``items'' are defined according to the rules of \TeX{} +for fetching undelimited parameters of a macro, which are exactly the same rules +as for \LaTeX{} and command arguments [they are the same things]). The word +`list' in `comma separated list of items' has its usual linguistic meaning, +and then an ``item'' is what is delimited by commas. + +So \csa{xintCSVtoList} takes on input a `comma separated list of items' and +converts it into a `\TeX{} list of braced items'. The argument to +|\xintCSVtoList| may be a macro: it will first be +\hyperref[sec:expansions]{\fexpan ded}. Hence the item before the first comma, +if it is itself a macro, will be expanded which may or may not be a good thing. +A space inserted at the start of the first item serves to stop that expansion +(and disappears). The macro \csbxint{CSVtoListNoExpand}\etype{n} does the same +job without +the initial expansion of the list argument. + +Apart from that no expansion of the items is done and the list items may thus be +completely arbitrary (and even contain perilous stuff such as unmatched |\if| +and |\fi| tokens). + +Contiguous spaces and tab characters, are collapsed by \TeX{} +into single spaces. All such spaces around commas\footnote{and multiple space + tokens are not a problem; but those at the top level (not hidden inside + braces) \emph{must} be of character code |32|.} \fbox{are removed}, as well as +the spaces at the start and the spaces at the end of the list.\footnote{let us + recall that this is all done completely expandably... There is absolutely no + alteration of any sort of the item apart from the stripping of initial and + final space tokens (of character code |32|) and brace removal if and only if + the item apart from intial and final spaces (or more generally multiple |char + 32| space tokens) is braced.} The items may contain explicit |\par|'s or +empty lines (converted by the \TeX{} input parsing into |\par| tokens). + +\begingroup + +\edef\X{\xintCSVtoList { 1 ,{ 2 , 3 , 4 , 5 }, a , {b,T} U , { c , d } , { {x , + y} } }} + +\centeredline{|\xintCSVtoList { 1 ,{ 2 , 3 , 4 , 5 }, a , {b,T} U , { c , d } , + { {x , y} } }|} +\centeredline{|->|% +{\makeatletter\digitstt{\expandafter\strip@prefix\meaning\X}}} + +One sees on this example how braces protect commas from +sub-lists to be perceived as delimiters of the top list. Braces around an entire +item are removed, even when surrounded by spaces before and/or after. Braces for +sub-parts of an item are not removed. + +We observe also that there is a slight difference regarding the brace stripping +of an item: if the braces were not surrounded by spaces, also the initial and +final (but no other) spaces of the \emph{enclosed} material are removed. This is +the only situation where spaces protected by braces are nevertheless removed. + +From the rules above: for an empty argument (only spaces, no braces, no comma) +the output is +\digitstt{\expandafter\detokenize\expandafter{\romannumeral0\xintcsvtolist { }}} +(a list with one empty item), +for ``|<opt. spaces>{}<opt. +spaces>|'' the output is +\digitstt{\expandafter\detokenize\expandafter + {\romannumeral0\xintcsvtolist { {} }}} +(again a list with one empty item, the braces were removed), +for ``|{ }|'' the output is +\digitstt{\expandafter\detokenize\expandafter + {\romannumeral0\xintcsvtolist {{ }}}} +(again a list with one empty item, the braces were removed and then +the inner space was removed), +for ``| { }|'' the output is +\digitstt{\expandafter\detokenize\expandafter +{\romannumeral0\xintcsvtolist { { }}}} (again a list with one empty item, the initial space served only to stop the expansion, so this was like ``|{ }|'' as input, the braces were removed and the inner space was stripped), +for ``\texttt{\ \{\ \ \}\ }'' the output is +\digitstt{\expandafter\detokenize\expandafter +{\romannumeral0\xintcsvtolist { { } }}} (this time the ending space of the first +item meant that after brace removal the inner spaces were kept; recall though +that \TeX{} collapses on input consecutive blanks into one space token), +for ``|,|'' the output consists of two consecutive +empty items +\digitstt{\expandafter\detokenize\expandafter{\romannumeral0\xintcsvtolist + {,}}}. Recall that on output everything is braced, a |{}| is an ``empty'' +item. +% +Most of the above is mainly irrelevant for every day use, apart perhaps from the +fact to be noted that an empty input does not give an empty output but a +one-empty-item list (it is as if an ending comma was always added at the end of +the input). + +\def\y { \a,\b,\c,\d,\e} +\expandafter\def\expandafter\Y\expandafter{\romannumeral0\xintcsvtolist{\y}} +\def\t {{\if},\ifnum,\ifx,\ifdim,\ifcat,\ifmmode} +\expandafter\def\expandafter\T\expandafter{\romannumeral0\xintcsvtolist{\t}} + +\centeredline{|\def\y{ \a,\b,\c,\d,\e} \xintCSVtoList\y->|% + {\makeatletter\digitstt{\expandafter\strip@prefix\meaning\Y}}} +\centeredline{|\def\t {{\if},\ifnum,\ifx,\ifdim,\ifcat,\ifmmode}|} \centeredline +{|\xintCSVtoList\t->|\makeatletter\digitstt{\expandafter\strip@prefix\meaning\T}} +The results above were automatically displayed using \TeX's primitive +\csa{meaning}, which adds a space after each control sequence name. These spaces +are not in the actual braced items of the produced lists. The first items |\a| +and |\if| were either preceded by a space or braced to prevent expansion. The +macro \csa{xintCSVtoListNoExpand} would have done the same job without the +initial expansion of the list argument, hence no need for such protection but if +|\y| is defined as |\def\y{\a,\b,\c,\d,\e}| we then must do: +\centeredline{|\expandafter\xintCSVtoListNoExpand\expandafter {\y}|} Else, we +may have direct use: \centeredline{|\xintCSVtoListNoExpand + {\if,\ifnum,\ifx,\ifdim,\ifcat,\ifmmode}|} +\centeredline{|->|\digitstt{\expandafter\detokenize\expandafter + {\romannumeral0\xintcsvtolistnoexpand + {\if,\ifnum,\ifx,\ifdim,\ifcat,\ifmmode}}}} +% +Again these spaces are an artefact from the use in the source of the document of +\csa{meaning} (or rather here, \csa{detokenize}) to display the result of using +\csa{xintCSVtoListNoExpand} (which is done for real in this document +source). + +For the similar conversion from comma separated list to braced items list, but +without removal of spaces around the commas, there is +\csa{xintCSVtoListNonStripped}\etype{f} and +\csa{xintCSVtoListNonStrippedNoExpand}\etype{n}. + +\endgroup + +\subsection{\csbh{xintNthElt}}\label{xintNthElt} + +% {\small New in release |1.06|. With |1.09b| negative indices count from the tail.\par} + +\def\macro #1{\the\numexpr 9-#1\relax} + +\csa{xintNthElt\x}\marg{list}\etype{\numx f} gets (expandably) the |x|th braced +item of the \meta{list}. An unbraced item token will be returned as is. The list +itself may be a macro which is first \fexpan ded. \centeredline{|\xintNthElt + {3}{{agh}\u{zzz}\v{Z}}| is \texttt{\xintNthElt {3}{{agh}\u{zzz}\v{Z}}}} +\centeredline{|\xintNthElt {3}{{agh}\u{{zzz}}\v{Z}}| is + \texttt{\expandafter\expandafter\expandafter + \detokenize\expandafter\expandafter\expandafter {\xintNthElt + {3}{{agh}\u{{zzz}}\v{Z}}}}} \centeredline{|\xintNthElt + {2}{{agh}\u{{zzz}}\v{Z}}| is \texttt{\expandafter\expandafter\expandafter + \detokenize\expandafter\expandafter\expandafter {\xintNthElt + {2}{{agh}\u{{zzz}}\v{Z}}}}} \centeredline{|\xintNthElt {37}{\xintFac + {100}}|\digitstt{=\xintNthElt {37}{\xintFac {100}}} is the thirty-seventh + digit of @100!@.} \centeredline{|\xintNthElt {10}{\xintFtoCv + {566827/208524}}|\digitstt{=\xintNthElt {10}{\xintFtoCv {566827/208524}}}} +is the tenth convergent of @566827/208524@ (uses \xintcfracname package). +\centeredline{|\xintNthElt {7}{\xintCSVtoList {1,2,3,4,5,6,7,8,9}}|% + \digitstt{=\xintNthElt {7}{\xintCSVtoList {1,2,3,4,5,6,7,8,9}}}}% +\centeredline{|\xintNthElt {0}{\xintCSVtoList {1,2,3,4,5,6,7,8,9}}|% + \digitstt{=\xintNthElt {0}{\xintCSVtoList {1,2,3,4,5,6,7,8,9}}}} +\centeredline{|\xintNthElt {-3}{\xintCSVtoList {1,2,3,4,5,6,7,8,9}}|% + \digitstt{=\xintNthElt {-3}{\xintCSVtoList {1,2,3,4,5,6,7,8,9}}}} If |x=0|, +the macro returns the \emph{length} of the expanded list: this is not equivalent +to \csbxint{Length} which does no pre-expansion. And it is different from +\csbxint{Len} which is to be used only on integers or fractions. + +If |x<0|, the macro returns the \texttt{|x|}th element from the end of the list. + \centeredline{|\xintNthElt + {-5}{{{agh}}\u{zzz}\v{Z}}| is \texttt{\expandafter\expandafter\expandafter + \detokenize + \expandafter\expandafter\expandafter{\xintNthElt + {-5}{{{agh}}\u{zzz}\v{Z}}}}} + + +The macro \csa{xintNthEltNoExpand}\etype{\numx n} does the same job but without first +expanding the list argument: |\xintNthEltNoExpand {-4}{\u\v\w T\x\y\z}| is +\xintNthEltNoExpand {-4}{\a\b\c\u\v\w T\x\y\z}. + +In cases where |x| is larger (in absolute value) than the length of the list +then |\xintNthElt| returns nothing. + +\subsection{\csbh{xintListWithSep}}\label{xintListWithSep} + +%{\small New with release |1.04|.\par} + +\def\macro #1{\the\numexpr 9-#1\relax} + +\csa{xintListWithSep}|{sep}|\marg{list}\etype{nf} inserts the given separator +|sep| in-between all items of the given list of braced items: this separator may +be a macro (or multiple tokens) but will not be expanded. The second argument +also may be itself a macro: it is \fexpan ded. Applying \csa{xintListWithSep} +removes the braces from the list items (for example |{1}{2}{3}| turns into +\digitstt{\xintListWithSep,{123}} via |\xintListWithSep{,}{{1}{2}{3}}|). An +empty input gives an empty output, a singleton gives a singleton, the separator +is used starting with at least two elements. Using an empty separator has the +net effect of unbracing the braced items constituting the \meta{list} (in such +cases the new list may thus be longer than the original). +\centeredline{|\xintListWithSep{:}{\xintFac + {20}}|\digitstt{=\xintListWithSep{:}{\xintFac {20}}}} + +The macro \csa{xintListWithSepNoExpand}\etype{nn} does the same +job without the initial expansion. + +\subsection{\csbh{xintApply}}\label{xintApply} + +%{\small New with release |1.04|.\par} + +\def\macro #1{\the\numexpr 9-#1\relax} + +\csa{xintApply}|{\macro}|\marg{list}\etype{ff} expandably applies the one +parameter command |\macro| to each item in the \meta{list} given as second +argument and returns a new list with these outputs: each item is given one after +the other as parameter to |\macro| which is expanded at that time (as usual, +\emph{i.e.} fully for what comes first), the results are braced and output +together as a succession of braced items (if |\macro| is defined to start with a +space, the space will be gobbled and the |\macro| will not be expanded; it is +allowed to have its own arguments, the list items serve as last arguments to +|\macro|). Hence |\xintApply{\macro}{{1}{2}{3}}| returns +|{\macro{1}}{\macro{2}}{\macro{3}}| where all instances of |\macro| have been +already \fexpan ded. + +Being expandable, |\xintApply| is useful for example inside alignments where +implicit groups make standard loops constructs usually fail. In such situation +it is often not wished that the new list elements be braced, see +\csbxint{ApplyUnbraced}. The |\macro| does not have to be expandable: +|\xintApply| will try to expand it, the expansion may remain partial. + +The \meta{list} may +itself be some macro expanding (in the previously described way) to the list of +tokens to which the command |\macro| will be applied. For example, if the +\meta{list} expands to some positive number, then each digit will be replaced by +the result of applying |\macro| on it. \centeredline{|\def\macro #1{\the\numexpr + 9-#1\relax}|} \centeredline{|\xintApply\macro{\xintFac + {20}}|\digitstt{=\xintApply\macro{\xintFac {20}}}} + +The macro \csa{xintApplyNoExpand}\etype{fn} does the same job without the first +initial expansion which gave the \meta{list} of braced tokens to which |\macro| +is applied. + +\subsection{\csbh{xintApplyUnbraced}}\label{xintApplyUnbraced} + +%{\small New in release |1.06b|.\par} + +\def\macro #1{\expandafter\def\csname myself#1\endcsname {#1}} +\xintApplyUnbraced\macro{{elta}{eltb}{eltc}} + +\csa{xintApplyUnbraced}|{\macro}|\marg{list}\etype{ff} is like \csbxint{Apply}. +The difference is that after having expanded its list argument, and applied +|\macro| in turn to each item from the list, it reassembles the outputs without +enclosing them in braces. The net effect is the same as doing +\centeredline{|\xintListWithSep {}{\xintApply {\macro}|\marg{list}|}|} This is +useful for preparing a macro which will itself define some other macros or make +assignments, as the scope will not be limited by brace pairs. +% +\dverb|@ + \def\macro #1{\expandafter\def\csname myself#1\endcsname {#1}} + \xintApplyUnbraced\macro{{elta}{eltb}{eltc}} + \meaning\myselfelta: "meaning"myselfelta + \meaning\myselfeltb: "meaning"myselfeltb + \meaning\myselfeltc: "meaning"myselfeltc| + +% +The macro \csa{xintApplyUnbracedNoExpand}\etype{fn} does the same job without +the first initial expansion which gave the \meta{list} of braced tokens to which +|\macro| is applied. + +\subsection{\csbh{xintSeq}}\label{xintSeq} +%{\small New with release |1.09c|.\par} + +\csa{xintSeq}|[d]{x}{y}|\etype{{{\upshape[\numx]}}\numx\numx} generates expandably |{x}{x+d}...| up to and +possibly including |{y}| if |d>0| or down to and including |{y}| if |d<0|. +Naturally |{y}| is omitted if |y-x| is not a multiple of |d|. If |d=0| the macro +returns |{x}|. If |y-x| and |d| have opposite signs, the macro returns nothing. +If the optional argument |d| is omitted it is taken to be the sign of |y-x|. + + +The current implementation is only for (short) integers; possibly, a future +variant could allow big integers and fractions, although one already has +access to similar +functionality using \csbxint{Apply} to get any arithmetic sequence of long +integers. Currently thus, |x| and |y| are expanded inside a +|\numexpr| so they may be count registers or a \LaTeX{} |\value{countername}|, +or arithmetic with such things. + +\centeredline{|\xintListWithSep{,\hskip2pt + plus 1pt minus 1pt }{\xintSeq {12}{-25}}|} +\noindent\digitstt{\xintListWithSep{,\hskip2pt plus 1pt minus 1pt }{\xintSeq + {12}{-25}}} +\centeredline{|\xintiiSum{\xintSeq [3]{1}{1000}}|\digitstt{=\xintiiSum{\xintSeq [3]{1}{1000}}}} + +\textbf{Important:} for reasons of efficiency, this macro, when not given the +optional argument |d|, works backwards, leaving in the token stream the already +constructed integers, from the tail down (or up). But this will provoke a +failure of \IMPORTANT{} the |tex| run if the number of such items exceeds the +input stack +limit; on my installation this limit is at @5000@. + +However, when given the optional argument |d| (which may be @+1@ or +@-1@), the macro proceeds differently and does not put stress on the input stack +(but is significantly slower for sequences with thousands of integers, +especially if they are somewhat big). For +example: |\xintSeq [1]{0}{5000}| works and |\xintiiSum{\xintSeq [1]{0}{5000}}| +returns the correct value \digitstt{\xintHalf{\xintiMul{5000}{5001}}}. + +The produced integers are with explicit litteral digits, so if used in |\ifnum| +or other tests they should be properly terminated\footnote{a \csa{space} will + stop the \TeX{} scanning of a number and be gobbled in the process, + maintaining expandability if this is required; the \csa{relax} stops the + scanning but is not gobbled and remains afterwards as a token.}. + +\subsection{Completely expandable prime test}\label{ssec:primesI} + +Let us now construct a completely expandable macro which returns @1@ if its +given input is prime and @0@ if not: +\dverb|@ +\def\remainder #1#2{\the\numexpr #1-(#1/#2)*#2\relax } +\def\IsPrime #1% + {\xintANDof {\xintApply {\remainder {#1}}{\xintSeq {2}{\xintiSqrt{#1}}}}}| + +This uses \csbxint{iSqrt} and assumes its input is at least @5@. Rather than +\xintname's own \csbxint{Rem} we used a quicker |\numexpr| expression as we +are dealing with short integers. Also we used \csbxint{ANDof} which will +return @1@ only if all the items are non-zero. The macro is a bit +silly with an even input, ok, let's enhance it to detect an even input: +\dverb|@ +\def\IsPrime #1% + {\xintifOdd {#1} + {\xintANDof % odd case + {\xintApply {\remainder {#1}} + {\xintSeq [2]{3}{\xintiSqrt{#1}}}% + }% + } + {\xintifEq {#1}{2}{1}{0}}% + }| + +We used the \xintname provided expandable tests (on big integers or fractions) +in oder for |\IsPrime| to be \fexpan dable. + +Our integers are short, but without |\expandafter|'s with +\makeatletter|\@firstoftwo|\catcode`@ \active, or some other related techniques, +direct use of |\ifnum..\fi| tests is dangerous. So to make the macro more +efficient we are going to use the expandable tests provided by the package +\href{http://ctan.org/pkg/etoolbox}{etoolbox}\footnote{\url{http://ctan.org/pkg/etoolbox}}. +The macro becomes: +% +\dverb|@ +\def\IsPrime #1% + {\ifnumodd {#1} + {\xintANDof % odd case + {\xintApply {\remainder {#1}}{\xintSeq [2]{3}{\xintiSqrt{#1}}}}} + {\ifnumequal {#1}{2}{1}{0}}}| + +In the odd case however we have to assume the integer is at least @7@, as +|\xintSeq| generates an empty list if |#1=3| or |5|, and |\xintANDof| returns +@1@ when supplied an empty list. Let us ease up a bit |\xintANDof|'s work by +letting it work on only @0@'s and @1@'s. We could use: +% +\dverb|@ +\def\IsNotDivisibleBy #1#2% + {\ifnum\numexpr #1-(#1/#2)*#2=0 \expandafter 0\else \expandafter1\fi}|% + +\noindent +where the |\expandafter|'s are crucial for this macro to be \fexpan dable and +hence work within the applied \csbxint{ANDof}. Anyhow, now that we have loaded +\href{http://ctan.org/pkg/etoolbox}{etoolbox}, we might as well use: +% +\dverb|@ +\newcommand{\IsNotDivisibleBy}[2]{\ifnumequal{#1-(#1/#2)*#2}{0}{0}{1}} +|% +Let us enhance our prime macro to work also on the small primes: +\dverb|@ +\newcommand{\IsPrime}[1] % returns 1 if #1 is prime, and 0 if not + {\ifnumodd {#1} + {\ifnumless {#1}{8} + {\ifnumequal{#1}{1}{0}{1}}% 3,5,7 are primes + {\xintANDof + {\xintApply + { \IsNotDivisibleBy {#1}}{\xintSeq [2]{3}{\xintiSqrt{#1}}}}% + }}% END OF THE ODD BRANCH + {\ifnumequal {#1}{2}{1}{0}}% EVEN BRANCH +}| + +The input is still assumed positive. There is a deliberate blank before +\csa{IsNotDivisibleBy} to use this feature of \csbxint{Apply}: a space stops the +expansion of the applied macro (and disappears). This expansion will be done by +\csbxint{ANDof}, which has been designed to skip everything as soon as it finds +a false (i.e. zero) input. This way, the efficiency is considerably improved. + +We did generate via the \csbxint{Seq} too many potential divisors though. Later +sections give two variants: one with \csbxint{iloop} (\autoref{ssec:primesII}) +which is still expandable and another one (\autoref{ssec:primesIII}) which is a +close variant of the |\IsPrime| code above but with the \csbxint{For} loop, thus +breaking expandability. The \hyperref[ssec:primesII]{xintiloop variant} does not +first evaluate the integer square root, the \hyperref[ssec:primesIII]{xintFor + variant} still does. I did not compare their efficiencies. + +% Hmm, if one really needs to compute primes fast, sure I do applaud using +% \xintname, but, well, there is some slight +% overhead\MyMarginNoteWithBrace{funny private joke} in using \TeX{} for these +% things (something like a factor @1000@? not tested\dots) compared to accessing +% to the |CPU| ressources via standard compiled code from a standard programming +% language\dots + +Let us construct with this expandable primality test a table of the prime +numbers up to @1000@. We need to count how many we have in order to know how +many tab stops one shoud add in the last row.\footnote{although a tabular row + may have less tabs than in the preamble, there is a problem with the + \char`\|\space\space + vertical rule, if one does that.} There is some subtlety for this +last row. Turns out to be better to insert a |\\| only when we know for sure we +are starting a new row; this is how we have designed the |\OneCell| macro. And +for the last row, there are many ways, we use again |\xintApplyUnbraced| but +with a macro which gobbles its argument and replaces it with a tabulation +character. The \csbxint{For*} macro would be more elegant here. +% +\dverb?@ +\newcounter{primecount} +\newcounter{cellcount} +\newcommand{\NbOfColumns}{13} +\newcommand{\OneCell}[1]{% + \ifnumequal{\IsPrime{#1}}{1} + {\stepcounter{primecount} + \ifnumequal{\value{cellcount}}{\NbOfColumns} + {\\\setcounter{cellcount}{1}#1} + {&\stepcounter{cellcount}#1}% + } % was prime + {}% not a prime, nothing to do +} +\newcommand{\OneTab}[1]{&} +\begin{tabular}{|*{\NbOfColumns}{r}|} +\hline +2 \setcounter{cellcount}{1}\setcounter{primecount}{1}% + \xintApplyUnbraced \OneCell {\xintSeq [2]{3}{999}}% + \xintApplyUnbraced \OneTab + {\xintSeq [1]{1}{\the\numexpr\NbOfColumns-\value{cellcount}\relax}}% + \\ +\hline +\end{tabular} +There are \arabic{primecount} prime numbers up to 1000.? + +The table has been put in \hyperref[primesupto1000]{float} which appears +\vpageref{primesupto1000}. +We had to be careful to use in the last row \csbxint{Seq} with its optional +argument |[1]| so as to not generate a decreasing sequence from |1| to |0|, but +really an empty sequence in case the row turns out to already have all its +cells (which doesn't happen here but would with a number of columns dividing +@168@). +% +\newcommand{\IsNotDivisibleBy}[2]{\ifnumequal{#1-(#1/#2)*#2}{0}{0}{1}} + +\newcommand{\IsPrime}[1] + {\ifnumodd {#1} + {\ifnumless {#1}{8} + {\ifnumequal{#1}{1}{0}{1}}% 3,5,7 are primes + {\xintANDof + {\xintApply + { \IsNotDivisibleBy {#1}}{\xintSeq [2]{3}{\xintiSqrt{#1}}}}% + }}% END OF THE ODD BRANCH + {\ifnumequal {#1}{2}{1}{0}}% EVEN BRANCH +} + +\newcounter{primecount} +\newcounter{cellcount} +\newcommand{\NbOfColumns}{13} +\newcommand{\OneCell}[1] + {\ifnumequal{\IsPrime{#1}}{1} + {\stepcounter{primecount} + \ifnumequal{\value{cellcount}}{\NbOfColumns} + {\\\setcounter{cellcount}{1}#1} + {&\stepcounter{cellcount}#1}% + } % was prime + {}% not a prime nothing to do +} +\newcommand{\OneTab}[1]{&} +\begin{figure*}[ht!] + \centering + \phantomsection\label{primesupto1000} + \begin{tabular}{|*{\NbOfColumns}{r}|} + \hline + 2\setcounter{cellcount}{1}\setcounter{primecount}{1}% + \xintApplyUnbraced \OneCell {\xintSeq [2]{3}{999}}% + \xintApplyUnbraced \OneTab + {\xintSeq [1]{1}{\the\numexpr\NbOfColumns-\value{cellcount}\relax}}% + \\ + \hline + \end{tabular} +\smallskip +\centeredline{There are \arabic{primecount} prime numbers up to 1000.} +\end{figure*} + +\subsection{\csbh{xintloop}, \csbh{xintbreakloop}, \csbh{xintbreakloopanddo}, \csbh{xintloopskiptonext}} +\label{xintloop} +\label{xintbreakloop} +\label{xintbreakloopanddo} +\label{xintloopskiptonext} +% {\small New with release |1.09g|. Release |1.09h| +% makes them long macros.\par} + +|\xintloop|\meta{stuff}|\if<test>...\repeat|\retype{} is an expandable loop +compatible with nesting. However to break out of the loop one almost always need +some un-expandable step. The cousin \csbxint{iloop} is \csbxint{loop} with an +embedded expandable mechanism allowing to exit from the loop. The iterated +commands may contain |\par| tokens or empty lines. + +If a sub-loop is to be used all the material from the start of the main loop and +up to the end of the entire subloop should be braced; these braces will be +removed and do not create a group. The simplest to allow the nesting of one or +more sub-loops is to brace everything between \csa{xintloop} and \csa{repeat}, +being careful not to leave a space between the closing brace and |\repeat|. + +As this loop and \csbxint{iloop} will primarily be of interest to experienced +\TeX{} macro programmers, my description will assume that the user is +knowledgeable enough. Some examples in this document will be perhaps more +illustrative than my attemps at explanation of use. + +One can abort the loop with \csbxint{breakloop}; this should not be used inside +the final test, and one should expand the |\fi| from the corresponding test +before. One has also \csbxint{breakloopanddo} whose first argument will be +inserted in the token stream after the loop; one may need a macro such as +|\xint_afterfi| to move the whole thing after the |\fi|, as a simple +|\expandafter| will not be enough. + +One will usually employ some count registers to manage the exit test from the +loop; this breaks expandability, see \csbxint{iloop} for an expandable integer +indexed loop. Use in alignments will be complicated by the fact that cells +create groups, and also from the fact that any encountered unexpandable material +will cause the \TeX{} input scanner to insert |\endtemplate| on each encountered +|&| or |\cr|; thus |\xintbreakloop| may not work as expected, but the situation +can be resolved via |\xint_firstofone{&}| or use of |\TAB| with |\def\TAB{&}|. +It is thus simpler for alignments to use rather than \csbxint{loop} either the +expandable \csbxint{ApplyUnbraced} or the non-expandable but alignment +compatible \csbxint{ApplyInline}, \csbxint{For} or \csbxint{For*}. + +As an example, let us suppose we have two macros |\A|\marg{i}\marg{j} and +|\B|\marg{i}\marg{j} behaving like (small) integer valued matrix entries, and we +want to define a macro |\C|\marg{i}\marg{j} giving the matrix product (|i| and +|j| may be count registers). We will assume that |\A[I]| expands to the number +of rows, |\A[J]| to the number of columns and want the produced |\C| to act in +the same manner. The code is very dispendious in use of |\count| registers, not +optimized in any way, not made very robust (the defined macro can not have the +same name as the first two matrices for example), we just wanted to quickly +illustrate use of the nesting capabilities of |\xintloop|.\footnote{for a more sophisticated implementation of matrix multiplication, inclusive of determinants, inverses, and display utilities, with entries big integers or decimal numbers or even fractions see \url{http://tex.stackexchange.com/a/143035/4686} from November 11, 2013.} +\begingroup +\makeatother +\begin{verbatim} +\newcount\rowmax \newcount\colmax \newcount\summax +\newcount\rowindex \newcount\colindex \newcount\sumindex +\newcount\tmpcount +\makeatletter +\def\MatrixMultiplication #1#2#3{% + \rowmax #1[I]\relax + \colmax #2[J]\relax + \summax #1[J]\relax + \rowindex 1 + \xintloop % loop over row index i + {\colindex 1 + \xintloop % loop over col index k + {\tmpcount 0 + \sumindex 1 + \xintloop % loop over intermediate index j + \advance\tmpcount \numexpr #1\rowindex\sumindex*#2\sumindex\colindex\relax + \ifnum\sumindex<\summax + \advance\sumindex 1 + \repeat }% + \expandafter\edef\csname\string#3{\the\rowindex.\the\colindex}\endcsname + {\the\tmpcount}% + \ifnum\colindex<\colmax + \advance\colindex 1 + \repeat }% + \ifnum\rowindex<\rowmax + \advance\rowindex 1 + \repeat + \expandafter\edef\csname\string#3{I}\endcsname{\the\rowmax}% + \expandafter\edef\csname\string#3{J}\endcsname{\the\colmax}% + \def #3##1{\ifx[##1\expandafter\Matrix@helper@size + \else\expandafter\Matrix@helper@entry\fi #3{##1}}% +}% +\def\Matrix@helper@size #1#2#3]{\csname\string#1{#3}\endcsname }% +\def\Matrix@helper@entry #1#2#3% + {\csname\string#1{\the\numexpr#2.\the\numexpr#3}\endcsname }% +\def\A #1{\ifx[#1\expandafter\A@size + \else\expandafter\A@entry\fi {#1}}% +\def\A@size #1#2]{\ifx I#23\else4\fi}% 3rows, 4columns +\def\A@entry #1#2{\the\numexpr #1+#2-1\relax}% not pre-computed... +\def\B #1{\ifx[#1\expandafter\B@size + \else\expandafter\B@entry\fi {#1}}% +\def\B@size #1#2]{\ifx I#24\else3\fi}% 4rows, 3columns +\def\B@entry #1#2{\the\numexpr #1-#2\relax}% not pre-computed... +\makeatother +\MatrixMultiplication\A\B\C \MatrixMultiplication\C\C\D % etc... +\[\begin{pmatrix} + \A11&\A12&\A13&\A14\\ + \A21&\A22&\A23&\A24\\ + \A31&\A32&\A33&\A34 + \end{pmatrix} +\times + \begin{pmatrix} + \B11&\B12&\B13\\ + \B21&\B22&\B23\\ + \B31&\B32&\B33\\ + \B41&\B42&\B43 + \end{pmatrix} += +\begin{pmatrix} + \C11&\C12&\C13\\ + \C21&\C22&\C23\\ + \C31&\C32&\C33 +\end{pmatrix}\] +\[\begin{pmatrix} + \C11&\C12&\C13\\ + \C21&\C22&\C23\\ + \C31&\C32&\C33 +\end{pmatrix}^2 = \begin{pmatrix} + \D11&\D12&\D13\\ + \D21&\D22&\D23\\ + \D31&\D32&\D33 +\end{pmatrix}\] +\end{verbatim} +\newcount\rowmax \newcount\colmax \newcount\summax +\newcount\rowindex \newcount\colindex \newcount\sumindex +\newcount\tmpcount +\makeatletter +\def\MatrixMultiplication #1#2#3{% + \rowmax #1[I]\relax + \colmax #2[J]\relax + \summax #1[J]\relax + \rowindex 1 + \xintloop % loop over row index i + {\colindex 1 + \xintloop % loop over col index k + {\tmpcount 0 + \sumindex 1 + \xintloop % loop over intermediate index j + \advance\tmpcount \numexpr #1\rowindex\sumindex*#2\sumindex\colindex\relax + \ifnum\sumindex<\summax + \advance\sumindex 1 + \repeat }% + \expandafter\edef\csname\string#3{\the\rowindex.\the\colindex}\endcsname + {\the\tmpcount}% + \ifnum\colindex<\colmax + \advance\colindex 1 + \repeat }% + \ifnum\rowindex<\rowmax + \advance\rowindex 1 + \repeat + \expandafter\edef\csname\string#3{I}\endcsname{\the\rowmax}% + \expandafter\edef\csname\string#3{J}\endcsname{\the\colmax}% + \def #3##1{\ifx[##1\expandafter\Matrix@helper@size + \else\expandafter\Matrix@helper@entry\fi #3{##1}}% +}% +\def\Matrix@helper@size #1#2#3]{\csname\string#1{#3}\endcsname }% +\def\Matrix@helper@entry #1#2#3% + {\csname\string#1{\the\numexpr#2.\the\numexpr#3}\endcsname }% +\def\A #1{\ifx[#1\expandafter\A@size + \else\expandafter\A@entry\fi {#1}}% +\def\A@size #1#2]{\ifx I#23\else4\fi}% 3rows, 4columns +\def\A@entry #1#2{\the\numexpr #1+#2-1\relax}% not pre-computed... +\def\B #1{\ifx[#1\expandafter\B@size + \else\expandafter\B@entry\fi {#1}}% +\def\B@size #1#2]{\ifx I#24\else3\fi}% 4rows, 3columns +\def\B@entry #1#2{\the\numexpr #1-#2\relax}% not pre-computed... +\makeatother +\MatrixMultiplication\A\B\C \MatrixMultiplication\C\C\D +\setlength{\unitlength}{1cm}% +% le picture de LaTeX est tout de même assez génial! +\begin{picture}(0,0) +\put(5,11){\vtop{\hsize8cm +\[\begin{pmatrix} + \A11&\A12&\A13&\A14\\ + \A21&\A22&\A23&\A24\\ + \A31&\A32&\A33&\A34 + \end{pmatrix} +\times + \begin{pmatrix} + \B11&\B12&\B13\\ + \B21&\B22&\B23\\ + \B31&\B32&\B33\\ + \B41&\B42&\B43 + \end{pmatrix} += +\begin{pmatrix} + \C11&\C12&\C13\\ + \C21&\C22&\C23\\ + \C31&\C32&\C33 +\end{pmatrix}\] +\[\begin{pmatrix} + \C11&\C12&\C13\\ + \C21&\C22&\C23\\ + \C31&\C32&\C33 +\end{pmatrix}^2 = \begin{pmatrix} + \D11&\D12&\D13\\ + \D21&\D22&\D23\\ + \D31&\D32&\D33 +\end{pmatrix}\]\MatrixMultiplication\C\D\E +\[\begin{pmatrix} + \C11&\C12&\C13\\ + \C21&\C22&\C23\\ + \C31&\C32&\C33 +\end{pmatrix}^3 = \begin{pmatrix} + \E11&\E12&\E13\\ + \E21&\E22&\E23\\ + \E31&\E32&\E33 +\end{pmatrix}\]\MatrixMultiplication\C\E\F +\[\begin{pmatrix} + \C11&\C12&\C13\\ + \C21&\C22&\C23\\ + \C31&\C32&\C33 +\end{pmatrix}^4 = \begin{pmatrix} + \F11&\F12&\F13\\ + \F21&\F22&\F23\\ + \F31&\F32&\F33 +\end{pmatrix}\]}} +\end{picture}\par +\endgroup + +\kern-2\baselineskip + +\subsection{\csbh{xintiloop}, \csbh{xintiloopindex}, \csbh{xintouteriloopindex}, + \csbh{xintbreakiloop}, \csbh{xintbreakiloopanddo}, \csbh{xintiloopskiptonext}, +\csbh{xintiloopskipandredo}} +\label{xintiloop} +\label{xintbreakiloop} +\label{xintbreakiloopanddo} +\label{xintiloopskiptonext} +\label{xintiloopskipandredo} +\label{xintiloopindex} +\label{xintouteriloopindex} +%{\small New with release |1.09g|.\par} + +\csa{xintiloop}|[start+delta]|\meta{stuff}|\if<test> ... \repeat|\retype{} is a +completely expandable nestable loop. complete expandability depends naturally on +the actual iterated contents, and complete expansion will not be achievable +under a sole \fexpan sion, as is indicated by the hollow star in the margin; +thus the loop can be used inside an |\edef| but not inside arguments to the +package macros. It can be used inside an |\xintexpr..\relax|. + +This loop benefits via \csbxint{iloopindex} to (a limited access to) the integer +index of the iteration. The starting value |start| (which may be a |\count|) and +increment |delta| (\emph{id.}) are mandatory arguments. A space after the +closing square bracket is not significant, it will be ignored. Spaces inside the +square brackets will also be ignored as the two arguments are first given to a +|\numexpr...\relax|. Empty lines and explicit |\par| tokens are accepted. + +As with \csbxint{loop}, this tool will mostly be of interest to advanced users. +For nesting, one puts inside braces all the +material from the start (immediately after |[start+delta]|) and up to and +inclusive of the inner loop, these braces will be removed and do not create a +loop. In case of nesting, \csbxint{outeriloopindex} gives access to the index of +the outer loop. If needed one could write on its model a macro giving access to +the index of the outer outer loop (or even to the |nth| outer loop). + + +The \csa{xintiloopindex} and \csa{xintouteriloopindex} can not be used inside +braces, and generally speaking this means they should be expanded first when +given as argument to a macro, and that this macro receives them as delimited +arguments, not braced ones. Or, but naturally this will break expandability, one +can assign the value of \csa{xintiloopindex} to some |\count|. Both +\csa{xintiloopindex} and \csa{xintouteriloopindex} extend to the litteral +representation of the index, thus in |\ifnum| tests, if it comes last one has to +correctly end the macro with a |\space|, or encapsulate it in a +|\numexpr..\relax|. + +When the repeat-test of the loop is, for example, |\ifnum\xintiloopindex<10 +\repeat|, this means that the last iteration will be with |\xintiloopindex=10| +(assuming |delta=1|). There is also |\ifnum\xintiloopindex=10 \else\repeat| to +get the last iteration to be the one with |\xintiloopindex=10|. + +One has \csbxint{breakiloop} and \csbxint{breakiloopanddo} to abort the loop. +The syntax of |\xintbreakiloopanddo| is a bit surprising, the sequence of tokens +to be executed after breaking the loop is not within braces but is delimited by +a dot as in: +% +\centeredline{|\xintbreakiloopanddo <afterloop>.etc.. etc... \repeat|} +% +The reason is that one may wish to use the then current value of +|\xintiloopindex| in |<afterloop>| but it can't be within braces at the time it +is evaluated. However, it is not that easy as |\xintiloopindex| must be expanded +before, so one ends up with code like this: +% +\centeredline +{|\expandafter\xintbreakiloopanddo\expandafter\macro\xintiloopindex.%|} +\centeredline{|etc.. etc.. \repeat|} +% +As moreover the |\fi| from the test leading to the decision of breaking out of +the loop must be cleared out of the way, the above should be +a branch of an expandable conditional test, else one needs something such +as: +\centeredline +{|\xint_afterfi{\expandafter\xintbreakiloopanddo\expandafter\macro\xintiloopindex.}%|} +\centeredline{|\fi etc..etc.. \repeat|} + + +There is \csbxint{iloopskiptonext} to abort the current iteration and skip to +the next, \hyperref[xintiloopskipandredo]{\ttfamily\hyphenchar\font45 \char92 + xintiloopskip\-and\-redo} to skip to the end of the current iteration and redo +it with the same value of the index (something else will have to change for this +not to become an eternal loop\dots ). + +Inside alignments, if the looped-over text contains a |&| or a |\cr|, any +un-expandable material before a \csbxint{iloopindex} will make it fail because +of |\endtemplate|; in such cases one can always either replace |&| by a macro +expanding to it or replace it by a suitable |\firstofone{&}|, and similarly for +|\cr|. + +\phantomsection\label{edefprimes} +As an example, let us construct an |\edef\z{...}| which will define |\z| to be a +list of prime numbers: +\dverb|@ +\edef\z +{\xintiloop [10001+2] + {\xintiloop [3+2] + \ifnum\xintouteriloopindex<\numexpr\xintiloopindex*\xintiloopindex\relax + \xintouteriloopindex, + \expandafter\xintbreakiloop + \fi + \ifnum\xintouteriloopindex=\numexpr + (\xintouteriloopindex/\xintiloopindex)*\xintiloopindex\relax + \else + \repeat + }% no space here + \ifnum \xintiloopindex < 10999 \repeat }% +\meaning\z| +\begingroup%\ttfamily +\edef\z +{\xintiloop [10001+2] + {\xintiloop [3+2] + \ifnum\xintouteriloopindex<\numexpr\xintiloopindex*\xintiloopindex\relax + \xintouteriloopindex, + \expandafter\xintbreakiloop + \fi + \ifnum\xintouteriloopindex=\numexpr + (\xintouteriloopindex/\xintiloopindex)*\xintiloopindex\relax + \else + \repeat + }% no space here + \ifnum \xintiloopindex < 10999 \repeat }% +\meaning\z and we should have taken some steps to not have a trailing comma, but +the point was to show that one can do that in an |\edef|\,! See also +\autoref{ssec:primesII} which extracts from this code its way of testing +primality. +\endgroup + + +Let us create an alignment where each row will contain all divisors of its +first entry. +\dverb|@ +\tabskip1ex +\halign{&\hfil#\hfil\cr + \xintiloop [1+1] + {\expandafter\bfseries\xintiloopindex & + \xintiloop [1+1] + \ifnum\xintouteriloopindex=\numexpr + (\xintouteriloopindex/\xintiloopindex)*\xintiloopindex\relax + \xintiloopindex&\fi + \ifnum\xintiloopindex<\xintouteriloopindex\space % \space is CRUCIAL + \repeat \cr }% + \ifnum\xintiloopindex<30 + \repeat }| + +% +\noindent We wanted this first entry in bold face, but |\bfseries| leads to +unexpandable tokens, so the |\expandafter| was necessary for |\xintiloopindex| +and |\xintouteriloopindex| not to be confronted with a hard to digest +|\endtemplate|. An alternative way of coding is: +% +\dverb|@ \tabskip1ex +\def\firstofone #1{#1}% +\halign{&\hfil#\hfil\cr + \xintiloop [1+1] + {\bfseries\xintiloopindex\firstofone{&}% + \xintiloop [1+1] \ifnum\xintouteriloopindex=\numexpr + (\xintouteriloopindex/\xintiloopindex)*\xintiloopindex\relax + \xintiloopindex\firstofone{&}\fi + \ifnum\xintiloopindex<\xintouteriloopindex\space % \space is CRUCIAL + \repeat \firstofone{\cr}}% + \ifnum\xintiloopindex<30 \repeat }| + +\noindent +Here is the output, thus obtained without any count register: +\begingroup\catcode`_ 11 +\begin{multicols}2 +\tabskip1ex +\halign{&\hfil#\hfil\cr + \xintiloop [1+1] + {\expandafter\bfseries\xintiloopindex & + \xintiloop [1+1] + \ifnum\xintouteriloopindex=\numexpr + (\xintouteriloopindex/\xintiloopindex)*\xintiloopindex\relax + \xintiloopindex&\fi + \ifnum\xintiloopindex<\xintouteriloopindex\space % CRUCIAL \space HERE + \repeat \cr }% + \ifnum\xintiloopindex<30 + \repeat +} +\end{multicols} +\endgroup + +\subsection{Another completely expandable prime test}\label{ssec:primesII} + +The |\IsPrime| macro from \autoref{ssec:primesI} checked expandably if a (short) +integer was prime, here is a partial rewrite using \csbxint{iloop}. We use the +|etoolbox| expandable conditionals for convenience, but not everywhere as +|\xintiloopindex| can not be evaluated while being braced. This is also the +reason why |\xintbreakiloopanddo| is delimited, and the next macro +|\SmallestFactor| which returns the smallest prime factor examplifies that. One +could write more efficient completely expandable routines, the aim here was only +to illustrate use of the general purpose \csbxint{iloop}. A little table giving +the first values of |\SmallestFactor| follows, its coding uses \csbxint{For}, +which is described later; none of this uses count registers. +% +\dverb?@ +\newcommand{\IsPrime}[1] % returns 1 if #1 is prime, and 0 if not + {\ifnumodd {#1} + {\ifnumless {#1}{8} + {\ifnumequal{#1}{1}{0}{1}}% 3,5,7 are primes + {\if + \xintiloop [3+2] + \ifnum#1<\numexpr\xintiloopindex*\xintiloopindex\relax + \expandafter\xintbreakiloopanddo\expandafter1\expandafter.% + \fi + \ifnum#1=\numexpr (#1/\xintiloopindex)*\xintiloopindex\relax + \else + \repeat 00\expandafter0\else\expandafter1\fi + }% + }% END OF THE ODD BRANCH + {\ifnumequal {#1}{2}{1}{0}}% EVEN BRANCH +}% +\catcode`_ 11 +\newcommand{\SmallestFactor}[1] % returns the smallest prime factor of #1>1 + {\ifnumodd {#1} + {\ifnumless {#1}{8} + {#1}% 3,5,7 are primes + {\xintiloop [3+2] + \ifnum#1<\numexpr\xintiloopindex*\xintiloopindex\relax + \xint_afterfi{\xintbreakiloopanddo#1.}% + \fi + \ifnum#1=\numexpr (#1/\xintiloopindex)*\xintiloopindex\relax + \xint_afterfi{\expandafter\xintbreakiloopanddo\xintiloopindex.}% + \fi + \iftrue\repeat + }% + }% END OF THE ODD BRANCH + {2}% EVEN BRANCH +}% +\catcode`_ 8 + \begin{tabular}{|c|*{10}c|} + \hline + \xintFor #1 in {0,1,2,3,4,5,6,7,8,9}\do {&\bfseries #1}\\ + \hline + \bfseries 0&--&--&2&3&2&5&2&7&2&3\\ + \xintFor #1 in {1,2,3,4,5,6,7,8,9}\do + {\bfseries #1% + \xintFor #2 in {0,1,2,3,4,5,6,7,8,9}\do + {&\SmallestFactor{#1#2}}\\}% + \hline + \end{tabular} +? +\catcode`_ 11 +\newcommand{\SmallestFactor}[1] % returns the smallest prime factor of #1>1 + {\ifnumodd {#1} + {\ifnumless {#1}{8} + {#1}% 3,5,7 are primes + {\xintiloop [3+2] + \ifnum#1<\numexpr\xintiloopindex*\xintiloopindex\relax + \xint_afterfi{\xintbreakiloopanddo#1.}% + \fi + \ifnum#1=\numexpr (#1/\xintiloopindex)*\xintiloopindex\relax + \xint_afterfi{\expandafter\xintbreakiloopanddo\xintiloopindex.}% + \fi + \iftrue\repeat + }% + }% END OF THE ODD BRANCH + {2}% EVEN BRANCH +}% +\catcode`_ 8 +{\centering + \begin{tabular}{|c|*{10}c|} + \hline + \xintFor #1 in {0,1,2,3,4,5,6,7,8,9}\do {&\bfseries #1}\\ + \hline + \bfseries 0&--&--&2&3&2&5&2&7&2&3\\ + \xintFor #1 in {1,2,3,4,5,6,7,8,9}\do + {\bfseries #1% + \xintFor #2 in {0,1,2,3,4,5,6,7,8,9}\do + {&\SmallestFactor{#1#2}}\\}% + \hline + \end{tabular}\par } + +\subsection{A table of factorizations} +\label{ssec:factorizationtable} + +As one more example with \csbxint{iloop} let us use an alignment to display the +factorization of some numbers. The loop will actually only play a minor r\^ole +here, just handling the row index, the row contents being almost entirely +produced via a macro |\factorize|. The factorizing macro does not use +|\xintiloop| as it didn't appear to be the convenient tool. As |\factorize| will +have to be used on |\xintiloopindex|, it has been defined as a delimited macro. + +To spare some fractions of a second in the compilation time of this document +(which has many many other things to do), \number"7FFFFFED{} and +\number"7FFFFFFF, which turn out to be prime numbers, are not given to +|factorize| but just typeset directly; this illustrates use of +\csbxint{iloopskiptonext}. + +\begingroup +\def\MacroFont{\ttfamily\baselineskip12pt\relax \catcode`\" 12 } +\dverb|@ +\tabskip1ex +\halign {\hfil\strut#\hfil&&\hfil#\hfil\cr\noalign{\hrule} + \xintiloop ["7FFFFFE0+1] + \expandafter\bfseries\xintiloopindex & + \ifnum\xintiloopindex="7FFFFFED + \number"7FFFFFED\cr\noalign{\hrule} + \expandafter\xintiloopskiptonext + \fi + \expandafter\factorize\xintiloopindex.\cr\noalign{\hrule} + \ifnum\xintiloopindex<"7FFFFFFE + \repeat + \bfseries \number"7FFFFFFF&\number "7FFFFFFF\cr\noalign{\hrule} +}|\par\smallskip +\endgroup + +The \hyperref[floatfactorize]{table} has been made into a float which appears +\vpageref{floatfactorize}. Here is now the code for factorization; the +conditionals use +the package provided |\xint_firstoftwo| and |\xint_secondoftwo|, one could have +employed rather \LaTeX{}'s own \texttt{\char92\string@firstoftwo} and +\texttt{\char92\string@secondoftwo}, or, simpler still in \LaTeX{} context, the +|\ifnumequal|, |\ifnumless| \dots, utilities from the package |etoolbox| which +do exactly that under the hood. Only \TeX{} acceptable numbers are treated here, +but it would be easy to make a translation and use the \xintname macros, thus +extending the scope to big numbers; naturally up to a cost in speed. + +The reason for some strange looking expressions is to avoid arithmetic overflow. + +\begingroup +\def\MacroFont{\ttfamily\baselineskip12pt\relax \catcode`\" 12 } +\dverb|@ +\catcode`_ 11 +\def\abortfactorize #1\xint_secondoftwo\fi #2#3{\fi} + +\def\factorize #1.{\ifnum#1=1 \abortfactorize\fi + % avoid overflow if #1="7FFFFFFF + \ifnum\numexpr #1-2=\numexpr ((#1/2)-1)*2\relax + \expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo + \fi + {2&\expandafter\factorize\the\numexpr#1/2.}% + {\factorize_b #1.3.}}% + +\def\factorize_b #1.#2.{\ifnum#1=1 \abortfactorize\fi + % this will avoid overflow which could result from #2*#2 + \ifnum\numexpr #1-(#2-1)*#2<#2 + #1\abortfactorize % this #1 is prime + \fi + % again, avoiding overflow as \numexpr integer division + % rounds rather than truncates. + \ifnum \numexpr #1-#2=\numexpr ((#1/#2)-1)*#2\relax + \expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo + \fi + {#2&\expandafter\factorize_b\the\numexpr#1/#2.#2.}% + {\expandafter\factorize_b\the\numexpr #1\expandafter.% + \the\numexpr #2+2.}}% +\catcode`_ 8| +\endgroup + +\catcode`_ 11 +\def\abortfactorize #1\xint_secondoftwo\fi #2#3{\fi} + +\def\factorize #1.{\ifnum#1=1 \abortfactorize\fi + \ifnum\numexpr #1-2=\numexpr ((#1/2)-1)*2\relax + \expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo + \fi + {2&\expandafter\factorize\the\numexpr#1/2.}% + {\factorize_b #1.3.}}% + +\def\factorize_b #1.#2.{\ifnum#1=1 \abortfactorize\fi + \ifnum\numexpr #1-(#2-1)*#2<#2 + #1\abortfactorize + \fi + \ifnum \numexpr #1-#2=\numexpr ((#1/#2)-1)*#2\relax + \expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo + \fi + {#2&\expandafter\factorize_b\the\numexpr#1/#2.#2.}% + {\expandafter\factorize_b\the\numexpr #1\expandafter.% + \the\numexpr #2+2.}}% +\catcode`_ 8 +\begin{figure*}[ht!] +\centering\phantomsection\label{floatfactorize} +\tabskip1ex +\centeredline{\vbox{\halign {\hfil\strut#\hfil&&\hfil#\hfil\cr\noalign{\hrule} + \xintiloop ["7FFFFFE0+1] + \expandafter\bfseries\xintiloopindex & + \ifnum\xintiloopindex="7FFFFFED + \number"7FFFFFED\cr\noalign{\hrule} + \expandafter\xintiloopskiptonext + \fi + \expandafter\factorize\xintiloopindex.\cr\noalign{\hrule} + \ifnum\xintiloopindex<"7FFFFFFE + \repeat + \bfseries \number"7FFFFFFF&\number "7FFFFFFF\cr\noalign{\hrule} +}}} +\centeredline{A table of factorizations} +\end{figure*} + + +\begin{framed} + The next utilities are not compatible with expansion-only context. +\end{framed} + +\subsection{\csbh{xintApplyInline}}\label{xintApplyInline} + +% {\small |1.09a|, enhanced in |1.09c| to be usable within alignments, and +% corrected in |1.09d| for a problem related to spaces at the very end of the +% list parameter.\par} + +\csa{xintApplyInline}|{\macro}|\marg{list}\ntype{o{\lowast f}} works non +expandably. It applies the one-parameter |\macro| to the first element of the +expanded list (|\macro| may have itself some arguments, the list item will be +appended as last argument), and is then re-inserted in the input stream after +the tokens resulting from this first expansion of |\macro|. The next item is +then handled. + +This is to be used in situations where one needs to do some repetitive +things. It is not expandable and can not be completely expanded inside a +macro definition, to prepare material for later execution, contrarily to what +\csbxint{Apply} or \csbxint{ApplyUnbraced} achieve. + +\dverb|@ +\def\Macro #1{\advance\cnta #1 , \the\cnta} +\cnta 0 +0\xintApplyInline\Macro {3141592653}.| +\def\Macro #1{\advance\cnta #1 , \the\cnta} +\cnta 0 +Output: 0\xintApplyInline\Macro {3141592653}. + + +The first argument |\macro| does not have to be an expandable macro. + +\csa{xintApplyInline} submits its second, token list parameter to an +\hyperref[sec:expansions]{\fexpan +sion}. Then, each \emph{unbraced} item will also be \fexpan ded. This provides +an easy way to insert one list inside another. \emph{Braced} items are not +expanded. Spaces in-between items are gobbled (as well as those at the start +or the end of the list), but not the spaces \emph{inside} the braced items. + +\csa{xintApplyInline}, despite being non-expandable, does survive to +contexts where the executed |\macro| closes groups, as happens inside +alignments with the tabulation character |&|. +This tabular for example:\par +\smallskip +\centeredline + {\begin{tabular}{ccc} + $N$ & $N^2$ & $N^3$ \\ \hline + \def\Row #1{ #1 & \xintiSqr {#1} & \xintiPow {#1}{3} \\ \hline }% + \xintApplyInline \Row {\xintCSVtoList{17,28,39,50,61}} + \end{tabular}} +\smallskip +% 38 = &, 43 = +, 36=$, 45 = - +was obtained from the following input: +\dverb|@ +\begin{tabular}{ccc} + $N$ & $N^2$ & $N^3$ \\ \hline + \def\Row #1{ #1 & \xintiSqr {#1} & \xintiPow {#1}{3} \\ \hline }% + \xintApplyInline \Row {\xintCSVtoList{17,28,39,50,61}} +\end{tabular}|% +Despite the fact that the first encountered tabulation character in the first +row close a group and thus erases |\Row| from \TeX's memory, |\xintApplyInline| +knows how to deal with this. + +Using \csbxint{ApplyUnbraced} is an alternative: the difference is that +this would have prepared all rows first and only put them back into the +token stream once they are all assembled, whereas with |\xintApplyInline| +each row is constructed and immediately fed back into the token stream: when +one does things with numbers having hundreds of digits, one learns that +keeping on hold and shuffling around hundreds of tokens has an impact on +\TeX{}'s speed (make this ``thousands of tokens'' for the impact to be +noticeable). + +One may nest various |\xintApplyInline|'s. For example (see the +\hyperref[float]{table} \vpageref{float}):\par +\dverb|@ +\def\Row #1{#1:\xintApplyInline {\Item {#1}}{0123456789}\\ }% +\def\Item #1#2{&\xintiPow {#1}{#2}}% +\begin{tabular}{ccccccccccc} + &0&1&2&3&4&5&6&7&8&9\\ \hline + \xintApplyInline \Row {0123456789} +\end{tabular}| +\begin{figure*}[ht!] + \centering\phantomsection\label{float} + \def\Row #1{#1:\xintApplyInline {\Item {#1}}{0123456789}\\ }% + \def\Item #1#2{&\xintiPow {#1}{#2}}% + \centeredline {\begin{tabular}{ccccccccccc} &0&1&2&3&4&5&6&7&8&9\\ \hline + \xintApplyInline \Row {0123456789} + \end{tabular}} +\end{figure*} + + +One could not move the definition of |\Item| inside the tabular, +as it would get lost after the first |&|. But this +works: +\dverb|@ +\begin{tabular}{ccccccccccc} + &0&1&2&3&4&5&6&7&8&9\\ \hline + \def\Row #1{#1:\xintApplyInline {&\xintiPow {#1}}{0123456789}\\ }% + \xintApplyInline \Row {0123456789} +\end{tabular}| + +A limitation is that, contrarily to what one may have expected, the +|\macro| for an |\xintApplyInline| can not be used to define +the |\macro| for a nested sub-|\xintApplyInline|. For example, +this does not work:\par +\dverb|@ + \def\Row #1{#1:\def\Item ##1{&\xintiPow {#1}{##1}}% + \xintApplyInline \Item {0123456789}\\ }% + \xintApplyInline \Row {0123456789} % does not work +|% +But see \csbxint{For}. + +\subsection{\csbh{xintFor}, \csbh{xintFor*}}\label{xintFor}\label{xintFor*} +% {\small New with |1.09c|. Extended in |1.09e| (\csbxint{BreakFor}, +% \csbxint{integers}, \dots). |1.09f| version handles all macro parameters up +% to +% |#9| and removes spaces around commas.\par} + +\csbxint{For}\ntype{on} is a new kind of for loop. Rather than using macros +for encapsulating list items, its behavior is more like a macro with parameters: +|#1|, |#2|, \dots, |#9| are used to represent the items for up to nine levels of +nested loops. Here is an example: +% +\dverb|@ +\xintFor #9 in {1,2,3} \do {% + \xintFor #1 in {4,5,6} \do {% + \xintFor #3 in {7,8,9} \do {% + \xintFor #2 in {10,11,12} \do {% + $$#9\times#1\times#3\times#2=\xintiiPrd{{#1}{#2}{#3}{#9}}$$}}}} +|% +This example illustrates that one does not have to use |#1| as the first one: +the order is arbitrary. But each level of nesting should have its specific macro +parameter. Nine levels of nesting is presumably overkill, but I did not know +where it was reasonable to stop. |\par| tokens are accepted in both the comma +separated list and the replacement text. + +\begin{framed} + A macro |\macro| whose definition uses internally an \csbxint{For} loop may be + used inside another \csbxint{For} loop even if the two loops both use the same + macro parameter. Note: the loop definition inside |\macro| must double + the character |#| as is the general rule in \TeX{} with definitions done + inside macros. + + The macros \csa{xintFor} and \csa{xintFor*} are not expandable, one can not + use them inside an |\edef|. But they may be used inside alignments (such as a + \LaTeX{} |tabular|), as will be shown in examples. +\end{framed} + +The spaces between the various declarative elements are all optional; +furthermore spaces around the commas or at the start and end of the list +argument are allowed, they will be removed. If an item must contain itself +commas, it should be braced to prevent these commas from being misinterpreted as +list separator. These braces will be removed during processing. The list +argument may be a macro |\MyList| expanding in one step to the comma separated +list (if it has no arguments, it does not have to be braced). It +will be expanded (only once) to reveal its comma separated items for processing, +comma separated items will not be expanded before being fed into the replacement +text as |#1|, or |#2|, etc\dots, only leading and trailing spaces are removed. + +A starred variant \csbxint{For*}\ntype{{\lowast f}n} deals with lists of braced +items, rather than comma separated items. It has also a distinct expansion +policy, which is detailed below. + +Contrarily to what happens in loops where the item is represented by a macro, +here it is truly exactly as when defining (in \LaTeX{}) a ``command'' with +parameters |#1|, etc... This may avoid the user quite a few troubles with +|\expandafter|s or other |\edef/\noexpand|s which one encounters at times when +trying to do things with \LaTeX's {\makeatother|\@for|} or other loops +which encapsulate the item in a macro expanding to that item. + +\begin{framed} + The non-starred variant \csbxint{For} deals with comma separated values + (\emph{spaces before and after the commas are removed}) and the comma + separated list may be a macro which is only expanded once (to prevent + expansion of the first item |\x| in a list directly input as |\x,\y,...| it + should be input as |{\x},\y,..| or |<space>\x,\y,..|, naturally all of that + within the mandatory braces of the \csa{xintFor \#n in \{list\}} syntax). The + items are not expanded, if the input is |<stuff>,\x,<stuff>| then |#1| will be + at some point |\x| not its expansion (and not either a macro with |\x| as + replacement text, just the token |\x|). Input such as |<stuff>,,<stuff>| + creates an empty |#1|, the iteration is not skipped. An empty list does lead + to the use of the replacement text, once, with an empty |#1| (or |#n|). Except + if the entire list is represented as a single macro with no parameters, + \fbox{it must be braced.} +\end{framed} + +\begin{framed} + The starred variant \csbxint{For*} deals with token lists (\emph{spaces + between braced items or single tokens are not significant}) and + \hyperref[sec:expansions]{\fexpan ds} each \emph{unbraced} list item. This + makes it easy to simulate concatenation of various list macros |\x|, |\y|, ... + If |\x| expands to |{1}{2}{3}| and |\y| expands to |{4}{5}{6}| then |{\x\y}| + as argument to |\xintFor*| has the same effect as |{{1}{2}{3}{4}{5}{6}}|% + \stepcounter{footnote}% + \makeatletter\hbox {\@textsuperscript {\normalfont \thefootnote + }}\makeatother. Spaces at the start, end, or in-between items are gobbled + (but naturally not the spaces which may be inside \emph{braced} items). Except + if the list argument is a single macro with no parameters, \fbox{it must be + braced.} Each item which is not braced will be fully expanded (as the |\x| + and |\y| in the example above). An empty list leads to an empty result. +\end{framed} +\begingroup\makeatletter +\def\@footnotetext #1{\insert\footins {\reset@font \footnotesize \interlinepenalty \interfootnotelinepenalty \splittopskip \footnotesep \splitmaxdepth \dp \strutbox \floatingpenalty \@MM \hsize \columnwidth \@parboxrestore \color@begingroup \@makefntext {\rule \z@ \footnotesep \ignorespaces #1\@finalstrut \strutbox }\color@endgroup }} +\addtocounter{footnote}{-1} +\edef\@thefnmark {\thefootnote} +\@footnotetext{braces around single token items + are optional so this is the same as \texttt{\{123456\}}.} +% \stepcounter{footnote} +% \edef\@thefnmark {\thefootnote} +% \@footnotetext{the \csa{space} will stop the \TeX{} scanning of a number and be +% gobbled in the process; the \csa{relax} stops the scanning but is not +% gobbled. Or one may do \csa{numexpr}\texttt{\#1}\csa{relax}, and then the +% \csa{relax} is gobbled.} +\endgroup +%\addtocounter{Hfootnote}{2} +\addtocounter{Hfootnote}{1} + +The macro \csbxint{Seq} which generates arithmetic sequences may only be used +with \csbxint{For*} (numbers from output of |\xintSeq| are braced, not separated +by commas). \centeredline{|\xintFor* #1 in {\xintSeq [+2]{-7}{+2}}\do {stuff + with #1}|} will have |#1=-7,-5,-3,-1, and 1|. The |#1| as issued from the +list produced by \csbxint{Seq} is the litteral representation as would be +produced by |\arabic| on a \LaTeX{} counter, it is not a count register. When +used in |\ifnum| tests or other contexts where \TeX{} looks for a number it +should thus be postfixed with |\relax| or |\space|. + +When nesting \csa{xintFor*} loops, using \csa{xintSeq} in the inner loops is +inefficient, as the arithmetic sequence will be re-created each time. A more +efficient style is: +% +\dverb|@ + \edef\innersequence {\xintSeq[+2]{-50}{50}}% + \xintFor* #1 in {\xintSeq {13}{27}} \do + {\xintFor* #2 in \innersequence \do {stuff with #1 and #2}% + .. some other macros .. }| + +This is a general remark applying for any nesting of loops, one should avoid +recreating the inner lists of arguments at each iteration of the outer loop. +However, in the example above, if the |.. some other macros ..| part +closes a group which was opened before the |\edef\innersequence|, then +this definition will be lost. An alternative to |\edef|, also efficient, +exists when dealing with arithmetic sequences: it is to use the +\csbxint{integers} keyword (described later) which simulates infinite +arithmetic sequences; the loops will then be terminated via a test |#1| +(or |#2| etc\dots) and subsequent use of \csbxint{BreakFor}. + + + +The \csbxint{For} loops are not completely expandable; but they may be nested +and used inside alignments or other contexts where the replacement text closes +groups. Here is an example (still using \LaTeX's tabular): + +\begingroup +\centeredline{\begin{tabular}{rccccc} + \xintFor #7 in {A,B,C} \do {% + #7:\xintFor* #3 in {abcde} \do {&($ #3 \to #7 $)}\\ }% +\end{tabular}} +\endgroup + +\dverb|@ +\begin{tabular}{rccccc} + \xintFor #7 in {A,B,C} \do {% + #7:\xintFor* #3 in {abcde} \do {&($ #3 \to #7 $)}\\ }% +\end{tabular}| + +When +inserted inside a macro for later execution the |#| characters must be +doubled.\footnote{sometimes what seems to be a macro argument isn't really; in + \csa{raisebox\{1cm\}\{}\csa{xintFor \#1 in \{a,b,c\} }\csa{do \{\#1\}\}} no + doubling should be done.} For example: +% +\dverb|@ +\def\T{\def\z {}% + \xintFor* ##1 in {{u}{v}{w}} \do {% + \xintFor ##2 in {x,y,z} \do {% + \expandafter\def\expandafter\z\expandafter {\z\sep (##1,##2)} }% + }% +}% +\T\def\sep {\def\sep{, }}\z |% +\def\T{\def\z {}% + \xintFor* ##1 in {{u}{v}{w}} \do {% + \xintFor ##2 in {x,y,z} \do {% + \expandafter\def\expandafter\z\expandafter {\z\sep (##1,##2)} }% + }}% +\centeredline{\T\def\sep {\def\sep{, }}\z} Similarly when the replacement text +of |\xintFor| defines a macro with parameters, the macro character |#| must be +doubled. + +It is licit to use inside an \csbxint{For} a |\macro| which itself has +been defined to use internally some other \csbxint{For}. The same macro +parameter |#1| can be used with no conflict (as mentioned above, in the +definition of |\macro| the |#| used in the \csbxint{For} declaration must be +doubled, as is the general rule in \TeX{} with things defined inside other +things). + +The iterated commands as well as the list items are allowed to contain explicit +|\par| tokens. Neither \csbxint{For} nor \csbxint{For*} create groups. The +effect is like piling up the iterated commands with each time |#1| (or |#2| ...) +replaced by an item of the list. However, contrarily to the completely +expandable \csbxint{ApplyUnbraced}, but similarly to the non completely +expandable \csbxint{ApplyInline} each iteration is executed first before looking +at the next |#1|\footnote{to be completely honest, both \csbxint{For} and + \csbxint{For*} intially scoop up both the list and the iterated commands; + \csbxint{For} scoops up a second time the entire comma separated list in order + to feed it to \csbxint{CSVtoList}. The starred variant \csbxint{For*} which + does not need this step will thus be a bit faster on equivalent inputs.} (and +the starred variant \csbxint{For*} keeps on expanding each unbraced item it +finds, gobbling spaces). + +\subsection{\csbh{xintifForFirst}, \csbh{xintifForLast}} +\label{xintifForFirst}\label{xintifForLast} +% {\small New in |1.09e|.\par} + + +\csbxint{ifForFirst}\,\texttt{\{YES branch\}\{NO branch\}}\etype{nn} + and \csbxint{ifForLast}\,\texttt{\{YES + branch\}\hskip 0pt plus 0.2em \{NO branch\}}\etype{nn} execute the |YES| or +|NO| branch +if the +\csbxint{For} +or \csbxint{For*} loop is currently in its first, respectively last, iteration. + +Designed to work as expected under nesting. Don't forget an empty brace pair +|{}| if a branch is to do nothing. May be used multiple times in the replacement +text of the loop. + +There is no such thing as an iteration counter provided by the \csa{xintFor} +loops; the user is invited to define if needed his own count register or +\LaTeX{} counter, for example with a suitable |\stepcounter| inside the +replacement text of the loop to update it. + +\subsection{ \csbh{xintBreakFor}, \csbh{xintBreakForAndDo}} +\label{xintBreakFor}\label{xintBreakForAndDo} +%{\small New in |1.09e|.\par} + +One may immediately terminate an \csbxint{For} or \csbxint{For*} loop with +\csbxint{BreakFor}. As the criterion for breaking will be decided on a +basis of some test, it is recommended to use for this test the syntax of +\href{http://ctan.org/pkg/ifthen}{ifthen}\footnote{\url{http://ctan.org/pkg/ifthen}} +or +\href{http://ctan.org/pkg/etoolbox}{etoolbox}\footnote{\url{http://ctan.org/pkg/etoolbox}} +or the \xintname own conditionals, rather than one of the various +|\if...\fi| of \TeX{}. Else (and this is without even mentioning all the various +pecularities of the +|\if...\fi| constructs), one has to carefully move the break after the closing +of +the conditional, typically with |\expandafter\xintBreakFor\fi|.\footnote{the + difficulties here are similar to those mentioned in \autoref{sec:ifcase}, + although less severe, as complete expandability is not to be maintained; hence + the allowed use of \href{http://ctan.org/pkg/ifthen}{ifthen}.} + +There is also \csbxint{BreakForAndDo}. Both are illustrated by various examples +in the next section which is devoted to ``forever'' loops. + + +\subsection{\csbh{xintintegers}, \csbh{xintdimensions}, \csbh{xintrationals}} +\label{xintegers}\label{xintintegers} +\label{xintdimensions}\label{xintrationals} +%{\small New in |1.09e|.\par} + +If the list argument to \csbxint{For} (or \csbxint{For*}, both are equivalent in +this context) is \csbxint{integers} (equivalently \csbxint{egers}) or more +generally \csbxint{integers}|[||start|\allowbreak|+|\allowbreak|delta||]| +(\emph{the whole within braces}!)\footnote{the |start+delta| optional + specification may have extra spaces around the plus sign of near the square + brackets, such spaces are removed. The same applies with \csa{xintdimensions} + and \csa{xintrationals}.}, then \csbxint{For} does an infinite iteration where +|#1| (or |#2|, \dots, |#9|) will run through the arithmetic sequence of (short) +integers with initial value |start| and increment |delta| (default values: +|start=1|, |delta=1|; if the optional argument is present it must contains both +of them, and they may be explicit integers, or macros or count registers). The +|#1| (or |#2|, \dots, |#9|) will stand for |\numexpr <opt sign><digits>\relax|, +and the litteral representation as a string of digits can thus be obtained as +\fbox{\csa{the\#1}} or |\number#1|. Such a |#1| can be used in an |\ifnum| test +with no need to be postfixed with a space or a |\relax| and one should +\emph{not} add them. + +If the list argument is \csbxint{dimensions} or more generally +\csbxint{dimensions}|[||start|\allowbreak|+|\allowbreak|delta||]| (\emph{within + braces}!), then +\csbxint{For} does an infinite iteration where |#1| (or |#2|, \dots, |#9|) will +run through the arithmetic sequence of dimensions with initial value +|start| and increment |delta|. Default values: |start=0pt|, |delta=1pt|; if +the optional argument is present it must contain both of them, and they may +be explicit specifications, or macros, or dimen registers, or length commands +in \LaTeX{} (the stretch and shrink components will be discarded). The |#1| +will be |\dimexpr <opt sign><digits>sp\relax|, from which one can get the +litteral (approximate) representation in points via |\the#1|. So |#1| can be +used anywhere \TeX{} expects a dimension (and there is no need in conditionals +to insert a |\relax|, and one should \emph{not} do it), and to print its value +one uses \fbox{\csa{the\#1}}. The chosen representation guarantees exact +incrementation with no rounding errors accumulating from converting into +points at each step. + + +% original definitions, a bit slow. + +% \def\DimToNum #1{\number\dimexpr #1\relax } +% % cube +% \xintNewNumExpr \FA [2] {{_DimToNum {$2}}^3/{_DimToNum {$1}}^2} %$ +% % square root +% \xintNewNumExpr \FB [2] {sqrt ({_DimToNum {$2}}*{_DimToNum {$1}})} +% \xintNewExpr \Ratio [2] {trunc({_DimToNum {$2}}/{_DimToNum{$1}},3)} + +% improved faster code (4 four times faster) + +\def\DimToNum #1{\the\numexpr \dimexpr#1\relax/10000\relax } +\def\FA #1#2{\xintDSH{-4}{\xintQuo {\xintiPow {\DimToNum {#2}}{3}}{\xintiSqr +{\DimToNum{#1}}}}} +\def\FB #1#2{\xintDSH {-4}{\xintiSqrt + {\xintiMul {\DimToNum {#2}}{\DimToNum{#1}}}}} +\def\Ratio #1#2{\xintTrunc {2}{\DimToNum {#2}/\DimToNum{#1}}} + +% a further 2.5 gain is made through using .25pt as horizontal step. +\begin{figure*}[ht!] +\phantomsection\hypertarget{graphic}{}% +\centeredline{% +\raisebox{-1cm}{\xintFor #1 in {\xintdimensions [0pt+.25pt]} \do + {\ifdim #1>2cm \expandafter\xintBreakFor\fi + {\color [rgb]{\Ratio {2cm}{#1},0,0}% + \vrule width .25pt height \FB {2cm}{#1}sp depth -\FA {2cm}{#1}sp }% + }% end of For iterated text +}% +\hspace{1cm}% +\scriptsize\def\MacroFont {\ttfamily\baselineskip8pt\relax} +\begin{minipage}{\dimexpr\linewidth-3cm-\parindent\relax} +\dverb|@ +\def\DimToNum #1{\number\dimexpr #1\relax } +\xintNewNumExpr \FA [2] {{_DimToNum {$2}}^3/{_DimToNum {$1}}^2} % cube +\xintNewNumExpr \FB [2] {sqrt ({_DimToNum {$2}}*{_DimToNum {$1}})} % sqrt +\xintNewExpr \Ratio [2] {trunc({_DimToNum {$2}}/{_DimToNum{$1}},3)} +\xintFor #1 in {\xintdimensions [0pt+.1pt]} \do + {\ifdim #1>2cm \expandafter\xintBreakFor\fi + {\color [rgb]{\Ratio {2cm}{#1},0,0}% + \vrule width .1pt height \FB {2cm}{#1}sp depth -\FA {2cm}{#1}sp }% + }% end of For iterated text +|\par +\end{minipage}} +\end{figure*} + +% attention, pour le \meaning dans cette note de base de page + +The\xintNewNumExpr \FA [2] {{_DimToNum {$2}}^3/{_DimToNum {$1}}^2} %$ +\hyperlink{graphic}{graphic}, with the code on its right\footnote{the somewhat + peculiar use of |\_| and |\$| is explained in \autoref{xintNewExpr}; they are + made necessary from the fact that the parameters are passed to a \emph{macro} + (\csa{DimToNum}) and not only to \emph{functions}, as are known to + \hyperref[sec:exprsummary]{\csa{xintexpr}}. But one can also define directly + the desired function, for example the constructed \csa{FA} turns out to have + meaning \texttt{\meaning\FA}, where the \csa{romannumeral} part is only to + ensure it expands in only two steps, and could be removed. A handwritten macro + would use here \csa{xintiPow} and not \csa{xintPow}, as we know it has to deal + with integers only. See the next footnote.}, is for illustration only, not +only because of pdf rendering artefacts when displaying adjacent rules (which do +\emph{not} show in |dvi| output as rendered by |xdvi|, and depend from your +viewer), but because not using anything but rules it is quite inefficient and +must do lots of computations to not confer a too ragged look to the borders. +With a width of |.5pt| rather than |.1pt| for the rules, one speeds up the +drawing by a factor of five, but the boundary is then visibly ragged. +\newbox\codebox +\begingroup\makeatletter +\def\x{% + \parindent0pt + \def\par{\@@par\leavevmode\null}% + \let\do\do@noligs \verbatim@nolig@list + \let\do\@makeother \dospecials + \catcode`\@ 14 \makestarlowast + \ttfamily \scriptsize\baselineskip 8pt \obeylines \@vobeyspaces + \catcode`\|\active + \lccode`\~`\|\lowercase{\let~\egroup}}% +\global\setbox\codebox \vbox\bgroup\x +\def\DimToNum #1{\the\numexpr \dimexpr#1\relax/10000\relax } % no need to be more precise! +\def\FA #1#2{\xintDSH {-4}{\xintQuo {\xintiPow {\DimToNum {#2}}{3}}{\xintiSqr {\DimToNum{#1}}}}} +\def\FB #1#2{\xintDSH {-4}{\xintiSqrt {\xintiMul {\DimToNum {#2}}{\DimToNum{#1}}}}} +\def\Ratio #1#2{\xintTrunc {2}{\DimToNum {#2}/\DimToNum{#1}}} +\xintFor #1 in {\xintdimensions [0pt+.25pt]} \do + {\ifdim #1>2cm \expandafter\xintBreakFor\fi + {\color [rgb]{\Ratio {2cm}{#1},0,0}% + \vrule width .25pt height \FB {2cm}{#1}sp depth -\FA {2cm}{#1}sp }% + }% end of For iterated text +|% +\endgroup +\footnote{to tell the whole truth we cheated and divided by |10| the + computation time through using the following definitions, together with a + horizontal step of |.25pt| rather than |.1pt|. The displayed original code + would make the slowest computation of all those done in this document using + the \xintname bundle macros!\par\smallskip + \noindent\box \codebox\par } + +If the list argument to \csbxint{For} (or \csbxint{For*}) is \csbxint{rationals} +or more generally +\csbxint{rationals}|[||start|\allowbreak|+|\allowbreak|delta||]| (\emph{within + braces}!), then \csbxint{For} does an infinite iteration where |#1| (or |#2|, +\dots, |#9|) will run through the arithmetic sequence of \xintfracname fractions +with initial value |start| and increment |delta| (default values: |start=1/1|, +|delta=1/1|). This loop works \emph{only with \xintfracname loaded}. if the +optional argument is present it must contain both of them, and they may be given +in any of the formats recognized by \xintfracname (fractions, decimal +numbers, numbers in scientific notations, numerators and denominators in +scientific notation, etc...) , or as macros or count registers (if they are +short integers). The |#1| (or |#2|, \dots, |#9|) will be an |a/b| fraction +(without a |[n]| part), where +the denominator |b| is the product of the denominators of +|start| and |delta| (for reasons of speed |#1| is not reduced to irreducible +form, and for another reason explained later |start| and |delta| are not put +either into irreducible form; the input may use explicitely \csa{xintIrr} to +achieve that). + +\begingroup\small +\noindent\dverb|@ +\xintFor #1 in {\xintrationals [10/21+1/21]} \do +{#1=\xintifInt {#1} + {\textcolor{blue}{\xintTrunc{10}{#1}}} + {\xintTrunc{10}{#1}}% in blue if an integer + \xintifGt {#1}{1.123}{\xintBreakFor}{, }% +}| + +\smallskip +\centeredline{\parbox{\dimexpr\linewidth-3em}{\xintFor #1 in {\xintrationals [10/21+1/21]} \do +{#1=\xintifInt {#1} + {\textcolor{blue}{\xintTrunc{10}{#1}}} + {\xintTrunc{10}{#1}}% display in blue if an integer + \xintifGt {#1}{1.123}{\xintBreakFor}{, }% + }}} +\endgroup + +\smallskip The example above confirms that computations are done exactly, and +illustrates that the two initial (reduced) denominators are not multiplied when +they are found to be equal. It is thus recommended to input |start| and |delta| +with a common smallest possible denominator, or as fixed point numbers with the +same numbers of digits after the decimal mark; and this is also the reason why +|start| and |delta| are not by default made irreducible. As internally the +computations are done with numerators and denominators completely expanded, one +should be careful not to input numbers in scientific notation with exponents in +the hundreds, as they will get converted into as many zeroes. + +\begingroup\footnotesize \def\MacroFont {\ttfamily\relax} +\noindent\dverb|@ +\xintFor #1 in {\xintrationals [0.000+0.125]} \do +{\edef\tmp{\xintTrunc{3}{#1}}% + \xintifInt {#1} + {\textcolor{blue}{\tmp}} + {\tmp}% + \xintifGt {#1}{2}{\xintBreakFor}{, }% + }| +\smallskip + +\centeredline{\parbox{\dimexpr.7\linewidth}{\raggedright +\xintFor #1 in {\xintrationals [0.000+0.125]} \do +{\edef\tmp{\xintTrunc{3}{#1}}% + \xintifInt {#1} + {\textcolor{blue}{\tmp}} + {\tmp}% + \xintifGt {#1}{2}{\xintBreakFor}{, }% + }}} + +\smallskip + +We see here that \csbxint{Trunc} outputs (deliberately) zero as @0@, not (here) +@0.000@, the idea being not to lose the information that the truncated thing was +truly zero. Perhaps this behavior should be changed? or made optional? Anyhow +printing of fixed points numbers should be dealt with via dedicated packages +such as |numprint| or |siunitx|.\par +\endgroup + + +\subsection{Another table of primes}\label{ssec:primesIII} + +As a further example, let us dynamically generate a tabular with the first @50@ +prime numbers after @12345@. First we need a macro to test if a (short) number +is prime. Such a completely expandable macro was given in \autoref{xintSeq}, +here we consider a variant which will be slightly more efficient. This new +|\IsPrime| has two parameters. The first one is a macro which it redefines to +expand to the result of the primality test applied to the second argument. For +convenience we use the \href{http://ctan.org/pkg/etoolbox}{etoolbox} wrappers to +various |\ifnum| tests, although here there isn't anymore the constraint of +complete expandability (but using explicit |\if..\fi| in tabulars has its +quirks); equivalent tests are provided by \xintname, but they have some overhead +as they are able to deal with arbitrarily big integers. + +\def\IsPrime #1#2% +{\edef\TheNumber {\the\numexpr #2}% positive integer + \ifnumodd {\TheNumber} + {\ifnumgreater {\TheNumber}{1} + {\edef\ItsSquareRoot{\xintiSqrt \TheNumber}% + \xintFor ##1 in {\xintintegers [3+2]}\do + {\ifnumgreater {##1}{\ItsSquareRoot} + {\def#1{1}\xintBreakFor} + {}% + \ifnumequal {\TheNumber}{(\TheNumber/##1)*##1} + {\def#1{0}\xintBreakFor } + {}% + }} + {\def#1{0}}}% 1 is not prime + {\ifnumequal {\TheNumber}{2}{\def#1{1}}{\def#1{0}}}% +}% + +\dverb|@ +\def\IsPrime #1#2% """color[named]{PineGreen}#1=\Result, #2=tested number (assumed >0).;! +{\edef\TheNumber {\the\numexpr #2}%"""color[named]{PineGreen} hence #2 may be a count or \numexpr.;! + \ifnumodd {\TheNumber} + {\ifnumgreater {\TheNumber}{1} + {\edef\ItsSquareRoot{\xintiSqrt \TheNumber}% + \xintFor """color{red}##1;! in {"""color{red}\xintintegers;! [3+2]}\do + {\ifnumgreater {"""color{red}##1;!}{\ItsSquareRoot} """color[named]{PineGreen}% "textcolor{red}{##1} is a \numexpr.;! + {\def#1{1}\xintBreakFor} + {}% + \ifnumequal {\TheNumber}{(\TheNumber/##1)*##1} + {\def#1{0}\xintBreakFor } + {}% + }} + {\def#1{0}}}% 1 is not prime + {\ifnumequal {\TheNumber}{2}{\def#1{1}}{\def#1{0}}}% +}| + +%\newcounter{primecount} +%\newcounter{cellcount} +\begin{figure*}[ht!] + \centering\phantomsection\label{primes} + \begin{tabular}{|*{7}c|} + \hline + \setcounter{primecount}{0}\setcounter{cellcount}{0}% + \xintFor #1 in {\xintintegers [12345+2]} \do + {\IsPrime\Result{#1}% + \ifnumgreater{\Result}{0} + {\stepcounter{primecount}% + \stepcounter{cellcount}% + \ifnumequal {\value{cellcount}}{7} + {\the#1 \\\setcounter{cellcount}{0}} + {\the#1 &}} + {}% + \ifnumequal {\value{primecount}}{50} + {\xintBreakForAndDo + {\multicolumn {6}{l|}{These are the first 50 primes after 12345.}\\}} + {}% + }\hline +\end{tabular} +\end{figure*} + +As we used \csbxint{For} inside a macro we had to double the |#| in its |#1| +parameter. Here is now the code which creates the prime table (the table has +been put in a \hyperref[primes]{float}, which appears +\vpageref[above]{primes}): +\dverb?@ +\newcounter{primecount} +\newcounter{cellcount} +\begin{figure*}[ht!] + \centering + \begin{tabular}{|*{7}c|} + \hline + \setcounter{primecount}{0}\setcounter{cellcount}{0}% + \xintFor """color{red}#1;! in {"""color{red}\xintintegers;! [12345+2]} \do +"""color[named]{PineGreen}% "textcolor{red}{#1} is a \numexpr.;! + {\IsPrime\Result{#1}% + \ifnumgreater{\Result}{0} + {\stepcounter{primecount}% + \stepcounter{cellcount}% + \ifnumequal {\value{cellcount}}{7} + {"""color{red}\the#1;! \\\setcounter{cellcount}{0}} + {"""color{red}\the#1;! &}} + {}% + \ifnumequal {\value{primecount}}{50} + {\xintBreakForAndDo + {\multicolumn {6}{l|}{These are the first 50 primes after 12345.}\\}} + {}% + }\hline +\end{tabular} +\end{figure*}? + +\subsection{Some arithmetic with Fibonacci numbers} +\label{ssec:fibonacci} + +Here is again the code employed on the title page to compute Fibonacci numbers: + +\begingroup\footnotesize\baselineskip10pt +\def\MacroFont {\ttfamily} +\dverb|@ +\def\Fibonacci #1{% \Fibonacci{N} computes F(N) with F(0)=0, F(1)=1. + \expandafter\Fibonacci_a\expandafter + {\the\numexpr #1\expandafter}\expandafter + {\romannumeral0\xintiieval 1\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval 1\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval 1\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval 0\relax}} +% +\def\Fibonacci_a #1{% + \ifcase #1 + \expandafter\Fibonacci_end_i + \or + \expandafter\Fibonacci_end_ii + \else + \ifodd #1 + \expandafter\expandafter\expandafter\Fibonacci_b_ii + \else + \expandafter\expandafter\expandafter\Fibonacci_b_i + \fi + \fi {#1}% +}% * signs are omitted from the next macros, tacit multiplications +\def\Fibonacci_b_i #1#2#3{\expandafter\Fibonacci_a\expandafter + {\the\numexpr #1/2\expandafter}\expandafter + {\romannumeral0\xintiieval sqr(#2)+sqr(#3)\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval (2#2-#3)#3\relax}% +}% end of Fibonacci_b_i +\def\Fibonacci_b_ii #1#2#3#4#5{\expandafter\Fibonacci_a\expandafter + {\the\numexpr (#1-1)/2\expandafter}\expandafter + {\romannumeral0\xintiieval sqr(#2)+sqr(#3)\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval (2#2-#3)#3\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval #2#4+#3#5\expandafter\relax\expandafter}\expandafter + {\romannumeral0\xintiieval #2#5+#3(#4-#5)\relax}% +}% end of Fibonacci_b_ii +\def\Fibonacci_end_i #1#2#3#4#5{\xintthe#5} +\def\Fibonacci_end_ii #1#2#3#4#5{\xinttheiiexpr #2#5+#3(#4-#5)\relax} +\def\Fibonacci_end_i #1#2#3#4#5{{#4}{#5}}% {F(N+1)}{F(N)} in \xintexpr format +\def\Fibonacci_end_ii #1#2#3#4#5% + {\expandafter + {\romannumeral0\xintiieval #2#4+#3#5\expandafter\relax + \expandafter}\expandafter + {\romannumeral0\xintiieval #2#5+#3(#4-#5)\relax}}% idem. +% \FibonacciN returns F(N) (in encapsulated format: needs \xintthe for printing) +\def\FibonacciN {\expandafter\xint_secondoftwo\romannumeral-`0\Fibonacci }% +|\par\endgroup + +\catcode`_ 11 +\def\Fibonacci_end_i #1#2#3#4#5{{#4}{#5}}% +\def\Fibonacci_end_ii #1#2#3#4#5% + {\expandafter + {\romannumeral0\xintiieval #2#4+#3#5\expandafter\relax + \expandafter}\expandafter + {\romannumeral0\xintiieval #2#5+#3(#4-#5)\relax}}% idem. +% \Fibonacci returns {F(N+1)}{F(N)} (both in \xintexpr encapsulation) +% \FibonacciN returns F(N) (also in encapsulated format) +\def\FibonacciN {\expandafter\xint_secondoftwo\romannumeral-`0\Fibonacci }% +\catcode`_ 8 + +% ok +% \def\Fibo #1.{\xintthe\FibonacciN {#1}}% to use \xintiloopindex... +% \message{\xintiloop [0+1] +% \expandafter\Fibo\xintiloopindex., +% \ifnum\xintiloopindex<49 \repeat \xintthe\FibonacciN{50}.} + +I have modified the ending, as I now want not only one specific value |F(N)| but +a pair of successive values which can serve as starting point of another routine +devoted to compute a whole sequence |F(N), F(N+1), F(N+2),....|. This pair is, +for efficiency, kept in the encapsulated internal \xintexprname format. +|\FibonacciN| outputs the single |F(N)|, also as an |\xintexpr|-ession, and +printing it will thus need the |\xintthe| prefix. + +\begingroup\footnotesize\sffamily\baselineskip 10pt\let\MacroFont\ttfamily +Here a code snippet which +checks the routine via a \string\message\ of the first @51@ Fibonacci +numbers (this is not an efficient way to generate a sequence of such +numbers, it is only for validating \csa{FibonacciN}). +% +\dverb|@ +\def\Fibo #1.{\xintthe\FibonacciN {#1}}% +\message{\xintiloop [0+1] \expandafter\Fibo\xintiloopindex., + \ifnum\xintiloopindex<49 \repeat \xintthe\FibonacciN{50}.}|\par +\endgroup + +The various |\romannumeral0\xintiieval| could very well all have been +|\xintiiexpr|'s but then we would have needed more |\expandafter|'s. +Indeed the order of expansion must be controlled for the whole thing to work, +and |\romannumeral0\xintiieval| is the first expanded form of |\xintiiexpr|. + +The way we use |\expandafter|'s to chain successive |\xintexpr| evaluations is +exactly analogous to well-known expandable techniques made possible by +|\numexpr|. + +\begin{framed} + There is a difference though: |\numexpr| is \emph{NOT} expandable, and to + force its expansion we must prefix it with |\the| or |\number|. On the other + hand |\xintexpr|, |\xintiexpr|, ..., (or |\xinteval|, |\xintieval|, ...) + expand fully when prefixed by |\romannumeral-`0|: the computation is fully + executed and its result encapsulated in a private format. + + Using |\xintthe| as prefix is necessary to print the result (this is like + |\the| for |\numexpr|), but it is not necessary to get the computation done + (contrarily to the situation with |\numexpr|). + + And, starting with release |1.09j|, it is also allowed to expand a non + |\xintthe| prefixed |\xintexpr|-ession inside an |\edef|: the private format + is now protected, hence the error message complaining about a missing + |\xintthe| will not be executed, and the integrity of the format will be + preserved. + + This new possibility brings some efficiency gain, when one writes + non-expandable algorithms using \xintexprname. If |\xintthe| is + employed inside |\edef| the number or fraction will be un-locked into + its possibly hundreds of digits and all these tokens will possibly + weigh on the upcoming shuffling of (braced) tokens. The private + encapsulated format has only a few tokens, hence expansion will + proceed a bit faster. + + \indent see footnote\footnotemark +\end{framed} + +\footnotetext{To be completely honest the examination by \TeX{} of all + successive digits was not avoided, as it occurs already in the locking-up of + the result, what is avoided is to spend time un-locking, and then have + the macros shuffle around possibly hundreds of digit tokens rather + than a few control words.\par + Technical note: I decided (somewhat hesitantly) for + reasons of optimization purposes to skip in the private \csa{xintexpr} + format a \csa{protect}-ion for the \csa{.=digits/digits[digits]} + control sequences used internally. Thus in the improbable case that + some macro package (such control sequence names are unavailable to the + casual user) has given a meaning to one such control sequence, there + is a possibility of a crash when embedding an \csa{xintexpr} without + \csa{xintthe} prefix in an \csa{edef} (the computations by themselves + do proceed perfectly correctly even if these control sequences have + acquired some non \csa{relax} meaning).} + +Our |\Fibonacci| expands completely under \fexpan sion, +so we can use \hyperref[fdef]{\ttfamily\char92fdef} rather than |\edef| in a +situation such as \centeredline {|\fdef \X {\FibonacciN {100}}|} but for the +reasons explained above, it is as efficient to employ |\edef|. And if we want +\centeredline{|\edef \Y {(\FibonacciN{100},\FibonacciN{200})}|,} then |\edef| is +necessary. + +Allright, so let's now give the code to generate a sequence of braced Fibonacci +numbers |{F(N)}{F(N+1)}{F(N+2)}...|, using |\Fibonacci| for the first +two and then using the standard recursion |F(N+2)=F(N+1)+F(N)|: + +\catcode`_ 11 +\def\FibonacciSeq #1#2{%#1=starting index, #2>#1=ending index + \expandafter\Fibonacci_Seq\expandafter + {\the\numexpr #1\expandafter}\expandafter{\the\numexpr #2-1}% +}% +\def\Fibonacci_Seq #1#2{% + \expandafter\Fibonacci_Seq_loop\expandafter + {\the\numexpr #1\expandafter}\romannumeral0\Fibonacci {#1}{#2}% +}% +\def\Fibonacci_Seq_loop #1#2#3#4{% standard Fibonacci recursion + {#3}\unless\ifnum #1<#4 \Fibonacci_Seq_end\fi + \expandafter\Fibonacci_Seq_loop\expandafter + {\the\numexpr #1+1\expandafter}\expandafter + {\romannumeral0\xintiieval #2+#3\relax}{#2}{#4}% +}% +\def\Fibonacci_Seq_end\fi\expandafter\Fibonacci_Seq_loop\expandafter + #1\expandafter #2#3#4{\fi {#3}}% +\catcode`_ 8 + +\begingroup\footnotesize\baselineskip10pt +\def\MacroFont {\ttfamily} +\dverb|@ +\catcode`_ 11 +\def\FibonacciSeq #1#2{%#1=starting index, #2>#1=ending index + \expandafter\Fibonacci_Seq\expandafter + {\the\numexpr #1\expandafter}\expandafter{\the\numexpr #2-1}% +}% +\def\Fibonacci_Seq #1#2{% + \expandafter\Fibonacci_Seq_loop\expandafter + {\the\numexpr #1\expandafter}\romannumeral0\Fibonacci {#1}{#2}% +}% +\def\Fibonacci_Seq_loop #1#2#3#4{% standard Fibonacci recursion + {#3}\unless\ifnum #1<#4 \Fibonacci_Seq_end\fi + \expandafter\Fibonacci_Seq_loop\expandafter + {\the\numexpr #1+1\expandafter}\expandafter + {\romannumeral0\xintiieval #2+#3\relax}{#2}{#4}% +}% +\def\Fibonacci_Seq_end\fi\expandafter\Fibonacci_Seq_loop\expandafter + #1\expandafter #2#3#4{\fi {#3}}% +\catcode`_ 8 +|\par\endgroup + +Deliberately and for optimization, this |\FibonacciSeq| macro is +completely expandable but not \fexpan dable. It would be easy to modify +it to be so. But I wanted to check that the \csbxint{For*} does apply +full expansion to what comes next each time it fetches an item from its +list argument. Thus, there is no need to generate lists of braced +Fibonacci numbers beforehand, as \csbxint{For*}, without using any +|\edef|, still manages to generate the list via iterated full expansion. + +I initially used only one |\halign| in a three-column |multicols| +environment, but |multicols| only knows to divide the page horizontally +evenly, thus I employed in the end one |\halign| for each column (I +could have then used a |tabular| as no column break was then needed). + + +\begin{figure*}[ht!] + \phantomsection\label{fibonacci} + \newcounter{index} + \fdef\Fibxxx{\FibonacciN {30}}% + \setcounter{index}{30}% +\centeredline{\tabskip 1ex +\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr + \xintFor* #1 in {\FibonacciSeq {30}{59}}\do + {\theindex &\xintthe#1 & + \xintRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{index}\cr }}% +}\vrule +\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr + \xintFor* #1 in {\FibonacciSeq {60}{89}}\do + {\theindex &\xintthe#1 & + \xintRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{index}\cr }}% +}\vrule +\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr + \xintFor* #1 in {\FibonacciSeq {90}{119}}\do + {\theindex &\xintthe#1 & + \xintRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{index}\cr }}% +}}% +% +\centeredline{Some Fibonacci numbers together with their residues modulo + |F(30)|\digitstt{=\xintthe\Fibxxx}} +\end{figure*} + +\begingroup\footnotesize\baselineskip10pt +\def\MacroFont {\ttfamily} +\dverb|@ +\newcounter{index} +\tabskip 1ex + \fdef\Fibxxx{\FibonacciN {30}}% + \setcounter{index}{30}% +\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr + \xintFor* #1 in {\FibonacciSeq {30}{59}}\do + {\theindex &\xintthe#1 & + \xintRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{index}\cr }}% +}\vrule +\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr + \xintFor* #1 in {\FibonacciSeq {60}{89}}\do + {\theindex &\xintthe#1 & + \xintRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{index}\cr }}% +}\vrule +\vbox{\halign{\bfseries#.\hfil&#\hfil &\hfil #\cr + \xintFor* #1 in {\FibonacciSeq {90}{119}}\do + {\theindex &\xintthe#1 & + \xintRem{\xintthe#1}{\xintthe\Fibxxx}\stepcounter{index}\cr }}% +}% +|\par\endgroup + +This produces the Fibonacci numbers from |F(30)| to |F(119)|, and +computes also all the +congruence classes modulo |F(30)|. The output has +been put in a \hyperref[fibonacci]{float}, which appears +\vpageref[above]{fibonacci}. I leave to the mathematically inclined +readers the task to explain the visible patterns\dots |;-)|. + +\subsection{\csbh{xintForpair}, \csbh{xintForthree}, \csbh{xintForfour}}\label{xintForpair}\label{xintForthree}\label{xintForfour} +% {\small New in |1.09c|. The \csa{xintifForFirst} +% |1.09e| mechanism was missing and has been added for |1.09f|. The |1.09f| +% version handles better spaces and admits all (consecutive) macro +% parameters.\par} + +The syntax\ntype{on} is illustrated in this +example. The notation is the usual one for |n|-uples, with parentheses and +commas. Spaces around commas and parentheses are ignored. +% +\dverb|@ +\begin{tabular}{cccc} + \xintForpair #1#2 in { ( A , a ) , ( B , b ) , ( C , c ) } \do {% + \xintForpair #3#4 in { ( X , x ) , ( Y , y ) , ( Z , z ) } \do {% + $\Biggl($\begin{tabular}{cc} + -#1- & -#3-\\ + -#4- & -#2-\\ + \end{tabular}$\Biggr)$&}\\\noalign{\vskip1\jot}}% +\end{tabular}|% +\centeredline{\begin{tabular}{cccc} + \xintForpair #1#2 in { ( A , a ) , ( B , b ) , ( C , c ) } \do {% + \xintForpair #3#4 in { ( X , x ) , ( Y , y ) , ( Z , z ) } \do {% + $\Biggl($\begin{tabular}{cc} + -#1- & -#3-\\ + -#4- & -#2-\\ + \end{tabular}$\Biggr)$&}\\\noalign{\vskip1\jot}}% +\end{tabular}} + +\smallskip Only |#1#2|, |#2#3|, |#3#4|, \dots, |#8#9| are valid (no error check +is done on the input syntax, |#1#3| or similar all end up in errors). +One can nest with \csbxint{For}, for disjoint sets of macro parameters. There is +also \csa{xintForthree} (from |#1#2#3| to |#7#8#9|) and \csa{xintForfour} (from +|#1#2#3#4| to |#6#7#8#9|). |\par| tokens are accepted in both the comma +separated list and the replacement text. + +% These three macros |\xintForpair|, |\xintForthree| and |\xintForfour| are to +% be considered in experimental status, and may be removed, replaced or +% substantially modified at some later stage. + +\subsection{\csbh{xintAssign}}\label{xintAssign} +%\small{ |1.09i| adds optional parameter. |1.09j| has default optional +% parameter |[]| rather than |[e]|\par} + +\csa{xintAssign}\meta{braced things}\csa{to}% +\meta{as many cs as they are things} %\ntype{{(f$\to$\lowast [x)}{\lowast N}} +% +defines (without checking if something gets overwritten) the control sequences +on the right of \csa{to} to expand to the successive tokens or braced items +found one after the otehr on the on the left of \csa{to}. It is not expandable. + +A `full' expansion is first applied to the material in front of +\csa{xintAssign}, which may thus be a macro expanding to a list of braced items. + +\xintAssign \xintiPow {7}{13}\to\SevenToThePowerThirteen +\xintAssign \xintDivision{1000000000000}{133333333}\to\Q\R + +Special case: if after this initial expansion no brace is found immediately +after \csa{xintAssign}, it is assumed that there is only one control sequence +following |\to|, and this control sequence is then defined via +|\def| to expand to the material between +\csa{xintAssign} and \csa{to}. Other types of expansions are specified through +an optional parameter to \csa{xintAssign}, see \emph{infra}. +\centeredline{|\xintAssign \xintDivision{1000000000000}{133333333}\to\Q\R|} +\centeredline{|\meaning\Q: |\digitstt{\meaning\Q}, |\meaning\R:| + \digitstt{\meaning\R}} \centeredline{|\xintAssign \xintiPow + {7}{13}\to\SevenToThePowerThirteen|} +\centeredline{|\SevenToThePowerThirteen|\digitstt{=\SevenToThePowerThirteen}} +\centeredline{(same as |\edef\SevenToThePowerThirteen{\xintiPow {7}{13}}|)} + + +\noindent\csa{xintAssign}\MyMarginNote{Changed!} 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 +definitions with |\def|, corresponding to an empty optional paramter |[]|. +Possibilities: |[], [g], [e], [x], [o], [go], [oo], [goo], [f], [gf]|. + +In all cases, recall that |\xintAssign| starts with an \fexpan sion of what +comes next; this produces some list of tokens or braced items, and the +optional parameter only intervenes to decide the expansion type to be applied +then to each one of these items. + +\emph{Note:} prior to release |1.09j|, |\xintAssign| did an |\edef| by +default, but it now does |\def|. Use the optional parameter |[e]| to force use +of |\edef|. + +% This +% macro uses various \csa{edef}'s, thus is incompatible with expansion-only +% contexts. + +\subsection{\csbh{xintAssignArray}}\label{xintAssignArray} +% {\small Changed in release |1.06| to let the defined macro pass its +% argument through a |\numexpr...\relax|. |1.09i| adds optional +% parameter. \par} + +\xintAssignArray \xintBezout {1000}{113}\to\Bez + +\csa{xintAssignArray}\meta{braced + things}\csa{to}\csa{myArray} %\ntype{{(f$\to$\lowast x)}N} +% +first expands fully what comes immediately after |\xintAssignArray| and +expects to find a list of braced things |{A}{B}...| (or tokens). It then +defines \csa{myArray} as a macro with one parameter, such that \csa{myArray\x} +expands to give the |x|th braced thing of this original +list (the argument \texttt{\x} itself is fed to a |\numexpr| by |\myArray|, +and |\myArray| expands in two steps to its output). With |0| as parameter, +\csa{myArray}|{0}| returns the number |M| of elements of the array so that the +successive elements are \csa{myArray}|{1}|, \dots, \csa{myArray}|{M}|. +\centeredline{|\xintAssignArray \xintBezout {1000}{113}\to\Bez|} will set +|\Bez{0}| to \digitstt{\Bez0}, |\Bez{1}| to \digitstt{\Bez1}, |\Bez{2}| to +\digitstt{\Bez2}, |\Bez{3}| to \digitstt{\Bez3}, |\Bez{4}| to +\digitstt{\Bez4}, and |\Bez{5}| to \digitstt{\Bez5}: +\digitstt{(\Bez3)${}\times{}$\Bez1${}-{}$(\Bez4)${}\times{}$\Bez2${}={}$\Bez5.} +This macro is incompatible with expansion-only contexts. + +\csa{xintAssignArray}\MyMarginNote{Changed!} admits now an optional +parameter, for example |\xintAssignArray [e]...|. This means that the +definitions of the macros will be made with |\edef|. The default is +|[]|, which makes the definitions with |\def|. Other possibilities: |[], +[o], [oo], [f]|. Contrarily to \csbxint{Assign} one can not use the |g| +here to make the definitions global. For this, one should rather do +|\xintAssignArray| within a group starting with |\globaldefs 1|. + +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{xintRelaxArray}}\label{xintRelaxArray} + +\csa{xintRelaxArray}\csa{myArray} %\ntype{N} +% +(globally) sets to \csa{relax} all macros which were defined by the previous +\csa{xintAssignArray} with \csa{myArray} as array macro. + +\subsection{\csbh{odef}, \csbh{oodef}, \csbh{fdef}} +\label{odef} +\label{oodef} +\label{fdef} + +\csa{oodef}|\controlsequence {<stuff>}| does +\dverb|@ + \expandafter\expandafter\expandafter\def + \expandafter\expandafter\expandafter\controlsequence + \expandafter\expandafter\expandafter{<stuff>}| + +% +This works only for a single +|\controlsequence|, with no parameter text, even without parameters. An +alternative would be: +\dverb|@ +\def\oodef #1#{\def\oodefparametertext{#1}% + \expandafter\expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\def + \expandafter\expandafter\expandafter\oodefparametertext + \expandafter\expandafter\expandafter }| +% + +\noindent +but it does not allow |\global| as prefix, and, besides, would have anyhow its +use (almost) limited to parameter texts without macro parameter tokens +(except if the expanded thing does not see them, or is designed to deal with +them). + +There is a similar macro |\odef| with only one expansion of the replacement text +|<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 \xinttoolsname finds them currently undefined. They +can be prefixed with |\global|. + + +\subsection{The Quick Sort algorithm illustrated}\label{ssec:quicksort} + +First a completely expandable macro which sorts a list of numbers. The |\QSfull| +macro expands its list argument, which may thus be a macro; its items must +expand to possibly big integers (or also decimal numbers or fractions if using +\xintfracname), but if an item is expressed as a computation, this computation +will be redone each time the item is considered! If the numbers have many digits +(i.e. hundreds of digits...), the expansion of |\QSfull| is fastest if each +number, rather than being explicitely given, is represented as a single token +which expands to it in one step. + +If the interest is only in \TeX{} integers, then one should replace the macros +|\QSMore|, |QSEqual|, |QSLess| with versions using the +\href{http://ctan.org/pkg/etoolbox}{etoolbox} (\LaTeX{} only) |\ifnumgreater|, +|\ifnumequal| and |\ifnumless| conditionals rather than \csbxint{ifGt}, +\csbxint{ifEq}, \csbxint{ifLt}. + +\begingroup\makeatletter\let\check@percent\relax +\def\MacroFont{\small\baselineskip12pt \ttfamily } +\begin{verbatim} +% THE QUICK SORT ALGORITHM EXPANDABLY +\input xintfrac.sty +% HELPER COMPARISON MACROS +\def\QSMore #1#2{\xintifGt {#2}{#1}{{#2}}{ }} +% the spaces are there to stop the \romannumeral-`0 originating +% in \xintapplyunbraced when it applies a macro to an item +\def\QSEqual #1#2{\xintifEq {#2}{#1}{{#2}}{ }} +\def\QSLess #1#2{\xintifLt {#2}{#1}{{#2}}{ }} +% +\makeatletter +\def\QSfull {\romannumeral0\qsfull } +\def\qsfull #1{\expandafter\qsfull@a\expandafter{\romannumeral-`0#1}} +\def\qsfull@a #1{\expandafter\qsfull@b\expandafter {\xintLength {#1}}{#1}} +\def\qsfull@b #1{\ifcase #1 + \expandafter\qsfull@empty + \or\expandafter\qsfull@single + \else\expandafter\qsfull@c + \fi +}% +\def\qsfull@empty #1{ } % the space stops the \QSfull \romannumeral0 +\def\qsfull@single #1{ #1} +% for simplicity of implementation, we pick up the first item as pivot +\def\qsfull@c #1{\qsfull@ci #1\undef {#1}} +\def\qsfull@ci #1#2\undef {\qsfull@d {#1}}% #3 is the list, #1 its first item +\def\qsfull@d #1#2{\expandafter\qsfull@e\expandafter + {\romannumeral0\qsfull + {\xintApplyUnbraced {\QSMore {#1}}{#2}}}% + {\romannumeral0\xintapplyunbraced {\QSEqual {#1}}{#2}}% + {\romannumeral0\qsfull + {\xintApplyUnbraced {\QSLess {#1}}{#2}}}% +}% +\def\qsfull@e #1#2#3{\expandafter\qsfull@f\expandafter {#2}{#3}{#1}}% +\def\qsfull@f #1#2#3{\expandafter\space #2#1#3} +\makeatother +% EXAMPLE +\edef\z {\QSfull {{1.0}{0.5}{0.3}{1.5}{1.8}{2.0}{1.7}{0.4}{1.2}{1.4}% + {1.3}{1.1}{0.7}{1.6}{0.6}{0.9}{0.8}{0.2}{0.1}{1.9}}} +\tt\meaning\z +\def\a {3.123456789123456789}\def\b {3.123456789123456788} +\def\c {3.123456789123456790}\def\d {3.123456789123456787} +\expandafter\def\expandafter\z\expandafter + {\romannumeral0\qsfull {{\a}\b\c\d}}% \a is braced to not be expanded +\meaning\z +\end{verbatim} + +% THE QUICK SORT ALGORITHM EXPANDABLY +\def\QSMore #1#2{\xintifGt {#2}{#1}{{#2}}{ }} +% the spaces stop the \romannumeral-`0 done by \xintapplyunbraced each time +% it applies its macro argument to an item +\def\QSEqual #1#2{\xintifEq {#2}{#1}{{#2}}{ }} +\def\QSLess #1#2{\xintifLt {#2}{#1}{{#2}}{ }} +% +\def\QSfull {\romannumeral0\qsfull } +\def\qsfull #1{\expandafter\qsfull@a\expandafter{\romannumeral-`0#1}} +\def\qsfull@a #1{\expandafter\qsfull@b\expandafter {\xintLength {#1}}{#1}} +\def\qsfull@b #1{\ifcase #1 + \expandafter\qsfull@empty + \or\expandafter\qsfull@single + \else\expandafter\qsfull@c + \fi +}% +\def\qsfull@empty #1{ } % the space stops the \QSfull \romannumeral0 +\def\qsfull@single #1{ #1} +\def\qsfull@c #1{\qsfull@ci #1\undef {#1}} % we pick up the first as Pivot +\def\qsfull@ci #1#2\undef {\qsfull@d {#1}} +\def\qsfull@d #1#2{\expandafter\qsfull@e\expandafter + {\romannumeral0\qsfull + {\xintApplyUnbraced {\QSMore {#1}}{#2}}}% + {\romannumeral0\xintapplyunbraced {\QSEqual {#1}}{#2}}% + {\romannumeral0\qsfull + {\xintApplyUnbraced {\QSLess {#1}}{#2}}}% +}% +\def\qsfull@e #1#2#3{\expandafter\qsfull@f\expandafter {#2}{#3}{#1}}% +\def\qsfull@f #1#2#3{\expandafter\space #2#1#3} +\makeatother +% EXAMPLE +\edef\z {\QSfull {{1.0}{0.5}{0.3}{1.5}{1.8}{2.0}{1.7}{0.4}{1.2}{1.4}% + {1.3}{1.1}{0.7}{1.6}{0.6}{0.9}{0.8}{0.2}{0.1}{1.9}}} +\noindent Output:\par +\texttt{\printnumber{\meaning\z}} + +\def\a {3.123456789123456789}\def\b {3.123456789123456788} +\def\c {3.123456789123456790}\def\d {3.123456789123456787} +\expandafter\def\expandafter\z\expandafter + {\romannumeral0\qsfull {{\a}\b\c\d}}% \a is braced to not be expanded +\texttt{\printnumber{\meaning\z}} +\endgroup + + + +We then turn to a graphical illustration of the algorithm. For simplicity the +pivot is always chosen to be the first list item. We also show later how to +illustrate the variant which picks up the last item of each unsorted +chunk as pivot. + +\begingroup +\makeatletter +\let\check@percent\relax +% il utilise MacroFont +\def\MacroFont{\small\baselineskip 12pt \ttfamily } +\begin{verbatim} +\input xintfrac.sty % if Plain TeX +% +\definecolor{LEFT}{RGB}{216,195,88} +\definecolor{RIGHT}{RGB}{208,231,153} +\definecolor{INERT}{RGB}{199,200,194} +\definecolor{PIVOT}{RGB}{109,8,57} +% +\def\QSMore #1#2{\xintifGt {#2}{#1}{{#2}}{ }}% space will be gobbled +\def\QSEqual #1#2{\xintifEq {#2}{#1}{{#2}}{ }} +\def\QSLess #1#2{\xintifLt {#2}{#1}{{#2}}{ }} +% +\makeatletter +\def\QS@a #1{\expandafter \QS@b \expandafter {\xintLength {#1}}{#1}} +\def\QS@b #1{\ifcase #1 + \expandafter\QS@empty + \or\expandafter\QS@single + \else\expandafter\QS@c + \fi +}% +\def\QS@empty #1{} +\def\QS@single #1{\QSIr {#1}} +\def\QS@c #1{\QS@d #1!{#1}} % we pick up the first as pivot. +\def\QS@d #1#2!{\QS@e {#1}}% #1 = first element, #3 = list +\def\QS@e #1#2{\expandafter\QS@f\expandafter + {\romannumeral0\xintapplyunbraced {\QSMore {#1}}{#2}}% + {\romannumeral0\xintapplyunbraced {\QSEqual {#1}}{#2}}% + {\romannumeral0\xintapplyunbraced {\QSLess {#1}}{#2}}% +}% +\def\QS@f #1#2#3{\expandafter\QS@g\expandafter {#2}{#3}{#1}}% +% Here \QSLr, \QSIr, \QSr have been let to \relax, so expansion stops. +% #2= elements < pivot, #1 = elements = pivot, #3 = elements > pivot +\def\QS@g #1#2#3{\QSLr {#2}\QSIr {#1}\QSRr {#3}}% +% +\def\DecoLEFT #1{\xintFor* ##1 in {#1} \do {\colorbox{LEFT}{##1}}} +\def\DecoINERT #1{\xintFor* ##1 in {#1} \do {\colorbox{INERT}{##1}}} +\def\DecoRIGHT #1{\xintFor* ##1 in {#1} \do {\colorbox{RIGHT}{##1}}} +\def\DecoPivot #1{\begingroup\color{PIVOT}\advance\fboxsep-\fboxrule + \fbox{#1}\endgroup} +\def\DecoLEFTwithPivot #1{% + \xintFor* ##1 in {#1} \do + {\xintifForFirst {\DecoPivot {##1}}{\colorbox{LEFT}{##1}}}% +} +\def\DecoRIGHTwithPivot #1{% + \xintFor* ##1 in {#1} \do + {\xintifForFirst {\DecoPivot {##1}}{\colorbox{RIGHT}{##1}}}% +} +% +\def\QSinitialize #1{\def\QS@list{\QSRr {#1}}% + \let\QSRr\DecoRIGHT +% \QS@list \par +\par\centerline{\QS@list} +} +\def\QSoneStep {\let\QSLr\DecoLEFTwithPivot + \let\QSIr\DecoINERT + \let\QSRr\DecoRIGHTwithPivot +% \QS@list +\centerline{\QS@list} +% \par + \def\QSLr {\noexpand\QS@a}% + \let\QSIr\relax + \def\QSRr {\noexpand\QS@a}% + \edef\QS@list{\QS@list}% + \let\QSLr\relax + \let\QSRr\relax + \edef\QS@list{\QS@list}% + \let\QSLr\DecoLEFT + \let\QSIr\DecoINERT + \let\QSRr\DecoRIGHT +% \QS@list +\centerline{\QS@list} +% \par +} +\begingroup\offinterlineskip +\small +\QSinitialize {{1.0}{0.5}{0.3}{1.5}{1.8}{2.0}{1.7}{0.4}{1.2}{1.4}% + {1.3}{1.1}{0.7}{1.6}{0.6}{0.9}{0.8}{0.2}{0.1}{1.9}} +\QSoneStep +\QSoneStep +\QSoneStep +\QSoneStep +\QSoneStep +\endgroup +\end{verbatim} + +\def\QSMore #1#2{\xintifGt {#2}{#1}{{#2}}{ }}% space will be gobbled +\def\QSEqual #1#2{\xintifEq {#2}{#1}{{#2}}{ }} +\def\QSLess #1#2{\xintifLt {#2}{#1}{{#2}}{ }} +% +\def\QS@a #1{\expandafter \QS@b \expandafter {\xintLength {#1}}{#1}} +\def\QS@b #1{\ifcase #1 + \expandafter\QS@empty + \or\expandafter\QS@single + \else\expandafter\QS@c + \fi +}% +\def\QS@empty #1{} +\def\QS@single #1{\QSIr {#1}} +\def\QS@c #1{\QS@d #1!{#1}} % we pick up the first as pivot. +\def\QS@d #1#2!{\QS@e {#1}}% #1 = first element, #3 = list +\def\QS@e #1#2{\expandafter\QS@f\expandafter + {\romannumeral0\xintapplyunbraced {\QSMore {#1}}{#2}}% + {\romannumeral0\xintapplyunbraced {\QSEqual {#1}}{#2}}% + {\romannumeral0\xintapplyunbraced {\QSLess {#1}}{#2}}% +}% +\def\QS@f #1#2#3{\expandafter\QS@g\expandafter {#2}{#3}{#1}}% +% #2= elements < pivot, #1 = elements = pivot, #3 = elements > pivot +% Here \QSLr, \QSIr, \QSr have been let to \relax, so expansion stops. +\def\QS@g #1#2#3{\QSLr {#2}\QSIr {#1}\QSRr {#3}}% +% +\def\DecoLEFT #1{\xintFor* ##1 in {#1} \do {\colorbox{LEFT}{##1}}} +\def\DecoINERT #1{\xintFor* ##1 in {#1} \do {\colorbox{INERT}{##1}}} +\def\DecoRIGHT #1{\xintFor* ##1 in {#1} \do {\colorbox{RIGHT}{##1}}} +\def\DecoPivot #1{\begingroup\color{PIVOT}\advance\fboxsep-\fboxrule + \fbox{#1}\endgroup} +\def\DecoLEFTwithPivot #1{% + \xintFor* ##1 in {#1} \do + {\xintifForFirst {\DecoPivot {##1}}{\colorbox{LEFT}{##1}}}% +} +\def\DecoRIGHTwithPivot #1{% + \xintFor* ##1 in {#1} \do + {\xintifForFirst {\DecoPivot {##1}}{\colorbox{RIGHT}{##1}}}% +} +% +\def\QSinitialize #1{\def\QS@list{\QSRr {#1}}% + \let\QSRr\DecoRIGHT +% \QS@list \par +\par\centerline{\QS@list} +} +\def\QSoneStep {\let\QSLr\DecoLEFTwithPivot + \let\QSIr\DecoINERT + \let\QSRr\DecoRIGHTwithPivot +% \QS@list +\centerline{\QS@list} +% \par + \def\QSLr {\noexpand\QS@a}% + \let\QSIr\relax + \def\QSRr {\noexpand\QS@a}% + \edef\QS@list{\QS@list}% + \let\QSLr\relax + \let\QSRr\relax + \edef\QS@list{\QS@list}% + \let\QSLr\DecoLEFT + \let\QSIr\DecoINERT + \let\QSRr\DecoRIGHT +% \QS@list +\centerline{\QS@list} +% \par +} + +\phantomsection\label{quicksort} +\begingroup\offinterlineskip +\small +\QSinitialize {{1.0}{0.5}{0.3}{1.5}{1.8}{2.0}{1.7}{0.4}{1.2}{1.4}% + {1.3}{1.1}{0.7}{1.6}{0.6}{0.9}{0.8}{0.2}{0.1}{1.9}} +\QSoneStep +\QSoneStep +\QSoneStep +\QSoneStep +\QSoneStep +\endgroup + + +If one wants rather to have the pivot from the end of the yet to sort chunks, +then one should use the following variants: +\begin{verbatim} +\def\QS@c #1{\expandafter\QS@e\expandafter + {\romannumeral0\xintnthelt {-1}{#1}}{#1}% +}% +\def\DecoLEFTwithPivot #1{% + \xintFor* ##1 in {#1} \do + {\xintifForLast {\DecoPivot {##1}}{\colorbox{LEFT}{##1}}}% +} +\def\DecoRIGHTwithPivot #1{% + \xintFor* ##1 in {#1} \do + {\xintifForLast {\DecoPivot {##1}}{\colorbox{RIGHT}{##1}}}% +} +\def\QSinitialize #1{\def\QS@list{\QSLr {#1}}% + \let\QSLr\DecoLEFT +% \QS@list \par +\par\centerline{\QS@list} +} +\end{verbatim} +\def\QS@c #1{\expandafter\QS@e\expandafter + {\romannumeral0\xintnthelt {-1}{#1}}{#1}% +}% +\def\DecoLEFTwithPivot #1{% + \xintFor* ##1 in {#1} \do + {\xintifForLast {\DecoPivot {##1}}{\colorbox{LEFT}{##1}}}% +} +\def\DecoRIGHTwithPivot #1{% + \xintFor* ##1 in {#1} \do + {\xintifForLast {\DecoPivot {##1}}{\colorbox{RIGHT}{##1}}}% +} +\def\QSinitialize #1{\def\QS@list{\QSLr {#1}}% + \let\QSLr\DecoLEFT +% \QS@list \par +\par\centerline{\QS@list} +} +\begingroup\offinterlineskip +\small +\QSinitialize {{1.0}{0.5}{0.3}{1.5}{1.8}{2.0}{1.7}{0.4}{1.2}{1.4}% + {1.3}{1.1}{0.7}{1.6}{0.6}{0.9}{0.8}{0.2}{0.1}{1.9}} +\QSoneStep +\QSoneStep +\QSoneStep +\QSoneStep +\QSoneStep +\QSoneStep +\QSoneStep +\QSoneStep +\QSoneStep +\QSoneStep +\endgroup + +\endgroup + +It is possible to modify this code to let it do \csa{QSonestep} repeatedly and +stop automatically when the sort is finished.\footnote{\url{http://tex.stackexchange.com/a/142634/4686}} + + +\section{Commands of the \xintname package} +\label{sec:xint} + + +In the description of the macros \texttt{\n} and \texttt{\m} stand for (long) +numbers within braces or for a control sequence possibly within braces and +\hyperref[sec:expansions]{\fexpan ding} to such a number (without the braces!), +or for material within braces which \fexpan ds to such a number, as is +acceptable on input by the \csbxint{Num} macro: a sequence of plus and minus +signs, followed by some string of zeroes, followed by digits. The margin +annotation for such an argument which is parsed by \csbxint{Num} is +\textcolor[named]{PineGreen}{\Numf}. Sometimes however only a +\textcolor[named]{PineGreen}{\emph{f}} symbol appears in the margin, signaling +that the input will not be parsed via \csbxint{Num}. + +The letter \texttt{x} (with margin annotation +\textcolor[named]{PineGreen}{\numx}) stands for something which will be inserted +in-between a |\numexpr| and a |\relax|. It will thus be completely expanded and +must give an integer obeying the \TeX{} bounds. Thus, it may be for example a +count register, or itself a \csa{numexpr} expression, or just a number written +explicitely with digits or something like |4*\count 255 + 17|, etc... + +For the rules regarding direct use of count registers or \csa{numexpr} +expression, in the argument to the package macros, see the +\hyperref[sec:useofcount]{Use of count} section. + +Some of these macros are extended by \xintfracname to accept fractions +on input, and, generally, to output a fraction. But this means that +additions, subtractions, multiplications output in fraction format; to +guarantee the integer format on output when the inputs are integers, the +original integer-only macros \csa{xintAdd}, \csa{xintSub}, +\csa{xintMul}, etc\dots are available under the names \csa{xintiAdd}, +\csa{xintiSub}, \csa{xintiMul}, \dots, also when \xintfracname is not +loaded. Even these originally integer-only macros will accept fractions +on input if \xintfracname is loaded as long as they are integers in +disguise; they produce on output integers without any forward +slash mark nor trailing |[n]|. + +But |\xintAdd| will output fractions |A/B[n]|, with |B| present even if its +value is one. See the \xintfracname \hyperref[sec:frac]{documentation} for +additional information. + +% on how macros of \xintname are modified after loading +% \xintfracname (or \xintexprname). + + +% \xintfracname will extend \csbxint{Num} for it to remove this unit +% denominator and convert the |[n]| part into explicit zeros; see also +% \csbxint{PRaw} which does not make the assumption that the fraction is an +% integer in disguise. + +% This is mandatory when the computation result is fetched +% into a context where \TeX{} expects a number (assuming it does not exceed +% @2^31@). See the also the \xintfracname \hyperref[sec:frac]{documentation} for +% more information on how macros of \xintname are modified after loading +% \xintfracname (or \xintexprname). + + +% Package \xintname also provides some general macro programming or token +% manipulation utilities (expandable as well as non-expandable), which are +% described in the next section (\autoref{sec:tools}). + +\localtableofcontents + +\subsection{\csbh{xintRev}} \label{xintRev} + +\csa{xintRev\n}\etype{f} will revert 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. +\centeredline{|\xintRev{-123000}|\digitstt{=\xintRev{-123000}}} +\centeredline{|\xintNum{\xintRev{-123000}}|% + \digitstt{=\xintNum{\xintRev{-123000}}}} + + +\subsection{\csbh{xintLen}}\label{xintiLen} + +\csa{xintLen\n}\etype{\Numf} returns the length of the number, not counting the +sign. \centeredline{|\xintLen{-12345678901234567890123456789}|\digitstt + {=\xintLen{-12345678901234567890123456789}}} Extended by \xintfracname to +fractions: the length of |A/B[n]| is the length of |A| plus the +length of |B| plus the absolute value of |n| and minus one (an integer input as +|N| is internally represented in a form equivalent to |N/1[0]| so the minus one +means that the extended \csa{xintLen} behaves the same as the original for +integers). \centeredline{|\xintLen{-1e3/5.425}|\digitstt + {=\xintLen{-1e3/5.425}}} The length is computed on the |A/B[n]| which would +have been returned by \csbxint{Raw}: |\xintRaw {-1e3/5.425}|\digitstt{=\xintRaw + {-1e3/5.425}}. + +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 +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 +\centeredline{|\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{xintNum}}\label{xintiNum} + +\csa{xintNum\n}\etype{f} removes chains of plus or minus signs, followed by +zeroes. \centeredline{|\xintNum{+---++----+--000000000367941789479}|\digitstt + {=\xintNum{+---++----+--000000000367941789479}}} Extended by \xintfracname to +accept also a fraction on input, as long as it reduces to an integer after +division of the numerator by the denominator. +\centeredline{|\xintNum{123.48/-0.03}|\digitstt{=\xintNum{123.48/-0.03}}} + + +\subsection{\csbh{xintSgn}}\label{xintiiSgn} + +\csa{xintSgn\n}\etype{\Numf} returns 1 if the number is positive, 0 if it is +zero and -1 if it is negative. Extended by \xintfracname to fractions. +\csbxint{iiSgn} skips the \csbxint{Num} overhead.\etype{f} + +\subsection{\csbh{xintOpp}}\label{xintiOpp}\label{xintiiOpp} + +\csa{xintOpp\n}\etype{\Numf} return the opposite |-N| of the number |N|. +Extended by \xintfracname to fractions. \csa{xintiOpp} is a synonym not modified +by \xintfracname\footnote{here, and in all similar instances, this means that + the macro remains integer-only both on input and output, but it does accept on + input a fraction which in disguise is a (big) integer.}, and +\csa{xintiiOpp} skips the \csbxint{Num} overhead.\etype{f} + + +\subsection{\csbh{xintAbs}}\label{xintiAbs}\label{xintiiAbs} + +\csa{xintAbs\n}\etype{\Numf} returns the absolute value of the number. Extended +by \xintfracname to fractions. \csa{xintiAbs} is a synonym not modified +by \xintfracname, and \csa{xintiiAbs} skips the \csbxint{Num} overhead.\etype{f} + + +\subsection{\csbh{xintAdd}}\label{xintiAdd}\label{xintiiAdd} + +\csa{xintAdd\n\m}\etype{\Numf\Numf} returns the sum of the two numbers. Extended +by \xintfracname to fractions. \csa{xintiAdd} is a synonym not modified by +\xintfracname, and \csa{xintiiAdd} skips the \csbxint{Num} overhead.\etype{ff} + + + +\subsection{\csbh{xintSub}}\label{xintiSub}\label{xintiiSub} + +\csa{xintSub\n\m}\etype{\Numf\Numf} returns the difference |N-M|. Extended +by \xintfracname to fractions. \csa{xintiSub} is a synonym not modified by +\xintfracname, and \csa{xintiiSub} skips the \csbxint{Num} overhead.\etype{ff} + + +\subsection{\csbh{xintCmp}}\label{xintiCmp} + +\csa{xintCmp\n\m}\etype{\Numf\Numf} returns 1 if |N>M|, 0 if |N=M|, and -1 +if |N<M|. Extended by \xintfracname to fractions. + +\subsection{\csbh{xintEq}}\label{xintEq} +%{\small New with release |1.09a|.\par} + +\csa{xintEq\n\m}\etype{\Numf\Numf} returns 1 if |N=M|, 0 otherwise. Extended +by \xintfracname to fractions. + +\subsection{\csbh{xintGt}}\label{xintGt} +%{\small New with release |1.09a|.\par} + +\csa{xintGt\n\m}\etype{\Numf\Numf} returns 1 if |N|$>$|M|, 0 otherwise. +Extended by \xintfracname to fractions. + +\subsection{\csbh{xintLt}}\label{xintLt} +%{\small New with release |1.09a|.\par} + +\csa{xintLt\n\m}\etype{\Numf\Numf} returns 1 if |N|$<$|M|, 0 otherwise. +Extended by \xintfracname to fractions. + +\subsection{\csbh{xintIsZero}}\label{xintIsZero} +%{\small New with release |1.09a|.\par} + +\csa{xintIsZero\n}\etype{\Numf} returns 1 if |N=0|, 0 otherwise. +Extended by \xintfracname to fractions. + +\subsection{\csbh{xintNot}}\label{xintNot} +%{\small New with release |1.09c|.\par} + +\csa{xintNot}\etype{\Numf} is a synonym for \csa{xintIsZero}. + +\subsection{\csbh{xintIsNotZero}}\label{xintIsNotZero} +%{\small New with release |1.09a|.\par} + +\csa{xintIsNotZero\n}\etype{\Numf} returns 1 if |N<>0|, 0 otherwise. +Extended by \xintfracname to fractions. + +\subsection{\csbh{xintIsOne}}\label{xintIsOne} +%{\small New with release |1.09a|.\par} + +\csa{xintIsOne\n}\etype{\Numf} returns 1 if |N=1|, 0 otherwise. +Extended by \xintfracname to fractions. + +\subsection{\csbh{xintAND}}\label{xintAND} +%{\small New with release |1.09a|.\par} + +\csa{xintAND\n\m}\etype{\Numf\Numf} returns 1 if |N<>0| and |M<>0| and zero +otherwise. Extended by \xintfracname to fractions. + +\subsection{\csbh{xintOR}}\label{xintOR} +%{\small New with release |1.09a|.\par} + +\csa{xintOR\n\m}\etype{\Numf\Numf} returns 1 if |N<>0| or |M<>0| and zero +otherwise. Extended by \xintfracname to fractions. + + +\subsection{\csbh{xintXOR}}\label{xintXOR} +%{\small New with release |1.09a|.\par} + +\csa{xintXOR\n\m}\etype{\Numf\Numf} returns 1 if exactly one of |N| or |M| +is true (i.e. non-zero). Extended by \xintfracname to fractions. + +\subsection{\csbh{xintANDof}}\label{xintANDof} +%{\small New with release |1.09a|.\par} + +\csa{xintANDof}|{{a}{b}{c}...}|\etype{f{$\to$}\lowast\Numf} returns 1 if all +are true (i.e. non zero) and zero otherwise. The list argument may be a macro, +it (or rather its first token) is \fexpan ded first (each item also is \fexpan +ded). Extended by \xintfracname to fractions. + +\subsection{\csbh{xintORof}}\label{xintORof} +%{\small New with release |1.09a|.\par} + +\csa{xintORof}|{{a}{b}{c}...}|\etype{f{$\to$}\lowast\Numf} returns 1 if at +least one is true (i.e. does not vanish). The list argument may be a macro, it +is \fexpan ded first. Extended by \xintfracname to fractions. + + +\subsection{\csbh{xintXORof}}\label{xintXORof} +%{\small New with release |1.09a|.\par} + +\csa{xintXORof}|{{a}{b}{c}...}|\etype{f{$\to$}\lowast\Numf} returns 1 if an odd +number of them are true (i.e. does not vanish). The list argument may be a +macro, it is \fexpan ded first. Extended by \xintfracname to fractions. + + +\subsection{\csbh{xintGeq}}\label{xintiGeq} + +\csa{xintGeq\n\m}\etype{\Numf\Numf} returns 1 if the \emph{absolute value} +of the first number is at least equal to the absolute value of the second +number. If \verb+|N|<|M|+ it returns 0. Extended by \xintfracname to fractions. +%(starting with release |1.07|) +Please note that the macro compares +\emph{absolute values}. + +\subsection{\csbh{xintMax}}\label{xintiMax} + +\csa{xintMax\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}|\digitstt{=\xintiMax{-5}{-6}}. Extended by \xintfracname to +fractions. \csa{xintiMax} is a synonym not modified by +\xintfracname. + +\subsection{\csbh{xintMaxof}}\label{xintMaxof} +%{\small New with release |1.09a|.\par} + +\csa{xintMaxof}|{{a}{b}{c}...}|\etype{f{$\to$}\lowast\Numf} returns the maximum. +The list argument may be a macro, it is \fexpan ded first. Extended by +\xintfracname to fractions. \csa{xintiMaxof} is a +synonym not modified by \xintfracname. + + +\subsection{\csbh{xintMin}}\label{xintiMin} + +\csa{xintMin\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}|\digitstt{=\xintiMin{-5}{-6}}. Extended by \xintfracname to fractions. +\csa{xintiMin} is a synonym not modified by +\xintfracname. + +\subsection{\csbh{xintMinof}}\label{xintMinof} +%{\small New with release |1.09a|.\par} + +\csa{xintMinof}|{{a}{b}{c}...}|\etype{f{$\to$}\lowast\Numf} returns the minimum. +The list argument may be a macro, it is \fexpan ded first. Extended by +\xintfracname to fractions. \csa{xintiMinof} is a synonym not modified by +\xintfracname. + + +\subsection{\csbh{xintSum}}\label{xintiiSum} + +\csa{xintSum}\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. +Note: the summands are \emph{not} parsed by \csbxint{Num}. + +\csa{xintSum} is +extended by \xintfracname to fractions. The original, which accepts (after +\fexpan sion) only (big) integers in the strict format and produces a (big) +integer is available as \csa{xintiiSum}, also with \xintfracname loaded. + +\centeredline{% + \csa{xintiiSum}|{{123}{-98763450}{\xintFac{7}}{\xintiMul{3347}{591}}}|% + \digitstt{=\xintiiSum{{123}{-98763450}{\xintFac{7}}{\xintiMul{3347}{591}}}}} +\centeredline{\csa{xintiiSum}|{1234567890}|\digitstt{=\xintiiSum{1234567890}}} +An empty sum is no error and returns zero: |\xintiiSum +{}|\digitstt{=\xintiiSum {}}. A sum with only one term returns that +number: |\xintiiSum {{-1234}}|\digitstt{=\xintiiSum {{-1234}}}. +Attention that |\xintiiSum {-1234}| is not legal input and will make the +\TeX{} run fail. On the other hand |\xintiiSum +{1234}|\digitstt{=\xintiiSum{1234}}. Extended by \xintfracname to +fractions. + +% retiré de la doc le 22 octobre 2013 + +% \subsection{\csbh{xintSumExpr}}\label{xintiiSumExpr} + +% \csa{xintSumExpr}\meta{braced things}\csa{relax} is to what \csa{xintSum} +% expands. The argument is then expanded (with the usual meaning) and should give +% a list of braced quantities or macros, each one will be expanded in turn. +% \centeredline{% +% \csa{xintiiSumExpr}| {123}{-98763450}|% +% |{\xintFac{7}}{\xintiMul{3347}{591}}\relax|\digitstt{=% +% \xintiiSumExpr {123}{-98763450}{\xintFac{7}}{\xintiMul{3347}{591}}\relax}} + +% Note: I am not so happy with the name which seems to suggest that the +% |+| sign should be used instead of braces. Perhaps this will change +% in the future. + +% Extended by \xintfracname to fractions. + +\subsection{\csbh{xintMul}}\label{xintiMul}\label{xintiiMul} +%{\small Modified in release |1.03|.\par} + +\csa{xintMul\n\m}\etype{\Numf\Numf} returns the product of the two numbers. +% Starting with release |1.03| of \xintname, the macro checks the lengths of the +% two numbers and then activates its algorithm with the best (or at least, +% hoped-so) choice of which one to put first. This makes the macro a bit slower +% for numbers up to 50 digits, but may give substantial speed gain when one of the +% number has 100 digits or more. +Extended by \xintfracname to fractions. +\csa{xintiMul} is a synonym not modified by \xintfracname, and +\csa{xintiiMul} skips the \csbxint{Num} overhead.\etype{ff} + +\subsection{\csbh{xintSqr}}\label{xintiSqr}\label{xintiiSqr} + +\csa{xintSqr\n}\etype{\Numf} returns the square. Extended by \xintfracname to +fractions. \csa{xintiSqr} is a synonym not modified by +\xintfracname, and \csa{xintiiSqr} skips the \csbxint{Num} overhead.\etype{f} + + + +\subsection{\csbh{xintPrd}}\label{xintiiPrd} + +\csa{xintPrd}\marg{braced things}\etype{{\lowast f}} after expanding its +argument expects to find a sequence of (of braced items or unbraced +single tokens). Each is +expanded (with the usual meaning), and the product of all these numbers is +returned. Note: the operands are \emph{not} parsed by \csbxint{Num}. +\centeredline{% + \csa{xintiiPrd}|{{-9876}{\xintFac{7}}{\xintiMul{3347}{591}}}|% + \digitstt{=% + \xintiiPrd{{-9876}{\xintFac{7}}{\xintiMul{3347}{591}}}}} +\centeredline{\csa{xintiiPrd}|{123456789123456789}|\digitstt{=% + \xintiiPrd{123456789123456789}}} An empty product is no error and returns 1: +|\xintiiPrd {}|\digitstt{=\xintiiPrd {}}. A product reduced to a single term +returns this number: |\xintiiPrd {{-1234}}|\digitstt{=\xintiiPrd {{-1234}}}. +Attention that |\xintiiPrd {-1234}| is not legal input and will make the \TeX{} +compilation fail. On the other hand |\xintiiPrd {1234}|\digitstt{=\xintiiPrd + {1234}}. \centeredline{$\displaystyle 2^{200}3^{100}7^{100}$} +\centeredline{|=\xintiiPrd {{\xintiPow {2}{200}}{\xintiPow {3}{100}}{\xintiPow + {7}{100}}}|} +\digitstt{=\printnumber{\xintNum {\xinttheexpr + 2^200*3^100*7^100\relax }}} + +With \xintexprname, the above could be coded simply as \centeredline +{|\xinttheiiexpr 2^200*3^100*7^100\relax |} + +Extended by \xintfracname to fractions. The original, which accepts (after +\fexpan sion) only (big) integers in the strict format and produces a (big) +integer is available as \csbxint{iiPrd}, also with \xintfracname loaded. + + +% I temporarily remove mention of \xintPrdExpr from the documentation; I +% really dislike the name now. + +% \subsection{\csbh{xintPrdExpr}}\label{xintiiPrdExpr} + +% {\small Name change in |1.06a|! I apologize, but I suddenly decided that +% \csa{xintProductExpr} was a bad choice; so I just replaced it by the current +% name. \par} + +% \csa{xintPrdExpr}\marg{argument}\csa{relax} is to what \csa{xintPrd} expands +% ; its argument is expanded (with the usual meaning) and should give a list of +% braced numbers or macros. Each will be expanded when it is its turn. +% \centeredline{\csa{xintiiPrdExpr}| 123456789123456789\relax|\digitstt{=% +% \xintiiPrdExpr 123456789123456789\relax}} + +% Note: I am not so happy with the name which seems to suggest that the +% |*| sign should be used instead of braces. Perhaps this will change +% in the future. + +% Extended by \xintfracname to fractions. + +\subsection{\csbh{xintPow}}\label{xintiPow}\label{xintiiPow} + +\csa{xintPow\n\x}\etype{\Numf\numx} returns |N^x|. When |x| is zero, this is 1. +If |N| is zero and |x<0|, if \verb+|N|>1+ and |x<0| negative, or if \verb+|N|>1+ +and |x>100000|,\MyMarginNote{Changed!} then an error is raised. Indeed |2^50000| +already has \digitstt{\xintLen{\xintFloatPow [1]{2}{50000}}} digits; each exact +multiplication of two one thousand digits numbers already takes a few seconds, +and it would take hours for the expandable computation to conclude with two +numbers with each circa @15000@ digits. Perhaps some completely expandable but +not \fexpan dable variants could fare better? + +Extended by \xintfracname to fractions (\csbxint{Pow}) and to floats +(\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 cause errors anymore. The float +version is able to deal with things such as |2^999999999| without any problem. +For example |\xintFloatPow[4]{2}{50000}|\digitstt{=\xintFloatPow[4]{2}{50000}} +and |\xintFloatPow[4]{2}{999999999}| +\digitstt{=\xintFloatPow[4]{2}{999999999}}.\footnote{On my laptop + |\string\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$\digitstt{9999}.} + +\csa{xintiPow} is a synonym not modified by \xintfracname, and \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. + +Within an \csbxint{iiexpr}|..\relax| the infix operator |^| is mapped to +\csa{xintiiPow}; within an \csbxint{expr}-ession\MyMarginNote{corr. of the + previous doc.} it is mapped to \csbxint{Pow} +(as extended by \xintfracname); in \csbxint{floatexpr}, it is mapped to +\csbxint{FloatPower}. + + + + +\subsection{\csbh{xintSgnFork}}\label{xintSgnFork} +%{\small New with release |1.07|. See also \csbxint{ifSgn}.\par} + +\csa{xintSgnFork}\verb+{-1|0|1}+\marg{A}\marg{B}\marg{C}\etype{xnnn} expandably +chooses to execute either the \meta{A}, \meta{B} or \meta{C} code, +depending on its first argument. This first argument should be anything +expanding to either |-1|, |0| or |1| (a count register must be +prefixed by |\the| and a |\numexpr...\relax| also must be prefixed by +|\the|). This utility is provided to help construct expandable macros +choosing depending on a condition which one of the package macros to +use, or which values to confer to their arguments. + +\subsection{\csbh{xintifSgn}}\label{xintifSgn} +%{\small New with release |1.09a|.\par} + +Similar to \csa{xintSgnFork}\etype{\Numf nnn} except that the first argument may +expand to a (big) integer (or a fraction if \xintfracname is loaded), and it is +its sign which decides which of the three branches is taken. Furthermore this +first argument may be a count register, with no |\the| or |\number| prefix. + +\subsection{\csbh{xintifZero}}\label{xintifZero} +%{\small New with release |1.09a|.\par} + +\csa{xintifZero}\marg{N}\marg{IsZero}\marg{IsNotZero}\etype{\Numf nn} expandably +checks if the first mandatory argument |N| (a number, possibly a fraction if +\xintfracname is loaded, or a macro expanding to one such) is zero or not. It +then either executes the first or the second branch. Beware that both branches +must be present. + +\subsection{\csbh{xintifNotZero}}\label{xintifNotZero} +%{\small New with release |1.09a|.\par} + +\csa{xintifNotZero}\marg{N}\marg{IsNotZero}\marg{IsZero}\etype{\Numf nn} +expandably checks if the first mandatory argument |N| (a number, possibly a +fraction if \xintfracname is loaded, or a macro expanding to one such) is not +zero or is zero. It then either executes the first or the second branch. Beware +that both branches must be present. + +\subsection{\csbh{xintifOne}}\label{xintifOne} +%{\small New with release |1.09i|.\par} + +\csa{xintifOne}\marg{N}\marg{IsOne}\marg{IsNotOne}\etype{\Numf nn} expandably +checks if the first mandatory argument |N| (a number, possibly a fraction if +\xintfracname is loaded, or a macro expanding to one such) is one or not. It +then either executes the first or the second branch. Beware that both branches +must be present. + + +\subsection{\csbh{xintifTrueAelseB}, \csbh{xint\-ifFalseAelseB}} +\label{xintifTrueAelseB} +\label{xintifFalseAelseB} + +%\label{xintifFalseTrue} +%{\small New with release |1.09c|, renamed in |1.09e|.\par} + +\csa{xintifTrueAelseB}\marg{N}\marg{true branch}\marg{false branch}\etype{\Numf + nn} is a synonym for \csbxint{ifNotZero}. + +{\small +\noindent 1. with |1.09i|, the synonyms |\xintifTrueFalse| and |\xintifTrue| are + deprecated + and will be removed in next release.\par +\noindent 2. These macros have no lowercase versions, use |\xintifzero|, +|\xintifnotzero|.\par } + +\csa{xintifFalseAelseB}\marg{N}\marg{false branch}\marg{true branch}\etype{\Numf + nn} is a synonym for \csbxint{ifZero}. + + + + +\subsection{\csbh{xintifCmp}}\label{xintifCmp} +%{\small New with release |1.09e|.\par} + +\csa{xintifCmp}\marg{A}\marg{B}\marg{if A<B}\marg{if A=B}\marg{if + A>B}\etype{\Numf\Numf nnn} compares +its arguments and chooses accordingly the correct branch. + +\subsection{\csbh{xintifEq}}\label{xintifEq} +%{\small New with release |1.09a|.\par} + +\csa{xintifEq}\marg{A}\marg{B}\marg{YES}\marg{NO}\etype{\Numf\Numf nn} +checks equality of its two first arguments (numbers, or fractions if +\xintfracname is loaded) and does the |YES| or the |NO| branch. + +\subsection{\csbh{xintifGt}}\label{xintifGt} +%{\small New with release |1.09a|.\par} + +\csa{xintifGt}\marg{A}\marg{B}\marg{YES}\marg{NO}\etype{\Numf\Numf nn} checks if +$A>B$ and in that case executes the |YES| branch. Extended to fractions (in +particular decimal numbers) by \xintfracname. + +\subsection{\csbh{xintifLt}}\label{xintifLt} +%{\small New with release |1.09a|.\par} + +\csa{xintifLt}\marg{A}\marg{B}\marg{YES}\marg{NO}\etype{\Numf\Numf nn} +checks if $A<B$ and in that case executes the |YES| branch. Extended to +fractions (in particular decimal numbers) by \xintfracname. + +\begin{framed} + The macros described next are all integer-only on input. With \xintfracname + loaded their argument is first given to \csbxint{Num} and may thus be + a fraction, as long as it is in fact an integer in disguise. +\end{framed} + +\subsection{\csbh{xintifOdd}}\label{xintifOdd} +%{\small New with release |1.09e|.\par} + +\csa{xintifOdd}\marg{A}\marg{YES}\marg{NO}\etype{\Numf nn} checks if $A$ is and +odd integer and in that case executes the |YES| branch. + + +\subsection{\csbh{xintFac}}\label{xintiFac} + +\csa{xintFac\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. + +With \xintfracname loaded, the macro is modified to accept a fraction as +argument, as long as this fraction turns out to be an integer: |\xintFac +{66/3}|\digitstt{=\xintFac {66/3}}. \csa{xintiFac} is a synonym not modified by +the loading of \xintfracname. + +% the construct |\xintFac{\xintAdd {2}{3}}| will fail, +% use either |\xintFac{\xintiAdd {2}{3}}| or |\xintFac{\xintNum{\xintAdd +% {2}{3}}}|. + +% temps obsolètes, mettre à jour +% 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 +% @3000!@ (which has 9131 digits) needs close to seven minutes\dots +% I have no idea how much time @10000!@ would need (do rather +% @9999!@ if you can, the algorithm has some overhead at the +% 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. + +\subsection{\csbh{xintDivision}}\label{xintDivision}\label{xintiiDivision} + +\csa{xintDivision\n\m}\etype{\Numf\Numf} returns |{quotient Q}{remainder R}|. +This is euclidean division: |N = QM + R|, |0|${}\leq{}$\verb+R < |M|+. So the +remainder is always non-negative and the formula |N = QM + R| always holds +independently of the signs of |N| or |M|. Division by zero is an error (even if +|N| vanishes) and returns |{0}{0}|. The variant \csa{xintiiDivision}\etype{ff} +skips the overhead of parsing via \csbxint{Num}. + +This macro is integer only (with \xintfracname loaded it accepts +fractions on input, but they must be integers in disguise) and not to be +confused with the \xintfracname macro \csbxint{Div} which divides one +fraction by another. + +\subsection{\csbh{xintQuo}}\label{xintQuo}\label{xintiiQuo} + +\csa{xintQuo\n\m}\etype{\Numf\Numf} returns the quotient from the euclidean +division. When both |N| and |M| are positive one has +\csa{xintQuo\n\m}|=\xintiTrunc {0}{N/M}| (using package \xintfracname). With +\xintfracname loaded it accepts fractions on input, but they must be integers in +disguise. The variant \csa{xintiiQuo}\etype{ff} +skips the overhead of parsing via \csbxint{Num}. + +\subsection{\csbh{xintRem}}\label{xintRem}\label{xintiiRem} + +\csa{xintRem\n\m}\etype{\Numf\Numf} returns the remainder from the euclidean +division. With \xintfracname loaded it accepts fractions on input, but they must +be integers in disguise. The variant \csa{xintiiRem}\etype{ff} +skips the overhead of parsing via \csbxint{Num}. + + +\subsection{\csbh{xintFDg}}\label{xintFDg}\label{xintiiFDg} + +\csa{xintFDg\n}\etype{\Numf} returns the first digit (most significant) of the +decimal expansion. The variant \csa{xintiiFDg}\etype{f} +skips the overhead of parsing via \csbxint{Num}. + +\subsection{\csbh{xintLDg}}\label{xintLDg}\label{xintiiLDg} + +\csa{xintLDg\n}\etype{\Numf} returns the least significant digit. When the +number is positive, this is the same as the remainder in the euclidean division +by ten. The variant \csa{xintiiLDg}\etype{f} +skips the overhead of parsing via \csbxint{Num}. + +\subsection{\csbh{xintMON}, \csbh{xintMMON}} +\label{xintMON}\label{xintMMON}\label{xintiiMON}\label{xintiiMMON} +%{\small New in version |1.03|.\par} + +\csa{xintMON\n}\etype{\Numf} returns |(-1)^N| and \csa{xintMMON\n} returns +|(-1)^{N-1}|. \centeredline{|\xintMON {-280914019374101929}|\digitstt{=\xintMON + {280914019374101929}}, |\xintMMON {-280914019374101929}|\digitstt{=\xintMMON + {280914019374101929}}} +The variants \csa{xintiiMON}\etype{f} and \csa{xintiiMMON} +skip the overhead of parsing via \csbxint{Num}. + +\subsection{\csbh{xintOdd}}\label{xintOdd}\label{xintiiOdd} + +\csa{xintOdd\n}\etype{\Numf} is 1 if the number is odd and 0 otherwise. The +variant \csa{xintiiOdd} skip the overhead of parsing via \csbxint{Num}.\etype{f} + + + +\subsection{\csbh{xintiSqrt}, \csbh{xintiSquareRoot}}\label{xintiSqrt} +\label{xintiSquareRoot} +%{\small New with |1.08|.\par} + +\xintAssign\xintiSquareRoot {17000000000000000000000000}\to\A\B + +\noindent\csa{xintiSqrt\n}\etype{\Numf} returns the largest integer whose +square is at most equal to |N|. \centeredline{|\xintiSqrt + {2000000000000000000000000000000000000}=|% + \digitstt{\xintiSqrt{2000000000000000000000000000000000000}}} +\centeredline{|\xintiSqrt {3000000000000000000000000000000000000}=|% + \digitstt{\xintiSqrt{3000000000000000000000000000000000000}}} +\centeredline{|\xintiSqrt {\xintDSH {-120}{2}}=|}% +\centeredline{\digitstt{\xintiSqrt {\xintDSH {-120}{2}}}} +\csa{xintiSquareRoot\n}\etype{\Numf} returns |{M}{d}| with |d>0|, |M^2-d=N| and +|M| smallest (hence |=1+|\csa{xint\-iSqrt}|{N}|). +\centeredline{|\xintAssign\xintiSquareRoot + {17000000000000000000000000}\to\A\B|}% +\centeredline{|\xintiSub{\xintiSqr\A}\B=\A^2-\B|}% +\centeredline{\digitstt{\xintiSub{\xintiSqr\A}\B=\A\string^2-\B}} A rational +approximation to $\sqrt{|N|}$ is $|M|-\frac{|d|}{|2M|}$ (this is a majorant and +the error is at most |1/2M|; if |N| is a perfect square |k^2| then |M=k+1| and +this gives |k+1/(2k+2)|, not |k|). + +Package \xintfracname has \csbxint{FloatSqrt} for square +roots of floating point numbers. + + +\begin{framed} + The macros described next are strictly for integer-only arguments. These + arguments are \emph{not} filtered via \csbxint{Num}. +\end{framed} + +\subsection{\csbh{xintInc}, \csbh{xintDec}} +\label{xintInc} +\label{xintDec} +%{\small New with |1.08|.\par} + +\csa{xintInc\n}\etype{f} is |N+1| and \csa{xintDec\n} is |N-1|. These macros +remain integer-only, even with \xintfracname loaded. + +\subsection{\csbh{xintDouble}, \csbh{xintHalf}} +\label{xintDouble} +\label{xintHalf} +%{\small New with |1.08|.\par} + +\csa{xintDouble\n}\etype{f} returns |2N| and \csa{xintHalf\n} is |N/2| rounded +towards zero. These macros remain integer-only, even with \xintfracname loaded. + +\subsection{\csbh{xintDSL}}\label{xintDSL} + +\csa{xintDSL\n}\etype{f} is decimal shift left, \emph{i.e.} multiplication by +ten. + +\subsection{\csbh{xintDSR}}\label{xintDSR} + +\csa{xintDSR\n}\etype{f} is decimal shift right, \emph{i.e.} it removes the last +digit (keeping the sign), equivalently it is the closest integer to |N/10| when +starting at zero. + +\subsection{\csbh{xintDSH}}\label{xintDSH} + +\csa{xintDSH\x\n}\etype{\numx f} is parametrized decimal shift. When |x| is +negative, it is like iterating \csa{xintDSL} \verb+|x|+ times (\emph{i.e.} +multiplication by @10^{-@|x|@}@). When |x| positive, it is like iterating +\csa{DSR} |x| times (and is more efficient), and for a non-negative |N| this is +thus the same as the quotient from the euclidean division by |10^x|. + +\subsection{\csbh{xintDSHr}, \csbh{xintDSx}}\label{xintDSHr}\label{xintDSx} +%{\small New in release |1.01|.\par} + +\csa{xintDSHr\x\n}\etype{\numx f} expects |x| to be zero or positive and it +returns then a value |R| which is correlated to the value |Q| returned by +\csa{xintDSH\x\n} in the following manner: +\begin{itemize} +\item if |N| is + positive or zero, |Q| and |R| are the quotient and remainder in + the euclidean division by |10^x| (obtained in a more efficient + manner than using \csa{xintDivision}), +\item if |N| is negative let + |Q1| and |R1| be the quotient and remainder in the euclidean + division by |10^x| of the absolute value of |N|. If |Q1| + does not vanish, then |Q=-Q1| and |R=R1|. If |Q1| vanishes, then + |Q=0| and |R=-R1|. +\item for |x=0|, |Q=N| and |R=0|. +\end{itemize} +So one has |N = 10^x Q + R| if |Q| turns out to be zero or +positive, and |N = 10^x Q - R| if |Q| turns out to be negative, +which is exactly the case when |N| is at most |-10^x|. + + +\csa{xintDSx\x\n}\etype{\numx f} for |x| negative is exactly as +\csa{xintDSH\x\n}, \emph{i.e.} multiplication by @10^{-@|x|@}@. For |x| zero or +positive it returns the two numbers |{Q}{R}| described above, each one within +braces. So |Q| is \csa{xintDSH\x\n}, and |R| is \csa{xintDSHr\x\n}, but computed +simultaneously. + +\begin{flushleft} + \xintAssign\xintDSx {-1}{-123456789}\to\M + \noindent{|\xintAssign\xintDSx {-1}{-123456789}\to\M|}\\ + |\meaning\M: |\digitstt{\meaning\M}.\\ + \xintAssign\xintDSx {-20}{1234567689}\to\M + {|\xintAssign\xintDSx {-20}{123456789}\to\M|}\\ + |\meaning\M: |\digitstt{\meaning\M}.\\ + \xintAssign\xintDSx{0}{-123004321}\to\Q\R + {|\xintAssign\xintDSx {0}{-123004321}\to\Q\R|}\\ + \noindent|\meaning\Q: |\digitstt{\meaning\Q}, |\meaning\R: + |\digitstt{\meaning\R.}\\ + |\xintDSH {0}{-123004321}|\digitstt{=\xintDSH {0}{-123004321}}, + |\xintDSHr {0}{-123004321}|\digitstt{=\xintDSHr {0}{-123004321}}\\ + \xintAssign\xintDSx {6}{-123004321}\to\Q\R + {|\xintAssign\xintDSx {6}{-123004321}\to\Q\R|}\\ + |\meaning\Q: |\digitstt{\meaning\Q}, + |\meaning\R: |\digitstt{\meaning\R.}\\ + |\xintDSH {6}{-123004321}|\digitstt{=\xintDSH {6}{-123004321}}, + |\xintDSHr {6}{-123004321}|\digitstt{=\xintDSHr {6}{-123004321}}\\ + \xintAssign\xintDSx {8}{-123004321}\to\Q\R + {|\xintAssign\xintDSx {8}{-123004321}\to\Q\R|}\\ + |\meaning\Q: |\digitstt{\meaning\Q}, + |\meaning\R: |\digitstt{\meaning\R.} \\ + |\xintDSH {8}{-123004321}|\digitstt{=\xintDSH {8}{-123004321}}, + |\xintDSHr {8}{-123004321}|\digitstt{=\xintDSHr {8}{-123004321}}\\ + \xintAssign\xintDSx {9}{-123004321}\to\Q\R + {|\xintAssign\xintDSx {9}{-123004321}\to\Q\R|}\\ + |\meaning\Q: |\digitstt{\meaning\Q}, + |\meaning\R: |\digitstt{\meaning\R.}\\ + |\xintDSH {9}{-123004321}|\digitstt{=\xintDSH {9}{-123004321}}, + |\xintDSHr {9}{-123004321}|\digitstt{=\xintDSHr {9}{-123004321}}\\ +\end{flushleft} + +\subsection{\csbh{xintDecSplit}}\label{xintDecSplit} + +%{\small This has been modified in release |1.01|.\par} + +\csa{xintDecSplit\x\n}\etype{\numx f} cuts the number into two pieces (each one +within a pair of enclosing braces). First the sign if present is \emph{removed}. +Then, for |x| positive or null, the second piece contains the |x| least +significant digits (\emph{empty} if |x=0|) and the first piece the remaining +digits (\emph{empty} when |x| equals or exceeds the length of |N|). Leading +zeroes in the second piece are not removed. When |x| is negative the first piece +contains the \verb+|x|+ most significant digits and the second piece the +remaining digits (\emph{empty} if @|x|@ equals or exceeds the length of |N|). +Leading zeroes in this second piece are not removed. So the absolute value of the +original number is always the concatenation of the first and second piece. + +{\footnotesize This macro's behavior for |N| non-negative is final and will not + change. I am still hesitant about what to do with the sign of a + negative |N|.\par} + + +\xintAssign\xintDecSplit {0}{-123004321}\to\L\R +\centeredline{|\xintAssign\xintDecSplit {0}{-123004321}\to\L\R|} +\noindent|\meaning\L: |\digitstt{\meaning\L}, |\meaning\R: |\digitstt{\meaning\R.} +\xintAssign\xintDecSplit {5}{-123004321}\to\L\R +\centeredline{|\xintAssign\xintDecSplit {5}{-123004321}\to\L\R|} +|\meaning\L: |\digitstt{\meaning\L}, |\meaning\R: |\digitstt{\meaning\R.} +\xintAssign\xintDecSplit {9}{-123004321}\to\L\R +\centeredline{|\xintAssign\xintDecSplit {9}{-123004321}\to\L\R|} +|\meaning\L: |\digitstt{\meaning\L}, |\meaning\R: |\digitstt{\meaning\R.} +\xintAssign\xintDecSplit {10}{-123004321}\to\L\R +\centeredline{|\xintAssign\xintDecSplit {10}{-123004321}\to\L\R|} +|\meaning\L: |\digitstt{\meaning\L}, |\meaning\R: |\digitstt{\meaning\R.} +\xintAssign\xintDecSplit {-5}{-12300004321}\to\L\R +\centeredline{|\xintAssign\xintDecSplit {-5}{-12300004321}\to\L\R|} +|\meaning\L: |\digitstt{\meaning\L}, |\meaning\R: |\digitstt{\meaning\R.} +\xintAssign\xintDecSplit {-11}{-12300004321}\to\L\R +\centeredline{|\xintAssign\xintDecSplit {-11}{-12300004321}\to\L\R|} +|\meaning\L: |\digitstt{\meaning\L}, |\meaning\R: |\digitstt{\meaning\R.} +\xintAssign\xintDecSplit {-15}{-12300004321}\to\L\R +\centeredline{|\xintAssign\xintDecSplit {-15}{-12300004321}\to\L\R|} +|\meaning\L: |\digitstt{\meaning\L}, |\meaning\R: |\digitstt{\meaning\R.} + +\subsection{\csbh{xintDecSplitL}}\label{xintDecSplitL} + +\csa{xintDecSplitL\x\n}\etype{\numx f} returns the first piece after the action +of \csa{xintDecSplit}. + +\subsection{\csbh{xintDecSplitR}}\label{xintDecSplitR} + +\csa{xintDecSplitR\x\n}\etype{\numx f} returns the second piece after the action +of \csa{xintDecSplit}. + + + +\section{Commands of the \xintfracname package} +\label{sec:frac} + +\def\x{\string{x\string}} + +This package was first included in release |1.03| of the \xintname bundle. The +general rule of the bundle that each macro first expands (what comes first, +fully) each one of its arguments applies. + + +|f|\ntype{\Ff} stands for an integer or a fraction (see \autoref{sec:inputs} +for the accepted input formats) or something which expands to an integer or +fraction. It is possible to use in the numerator or the denominator of |f| count +registers and even expressions with infix arithmetic operators, under some rules +which are explained in the previous \hyperref[sec:useofcount]{Use of count + registers} section. + +As in the \hyperref[sec:xint]{xint.sty} documentation, |x|\ntype{\numx} +stands for something which will internally be embedded in a \csa{numexpr}. +It +may thus be a count register or something like |4*\count 255 + 17|, etc..., but +must expand to an integer obeying the \TeX{} bound. + +The fraction format on output is the scientific notation for the `float' macros, +and the |A/B[n]| format for all other fraction macros, with the exception of +\csbxint{Trunc}, {\color{blue}\string\xint\-Round} (which produce decimal +numbers) and \csbxint{Irr}, \csbxint{Jrr}, \csbxint{RawWithZeros} (which returns +an |A/B| with no trailing |[n]|, and prints the |B| even if it is |1|), and +\csbxint{PRaw} which does not print the |[n]| if |n=0| or the |B| if |B=1|. + +To be certain to print an integer output without trailing |[n]| nor fraction +slash, one should use either |\xintPRaw {\xintIrr {f}}| or |\xintNum {f}| when +it is already known that |f| evaluates to a (big) integer. For example +|\xintPRaw {\xintAdd {2/5}{3/5}}| gives a perhaps disappointing +\digitstt{\xintPRaw {\xintAdd {2/5}{3/5}}}\footnote{yes, \csbxint{Add} blindly + multiplies denominators... }, whereas |\xintPRaw {\xintIrr {\xintAdd + {2/5}{3/5}}}| returns \digitstt{\xintPRaw {\xintIrr {\xintAdd + {2/5}{3/5}}}}. As we knew the result was an integer we could have used +|\xintNum {\xintAdd {2/5}{3/5}}=|\xintNum {\xintAdd {2/5}{3/5}}. + +Some macros (such as \csbxint{iTrunc}, +\csbxint{iRound}, and \csbxint{Fac}) always produce directly integers on output. + + +\localtableofcontents + +\subsection{\csbh{xintNum}}\label{xintNum} + +The macro\etype{f} is extended to accept a fraction on input. But this fraction +should reduce to an integer. If not an error will be raised. The original is +available as \csbxint{iNum}. It is imprudent to apply \csa{xintNum} to numbers +with a large power of ten given either in scientific notation or with the |[n]| +notation, as the macro will add the necessary zeroes to get an explicit integer. + +\subsection{\csbh{xintifInt}}\label{xintifInt} +%{\small New with release |1.09e|.\par} + +\csa{xintifInt}|{f}{YES branch}{NO branch}|\etype{\Ff nn} expandably chooses the +|YES| branch if |f| reveals itself after expansion and simplification to be an +integer. As with the other \xintname conditionals, both branches must be present +although one of the two (or both, but why then?) may well be an empty brace pair +|{}|. As will all other \xintname conditionals, spaces in-between the braced +things do not matter, but a space after the closing brace of the |NO| branch is +significant. + + +\subsection{\csbh{xintLen}}\label{xintLen} + +The original macro\etype{\Ff} is extended to accept a fraction on input. +\centeredline {|\xintLen {201710/298219}|\digitstt{=\xintLen {201710/298219}}, +|\xintLen {1234/1}|\digitstt{=\xintLen {1234/1}}, |\xintLen {1234}|% + \digitstt{=\xintLen {1234}}} + + +\subsection{\csbh{xintRaw}}\label{xintRaw} +%{\small New with release |1.04|.\par} +%{\small \color{red}MODIFIED IN |1.07|.\par} + +This macro `prints' the\etype{\Ff} +fraction |f| as it is received by the package after its parsing and +expansion, in a form |A/B[n]| equivalent to the internal +representation: the denominator |B| is always strictly positive and is +printed even if it has value |1|. +\centeredline{|\xintRaw{\the\numexpr 571*987\relax.123e-10/\the\numexpr + -201+59\relax e-7}=|}% +\centeredline{\digitstt{\xintRaw{\the\numexpr + 571*987\relax.123e-10/\the\numexpr -201+59\relax e-7}}} + +\subsection{\csbh{xintPRaw}}\label{xintPRaw} +%{\small New in |1.09b|.\par} + +|PRaw|\etype{\Ff} stands for ``pretty raw''. It does \emph{not} show the |[n]| +if |n=0| and does \emph{not} show the |B| if |B=1|. \centeredline{|\xintPRaw + {123e10/321e10}=|\digitstt{\xintPRaw {123e10/321e10}}, |\xintPRaw + {123e9/321e10}=|\digitstt{\xintPRaw {123e9/321e10}}} \centeredline{|\xintPRaw + {\xintIrr{861/123}}=|\digitstt{\xintPRaw{\xintIrr{861/123}}} \ vz.\ + |\xintIrr{861/123}=|\digitstt{\xintIrr{861/123}}} See also \csbxint{Frac} (or +\csbxint{FwOver}) for math mode. As is examplified above the \csbxint{Irr} macro +which puts the fraction into irreducible form does not remove the |/1| if the +fraction is an integer. One can use \csbxint{Num} for that, but there will be an +error message if the fraction was not an integer; so the combination +|\xintPRaw{\xintIrr{f}}| is the way to go. + +\subsection{\csbh{xintNumerator}}\label{xintNumerator} + +This returns\etype{\Ff} the numerator corresponding to the internal +representation of a fraction, with positive powers of ten converted into zeroes +of this numerator: \centeredline{|\xintNumerator + {178000/25600000[17]}|\digitstt{=\xintNumerator {178000/25600000[17]}}} +\centeredline{|\xintNumerator {312.289001/20198.27}|% + \digitstt{=\xintNumerator {312.289001/20198.27}}} +\centeredline{|\xintNumerator {178000e-3/256e5}|\digitstt{=\xintNumerator + {178000e-3/256e5}}} \centeredline{|\xintNumerator + {178.000/25600000}|\digitstt{=\xintNumerator {178.000/25600000}}} As shown by +the examples, no simplification of the input is done. For a result uniquely +associated to the value of the fraction first apply \csa{xintIrr}. + +\subsection{\csbh{xintDenominator}}\label{xintDenominator} + +This returns\etype{\Ff} the denominator corresponding to the internal +representation of the fraction:\footnote{recall that the |[]| construct excludes + presence of a decimal point.} \centeredline{|\xintDenominator + {178000/25600000[17]}|\digitstt{=\xintDenominator {178000/25600000[17]}}}% +\centeredline{|\xintDenominator {312.289001/20198.27}|% + \digitstt{=\xintDenominator {312.289001/20198.27}}} +\centeredline{|\xintDenominator {178000e-3/256e5}|\digitstt{=\xintDenominator + {178000e-3/256e5}}} \centeredline{|\xintDenominator + {178.000/25600000}|\digitstt{=\xintDenominator {178.000/25600000}}} As shown +by the examples, no simplification of the input is done. The denominator looks +wrong in the last example, but the numerator was tacitly multiplied by @1000@ +through the removal of the decimal point. For a result uniquely associated to +the value of the fraction first apply \csa{xintIrr}. + +\subsection{\csbh{xintRawWithZeros}}\label{xintRawWithZeros} +%{\small New name in |1.07| (former name |\xintRaw|).\par} + +This macro `prints'\etype{\Ff} the +fraction |f| (after its parsing and expansion) in |A/B| form, with |A| +as returned by \csa{xintNumerator}|{f}| and |B| as returned by +\csa{xintDenominator}|{f}|. +\centeredline{|\xintRawWithZeros{\the\numexpr 571*987\relax.123e-10/\the\numexpr + -201+59\relax e-7}=|}% +\centeredline{\digitstt{\xintRawWithZeros{\the\numexpr + 571*987\relax.123e-10/\the\numexpr -201+59\relax e-7}}} + + +\subsection{\csbh{xintREZ}}\label{xintREZ} + +This command\etype{\Ff} normalizes a fraction by removing the powers of ten from +its numerator and denominator: \centeredline{|\xintREZ + {178000/25600000[17]}|\digitstt{=\xintREZ {178000/25600000[17]}}} +\centeredline{|\xintREZ {1780000000000e30/2560000000000e15}|\digitstt{=\xintREZ + {1780000000000e30/2560000000000e15}}} As shown by the example, it does not +otherwise simplify the fraction. + + +\subsection{\csbh{xintFrac}}\label{xintFrac} + +This is a \LaTeX{} only command,\etype{\Ff} to be used in math mode only. It +will print a fraction, internally represented as something equivalent to +|A/B[n]| as |\frac {A}{B}10^n|. The power of ten is omitted when |n=0|, the +denominator is omitted when it has value one, the number being separated from +the power of ten by a |\cdot|. |$\xintFrac {178.000/25600000}$| gives $\xintFrac +{178.000/25600000}$, |$\xintFrac {178.000/1}$| gives $\xintFrac {178.000/1}$, +|$\xintFrac {3.5/5.7}$| gives $\xintFrac {3.5/5.7}$, and |$\xintFrac {\xintNum + {\xintFac{10}/|\allowbreak|\xintiSqr{\xintFac {5}}}}$| gives $\xintFrac +{\xintNum {\xintFac{10}/\xintiSqr{\xintFac {5}}}}$. As shown by the examples, +simplification of the input (apart from removing the decimal points and moving +the minus sign to the numerator) is not done automatically and must be the +result of macros such as |\xintIrr|, |\xintREZ|, or |\xintNum| (for fractions +being in fact integers.) + +\subsection{\csbh{xintSignedFrac}}\label{xintSignedFrac} + +%{\small New with release |1.04|.\par} + +This is as \csbxint{Frac}\etype{\Ff} except that a negative fraction has the +sign put in front, not in the numerator. \centeredline{|\[\xintFrac + {-355/113}=\xintSignedFrac {-355/113}\]|} +\[\xintFrac {-355/113}=\xintSignedFrac {-355/113}\] + +\subsection{\csbh{xintFwOver}}\label{xintFwOver} + +This does the same as \csa{xintFrac}\etype{\Ff} except that the \csa{over} +primitive is used for the fraction (in case the denominator is not one; and a +pair of braces contains the |A\over B| part). |$\xintFwOver {178.000/25600000}$| +gives $\xintFwOver {178.000/25600000}$, |$\xintFwOver {178.000/1}$| gives +$\xintFwOver {178.000/1}$, |$\xintFwOver {3.5/5.7}$| gives $\xintFwOver +{3.5/5.7}$, and |$\xintFwOver {\xintNum {\xintFac{10}/\xintiSqr{\xintFac + {5}}}}$| gives $\xintFwOver {\xintNum {\xintFac{10}/\xintiSqr{\xintFac + {5}}}}$. + +\subsection{\csbh{xintSignedFwOver}}\label{xintSignedFwOver} + +%{\small New with release |1.04|.\par} + +This is as \csbxint{FwOver}\etype{\Ff} except that a negative fraction has the +sign put in front, not in the numerator. \centeredline{|\[\xintFwOver + {-355/113}=\xintSignedFwOver {-355/113}\]|} +\[\xintFwOver {-355/113}=\xintSignedFwOver {-355/113}\] + + +\subsection{\csbh{xintIrr}}\label{xintIrr} + +This puts the fraction\etype{\Ff} into its unique irreducible form: +\centeredline{|\xintIrr {178.256/256.178}|% + \digitstt{=\xintIrr {178.256/256.178}}${}=\xintFrac{\xintIrr + {178.256/256.178}[0]}$}% +Note that the current implementation does not cleverly first factor powers of 2 +and 5, so input such as |\xintIrr {2/3[100]}| will make \xintfracname do the +Euclidean division of |2|\raisebox{.5ex}{|.|}|10^{100}| by |3|, which is a bit +stupid. + +Starting with release |1.08|, \csa{xintIrr} does not remove the trailing |/1| +when the output is an integer. This was deemed better for various (stupid?) +reasons and thus the output format is now \emph{always} |A/B| with |B>0|. Use +\csbxint{PRaw} on top of \csa{xintIrr} if it is needed to get rid of a possible +trailing |/1|. For display in math mode, use rather |\xintFrac{\xintIrr {f}}| or +|\xintFwOver{\xintIrr {f}}|. + +\subsection{\csbh{xintJrr}}\label{xintJrr} + +This also puts the fraction\etype{\Ff} into its unique irreducible form: +\centeredline{|\xintJrr {178.256/256.178}|% + \digitstt{=\xintJrr {178.256/256.178}}}% +This is faster than \csa{xintIrr} for fractions having some big common +factor in the numerator and the denominator.\par +{\centering |\xintJrr {\xintiPow{\xintFac {15}}{3}/\xintiiPrdExpr +{\xintFac{10}}{\xintFac{30}}{\xintFac{5}}\relax }|\digitstt{=% + \xintJrr {\xintiPow{\xintFac {15}}{3}/\xintiiPrdExpr +{\xintFac{10}}{\xintFac{30}}{\xintFac{5}}\relax }}\par} But to notice the +difference one would need computations with much bigger numbers than in this +example. +Starting with release |1.08|, \csa{xintJrr} does not remove the trailing |/1| +when the output is an integer. + + +\subsection{\csbh{xintTrunc}}\label{xintTrunc} + +\csa{xintTrunc}|{x}{f}|\etype{\numx\Ff} returns the integral part, a dot, and +then the first |x| digits of the decimal +expansion of the fraction |f|. The +argument |x| should be non-negative. + +In the special case when |f| evaluates to @0@, the output is @0@ with no decimal +point nor decimal digits, else the post decimal mark digits are always printed. +A non-zero negative |f| which is smaller in absolute value than |10^{-x}| will +give @-0.000...@. +\centeredline{|\xintTrunc + {16}{-803.2028/20905.298}|\digitstt{=\xintTrunc {16}{-803.2028/20905.298}}}% +\centeredline{|\xintTrunc {20}{-803.2028/20905.298}|\digitstt{=\xintTrunc + {20}{-803.2028/20905.298}}}% +\centeredline{|\xintTrunc {10}{\xintPow {-11}{-11}}|\digitstt{=\xintTrunc + {10}{\xintPow {-11}{-11}}}}% +\centeredline{|\xintTrunc {12}{\xintPow {-11}{-11}}|\digitstt{=\xintTrunc + {12}{\xintPow {-11}{-11}}}}% +\centeredline{|\xintTrunc {12}{\xintAdd {-1/3}{3/9}}|\digitstt{=\xintTrunc + {12}{\xintAdd {-1/3}{3/9}}}} The digits printed are exact up to and +including the last one. + +% The identity |\xintTrunc {x}{-f}=-\xintTrunc {x}{f}| +% holds.\footnote{Recall that |-\string\macro| is not valid as argument to any +% package macro, one must use |\string\xintOpp\string{\string\macro\string}| or +% |\string\xintiOpp\string{\string\macro\string}|, except inside +% |\string\xinttheexpr...\string\relax|.} + +\subsection{\csbh{xintiTrunc}}\label{xintiTrunc} + +\csa{xintiTrunc}|{x}{f}|\etype{\numx\Ff} returns the integer equal to |10^x| +times what \csa{xintTrunc}|{x}{f}| would produce. +% +\centeredline{|\xintiTrunc + {16}{-803.2028/20905.298}|\digitstt{=\xintiTrunc {16}{-803.2028/20905.298}}}% +\centeredline{|\xintiTrunc {10}{\xintPow {-11}{-11}}|\digitstt{=\xintiTrunc + {10}{\xintPow {-11}{-11}}}}% +\centeredline{|\xintiTrunc {12}{\xintPow {-11}{-11}}|\digitstt{=\xintiTrunc + {12}{\xintPow {-11}{-11}}}}% +The difference between \csa{xintTrunc}|{0}{f}| and \csa{xintiTrunc}|{0}{f}| is +that the latter never has the decimal mark always present in the former except +for |f=0|. And \csa{xintTrunc}|{0}{-0.5}| returns ``\digitstt{\xintTrunc + 0{-0.5}}'' whereas \csa{xintiTrunc}|{0}{-0.5}| simply returns +``\digitstt{\xintiTrunc 0{-0.5}}''. + +\subsection{\csbh{xintXTrunc}}\label{xintXTrunc} + +%{\small New with release |1.09j|.\par} + +\csa{xintXTrunc}|{x}{f}|\retype{\numx\Ff} is completely expandable but not +\fexpan dable, as is indicated by the hollow star in the margin. It can not be +used as argument to the other package macros, but is designed to be used inside +an |\edef|, or rather a |\write|. Here is an example session where the user +after some warming up checks that @1/66049=1/257^2@ has period @257*256=65792@ +(it is also checked here that this is indeed the smallest period). +% +\begingroup\small +\dverb|@ +xxx:_xint $ etex -jobname worksheet-66049 +This is pdfTeX, Version 3.1415926-2.5-1.40.14 (TeX Live 2013) + restricted \write18 enabled. +**\relax +entering extended mode + +*\input xintfrac.sty +(./xintfrac.sty (./xint.sty (./xinttools.sty))) +*\message{\xintTrunc {100}{1/71}}% Warming up! + +0.01408450704225352112676056338028169014084507042253521126760563380281690140845 +07042253521126760563380 +*\message{\xintTrunc {350}{1/71}}% period is 35 + +0.01408450704225352112676056338028169014084507042253521126760563380281690140845 +0704225352112676056338028169014084507042253521126760563380281690140845070422535 +2112676056338028169014084507042253521126760563380281690140845070422535211267605 +6338028169014084507042253521126760563380281690140845070422535211267605633802816 +901408450704225352112676056338028169 +*\edef\Z {\xintXTrunc {65792}{1/66049}}% getting serious... + +*\def\trim 0.{}\oodef\Z {\expandafter\trim\Z}% removing 0. + +*\edef\W {\xintXTrunc {131584}{1/66049}}% a few seconds + +*\oodef\W {\expandafter\trim\W} + +*\oodef\ZZ {\expandafter\Z\Z}% doubling the period + +*\ifx\W\ZZ \message{YES!}\else\message{BUG!}\fi % xint never has bugs... +YES! +*\message{\xintTrunc {260}{1/66049}}% check visually that 256 is not a period + +0.00001514027464458205271843631243470756559523989765174340262532362337052794137 +6856576178291874214598252812306015231116292449545034746930309315810988811337037 +6538630410755651107511090251177156353616254598858423291798513225029902042423049 +5541189117170585474420505 +*\edef\X {\xintXTrunc {257*128}{1/66049}}% infix here ok, less than 8 tokens + +*\oodef\X {\expandafter\trim\X}% we now have the first 257*128 digits + +*\oodef\XX {\expandafter\X\X}% was 257*128 a period? + +*\ifx\XX\Z \message{257*128 is a period}\else \message{257 * 128 not a period}\fi +257 * 128 not a period +*\immediate\write-1 {1/66049=0.\Z... (repeat)} + +*\oodef\ZA {\xintNum {\Z}}% we remove the 0000, or we could use next \xintiMul + +*\immediate\write-1 {10\string^65792-1=\xintiiMul {\ZA}{66049}} + +*% This was slow :( I should write a multiplication, still completely + +*% expandable, but not f-expandable, which could be much faster on such cases. + +*\bye +No pages of output. +Transcript written on worksheet-66049.log. +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. + +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 +smallest denominator hence does not extend |B| with zeroes, and technical +reasons lead to the use of some tricks.\footnote{Technical note: I do not + provide an |\char92 xintXFloat| because this would almost certainly mean + having to clone the entire core division routines into a ``long division'' + variant. But this could have given another approach to the implementation of + |\char 92 xintXTrunc|, especially for the case of a negative |N|. Doing these + things with \TeX{} is an effort. Besides an + |\char 92 xintXFloat| would be interesting only if also for example the square + root routine was provided in an |X| version (I have not given thought to + that). If feasible |X| routines would be interesting in the |\char 92 + xintexpr| context where things are expanded inside |\char92 csname..\char92 + endcsname|.} + +Contrarily to \csbxint{Trunc}, in the case of the second argument revealing +itself to be exactly zero, \csbxint{XTrunc} will output @0.000...@, not @0@. +Also, the first argument must be at least @1@. + +\subsection{\csbh{xintRound}}\label{xintRound} + +%{\small New with release |1.04|.\par} + +\csa{xintRound}|{x}{f}|\etype{\numx\Ff} returns the start of the decimal +expansion of the fraction |f|, rounded to |x| digits precision after the decimal +point. The argument |x| should be non-negative. Only when |f| evaluates exactly +to zero does \csa{xintRound} return |0| without decimal point. When |f| is not +zero, its sign is given in the output, also when the digits printed are all +zero. \centeredline{|\xintRound {16}{-803.2028/20905.298}|\digitstt{=\xintRound + {16}{-803.2028/20905.298}}}% +\centeredline{|\xintRound {20}{-803.2028/20905.298}|\digitstt{=\xintRound + {20}{-803.2028/20905.298}}}% +\centeredline{|\xintRound {10}{\xintPow {-11}{-11}}|\digitstt{=\xintRound + {10}{\xintPow {-11}{-11}}}}% +\centeredline{|\xintRound {12}{\xintPow {-11}{-11}}|\digitstt{=\xintRound + {12}{\xintPow {-11}{-11}}}}% +\centeredline{|\xintRound {12}{\xintAdd {-1/3}{3/9}}|\digitstt{=\xintRound + {12}{\xintAdd {-1/3}{3/9}}}} The identity |\xintRound {x}{-f}=-\xintRound +{x}{f}| holds. And regarding $(-11)^{-11}$ here is some more of its expansion: +\centeredline{\digitstt{\xintTrunc {50}{\xintPow {-11}{-11}}\dots}} + +\subsection{\csbh{xintiRound}}\label{xintiRound} + +%{\small New with release |1.04|.\par} + +\csa{xintiRound}|{x}{f}|\etype{\numx\Ff} returns the integer equal to |10^x| +times what \csa{xintRound}|{x}{f}| would return. \centeredline{|\xintiRound + {16}{-803.2028/20905.298}|\digitstt{=\xintiRound {16}{-803.2028/20905.298}}}% +\centeredline{|\xintiRound {10}{\xintPow {-11}{-11}}|\digitstt{=\xintiRound + {10}{\xintPow {-11}{-11}}}}% +Differences between \csa{xintRound}|{0}{f}| and \csa{xintiRound}|{0}{f}|: the +former cannot be used inside integer-only macros, and the latter removes the +decimal point, and never returns |-0| (and removes all superfluous leading +zeroes.) + +\subsection{\csbh{xintFloor}}\label{xintFloor} +%{\small New with release |1.09a|.\par} + +|\xintFloor {f}|\etype{\Ff} returns the largest relative integer |N| with +|N|${}\leq{}$|f|. \centeredline{|\xintFloor {-2.13}|\digitstt{=\xintFloor + {-2.13}}, |\xintFloor {-2}|\digitstt{=\xintFloor {-2}}, |\xintFloor + {2.13}|\digitstt{=\xintFloor {2.13}}% +} + +\subsection{\csbh{xintCeil}}\label{xintCeil} +%{\small New with release |1.09a|.\par} + +|\xintCeil {f}|\etype{\Ff} returns the smallest relative integer |N| with +|N|${}>{}$|f|. \centeredline{|\xintCeil {-2.13}|\digitstt{=\xintCeil {-2.13}}, + |\xintCeil {-2}|\digitstt{=\xintCeil {-2}}, |\xintCeil + {2.13}|\digitstt{=\xintCeil {2.13}}% +} + +\subsection{\csbh{xintTFrac}}\label{xintTFrac} + +\csa{xintTFrac}|{f}|\etype{\Ff} returns the fractional part, +|f=trunc(f)+frac(f)|. +The |T| stands for `Trunc', and there could similar macros associated to +`Round', `Floor', and `Ceil'. Inside |\xintexpr..\relax|, the function |frac| is +mapped to \csa{xintTFrac}. Inside |\xint|\-|floatexpr..\relax|, |frac| first +applies +\csa{xintTFrac} to its argument (which may be in float format, or +an exact fraction), and only next makes the float conversion. +\centeredline{|\xintTFrac {1235/97}|\digitstt{=\xintTFrac {1235/97}}\quad + |\xintTFrac {-1235/97}|\digitstt{=\xintTFrac {-1235/97}}} +\centeredline{|\xintTFrac {1235.973}|\digitstt{=\xintTFrac {1235.973}}\quad + |\xintTFrac {-1235.973}|\digitstt{=\xintTFrac {-1235.973}}} +\centeredline{|\xintTFrac {1.122435727e5}|% + \digitstt{=\xintTFrac {1.122435727e5}}} + + +\subsection{\csbh{xintE}}\label{xintE} +%{\small New with |1.07|.} + +|\xintE {f}{x}|\etype{\Ff\numx} multiplies the fraction |f| by @10^x@. The +\emph{second} argument |x| must obey the \TeX{} bounds. Example: +\centeredline{|\count 255 123456789 \xintE {10}{\count 255}|\digitstt{->\count + 255 123456789 \xintE {10}{\count 255}}} Be careful that for obvious reasons +such gigantic numbers should not be given to \csbxint{Num}, or added to +something with a widely different order of magnitude, as the package always +works to get the \emph{exact} result. There is \emph{no problem} using them for +\emph{float} operations:\centeredline{|\xintFloatAdd + {1e1234567890}{1}|\digitstt{=\xintFloatAdd {1e1234567890}{1}}} + +\subsection{\csbh{xintFloatE}}\label{xintFloatE} +%{\small New with |1.097|.} + +|\xintFloatE [P]{f}{x}|\etype{{\upshape[\numx]}\Ff\numx} multiplies the input +|f| by @10^x@, and +converts it to float format according to the optional first argument or current +value of |\xintDigits|. +\centeredline{|\xintFloatE {1.23e37}{53}|\digitstt{=\xintFloatE {1.23e37}{53}}} + +\subsection{\csbh{xintDigits}, \csbh{xinttheDigits}}\label{xintDigits} + +%{\small New with release |1.07|.\par} + +The syntax |\xintDigits := D;| (where spaces do not matter) assigns the +value of |D| to the number of digits to be used by floating point +operations. The default is |16|. The maximal value is |32767|. The macro +|\xinttheDigits|\etype{} serves to print the current value. + +\subsection{\csbh{xintFloat}}\label{xintFloat} + +%{\small New with release |1.07|.\par} + +The macro |\xintFloat [P]{f}|\etype{{\upshape[\numx]}\Ff} has an optional argument |P| which replaces +the current value of |\xintDigits|. The (rounded truncation of the) fraction +|f| is then printed in scientific form, with |P| digits, +a lowercase |e| and an exponent |N|. The first digit is from |1| to |9|, it is +preceded by an optional minus sign and +is followed by a dot and |P-1| digits, the trailing zeroes +are not trimmed. In the exceptional case where the +rounding went to the next power of ten, the output is |10.0...0eN| +(with a sign, perhaps). The sole exception is for a zero value, which then gets +output as |0.e0| (in an \csa{xintCmp} test it is the only possible output of +\csa{xintFloat} or one of the `Float' macros which will test positive for +equality with zero). +\centeredline{|\xintFloat[32]{1234567/7654321}|% + \digitstt{=\xintFloat[32]{1234567/7654321}}} +% \pdfresettimer +\centeredline{|\xintFloat[32]{1/\xintFac{100}}|% + \digitstt{=\xintFloat[32]{1/\xintFac{100}}}} +% \the\pdfelapsedtime +% 992: plus rapide que ce que j'aurais cru.. + +The argument to \csa{xintFloat} may be an |\xinttheexpr|-ession, like the +other macros; only its final evaluation is submitted to \csa{xintFloat}: the +inner evaluations of chained arguments are not at all done in `floating' +mode. For this one must use |\xintthefloatexpr|. + + +\subsection{\csbh{xintAdd}}\label{xintAdd} + +The original\etype{\Ff\Ff} macro is extended to accept fractions on input. Its +output will now always be in the form |A/B[n]|. The original is available as +\csbxint{iAdd}. + +\subsection{\csbh{xintFloatAdd}}\label{xintFloatAdd} + +%{\small New with release |1.07|.\par} + +|\xintFloatAdd [P]{f}{g}|\etype{{\upshape[\numx]}\Ff\Ff} first replaces |f| and +|g| with their float approximations, with 2 safety digits. It then adds exactly +and outputs in float format with precision |P| (which is optional) or +|\xintDigits| if |P| was absent, the result of this computation. + + +\subsection{\csbh{xintSub}}\label{xintSub} + +The original\etype{\Ff\Ff} macro is extended to accept fractions on input. Its +output will now always be in the form |A/B[n]|. The original is available as +\csbxint{iSub}. + +\subsection{\csbh{xintFloatSub}}\label{xintFloatSub} + +%{\small New with release |1.07|.\par} + +|\xintFloatSub [P]{f}{g}|\etype{{\upshape[\numx]}\Ff\Ff} first replaces |f| and +|g| with their float approximations, with 2 safety digits. It then subtracts +exactly and outputs in float format with precision |P| (which is optional), or +|\xintDigits| if |P| was absent, the result of this computation. + + +\subsection{\csbh{xintMul}}\label{xintMul} + +The original\etype{\Ff\Ff} macro is extended to accept fractions on input. Its +output will now always be in the form |A/B[n]|. The original, only for big +integers, and outputting a big integer, is available as \csbxint{iMul}. + +\subsection{\csbh{xintFloatMul}}\label{xintFloatMul} + +%{\small New with release |1.07|.\par} + +|\xintFloatMul [P]{f}{g}|\etype{{\upshape[\numx]}\Ff\Ff} first replaces |f| and +|g| with their float approximations, with 2 safety digits. It then multiplies +exactly and outputs in float format with precision |P| (which is optional), or +|\xintDigits| if |P| was absent, the result of this computation. + +\subsection{\csbh{xintSqr}}\label{xintSqr} + +The original\etype{\Ff} macro is extended to accept a fraction on input. Its +output will now always be in the form |A/B[n]|. The original which outputs only +big integers is available as \csbxint{iSqr}. + +\subsection{\csbh{xintDiv}}\label{xintDiv} + +\csa{xintDiv}|{f}{g}|\etype{\Ff\Ff} computes the fraction |f/g|. As with all +other computation macros, no simplification is done on the output, which is in +the form |A/B[n]|. + +\subsection{\csbh{xintFloatDiv}}\label{xintFloatDiv} + +%{\small New with release |1.07|.\par} + +|\xintFloatDiv [P]{f}{g}|\etype{{\upshape[\numx]}\Ff\Ff} first replaces |f| and +|g| with their float approximations, with 2 safety digits. It then divides +exactly and outputs in float format with precision |P| (which is optional), or +|\xintDigits| if |P| was absent, the result of this computation. + + +\subsection{\csbh{xintFac}}\label{xintFac} +%{\small Modified in |1.08b| (to allow fractions on input).\par} + +The original\etype{\Numf} is extended to allow a fraction on input but this +fraction |f| must simplify to a integer |n| (non negative and at most |999999|, +but already |100000!| is prohibitively time-costly). On output |n!| (no trailing +|/1[0]|). The original macro (which has less overhead) is still available as +\csbxint{iFac}. + +\subsection{\csbh{xintPow}}\label{xintPow} + +\csa{xintPow}{|{f}{g}|}:\etype{\Ff\Numf} the original macro is extended to +accept fractions on input. The output will now always be in the form |A/B[n]| +(even when the exponent vanishes: |\xintPow +{2/3}{0}|\digitstt{=\xintPow{2/3}{0}}). The original is available as +\csbxint{iPow}. + +The exponent is allowed to be input as a fraction but it must simplify to an +integer: |\xintPow {2/3}{10/2}|\digitstt{=\xintPow {2/3}{10/2}}. This integer +will be checked to not exceed |100000|. Indeed |2^50000| already has +\digitstt{\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} + +|\xintFloatPow [P]{f}{x}|\etype{{\upshape[\numx]}\Ff\numx} uses either the +optional argument |P| or the value of |\xintDigits|. It computes a floating +approximation to |f^x|. The precision |P| must be at least |1|, naturally. + +The exponent |x| will be fed to a |\numexpr|, hence count registers are accepted +on input for this |x|. And the absolute value \verb+|x|+ must obey the \TeX{} +bound. For larger exponents use the slightly slower routine \csbxint{FloatPower} +which allows the exponent to be a fraction simplifying to an integer and does +not limit its size. This slightly slower routine is the one to which |^| is +mapped inside |\xintthefloatexpr...\relax|. + + +The macro |\xintFloatPow| chooses dynamically an appropriate number of +digits for the intermediate computations, large enough to achieve the desired +accuracy (hopefully). + +\centeredline{|\xintFloatPow [8]{3.1415}{1234567890}|% + \digitstt{=\xintFloatPow [8]{3.1415}{1234567890}}} + + + +\subsection{\csbh{xintFloatPower}}\label{xintFloatPower} +%{\small New with |1.07|.\par} + +\csa{xintFloatPower}|[P]{f}{g}|\etype{{\upshape[\numx]}\Ff\Numf} computes a +floating point value |f^g| where the exponent |g| is not constrained to be at +most the \TeX{} bound \texttt{\number "7FFFFFFF}. It may even be a fraction +|A/B| but must simplify to a (possibly big) integer. +\centeredline{|\xintFloatPower [8]{1.000000000001}{1e12}|% + \digitstt{=\xintFloatPower [8]{1.000000000001}{1e12}}} +\centeredline{|\xintFloatPower [8]{3.1415}{3e9}|% + \digitstt{=\xintFloatPower [8]{3.1415}{3e9}}} Note that |3e9>2^31|. But the +number following |e| in the output must at any rate obey the \TeX{} +\digitstt{\number"7FFFFFFF} bound. + + +Inside an |\xintfloatexpr|-ession, \csa{xintFloatPower} is the function to which +|^| is mapped. The exponent may then be something like |(144/3/(1.3-.5)-37)| +which is, in disguise, an integer. + + +The intermediate multiplications are done with a higher precision than +|\xintDigits| or the optional |P| argument, in order for the +final result to hopefully have the desired accuracy. + +\subsection{\csbh{xintFloatSqrt}}\label{xintFloatSqrt} +%{\small New with |1.08|.\par} + +\csa{xintFloatSqrt}|[P]{f}|\etype{{\upshape[\numx]}\Ff} computes a floating +point approximation of $\sqrt{|f|}$, either using the optional precision |P| or +the value of |\xintDigits|. The computation is done for a precision of at least +17 figures (and the output is rounded if the asked-for precision was smaller). +\centeredline{|\xintFloatSqrt [50]{12.3456789e12}|}% +\centeredline{${}\approx{}$\digitstt{\xintFloatSqrt [50]{12.3456789e12}}}% +\centeredline{|\xintDigits:=50;\xintFloatSqrt {\xintFloatSqrt {2}}|}% +\centeredline{% + ${}\approx{}$\xintDigits:=50;\digitstt{\xintFloatSqrt {\xintFloatSqrt {2}}}} + +% maple: 0.351364182864446216166582311675807703715914271812431919843183 1O^7 +% 3.5136418286444621616658231167580770371591427181243e6 +% maple: 1.18920711500272106671749997056047591529297209246381741301900 +% 1.1892071150027210667174999705604759152929720924638e0 + + +\xintDigits:=16; + +% removed from doc october 22 + +% \subsection{\csbh{xintSum}, \csbh{xintSumExpr}}\label{xintSum} +% \label{xintSumExpr} + +\subsection{\csbh{xintSum}}\label{xintSum}\label{xintSumExpr} + +% The original commands are extended to accept fractions on input and produce +% fractions on output. Their outputs will now always be in the form |A/B[n]|. The +% originals are available as \csa{xintiiSum} and \csa{xintiiSumExpr}. + +The original\etype{f{$\to$}{\lowast\Ff}} command is extended to accept fractions +on input and produce fractions on output. The output will now always be in the +form |A/B[n]|. The original, for big integers only (in strict format), is +available as \csa{xintiiSum}. + + +% \subsection{\csbh{xintPrd}, \csbh{xintPrdExpr}}\label{xintPrd}\label{xintPrdExpr} + +\subsection{\csbh{xintPrd}}\label{xintPrd}\label{xintPrdExpr} + +The original\etype{f{$\to$}{\lowast\Ff}} is extended to accept fractions on +input and produce fractions on output. The output will now always be in the form +|A/B[n]|. The original, for big integers only (in strict format), is available +as \csa{xintiiPrd}. + +\subsection{\csbh{xintCmp}}\label{xintCmp} +%{\small Rewritten in |1.08a|.\par} + +The macro\etype{\Ff\Ff} is extended to fractions. Its output is still either +|-1|, |0|, or |1| with no forward slash nor trailing |[n]|. + +For choosing branches according to the result of comparing |f| and |g|, the +following syntax is recommended: |\xintSgnFork{\xintCmp{f}{g}}{code for + f<g}{code for f=g}{code for f>g}|. + +% Note that since release |1.08a| using this macro on inputs with large powers of +% tens does not take a quasi-infinite time, contrarily to the earlier, somewhat +% dumb version (the earlier version indirectly led to the creation of giant chains +% of zeroes in certain circumstances, causing a serious efficiency impact). + +\subsection{\csbh{xintIsOne}} +See \csbxint{IsOne}\etype{\Ff} (\autoref{xintIsOne}). + +\subsection{\csbh{xintGeq}}\label{xintGeq} +%{\small Rewritten in |1.08a|.\par} + +The macro\etype{\Ff\Ff} is extended to fractions. Beware that the comparison is +on the \emph{absolute values} of the fractions. Can be used as: +\verb+\xintSgnFork{\xintGeq{f}{g}}{}{code for |f|<|g|}{code for + |f|+$\geqslant$\verb+|g|}+ + + + +\subsection{\csbh{xintMax}}\label{xintMax} +%{\small Rewritten in |1.08a|.\par} + +The macro is extended to fractions.\etype{\Ff\Ff} But now |\xintMax {2}{3}| +returns \digitstt{\xintMax {2}{3}}. The original, for use with (possibly big) +integers only, is available as \csbxint{iMax}: |\xintiMax +{2}{3}=|\digitstt{\xintiMax {2}{3}}. + +\subsection{\csbh{xintMaxof}} +See \csbxint{Maxof} (\autoref{xintMaxof}).\etype{f{$\to$}{\lowast\Ff}} + +\subsection{\csbh{xintMin}}\label{xintMin} +%{\small Rewritten in |1.08a|.\par} + +The macro is extended to fractions.\etype{\Ff\Ff} The original, for (big) +integers only, is available as \csbxint{iMin}. + +\subsection{\csbh{xintMinof}} +See \csbxint{Minof} (\autoref{xintMinof}).\etype{f{$\to$}{\lowast\Ff}} + +\subsection{\csbh{xintAbs}}\label{xintAbs} + +The macro is extended to fractions.\etype{\Ff} The original, for (big) integers +only, is available as \csbxint{iAbs}. Note that |\xintAbs +{-2}|\digitstt{=\xintAbs {-2}} whereas |\xintiAbs {-2}|\digitstt{=\xintiAbs + {-2}}. + +\subsection{\csbh{xintSgn}}\label{xintSgn} + +The macro is extended to fractions.\etype{\Ff} Naturally, its output is still +either |-1|, |0|, or |1| with no forward slash nor trailing |[n]|. + +\subsection{\csbh{xintOpp}}\label{xintOpp} + +The macro is extended to fractions.\etype{\Ff} The original is available as +\csbxint{iOpp}. Note that |\xintOpp {3}| now outputs \digitstt{\xintOpp {3}} +whereas |\xintiOpp {3}| returns \digitstt{\xintiOpp {3}}. + +\subsection{\csbh{xintDivision}, \csbh{xint\-Quo}, \csbh{xint\-Rem}, + \csbh{xintFDg}, \csbh{xintLDg}, \csbh{xintMON}, \csbh{xintMMON}, \csbh{xintOdd}} + +These macros\etype{\Ff\Ff} accept a fraction on input if this fraction in fact +reduces to an integer (if not an |\xintError:NotAnInteger| will be +raised).\etype{{\textcolor{black}{\upshape or}}\Ff} There is no difference in +the format of the outputs, which are still (possibly big) integers without +fraction slash nor trailing |[n]|, the sole difference is in the extended range +of accepted inputs. + +All have variants whose names start with |xintii| rather than |xint|; these +variants accept on input only integers in the strict format (they do not use +\csbxint{Num}). They thus have less overhead, and may be used when one is +dealing exclusively with (big) integers. These variants are already available in +\xintname, there is no need for \xintfracname to be loaded. + +\centeredline{|\xintNum {1e80}|} +\centeredline{\digitstt{\xintNum{1e80}}} + + +\etocdepthtag.toc {xintexpr} + +\section{Expandable expressions with the \xintexprname package}% +\label{sec:expr} + +The \xintexprname package was first released with version |1.07| of the +\xintname bundle. It loads automatically \xintfracname, hence +also \xintname and \xinttoolsname. + +% Release |1.09a| has extended the scope of |\xintexpr|-essions: infix +% comparison operators (|<|, |>|, |=|), logical operators (|&|, \verb+|+), +% functions (|round|, |sqrt|, |max|, |all|, etc...), conditional ``branching'' +% (|if| and |?|, |ifsgn| and |:|). + +The syntax is described in \autoref{sec:exprsummary} and +\autoref{sec:exprsummaryII}. + +\localtableofcontents + + +\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 \marg{expandable} may be serving as a +macro parameter, or a branch of the |?| two-way and |:| three-way operators; +else it is treated in a special manner: +\begin{enumerate} +\item it is allowed to occur only at the spots where numbers are legal, +\item the \meta{expandable} contents is then completely expanded as if it were + put in a |\csname..\endcsname|,\footnote{well, actually it \emph{is} put in + such a \texttt{\char92csname..\char92endcsname}.} thus it escapes entirely + the parser scope and infix notations will not be recognized except if the + expanded macros know how to handle them by themselves, +\item and this complete expansion \emph{must} produce a number or a fraction, + possibly with decimal mark and trailing |[n]|, the scientific notation is + \emph{not} authorized. +\end{enumerate} +Braces are the only way to input some number or fraction with +a trailing |[n]|: square brackets are +\emph{not} accepted in a |\xintexpr...\relax| if not within such braces. + + +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 +employed as argument to the other package macros. For this one must use one +of the two equivalent forms: +\begin{itemize} +\item \csbxint{theexpr}\meta{expandable\_expression}|\relax|\etype{x}, or +\item \csbxint{the}|\xintexpr|\meta{expandable\_expression}|\relax|.\etype{x} +\end{itemize} + +The computations are done \emph{exactly}, and with no simplification of the +result. The output format for the result can be coded inside the expression +through the use of one of the functions |round|, |trunc|, |float|, +|reduce|.\footnote{In |round| and |trunc| the second optional parameter is the + number of digits of the fractional part; in |float| it is the total number of + digits of the mantissa.} Here are some examples\par +\begingroup\raggedright\leftskip.5cm +{|\xinttheexpr 1/5!-1/7!-1/9!\relax|% + \digitstt{=\xinttheexpr 1/5!-1/7!-1/9!\relax}}\\ +{|\xinttheexpr round(1/5!-1/7!-1/9!,18)\relax|% + \digitstt{=\xinttheexpr round(1/5!-1/7!-1/9!,18)\relax}}\\ +{|\xinttheexpr float(1/5!-1/7!-1/9!,18)\relax|% + \digitstt{=\xinttheexpr float(1/5!-1/7!-1/9!,18)\relax}}\\ +{|\xinttheexpr reduce(1/5!-1/7!-1/9!)\relax|% + \digitstt{=\xinttheexpr reduce(1/5!-1/7!-1/9!)\relax}}\\ +{|\xinttheexpr 1.99^-2 - 2.01^-2 \relax|% + \digitstt{=\xinttheexpr 1.99^-2 - 2.01^-2 \relax}}\\ +{|\xinttheexpr round(1.99^-2 - 2.01^-2, 10)\relax|% + \digitstt{=\xinttheexpr round(1.99^-2 - 2.01^-2, 10) \relax}}\par +\endgroup + +\smallskip +\begingroup % 18 octobre, je reprends la méthode déjà utilisée au début du + % document le 9 octobre. +\leftmargini 0pt +\list\labelitemi{\def\makelabel#1{\hss\llap{#1}}\listparindent\parindent + \labelwidth\parindent + \itemindent\labelwidth}% +\item the expression may contain arbitrarily many levels of nested parenthesized + sub-expressions. +\item sub-contents giving numbers of fractions should be either + \begin{enumerate} + \item parenthesized, + \item a sub-expression |\xintexpr...\relax|, + \item or within braces. + \end{enumerate} + When a sub-expression is hit against in the midst of absorbing the + digits of a number, a |*| to force tacit multiplication is + inserted.\inmarg{1.09j}. Similarly, if it is an opening parenthesis + which is hit against.\inmarg{1.09k} + \item an expression can not be given as argument to the other package macros, + nor printed, for this one must use |\xinttheexpr...\relax| or + |\xintthe\xintexpr...\relax|. + \item one does not use |\xinttheexpr...\relax| as a sub-constituent of an + |\xintexpr...\relax| but simply |\xintexpr...\relax|; this is mainly because + most of the time |\xinttheexpr..\relax| will insert explicit square brackets + which are not parsable, as already mentioned, in the surrounding expression. +\item each \xintexprname{}ession is completely expandable and obtains + its result in two expansion steps. +\endlist +\endgroup + +In an algorithm implemented non-expandably, one may define macros to +expand to infix expressions to be used within others. One then has the +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 |\oodef\x {\xintexpr \a+\b\relax}| will do the +computation on the spot. + +\subsection{\texorpdfstring{\texttt{\protect\string\numexpr}}{\textbackslash + numexpr} or \texorpdfstring{\texttt{\protect\string\dimexpr}}{\textbackslash + dimexpr} expressions, count and dimension registers and variables} +\label{ssec:countinexpr} + +Count registers, count control sequences, dimen registers, +dimen control sequences, 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|. + +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. + +A token list variable must be prefixed by |\the|, it will not be unpacked +automatically (the parser will actually try |\number|, and thus fail). Do not +use |\the| but only |\number| with a dimen or skip, as the |\xintexpr| parser +doesn't understand |pt| and its presence is a syntax error. To use a dimension +expressed in terms of points or other \TeX{} recognized units, incorporate it in +|\dimexpr...\relax|. + +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{\digitstt{\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}. + +\subsection{Catcodes and spaces} + +\subsubsection{\csbh{xintexprSafeCatcodes}} +\label{xintexprSafeCatcodes} +%{\small New with release |1.09a|.\par} + +Active characters will interfere with |\xintexpr|-essions. One may prefix them +with |\string| within |\xintexpr..\relax|, thus preserving expandability, or +there is the non-expandable \csa{xintexprSafeCatcodes} which can be issued +before the use of |\xintexpr|. This command sets (not globally) the catcodes of +the relevant characters to safe values. This is used internally by +\csbxint{NewExpr} (restoring the catcodes on exit), hence \csbxint{NewExpr} does +not have to be protected against active characters. + +\subsubsection{\csbh{xintexprRestoreCatcodes}}\label{xintexprRestoreCatcodes} +%{\small New with release |1.09a|.\par} + +Restores the catcodes to the earlier state. + +\bigskip + +Unbraced spaces inside an |\xinttheexpr...\relax| should mostly be +innocuous (except inside macro arguments). + +|\xintexpr| and |\xinttheexpr| are for the most part agnostic regarding +catcodes: +(unbraced) digits, binary operators, minus and plus signs as prefixes, dot as +decimal mark, parentheses, may be indifferently of catcode letter or other or +subscript or superscript, ..., it doesn't matter.\footnote{Furthermore, although + \csbxint{expr} uses \csa{string}, it is (we hope) escape-char agnostic.} + +The characters \verb[+,-,*,/,^,!,&,|,?,:,<,>,=,(,),"[, the dot and the comma +should not be active 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. + + +% In the case of the factorial, the macro +% |\xintFac| may be used rather than the postfix |!|, preferably within braces as +% this will avoid the subsequent slow scan digit by digit of its expansion (other +% macros from the \xintfracname package generally \emph{must} be used within a +% brace pair, as they expand to fractions |A/B[n]| with the trailing |[n]|; the +% |\xintFac| produces an integer with no |[n]| and braces are only optional, but +% preferable, as the scanner will get the job done faster.) + +% Sub-material within braces is treated technically in a different manner, and +% depending on the macros used therein may be more sensitive to the catcode of the +% five operations. + +Digits, slash, square brackets, minus sign, in the output from an |\xinttheexpr| +are all of catcode 12. For |\xintthefloatexpr| the `e' in the output is of +catcode 11. + +A macro with arguments will expand and grab its arguments before the +parser may get a chance to see them, so the situation with catcodes and spaces +is not the same within such macro arguments (or within braces used to protect +square brackets). + + +\subsection{Expandability, \csh{xinteval}} + +As is the case with all other package macros |\xintexpr| \fexpan ds (in two +steps) to its final (non-printable) result; and |\xinttheexpr| \fexpan ds (in +two steps) to the chain of digits (and possibly minus sign |-|, decimal mark +|.|, fraction slash |/|, scientific |e|, square brackets |[|, |]|) representing +the result. + +Starting with |1.09j|, an |\xintexpr..\relax| can be inserted without |\xintthe| +prefix inside an |\edef|, or a |\write|.\MyMarginNote{New with 1.09j!} It +expands to a private more compact representation (five tokens) than +|\xinttheexpr| or |\xintthe\xintexpr|. + +The material between |\xintexpr| and |relax| should contain only expandable +material; the exception is with brace pairs which, apart from their usual r\^ole +for macro arguments, are also allowed in places where the scanner expects a +numeric operand, the braced material should expand to some number (or fraction), +but scientific notation is not allowed. Conversely fractions in |A/B[N]| format +(either explicit or from macro expansion) must be enclosed in such a brace pair. + +The once expanded |\xintexpr| is |\romannumeral0\xinteval|. And there is +similarly |\xintieval|, |\xintiieval|, and |\xintfloateval|. For the other cases +one can use |\romannumeral-`0| as prefix. For an example of expandable +algorithms making use of chains of |\xinteval|-uations connected via +|\expandafter| see \autoref{ssec:fibonacci}.\MyMarginNote{New with 1.09j!} + +An expression can only be legally finished by a |\relax| token, which +will be absorbed. + + +\subsection{Memory considerations} + +The parser creates an undefined control sequence for each intermediate +computation (this does not refer to the intermediate steps needed in +the evaluations of the \csbxint{Add}, \csbxint{Mul}, etc... macros corresponding +to the infix operators, but only to each conversion of such an infix operator +into a computation). So, a moderately sized expression might create 10, or 20 +such control sequences. On my \TeX{} installation, the memory available for such +things is of circa \np{200000} multi-letter control words. So this means that a +document containing hundreds, perhaps even thousands of expressions will compile +with no problem. + +Besides the hash table, also \TeX{} main memory is impacted. Thus, if +\xintexprname is used for computing plots\footnote{this is not very + probable as so far \xintname does not include a mathematical library + with floating point calculations, but provides only the basic + operations of algebra.}, this may cause a problem. + + + +There is a solution.\footnote{which convinced me that I could stick with the + parser implementation despite its potential impact on the hash-table + and other parts of \TeX{}'s memory.} + +A +document can possibly do tens of thousands of evaluations only +if some formulas are being used repeatedly, for example inside loops, with +counters being incremented, or with data being fetched from a file. So it is the +same formula used again and again with varying numbers inside. + +With the \csbxint{NewExpr} command, it is possible to convert once and +for all an expression containing parameters into an expandable macro +with parameters. Only this initial definition of this macro actually +activates the \csbxint{expr} parser and will (very moderately) impact +the hash-table: once this unique parsing is done, a macro with +parameters is produced which is built-up recursively from the +\csbxint{Add}, \csbxint{Mul}, etc... macros, exactly as it would be +necessary to do without the facilities of the \xintexprname package. + +\subsection{The \csbh{xintNewExpr} command}\label{xintNewExpr} + +% This allows to define a completely expandable macro with parameters, expanding +% in two steps to its final evaluation, and corresponding to the given +% \xintname{}expression where the parameters are input using the usual +% macro-parameter: |#1|, ..., |#9|. + +The command is used +as:\centeredline{|\xintNewExpr{\myformula}[n]|\marg{stuff}, where} +\begin{itemize} +\item \meta{stuff} will be inserted inside |\xinttheexpr . . . \relax|, +\item |n| is an integer between zero and nine, inclusive, and tells how many + parameters will |\myformula| have (it is \emph{mandatory} even if + |n=0|\footnote{there is some use for \csa{xintNewExpr}|[0]| compared to an + \csa{edef} as \csa{xintNewExpr} has some built-in catcode protection.}) +\item the placeholders |#1|, |#2|, ..., |#n| are used inside \meta{stuff} + in their usual r\^ole. +\end{itemize} + +The macro |\myformula| is defined without checking if it +already exists, \LaTeX{} users might prefer to do first |\newcommand*\myformula +{}| to get a reasonable error message in case |\myformula| already exists. + +The definition of |\myformula| made by |\xintNewExpr| is global. The protection +against active characters is done automatically. + +It will be a completely expandable macro entirely built-up using |\xintAdd|, +|\xintSub|, |\xintMul|, |\xintDiv|, |\xintPow|, etc\dots as corresponds to the +expression written with the infix operators. + +\begin{framed} + A ``formula'' created by |\xintNewExpr| is thus a macro whose parameters are + given to a possibly very complicated combination of the various macros of + \xintname and \xintfracname; hence one can not use infix notation inside the + arguments, as in for example |\myformula {28^7-35^12}| which would have been + allowed by + \centeredline{|\def\myformula #1{\xinttheexpr (#1)^3\relax}|} + One will have to do |\myformula {\xinttheexpr 28^7-35^12\relax}|, or redefine + |\myformula| to have more parameters. +\end{framed} + +% The formula may contain besides the infix operators and macro +% parameters some arbitrary decimal numbers, fractions (within braces) and also +% macros. If these macros do not involve the parameters, nothing special needs to +% be done, they will be expanded once during the construction of the formula. But +% if the parameters are to be used within the macros themselves, then the macro +% should be code with an underscore |_| rather than a backslash |\|. + +\dverb|@ +@\xintNewExpr\myformA[4]{ #1 + #2 * #3^#4 } +@\xintNewExpr\myformB[3]{ (#1 + 1.75)^#2 + #3*2.7 } +@\xintNewExpr\myformC[3]{ #1*#1+#2*#2+#3*#3-(#1*#2+#2*#3+#3*#1) } +@\xintNewExpr\myformD[2]{ (1+1.5*#1)^#2 - (1+1.5*#2)^#1 } +@\xintNewExpr\myformE[2]{ -----((((((#1*10-5*#2)))))) } +@\xintNewExpr\myformF[4]{ -#1^-#2*-#3-#4 } +@\xintNewExpr\myformG[4]{ -#1*-#2^-#3-#4 } +\xintNewExpr\DET[9]{ #1*#5*#9+#2*#6*#7+#3*#4*#8-#1*#6*#8-#2*#4*#9-#3*#5*#7 }| + +% \xintNewExpr\myformA[4]{ #1 + #2 * #3^#4 } +% \xintNewExpr\myformB[3]{ (#1 + 1.75)^#2 + #3*2.7 } +% \xintNewExpr\myformC[3]{ #1*#1+#2*#2+#3*#3-(#1*#2+#2*#3+#3*#1) } +% \xintNewExpr\myformD[2]{ (1+1.5*#1)^#2 - (1+1.5*#2)^#1 } +% \xintNewExpr\myformE[2]{ -----((((((#1*10-5*#2)))))) } +% \xintNewExpr\myformF[4]{ -#1^-#2*-#3-#4 } +% \xintNewExpr\myformG[4]{ -#1*-#2^-#3-#4 } +\xintNewExpr\DET[9]{ #1*#5*#9+#2*#6*#7+#3*#4*#8-#1*#6*#8-#2*#4*#9-#3*#5*#7 } + +\ttfamily +% |\meaning\myformA:|\printnumber{\meaning\myformA}\endgraf +% |\meaning\myformB:|\printnumber{\meaning\myformB}\endgraf +% |\meaning\myformC:|\printnumber{\meaning\myformC}\endgraf +% |\meaning\myformD:|\printnumber{\meaning\myformD}\endgraf +% |\meaning\myformE:|\printnumber{\meaning\myformE}\endgraf +% |\meaning\myformF:|\printnumber{\meaning\myformF}\endgraf +% |\meaning\myformG:|\printnumber{\meaning\myformG}\endgraf +|\meaning\DET:|\printnumber{\meaning\DET}\endgraf + + +\centeredline{|\xintNum{\DET {1}{1}{1}{10}{-10}{5}{11}{-9}{6}}|% + \digitstt{=\xintNum{\DET {1}{1}{1}{10}{-10}{5}{11}{-9}{6}}}}% +\centeredline{|\xintNum{\DET {1}{2}{3}{10}{0}{-10}{21}{2}{-17}}|% + \digitstt{=\xintNum{\DET {1}{2}{3}{10}{0}{-10}{21}{2}{-17}}}} + + +\rmfamily + + +\emph{Remark:} |\meaning| has been used within the argument to a |\printnumber| +command, to avoid going into the right margin, but this zaps all spaces +originally in the output from |\meaning|. Here is as an illustration the raw +output of +|\meaning| on the previous example: + +\ttfamily +\meaning\DET +\rmfamily + +This is why |\printnumber| was used, to have breaks across lines. + +\subsubsection {Use of conditional operators} + +The |1.09a| conditional operators |?| and |:| cannot be parsed by |\xintNewExpr| +when they contain macro parameters |#1|,\dots, |#9| within their scope. However +replacing them with the functions |if| and, respectively |ifsgn|, the parsing +should succeed. And the created macro will \emph{not evaluate the branches + to be skipped}, thus behaving exactly like |?| and |:| would have in the +|\xintexpr|. + +\xintNewExpr\Formula [3]{ if((#1>#2) & (#2>#3), + sqrt(#1-#2)*sqrt(#2-#3), #1^2+#3/#2) } + +\centeredline{|\xintNewExpr\Formula [3]|} +\centeredline{|{ if((#1>#2) & (#2>#3), + sqrt(#1-#2)*sqrt(#2-#3), #1^2+#3/#2) }|} + +\ttfamily +\noindent|\meaning\Formula:|\printnumber{\meaning\Formula}\endgraf + +\rmfamily +This formula (with |\xintifNotZero|) will gobble the false branch. + +Remark: this +|\XINTinFloatSqrt| macro is a non-user package macro used internally within +|\xintexpr|-essions, it produces the result in |A[n]| form rather +than in scientific notation, and for reasons of the inner workings of +|\xintexpr|-essions, this is necessary; a hand-made macro would +have used instead the equivalent |\xintFloatSqrt|. + +Another example + +\xintNewExpr\myformula[3]{ ifsgn(#1,#2/#3,#2-#3,#2*#3) } +\centeredline{|\xintNewExpr\myformula [3]|} +\centeredline{|{ ifsgn(#1,#2/#3,#2-#3,#2*#3) }|} + +\ttfamily +\noindent\printnumber{\meaning\myformula}\endgraf + +\rmfamily +Again, this macro gobbles the false branches, as would have the operator |:| +inside an |\xintexpr|-ession. + + + +\subsubsection{Use of macros} + + +For macros to be inserted within such a created \xintname-formula command, there +are two cases: +\begin{itemize} +\item the macro does not involve the numbered parameters in its arguments: it + may then be left as is, and will be evaluated once during the construction of + the formula, +\item it does involve at least one of the parameters as argument. Then: + \begin{enumerate} + \item the whole thing (macro + argument) should be braced (not necessary if it + is already included into a braced group), + \item the macro should be coded with an underscore |_| in place of the + backslash |\|. + \item the parameters should be coded with a dollar sign |$1|, |$2|, etc... + \end{enumerate} +\end{itemize} + +Here is a silly example illustrating the general principle (the macros here have +equivalent functional forms which are more convenient; but some of the more +obscure package macros of \xintname dealing with integers do not have functions +pre-defined to be in correspondance with them): + +\dverb|@ +\xintNewExpr\myformI[2]{ {_xintRound{$1}{$2}} - {_xintTrunc{$1}{$2}} } +\meaning\myformI:| + +\xintNewExpr\myformI[2]{ {_xintRound{$1}{$2}} - {_xintTrunc{$1}{$2}} } +\ttfamily +\centeredline{\meaning\myformI} + +\dverb|@ +\xintNewIIExpr\formula [3]{rem(#1,quo({_the_numexpr $2_relax},#3))} +\meaning\formula:|%$ + +\xintNewIIExpr\formula [3]{rem(#1,quo({_the_numexpr $2_relax},#3))}%$ +\noindent{\meaning\formula}\endgraf + +\rmfamily + +\subsection{\csbh{xintiexpr}, \csbh{xinttheiexpr}} +\label{xintiexpr}\label{xinttheiexpr} +% \label{xintnumexpr}\label{xintthenumexpr} + +Equivalent\etype{x} to doing |\xintexpr round(...)\relax|. Thus, only the final +result is rounded to an integer. Half integers are rounded towards $+\infty$ for +positive numbers and towards $-\infty$ for negative ones. Can be used on comma +separated lists of expressions. + +Initially\MyMarginNote{|1.09i| warning} baptized |\xintnumexpr|, +|\xintthenumexpr| but +I am not too happy about this choice of name; one should keep in mind that +|\numexpr|'s integer division rounds, whereas in |\xintiexpr|, the |/| is an +exact fractional operation, and only the final result is rounded to an integer. + +So |\xintnumexpr|, |\xintthenumexpr| are deprecated, and although still provided +for the time being this might change in the future. + +\subsection{\csbh{xintiiexpr}, \csbh{xinttheiiexpr}} +\label{xintiiexpr}\label{xinttheiiexpr} + +This variant\etype{x} maps |/| to the euclidean quotient and deals almost only +with (long) integers. It uses the `ii' macros for addition, subtraction, +multiplication, power, square, sums, products, euclidean quotient and remainder. +The |round| and |trunc|, in the presence of the second optional argument, are +mapped to \csbxint{iRound}, respectively \csbxint{iTrunc}, hence they always +produce (long) integers. + +To input a fraction to |round|, |trunc|, |floor| or |ceil| one can +use braces, else the |/| will do the euclidean quotient. +The minus sign should be put together with the fraction: |round(-{30/18})| is +illegal (even if the fraction had been an integer), use +|round({-30/18})|\digitstt{=\xinttheiiexpr round({-30/18})\relax}. + +Decimal numbers are allowed only if postfixed immediately with |e| or |E|, the +number will then be truncated to an integer after multiplication by the power of +ten with exponent the number following |e| or |E|. +\centeredline{|\xinttheiiexpr 13.4567e3+10000123e-3\relax|% + \digitstt{=\xinttheiiexpr 13.4567e3+10000123e-3\relax}} +% + +A fraction within braces should be followed immediately by an |e| (or inside a +|round|, |trunc|, etc...) to convert it +into an integer as expected by the main operations. The truncation is only done +after the |e| action. + +The |reduce| function is not available and will raise un error. The |frac| +function also. The |sqrt| function is mapped to \csbxint{iSqrt}. + +Numbers in float notation, obtained via a macro like \csbxint{FloatSqrt}, are a +bit of a challenge: they can not be within braces (this has been mentioned +already, |e| is not legal within braces) and if not braced they will be +truncated when the parser meets the |e|. The way out of the dilemma is to use a +sub-expression: +\centeredline{|\xinttheiiexpr \xintFloatSqrt{2}\relax|% + \digitstt{=\xinttheiiexpr \xintFloatSqrt{2}\relax}} +\centeredline{|\xinttheiiexpr \xintexpr\xintFloatSqrt{2}\relax e10\relax|% + \digitstt{=\xinttheiiexpr \xintexpr\xintFloatSqrt{2}\relax e10\relax}} +\centeredline{|\xinttheiiexpr round(\xintexpr\xintFloatSqrt{2}\relax,10)\relax|% + \digitstt{=\xinttheiiexpr round(\xintexpr\xintFloatSqrt{2}\relax,10)\relax}} +(recall that |round| is mapped within |\xintiiexpr..\relax| to \csbxint{iRound} +which always outputs an integer). + +The whole point of \csbxint{iiexpr} is to gain some speed in integer only +algorithms, and the above explanations related to how to 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. + + +\subsection{\csbh{xintboolexpr}, + \csbh{xinttheboolexpr}}\label{xintboolexpr}\label{xinttheboolexpr} +%{\small New in |1.09c|.\par} + +Equivalent\etype{x} to doing |\xintexpr ...\relax| and returning @1@ if the +result does not vanish, and @0@ is the result is zero. As |\xintexpr|, this +can be used on comma separated lists of expressions, and will return a +comma separated list of @0@'s and @1@'s. + + +\subsection{\csbh{xintfloatexpr}, + \csbh{xintthe\-float\-expr}}\label{xintfloatexpr}\label{xintthefloatexpr} + +\csbxint{floatexpr}|...\relax|\etype{x} is exactly like |\xintexpr...\relax| but +with the four binary operations and the power function mapped to +\csa{xintFloatAdd}, \csa{xintFloatSub}, \csa{xintFloatMul}, \csa{xintFloatDiv} +and \csa{xintFloatPower}. The precision is from the current setting of +|\xintDigits| (it can not be given as an optional parameter). + +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 +|D=\xinttheDigits| set to nine or less. Indeed the addition implicit in |1+1e-9| +(and executed when the closing parenthesis is found) will provoke the rounding +to |1|. Whereas |1.000000001|, when found as operand of one of the four +elementary operations is kept with |D+2| digits, and even more for the power +function. \centeredline{|\xintDigits:= 9; \xintthefloatexpr + (1+1e-9)-1\relax|\digitstt{=\xintthefloatexpr (1+1e-9)-1\relax}} +\centeredline{|\xintDigits:= 9; \xintthefloatexpr + 1.000000001-1\relax|\digitstt{=\xintthefloatexpr 1.000000001-1\relax}} + +For the fun of it:\xintDigits:=20; |\xintDigits:=20;|% +\centeredline{|\xintthefloatexpr (1+1e-7)^1e7\relax|% + \digitstt{=\xintthefloatexpr (1+1e-7)^1e7\relax}} + +|\xintDigits:=36;|\xintDigits:=36; +\centeredline{|\xintthefloatexpr + ((1/13+1/121)*(1/179-1/173))/(1/19-1/18)\relax|} +\centeredline{\digitstt{\xintthefloatexpr + ((1/13+1/121)*(1/179-1/173))/(1/19-1/18)\relax}} +\centeredline{|\xintFloat{\xinttheexpr + ((1/13+1/121)*(1/179-1/173))/(1/19-1/18)\relax}|} +\centeredline{\digitstt{\xintFloat + {\xinttheexpr((1/13+1/121)*(1/179-1/173))/(1/19-1/18)\relax}}} + +\xintDigits := 16; + +The latter result is the rounding of the exact result. The previous one has +rounding errors coming from the various roundings done for each +sub-expression. It was a bit funny to discover that |maple|, configured with +|Digits:=36;| and with decimal dots everywhere to let it input the numbers as +floats, gives exactly the same result with the same rounding errors +as does |\xintthefloatexpr|! + +Using |\xintthefloatexpr| only pays off compared to using |\xinttheexpr| +followed with |\xintFloat| if the computations turn out to involve hundreds of +digits. For elementary calculations with hand written numbers (not using the +scientific notation with exponents differing greatly) it will generally be more +efficient to use |\xinttheexpr|. The situation is quickly otherwise if one +starts using the Power function. Then, |\xintthefloat| is often useful; and +sometimes indispensable to achieve the (approximate) computation in reasonable +time. + +We can try some crazy things: +% +\centeredline{|\xintDigits:=12;\xintthefloatexpr 1.000000000000001^1e15\relax|} +% +\centeredline{\xintDigits:=12;% + \digitstt{\xintthefloatexpr 1.000000000000001^1e15\relax}} +% +Contrarily to some professional computing sofware which are our concurrents on +this market, the \digitstt{1.000000000000001} wasn't rounded to |1| despite the +setting of \csa{xintDigits}; it would have been if we had input it as +|(1+1e-15)|. + +% \xintDigits:=12; +% \pdfresettimer +% \edef\z{\xintthefloatexpr 1.000000000000001^1e15\relax}% +% \edef\temps{\the\pdfelapsedtime}% +% \xintRound {5}{\temps/65536}s\endgraf + + +\xintDigits := 16; % mais en fait \centeredline crée un groupe. + + +\subsection{\csbh{xintifboolexpr}}\label{xintifboolexpr} +%{\small New in |1.09c|.\par} + +\csh{xintifboolexpr}|{<expr>}{YES}{NO}|\etype{xnn} does |\xinttheexpr +<expr>\relax| and then executes the |YES| or the |NO| branch depending on +whether the outcome was non-zero or zero. |<expr>| can involove various |&| and +\verb+|+, parentheses, |all|, |any|, |xor|, the |bool| or |togl| operators, but +is not limited to them: the most general computation can be done, the test is on +whether the outcome of the computation vanishes or not. + +Will not work on an expression composed of comma separated sub-expressions. + +\subsection{\csbh{xintifboolfloatexpr}}\label{xintifboolfloatexpr} +%{\small New in |1.09c|.\par} + +\csh{xintifboolfloatexpr}|{<expr>}{YES}{NO}|\etype{xnn} does |\xintthefloatexpr +<expr>\relax| and then executes the |YES| or the |NO| branch depending on +whether the outcome was non zero or zero. + +\subsection{\csbh{xintifbooliiexpr}}\label{xintifbooliiexpr} +%{\small New in |1.09i|.\par} + +\csh{xintifbooliiexpr}|{<expr>}{YES}{NO}|\etype{xnn} does |\xinttheiiexpr +<expr>\relax| and then executes the |YES| or the |NO| branch depending on +whether the outcome was non zero or zero. + +\subsection{\csbh{xintNewFloatExpr}}\label{xintNewFloatExpr} + +This is exactly like \csbxint{NewExpr} except that the created formulas are +set-up to use |\xintthefloatexpr|. The precision used for numbers fetched as +parameters will be the one locally given by |\xintDigits| at the time of use of +the created formulas, not |\xintNewFloatExpr|. However, the numbers hard-wired +in the original expression will have been evaluated with the then current +setting for |\xintDigits|. + +\subsection{\csbh{xintNewIExpr}}\label{xintNewIExpr} +%{\small New in |1.09c|.\par } + +Like \csbxint{NewExpr} but using |\xinttheiexpr|. Former denomination was +|\xintNewNumExpr| which is deprecated and should not be used. + +\subsection{\csbh{xintNewIIExpr}}\label{xintNewIIExpr} +%{\small New in |1.09i|.\par } + +Like \csbxint{NewExpr} but using |\xinttheiiexpr|. + +\subsection{\csbh{xintNewBoolExpr}}\label{xintNewBoolExpr} +%{\small New in |1.09c|.\par } + +Like \csbxint{NewExpr} but using |\xinttheboolexpr|. + +\xintDigits:= 16; + +\subsection{Technicalities} + +As already mentioned \csa{xintNewExpr}|\myformula[n]| does not check the prior +existence of a macro |\myformula|. And the number of parameters |n| given as +mandatory argument withing square brackets should be (at least) equal +to the number of parameters in the expression. + +Obviously I should mention that \csa{xintNewExpr} itself can not be used in an +expansion-only context, as it creates a macro. + +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 +|\XINT_expr_usethe| which prints an error message in the document and in +the log file if it is executed, then a |\xint_protect| token, a token +doing the actual printing and finally a token |\.=A/B[n]|. Using +|\xinttheexpr| means zapping the first three things, the fourth one will +then unlock |A/B[n]| from the (presumably undefined, but it does not +matter) control sequence |\.=A/B[n]|. + +Thanks to the release |1.09j| added |\xint_protect| token and the fact +that |\XINT_expr_usethe| is |\protected|, one can now use |\xintexpr| +inside an |\edef|, with no need of the |\xintthe| prefix. + +\begin{framed} + Note that |\xintexpr| is thus compatible with complete expansion, contrarily + to |\numexpr| which is non-expandable, if not prefixed by |\the| or |\number|, + and away from contexts where \TeX{} is building a number. See + \autoref{ssec:fibonacci} for some illustration. +% +% \MyMarginNote[\kern\dimexpr\FrameSep+\FrameRule\relax]{New with 1.09j!} +\end{framed} + +I decided to put all intermediate results (from each evaluation of an infix +operators, or of a parenthesized subpart of the expression, or from application +of the minus as prefix, or of the exclamation sign as postfix, or any +encountered braced material) inside |\csname...\endcsname|, as this can be done +expandably and encapsulates an arbitrarily long fraction in a single token (left +with undefined meaning), thus providing tremendous relief to the programmer in +his/her expansion control. + +\begin{framed} + As the |\xintexpr| computations corresponding to functions and infix + or postfix operators are done inside |\csname...\endcsname|, the + \fexpan dability could possibly be dropped and one could imagine + implementing the basic operations with expandable but not \fexpan + dable macros (as \csbxint{XTrunc}.) I have not investigated that + 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. + +Some other problems will give rise to `error messages' macros giving some +indication on the location and nature of the problem. Mainly, an attempt has +been made to handle gracefully missing or extraneous parentheses. + +When the scanner is looking for a number and finds something else not otherwise +treated, it assumes it is the start of the function name and will expand forward +in the hope of hitting an opening parenthesis; if none is found at least it +should stop when encountering the |\relax| marking the end of the expressions. + +Note that |\relax| is mandatory (contrarily to a |\numexpr|). + + +\subsection{Acknowledgements} + +I was greatly helped in my preparatory thinking, prior to producing such an +expandable parser, by the commented source of the +\href{http://www.ctan.org/pkg/l3kernel}{l3fp} package, specifically the +|l3fp-parse.dtx| file (in the version of April-May 2013). Also the source of the +|calc| package was instructive, despite the fact that here for |\xintexpr| the +principles are necessarily different due to the aim of achieving expandability. + + +\etocdepthtag.toc {commandsB} + +\section{Commands of the \xintbinhexname package} +\label{sec:binhex} + +This package was first included in the |1.08| release of \xintname. It +provides expandable conversions of arbitrarily long numbers +to and from binary and hexadecimal. + +The argument is first \fexpan ded. It then may start with an optional minus +sign (unique, of category code other), followed with optional leading zeroes +(arbitrarily many, category code other) and then ``digits'' (hexadecimal +letters may be of category code letter or other, and must be +uppercased). The optional (unique) minus sign (plus sign is not allowed) is +kept in the output. Leading zeroes are allowed, and stripped. The +hexadecimal letters on output are of category code letter, and +uppercased. + +% \clearpage + +\localtableofcontents + + + +\subsection{\csbh{xintDecToHex}}\label{xintDecToHex} + +Converts from decimal to hexadecimal.\etype{f} + +\texttt{\string\xintDecToHex \string{\printnumber{2718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427427466391932003}\string}}\endgraf\noindent\digitstt{->\printnumber{\xintDecToHex{2718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427427466391932003}}} + +\subsection{\csbh{xintDecToBin}}\label{xintDecToBin} + +Converts from decimal to binary.\etype{f} + +\texttt{\string\xintDecToBin \string{\printnumber{2718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427427466391932003}\string}}\endgraf\noindent\digitstt{->\printnumber{\xintDecToBin{2718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427427466391932003}}} + +\subsection{\csbh{xintHexToDec}}\label{xintHexToDec} + +Converts from hexadecimal to decimal.\etype{f} + +\texttt{\string\xintHexToDec + \string{\printnumber{11A9397C66949A97051F7D0A817914E3E0B17C41B11C48BAEF2B5760BB38D272F46DCE46C6032936BF37DAC918814C63}\string}}\endgraf\noindent +\digitstt{->\printnumber{\xintHexToDec{11A9397C66949A97051F7D0A817914E3E0B17C41B11C48BAEF2B5760BB38D272F46DCE46C6032936BF37DAC918814C63}}} + +\subsection{\csbh{xintBinToDec}}\label{xintBinToDec} + +Converts from binary to decimal.\etype{f} + +\texttt{\string\xintBinToDec + \string{\printnumber{100011010100100111001011111000110011010010100100110101001011100000101000111110111110100001010100000010111100100010100111000111110000010110001011111000100000110110001000111000100100010111010111011110010101101010111011000001011101100111000110100100111001011110100011011011100111001000110110001100000001100101001001101101011111100110111110110101100100100011000100000010100110001100011}\string}}\endgraf\noindent +\digitstt{->\printnumber{\xintBinToDec{100011010100100111001011111000110011010010100100110101001011100000101000111110111110100001010100000010111100100010100111000111110000010110001011111000100000110110001000111000100100010111010111011110010101101010111011000001011101100111000110100100111001011110100011011011100111001000110110001100000001100101001001101101011111100110111110110101100100100011000100000010100110001100011}}} + +\subsection{\csbh{xintBinToHex}}\label{xintBinToHex} + +Converts from binary to hexadecimal.\etype{f} + +\texttt{\string\xintBinToHex + \string{\printnumber{100011010100100111001011111000110011010010100100110101001011100000101000111110111110100001010100000010111100100010100111000111110000010110001011111000100000110110001000111000100100010111010111011110010101101010111011000001011101100111000110100100111001011110100011011011100111001000110110001100000001100101001001101101011111100110111110110101100100100011000100000010100110001100011}\string}}\endgraf\noindent +\digitstt{->\printnumber{\xintBinToHex{100011010100100111001011111000110011010010100100110101001011100000101000111110111110100001010100000010111100100010100111000111110000010110001011111000100000110110001000111000100100010111010111011110010101101010111011000001011101100111000110100100111001011110100011011011100111001000110110001100000001100101001001101101011111100110111110110101100100100011000100000010100110001100011}}} + +\subsection{\csbh{xintHexToBin}}\label{xintHexToBin} + +Converts from hexadecimal to binary.\etype{f} + +\texttt{\string\xintHexToBin + \string{\printnumber{11A9397C66949A97051F7D0A817914E3E0B17C41B11C48BAEF2B5760BB38D272F46DCE46C6032936BF37DAC918814C63}\string}}\endgraf\noindent +\digitstt{->\printnumber{\xintHexToBin{11A9397C66949A97051F7D0A817914E3E0B17C41B11C48BAEF2B5760BB38D272F46DCE46C6032936BF37DAC918814C63}}} + + +\subsection{\csbh{xintCHexToBin}}\label{xintCHexToBin} + +Also converts from hexadecimal to binary.\etype{f} Faster on inputs with at +least one hundred hexadecimal digits. + +\texttt{\string\xintCHexToBin + \string{\printnumber{11A9397C66949A97051F7D0A817914E3E0B17C41B11C48BAEF2B5760BB38D272F46DCE46C6032936BF37DAC918814C63}\string}}\endgraf\noindent +\digitstt{->\printnumber{\xintCHexToBin{11A9397C66949A97051F7D0A817914E3E0B17C41B11C48BAEF2B5760BB38D272F46DCE46C6032936BF37DAC918814C63}}} + + + +\section{Commands of the \xintgcdname package} +\label{sec:gcd} + + +This package was included in the original release |1.0| of the \xintname bundle. + +Since release |1.09a| the macros filter their inputs through the \csbxint{Num} +macro, so one can use count registers, or fractions as long as they reduce to +integers. + +%% \clearpage + +\localtableofcontents + +\subsection{\csbh{xintGCD}}\label{xintGCD} + +\csa{xintGCD\n\m}\etype{\Numf\Numf} computes the greatest common divisor. It is +positive, except when both |N| and |M| vanish, in which case the macro returns +zero. +\centeredline{\csa{xintGCD}|{10000}{1113}|\digitstt{=\xintGCD{10000}{1113}}} +\centeredline{|\xintGCD{123456789012345}{9876543210321}=|\digitstt + {\xintGCD{123456789012345}{9876543210321}}} + +\subsection{\csbh{xintGCDof}}\label{xintGCDof} +%{\small New with release |1.09a|.\par} + +\csa{xintGCDof}|{{a}{b}{c}...}|\etype{f{$\to$}{\lowast\Numf}} computes the greatest common divisor of all +integers |a|, |b|, \dots{} The list argument +may be a macro, it is \fexpan ded first and must contain at least one item. + + +\subsection{\csbh{xintLCM}}\label{xintLCM} +%{\small New with release |1.09a|.\par} + +\csa{xintGCD\n\m}\etype{\Numf\Numf} computes the least common multiple. It is +|0| if one of the two integers vanishes. + +\subsection{\csbh{xintLCMof}}\label{xintLCMof} +%{\small New with release |1.09a|.\par} + +\csa{xintLCMof}|{{a}{b}{c}...}|\etype{f{$\to$}{\lowast\Numf}} computes the least +common multiple of all integers |a|, |b|, \dots{} The list argument may be a +macro, it is \fexpan ded first and must contain at least one item. + +\subsection{\csbh{xintBezout}}\label{xintBezout} + +\xintAssign{{\xintBezout {10000}{1113}}}\to\X +\xintAssign {\xintBezout {10000}{1113}}\to\A\B\U\V\D + +\csa{xintBezout\n\m}\etype{\Numf\Numf} returns five numbers |A|, |B|, |U|, |V|, +|D| within braces. |A| is the first (expanded, as usual) input number, |B| the +second, |D| is the GCD, and \digitstt{UA - VB = D}. \centeredline{|\xintAssign + {{\xintBezout {10000}{1113}}}\to\X|} \centeredline{|\meaning\X: + |\digitstt{\meaning\X }.} +\noindent{|\xintAssign {\xintBezout {10000}{1113}}\to\A\B\U\V\D|}\\ +|\A: |\digitstt{\A }, +|\B: |\digitstt{\B }, +|\U: |\digitstt{\U }, +|\V: |\digitstt{\V }, +|\D: |\digitstt{\D }.\\ +\xintAssign {\xintBezout {123456789012345}{9876543210321}}\to\A\B\U\V\D +\noindent{|\xintAssign {\xintBezout {123456789012345}{9876543210321}}\to\A\B\U\V\D +|}\\ +|\A: |\digitstt{\A }, +|\B: |\digitstt{\B }, +|\U: |\digitstt{\U }, +|\V: |\digitstt{\V }, +|\D: |\digitstt{\D }. + + +\subsection{\csbh{xintEuclideAlgorithm}}\label{xintEuclideAlgorithm} + +\xintAssign {{\xintEuclideAlgorithm {10000}{1113}}}\to\X + +\def\restorebracecatcodes + {\catcode`\{=1 \catcode`\}=2 } + +\def\allowlistsplit + {\catcode`\{=12 \catcode`\}=12 \allowlistsplita } + +\def\allowlistsplitx {\futurelet\listnext\allowlistsplitxx } + +\def\allowlistsplitxx {\ifx\listnext\relax \restorebracecatcodes + \else \expandafter\allowlistsplitxxx \fi } +\begingroup +\catcode`\[=1 +\catcode`\]=2 +\catcode`\{=12 +\catcode`\}=12 +\gdef\allowlistsplita #1{[#1\allowlistsplitx {] +\gdef\allowlistsplitxxx {#1}% + [{#1}\hskip 0pt plus 1pt \allowlistsplitx ] +\endgroup + +\csa{xintEuclideAlgorithm\n\m}\etype{\Numf\Numf} applies the Euclide algorithm +and keeps a copy of all quotients and remainders. \centeredline{|\xintAssign + {{\xintEuclideAlgorithm {10000}{1113}}}\to\X|} + +|\meaning\X: |\digitstt{\expandafter\allowlistsplit + \meaning\X\relax .} + +The first token is the number of steps, the second is |N|, the +third is the GCD, the fourth is |M| then the first quotient and +remainder, the second quotient and remainder, \dots until the +final quotient and last (zero) remainder. + +\subsection{\csbh{xintBezoutAlgorithm}}\label{xintBezoutAlgorithm} + + +\xintAssign {{\xintBezoutAlgorithm {10000}{1113}}}\to\X + +\csa{xintBezoutAlgorithm\n\m}\etype{\Numf\Numf} applies the Euclide algorithm +and keeps a copy of all quotients and remainders. Furthermore it computes the +entries of the successive products of the 2 by 2 matrices +$\left(\vcenter{\halign {\,#&\,#\cr q & 1 \cr 1 & 0 \cr}}\right)$ formed from +the quotients arising in the algorithm. \centeredline{|\xintAssign + {{\xintEuclideAlgorithm {10000}{1113}}}\to\X|} + +|\meaning\X: |\digitstt{\expandafter\allowlistsplit\meaning\X \relax .} + +The first token is the number of steps, the second is |N|, then +|0|, |1|, the GCD, |M|, |1|, |0|, the first quotient, the first +remainder, the top left entry of the first matrix, the bottom left +entry, and then these four things at each step until the end. + + +\subsection{\csbh{xintTypesetEuclideAlgorithm}\texorpdfstring{\allowbreak\null\hspace*{.25cm}}{}}% +\label{xintTypesetEuclideAlgorithm} + +This macro is just an example of how to organize the data returned by +\csa{xintEuclideAlgorithm}.\ntype{\Numf\Numf} Copy the source code to a new +macro and modify it to what is needed. +\centeredline{|\xintTypesetEuclideAlgorithm {123456789012345}{9876543210321}|} +\xintTypesetEuclideAlgorithm {123456789012345}{9876543210321} + + +\subsection{\csbh{xintTypesetBezoutAlgorithm}}% +\label{xintTypesetBezoutAlgorithm} + +This macro is just an example of how to organize the data returned by +\csa{xintBezoutAlgorithm}.\ntype{\Numf\Numf} Copy the source code to a new +macro and modify it to what is needed. +\centeredline{|\xintTypesetBezoutAlgorithm {10000}{1113}|} +\xintTypesetBezoutAlgorithm {10000}{1113} + + +\section{Commands of the \xintseriesname package} +\label{sec:series} + +Some arguments to the package commands are macros which are expanded only later, +when given their parameters. The arguments serving as indices are systematically +given to a |\numexpr| expressions (new with |1.06|!) , hence \fexpan ded, +they may be count registers, etc... + +This package was first released with version |1.03| of the \xintname bundle. + +We use \Ff{} for the expansion type of various macro arguments, but if only +\xintname and not \xintfracname is loaded this should be more appropriately +\Numf. The macro \csbxint{iSeries} is special and expects summing big integers +obeying the strict format, even if \xintfracname is loaded. + +%% \clearpage + +\localtableofcontents + +\subsection{\csbh{xintSeries}}\label{xintSeries} + +\def\coeff #1{\xintiiMON{#1}/#1.5} % (-1)^n/(n+1/2) +\edef\w {\xintSeries {0}{50}{\coeff}} +\edef\z {\xintJrr {\w}[0]} + +\csa{xintSeries}|{A}{B}{\coeff}|\etype{\numx\numx\Ff} computes +$\sum_{\text{|n=A|}}^{\text{|n=B|}}|\coeff{n}|$. The initial and final indices +must obey the |\numexpr| constraint of expanding to numbers at most |2^31-1|. +The |\coeff| macro must be a one-parameter \fexpan dable command, taking on +input an explicit number |n| and producing some number or fraction |\coeff{n}|; +it is expanded at the time it is +needed.\footnote{\label{fn:xintiiMON}\csbxint{iiMON} is like \csbxint{MON} but + does not parse its argument through \csbxint{Num}, for efficiency; other + macros of this type are \csbxint{iiAdd}, \csbxint{iiMul}, + \csbxint{iiSum}, \csbxint{iiPrd}, \csbxint{iiMMON}, + \csbxint{iiLDg}, \csbxint{iiFDg}, \csbxint{iiOdd}, \dots} +% +\dverb|@ +\def\coeff #1{\xintiiMON{#1}/#1.5} % (-1)^n/(n+1/2) +\edef\w {\xintSeries {0}{50}{\coeff}} % we want to re-use it +\edef\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 \]| +\[ \sum_{n=0}^{n=50} \frac{(-1)^n}{n+\frac12} = \xintFrac\z \] +For info, +before action by |\xintJrr| the inner representation of the result has a +denominator of |\xintLen {\xintDenominator\w}=|\xintLen +{\xintDenominator\w} digits. This troubled me as @101!!@ has only 81 +digits: |\xintLen {\xintQuo {\xintFac {101}}{\xintiMul {\xintiPow + {2}{50}}{\xintFac{50}}}}|\digitstt{=\xintLen {\xintQuo {\xintFac + {101}}{\xintiMul {\xintiPow {2}{50}}{\xintFac{50}}}}}. The +explanation lies in the too clever to be efficient |#1.5| trick. It +leads to a silly extra @5^{51}@ (which has \xintLen {\xintPow {5}{51}} +digits) in the denominator. See the explanations in the next section. + +\begin{framed} + Note: as soon as the coefficients look like factorials, it is more + efficient to use the \csbxint{RationalSeries} macro whose evaluation + will avoid a denominator build-up; indeed the raw operations of + addition and subtraction of fractions blindly multiply out + denominators. So the raw evaluation of $\sum_{n=0}^{|N|}1/n!$ with + \csa{xintSeries} will have a denominator equal to $\prod_{n=0}^{|N|} + n!$. Needless to say this makes it more difficult to compute the exact + value of this sum with |N=50|, for example, whereas with + \csbxint{RationalSeries} the denominator does not + get bigger than $50!$. + +\footnotesize + For info: by the way $\prod_{n=0}^{50} n!$ is easily computed by \xintname + and is a number with 1394 digits. And $\prod_{n=0}^{100} n!$ is also + computable by \xintname (24 seconds on my laptop for the brute force + iterated multiplication of all factorials, a + specialized routine would do it faster) and has 6941 digits (this + means more than two pages if printed...). Whereas $100!$ only has + 158 digits. +\end{framed} + +% \newcount\cntb +% \cnta 2 +% \loop +% \advance\cntb by \xintLen{\xintFac{\the\cnta}}% +% \ifnum\cnta < 50 +% \advance\cnta 1 +% \repeat +% \the\cntb + +% \cnta 2 +% \def\z{1} +% \pdfresettimer +% \loop +% \edef\z {\xintiMul\z{\xintFac{\the\cnta}}}% +% \ifnum\cnta < 100 +% \advance\cnta 1 +% \repeat +% \edef\temps{\the\pdfelapsedtime}% + +% \temps: \xintQuo\temps{\xintiMul{60}{65536}} minutes, +% \xintQuo{\xintRem\temps{\xintiMul{60}{65536}}}{65536} secondes et +% \xintiTrunc {2}{\xintRem\temps{65536}/65536} centièmes de secondes +% 1573518: 0 minutes, 24 secondes et 0 centièmes de secondes +% nota bene, marrant c'était 0,99 centièmes en fait. + +% \xintLen\z + +% \printnumber\z + +\setlength{\columnsep}{0pt} +\dverb|@ +\def\coeffleibnitz #1{\the\numexpr\ifodd #1 1\else-1\fi\relax/#1[0]} +\cnta 1 +\loop % in this loop we recompute from scratch each partial sum! +% we can afford that, as \xintSeries is fast enough. +\noindent\hbox to 2em{\hfil\texttt{\the\cnta.} }% + \xintTrunc {12} + {\xintSeries {1}{\cnta}{\coeffleibnitz}}\dots +\endgraf +\ifnum\cnta < 30 \advance\cnta 1 \repeat| +\begin{multicols}{3} + \def\coeffleibnitz #1{\the\numexpr\ifodd #1 1\else-1\fi\relax/#1[0]} \cnta 1 + \loop + \noindent\hbox to 2em{\hfil\digitstt{\the\cnta.} }% + \xintTrunc {12}{\xintSeries {1}{\cnta}{\coeffleibnitz}}\dots + \endgraf + \ifnum\cnta < 30 \advance\cnta 1 \repeat +\end{multicols} + +\subsection{\csbh{xintiSeries}}\label{xintiSeries} + +\def\coeff #1{\xintiTrunc {40} + {\the\numexpr\ifodd #1 -2\else2\fi\relax/\the\numexpr 2*#1+1\relax [0]}}% + + \csa{xintiSeries}|{A}{B}{\coeff}|\etype{\numx\numx f} computes + $\sum_{\text{|n=A|}}^{\text{|n=B|}}|\coeff{n}|$ where |\coeff{n}| + must \fexpan d to a (possibly long) integer in the strict format. +\dverb|@ +\def\coeff #1{\xintiTrunc {40}{\xintMON{#1}/#1.5}}% +% better: +\def\coeff #1{\xintiTrunc {40} + {\the\numexpr 2*\xintiiMON{#1}\relax/\the\numexpr 2*#1+1\relax [0]}}% +% better still: +\def\coeff #1{\xintiTrunc {40} + {\the\numexpr\ifodd #1 -2\else2\fi\relax/\the\numexpr 2*#1+1\relax [0]}}% +% (-1)^n/(n+1/2) times 10^40, truncated to an integer. +\[ \sum_{n=0}^{n=50} \frac{(-1)^n}{n+\frac12} \approx + \xintTrunc {40}{\xintiSeries {0}{50}{\coeff}[-40]}\dots\]| + +The |#1.5| trick to define the |\coeff| macro was neat, but |1/3.5|, for +example, turns internally into |10/35| whereas it would be more efficient to +have |2/7|. The second way of coding the wanted coefficient avoids a superfluous +factor of five and leads to a faster evaluation. The third way is faster, after +all there is no need to use \csbxint{MON} (or rather +\hyperref[fn:xintiiMON]{\csa{xintiiMON}} which has +less parsing overhead) on integers +obeying the \TeX{} bound. The denominator having no sign, we have added the +|[0]| as this speeds up (infinitesimally) the parsing. +\[ \sum_{n=0}^{n=50} \frac{(-1)^n}{n+\frac12} \approx \xintTrunc +{40}{\xintiSeries {0}{50}{\coeff}[-40]}\] We should have cut out at +least the last two digits: truncating errors originating with the first +coefficients of the sum will never go away, and each truncation +introduces an uncertainty in the last digit, so as we have 40 terms, we +should trash the last two digits, or at least round at 38 digits. It is +interesting to compare with the computation where rounding rather than +truncation is used, and with the decimal +expansion of the exactly computed partial sum of the series: +\dverb|@ +\def\coeff #1{\xintiRound {40} % rounding at 40 + {\the\numexpr\ifodd #1 -2\else2\fi\relax/\the\numexpr 2*#1+1\relax [0]}}% +% (-1)^n/(n+1/2) times 10^40, rounded to an integer. +\[ \sum_{n=0}^{n=50} \frac{(-1)^n}{n+\frac12} \approx + \xintTrunc {40}{\xintiSeries {0}{50}{\coeff}[-40]}\] +\def\exactcoeff #1% + {\the\numexpr\ifodd #1 -2\else2\fi\relax/\the\numexpr 2*#1+1\relax [0]}% +\[ \sum_{n=0}^{n=50} \frac{(-1)^n}{n+\frac12} + = \xintTrunc {50}{\xintSeries {0}{50}{\exactcoeff}}\dots\]| + +\def\coeff #1{\xintiRound {40} + {\the\numexpr\ifodd #1 -2\else2\fi\relax/\the\numexpr 2*#1+1\relax [0]}}% +% (-1)^n/(n+1/2) times 10^40, rounded to an integer. +\[ \sum_{n=0}^{n=50} \frac{(-1)^n}{n+\frac12} \approx + \xintTrunc {40}{\xintiSeries {0}{50}{\coeff}[-40]}\] +\def\exactcoeff #1% + {\the\numexpr\ifodd #1 -2\else2\fi\relax/\the\numexpr 2*#1+1\relax [0]}% +\[ \sum_{n=0}^{n=50} \frac{(-1)^n}{n+\frac12} + = \xintTrunc {50}{\xintSeries {0}{50}{\exactcoeff}}\dots\] +This shows indeed that our sum of truncated terms +estimated wrongly the 39th and 40th digits of the exact result\footnote{as + the series + is alternating, we can roughly expect an error of $\sqrt{40}$ and the + last two digits are off by 4 units, which is not contradictory to our + expectations.} and that the sum of rounded terms fared a bit better. + +\subsection{\csbh{xintRationalSeries}}\label{xintRationalSeries} + +%{\small \hspace*{\parindent}New with release |1.04|.\par} + +\noindent \csa{xintRationalSeries}|{A}{B}{f}{\ratio}|\etype{\numx\numx\Ff\Ff} +evaluates $\sum_{\text{|n=A|}}^{\text{|n=B|}}|F(n)|$, where |F(n)| is specified +indirectly via the data of |f=F(A)| and the one-parameter macro |\ratio| which +must be such that |\macro{n}| expands to |F(n)/F(n-1)|. The name indicates that +\csa{xintRationalSeries} was designed to be useful in the cases where +|F(n)/F(n-1)| is a rational function of |n| but it may be anything expanding to +a fraction. The macro |\ratio| must be an expandable-only compatible command and +expand to its value after iterated full expansion of its first token. |A| and +|B| are fed to a |\numexpr| hence may be count registers or arithmetic +expressions built with such; they must obey the \TeX{} bound. The initial term +|f| may be a macro |\f|, it will be expanded to its value representing |F(A)|. + +\dverb|@ +\def\ratio #1{2/#1[0]}% 2/n, to compute exp(2) +\cnta 0 % previously declared count +\loop \edef\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{}\endgraf +\ifnum\cnta<20 \advance\cnta 1 \repeat| + +\def\ratio #1{2/#1[0]}% 2/n, comes from the series of exp(2) +\cnta 0 +\loop +\edef\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{}\endgraf +\ifnum\cnta<20 \advance\cnta 1 \repeat + +\medskip +Such computations would become quickly completely inaccessible via the +\csbxint{Series} macros, as the factorials in the denominators would get +all multiplied together: the raw addition and subtraction on fractions +just blindly multiplies denominators! Whereas \csa{xintRationalSeries} +evaluate the partial sums via a less silly iterative scheme. +\dverb|@ +\def\ratio #1{-1/#1[0]}% -1/n, comes from the series of exp(-1) +\cnta 0 % previously declared count +\loop +\edef\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{}\endgraf +\ifnum\cnta<20 \advance\cnta 1 \repeat| + +\def\ratio #1{-1/#1[0]}% -1/n, comes from the series of exp(-1) +\cnta 0 % previously declared count + +\loop +\edef\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{}\endgraf +\ifnum\cnta<20 \advance\cnta 1 \repeat + + + \def\ratioexp #1#2{\xintDiv{#1}{#2}}% #1/#2 + +\medskip We can incorporate an indeterminate if we define |\ratio| to be +a macro with two parameters: |\def\ratioexp + #1#2{\xintDiv{#1}{#2}}|\texttt{\%}| x/n: x=#1, n=#2|. +Then, if |\x| expands to some fraction |x|, the +command \centeredline{|\xintRationalSeries {0}{b}{1}{\ratioexp{\x}}|} +will compute $\sum_{n=0}^{n=b} x^n/n!$:\par +\dverb|@ +\cnta 0 +\def\ratioexp #1#2{\xintDiv{#1}{#2}}% #1/#2 +\loop +\noindent +$\sum_{n=0}^{\the\cnta} (.57)^n/n! = \xintTrunc {50} + {\xintRationalSeries {0}{\cnta}{1}{\ratioexp{.57}}}\dots$ + \vtop to 5pt {}\endgraf +\ifnum\cnta<50 \advance\cnta 10 \repeat| + +\cnta 0 +\loop +\noindent +$\sum_{n=0}^{\the\cnta} (.57)^n/n! = \xintTrunc {50} + {\xintRationalSeries {0}{\cnta}{1}{\ratioexp{.57}}}\dots$ + \vtop to 5pt {}\endgraf +\ifnum\cnta<50 \advance\cnta 10 \repeat +Observe that in this last example the |x| was directly inserted; if it +had been a more complicated explicit fraction it would have been +worthwile to use |\ratioexp\x| with |\x| defined to expand to its value. +In the further situation where this fraction |x| is not explicit but +itself defined via a complicated, and time-costly, formula, it should be +noted that \csa{xintRationalSeries} will do again the evaluation of |\x| +for each term of the partial sum. The easiest is thus when |x| can be +defined as an |\edef|. If however, you are in an expandable-only context +and cannot store in a macro like |\x| the value to be used, a variant of +\csa{xintRationalSeries} is needed which will first evaluate this |\x| and then +use this result without recomputing it. This is \csbxint{RationalSeriesX}, +documented next. + +Here is a slightly more complicated evaluation: +\dverb|@ +\cnta 1 +\loop \edef\z {\xintRationalSeries + {\cnta} + {2*\cnta-1} + {\xintiPow {\the\cnta}{\cnta}/\xintFac{\cnta}} + {\ratioexp{\the\cnta}}}% +\edef\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!} = + \xintTrunc{8}{\xintDiv\z\w}\dots$ \vtop to 5pt{}\endgraf +\ifnum\cnta<20 \advance\cnta 1 \repeat| + +\cnta 1 +\begin{multicols}{2} +\loop \edef\z {\xintRationalSeries + {\cnta} + {2*\cnta-1} + {\xintiPow {\the\cnta}{\cnta}/\xintFac{\cnta}} + {\ratioexp{\the\cnta}}}% +\edef\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!} = + \xintTrunc{8}{\xintDiv\z\w}\dots$ \vtop to 5pt{}\endgraf +\ifnum\cnta<20 \advance\cnta 1 \repeat +\end{multicols} + +\subsection{\csbh{xintRationalSeriesX}}\label{xintRationalSeriesX} + +%{\small \hspace*{\parindent}New with release |1.04|.\par} + +\noindent\csa{xintRationalSeriesX}|{A}{B}{\first}{\ratio}{\g}|% +\etype{\numx\numx\Ff\Ff f} is a parametrized version of \csa{xintRationalSeries} +where |\first| is now a one-parameter macro such that |\first{\g}| gives the +initial term and |\ratio| is a two-parameter macro such that |\ratio{n}{\g}| +represents the ratio of one term to the previous one. The parameter |\g| is +evaluated only once at the beginning of the computation, and can thus itself be +the yet unevaluated result of a previous computation. + +Let |\ratio| be such a two-parameter macro; note the subtle differences +between\centeredline{|\xintRationalSeries {A}{B}{\first}{\ratio{\g}}|} +\centeredline{and |\xintRationalSeriesX {A}{B}{\first}{\ratio}{\g}|.} First the +location of braces differ... then, in the former case |\first| is a +\emph{no-parameter} macro expanding to a fractional number, and in the latter, +it is a +\emph{one-parameter} macro which will use |\g|. Furthermore the |X| variant +will expand |\g| at the very beginning whereas the former non-|X| former variant +will evaluate it each time it needs it (which is bad if this +evaluation is time-costly, but good if |\g| is a big explicit fraction +encapsulated in a macro). + + +The example will use the macro \csbxint{PowerSeries} which computes +efficiently exact partial sums of power series, and is discussed in the +next section. +\dverb|@ +\def\firstterm #1{1[0]}% first term of the exponential series +% although it is the constant 1, here it must be defined as a +% one-parameter macro. Next comes the ratio function for exp: +\def\ratioexp #1#2{\xintDiv {#1}{#2}}% x/n +% These are the (-1)^{n-1}/n of the log(1+h) series: +\def\coefflog #1{\the\numexpr\ifodd #1 1\else-1\fi\relax/#1[0]}% +% Let L(h) be the first 10 terms of the log(1+h) series and +% let E(t) be the first 10 terms of the exp(t) series. +% The following computes E(L(a/10)) for a=1,...,12. +\cnta 0 +\loop +\noindent\xintTrunc {18}{% + \xintRationalSeriesX {0}{9}{\firstterm}{\ratioexp} + {\xintPowerSeries{1}{10}{\coefflog}{\the\cnta[-1]}}}\dots +\endgraf +\ifnum\cnta < 12 \advance \cnta 1 \repeat| + +\def\firstterm #1{1[0]}% first term of the exponential series +% although it is the constant 1, here it must be defined as a +% one-parameter macro. Next comes the ratio function for exp: +\def\ratioexp #1#2{\xintDiv {#1}{#2}}% x/n +% These are the (-1)^{n-1}/n of the log(1+h) series +\def\coefflog #1{\the\numexpr\ifodd #1 1\else-1\fi\relax/#1[0]}% +% Let L(h) be the first 10 terms of the log(1+h) series and +% let E(t) be the first 10 terms of the exp(t) series. +% The following computes E(L(a/12)) for a=1,..., 12. +\begin{multicols}{3}\raggedcolumns + \cnta 1 + \loop + \noindent\xintTrunc {18}{% + \xintRationalSeriesX {0}{9}{\firstterm}{\ratioexp} + {\xintPowerSeries{1}{10}{\coefflog}{\the\cnta[-1]}}}\dots + \endgraf + \ifnum\cnta < 12 \advance \cnta 1 \repeat +\end{multicols} + % to see how they look like... + % \loop + % \noindent\printnumber{% + % \xintRationalSeriesX {0}{9}{\firstterm}{\ratioexp} + % {\xintPowerSeries{1}{10}{\coefflog}{\the\cnta[-2]}}}\dots + % \endgraf + % \ifnum\cnta < 60 \advance \cnta 1 \repeat + +These completely exact operations rapidly create numbers with many digits. Let +us print in full the raw fractions created by the operation illustrated above: + +\edef\z{\xintRationalSeriesX {0}{9}{\firstterm} +{\ratioexp}{\xintPowerSeries{1}{10}{\coefflog}{1[-1]}}} + +|E(L(1[-1]))=|\digitstt{\printnumber{\z}} (length of numerator: +\xintLen {\xintNumerator \z}) + +\edef\z{\xintRationalSeriesX {0}{9}{\firstterm} +{\ratioexp}{\xintPowerSeries{1}{10}{\coefflog}{12[-2]}}} + +|E(L(12[-2]))=|\digitstt{\printnumber{\z}} (length of numerator: +\xintLen {\xintNumerator \z}) + +\edef\z{\xintRationalSeriesX {0}{9}{\firstterm} +{\ratioexp}{\xintPowerSeries{1}{10}{\coefflog}{123[-3]}}} + +|E(L(123[-3]))=|\digitstt{\printnumber{\z}} (length of numerator: +\xintLen {\xintNumerator \z}) + + +We see that the denominators here remain the same, as our input only had various +powers of ten as denominators, and \xintfracname efficiently assemble (some +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: + + +\edef\z{\xintRationalSeriesX {0}{9}{\firstterm} +{\ratioexp}{\xintPowerSeries{1}{10}{\coefflog}{1/7}}} + +|E(L(1/7))=|\digitstt{\printnumber{\z}} (length of numerator: +\xintLen {\xintNumerator \z}; length of denominator: +\xintLen {\xintDenominator \z}) + +\edef\z{\xintRationalSeriesX {0}{9}{\firstterm} +{\ratioexp}{\xintPowerSeries{1}{10}{\coefflog}{1/71}}} + +|E(L(1/71))=|\digitstt{\printnumber{\z}} (length of numerator: +\xintLen {\xintNumerator \z}; length of denominator: +\xintLen {\xintDenominator \z}) + + +\edef\z{\xintRationalSeriesX {0}{9}{\firstterm} +{\ratioexp}{\xintPowerSeries{1}{10}{\coefflog}{1/712}}} + +|E(L(1/712))=|\digitstt{\printnumber{\z}} (length of numerator: +\xintLen {\xintNumerator \z}; length of denominator: +\xintLen {\xintDenominator \z}) + +% \pdfresettimer +% \edef\w{\xintDenominator{\xintIrr{\z}}} +% \the\pdfelapsedtime + +For info the last fraction put into irreducible form still has 288 digits in its +denominator.\footnote{putting this fraction in irreducible form takes more time + than is typical of the other computations in this document; so exceptionally I + have hard-coded the 288 in the document source.} Thus +decimal numbers such as |0.123| (equivalently +|123[-3]|) give less computing intensive tasks than fractions such as |1/712|: +in the case of decimal numbers the (raw) denominators originate in the +coefficients of the series themselves, powers of ten of the input within +brackets being treated separately. And even then the +numerators will grow with the size of the input in a sort of linear way, the +coefficient being given by the order of series: here 10 from the log and 9 from +the exp, so 90. One more digit in the input means 90 more digits in the +numerator of the output: obviously we can not go on composing such partial sums +of series and hope that \xintname will joyfully do all at the speed of light! +Briefly said, imagine that the rules of the game make the programmer like a +security guard at an airport scanning machine: a never-ending flux of passengers +keep on arriving and all you can do is re-shuffle the first nine of them, +organize marriages among some, execute some, move children farther back among +the first nine only. If a passenger comes along with many hand luggages, this +will slow down the process even if you move him to ninth position, because +sooner or later you will have to digest him, and the children will be big too. +There is no way to move some guy out of the file and to a discrete interrogatory +room for separate treatment or to give him/her some badge saying ``I left my +stuff in storage box 357''. + +Hence, truncating the output (or better, rounding) is the only way to go if one +needs a general calculus of special functions. This is why the package +\xintseriesname provides, besides \csbxint{Series}, \csbxint{RationalSeries}, or +\csbxint{PowerSeries} which compute \emph{exact} sums, also has +\csbxint{FxPtPowerSeries} for fixed-point computations. + +Update: release |1.08a| of \xintseriesname now includes a tentative naive +\csbxint{FloatPowerSeries}. + +\subsection{\csbh{xintPowerSeries}}\label{xintPowerSeries} + +\csa{xintPowerSeries}|{A}{B}{\coeff}{f}|\etype{\numx\numx\Ff\Ff} +evaluates the sum +$\sum_{\text{|n=A|}}^{\text{|n=B|}}|\coeff{n}|\cdot |f|^{\text{|n|}}$. The +initial and final indices are given to a |\numexpr| expression. The |\coeff| +macro (which, as argument to \csa{xintPowerSeries} is expanded only at the time +|\coeff{n}| is needed) should be defined as a one-parameter expandable command, +its input will be an explicit number. + +The |f| can be either a fraction directly input or a macro |\f| expanding to +such a fraction. It is actually more efficient to encapsulate an explicit +fraction |f| in such a macro, if it has big numerators and denominators (`big' +means hundreds of digits) as it will then take less space in the processing +until being (repeatedly) used. + +This macro computes the \emph{exact} result (one can use it also for polynomial +evaluation). Starting with release |1.04| a Horner scheme for polynomial +evaluation is used, which has the advantage to avoid a denominator build-up +which was plaguing the |1.03| version. \footnote{with powers |f\string^k|, from + |k=0| to |N|, a denominator |d| of |f| became + |d\string^\string{1+2+\dots+N\string}|, which is bad. With the |1.04| method, + the part of the denominator originating from |f| does not accumulate to more + than |d\string^N|. } + +\begin{framed} + Note: as soon as the coefficients look like factorials, it is more efficient + to use the \csbxint{RationalSeries} macro whose evaluation, also based on a + similar Horner scheme, will avoid a denominator build-up originating in the + coefficients themselves. +\end{framed} + +\dverb|@ +\def\geom #1{1[0]} % the geometric series +\def\f {5/17[0]} +\[ \sum_{n=0}^{n=20} \Bigl(\frac 5{17}\Bigr)^n + =\xintFrac{\xintIrr{\xintPowerSeries {0}{20}{\geom}{\f}}} + =\xintFrac{\xinttheexpr (17^21-5^21)/12/17^20\relax}\]|% +\def\geom #1{1[0]} % the geometric series +\def\f {5/17[0]} % +\[ \sum_{n=0}^{n=20} \Bigl(\frac 5{17}\Bigr)^n + =\xintFrac{\xintIrr{\xintPowerSeries {0}{20}{\geom}{\f}}} + =\xintFrac{\xinttheexpr (17^21-5^21)/12/17^20\relax}\] + +\dverb|@ +\def\coefflog #1{1/#1[0]}% 1/n +\def\f {1/2[0]}% +\[ \log 2 \approx \sum_{n=1}^{20} \frac1{n\cdot 2^n} + = \xintFrac {\xintIrr {\xintPowerSeries {1}{20}{\coefflog}{\f}}}\] +\[ \log 2 \approx \sum_{n=1}^{50} \frac1{n\cdot 2^n} + = \xintFrac {\xintIrr {\xintPowerSeries {1}{50}{\coefflog}{\f}}}\]|% +\def\coefflog #1{1/#1[0]} % 1/n +\def\f {1/2[0]}% +\[ \log 2 \approx \sum_{n=1}^{20} \frac1{n\cdot 2^n} + = \xintFrac {\xintIrr {\xintPowerSeries + {1}{20}{\coefflog}{\f}}}\] +\[ \log 2 \approx \sum_{n=1}^{50} \frac1{n\cdot 2^n} + = \xintFrac {\xintIrr {\xintPowerSeries {1}{50}{\coefflog}{\f}}}\] +\dverb|@ +\cnta 1 % previously declared count +\loop % in this loop we recompute from scratch each partial sum! +% we can afford that, as \xintPowerSeries is fast enough. +\noindent\hbox to 2em{\hfil\texttt{\the\cnta.} }% + \xintTrunc {12} + {\xintPowerSeries {1}{\cnta}{\coefflog}{\f}}\dots +\endgraf +\ifnum \cnta < 30 \advance\cnta 1 \repeat| +\setlength{\columnsep}{0pt} +\begin{multicols}{3} + \cnta 1 % previously declared count + \loop % in this loop we recompute from scratch each partial sum! +% we can afford that, as \xintPowerSeries is fast enough. +\noindent\hbox to 2em{\hfil\texttt{\the\cnta.} }% + \xintTrunc {12}{\xintPowerSeries {1}{\cnta}{\coefflog}{\f}}\dots +\endgraf +\ifnum \cnta < 30 \advance\cnta 1 \repeat +\end{multicols} +\dverb|@ +%\def\coeffarctg #1{1/\the\numexpr\xintMON{#1}*(2*#1+1)\relax }% +\def\coeffarctg #1{1/\the\numexpr\ifodd #1 -2*#1-1\else2*#1+1\fi\relax }% +% the above gives (-1)^n/(2n+1). The sign being in the denominator, +% **** no [0] should be added ****, +% else nothing is guaranteed to work (even if it could by sheer luck) +% NOTE in passing this aspect of \numexpr: +% **** \numexpr -(1)\relax does not work!!! **** +\def\f {1/25[0]}% 1/5^2 +\[\mathrm{Arctg}(\frac15)\approx + \frac15\sum_{n=0}^{15} \frac{(-1)^n}{(2n+1)25^n} += \xintFrac{\xintIrr {\xintDiv + {\xintPowerSeries {0}{15}{\coeffarctg}{\f}}{5}}}\]| + +\def\coeffarctg #1{1/\the\numexpr\ifodd #1 -2*#1-1\else2*#1+1\fi\relax }% +\def\f {1/25[0]}% 1/5^2 +\[\mathrm{Arctg}(\frac15)\approx + \frac15\sum_{n=0}^{15} \frac{(-1)^n}{(2n+1)25^n} += \xintFrac{\xintIrr {\xintDiv + {\xintPowerSeries {0}{15}{\coeffarctg}{\f}}{5}}}\] + +\subsection{\csbh{xintPowerSeriesX}}\label{xintPowerSeriesX} + +%{\small\hspace*{\parindent}New with release |1.04|.\par} + +\noindent This is the same as \csbxint{PowerSeries}\ntype{\numx\numx\Ff\Ff} +apart +from the fact that the last parameter |f| is expanded once and for all before +being then used repeatedly. If the |f| parameter is to be an explicit big +fraction with many (dozens) digits, rather than using it directly it is slightly +better to have some macro |\g| defined to expand to the explicit fraction and +then use \csbxint{PowerSeries} with |\g|; but if |f| has not yet been evaluated +and will be the output of a complicated expansion of some |\f|, and if, due to +an expanding only context, doing |\edef\g{\f}| is no option, then +\csa{xintPowerSeriesX} should be used with |\f| as last parameter. +% +\dverb|@ +\def\ratioexp #1#2{\xintDiv {#1}{#2}}% x/n +% These are the (-1)^{n-1}/n of the log(1+h) series: +\def\coefflog #1{\the\numexpr\ifodd #1 1\else-1\fi\relax/#1[0]}% +% Let L(h) be the first 10 terms of the log(1+h) series and +% let E(t) be the first 10 terms of the exp(t) series. +% The following computes L(E(a/10)-1) for a=1,..., 12. +\cnta 1 +\loop +\noindent\xintTrunc {18}{% + \xintPowerSeriesX {1}{10}{\coefflog} + {\xintSub + {\xintRationalSeries {0}{9}{1[0]}{\ratioexp{\the\cnta[-1]}}} + {1}}}\dots +\endgraf +\ifnum\cnta < 12 \advance \cnta 1 \repeat| + +\cnta 0 +\def\ratioexp #1#2{\xintDiv {#1}{#2}}% x/n +% These are the (-1)^{n-1}/n of the log(1+h) series +\def\coefflog #1{\the\numexpr\ifodd #1 1\else-1\fi\relax/#1[0]}% +% Let L(h) be the first 10 terms of the log(1+h) series and +% let E(t) be the first 10 terms of the exp(t) series. +% The following computes L(E(a/10)-1) for a=1,..., 12. +\begin{multicols}{3}\raggedcolumns +\cnta 1 + \loop + \noindent\xintTrunc {18}{% + \xintPowerSeriesX {1}{10}{\coefflog} + {\xintSub + {\xintRationalSeries {0}{9}{1[0]}{\ratioexp{\the\cnta[-1]}}} + {1}}}\dots + \endgraf + \ifnum\cnta < 12 \advance \cnta 1 \repeat +\end{multicols} + + +\subsection{\csbh{xintFxPtPowerSeries}}\label{xintFxPtPowerSeries} + +\csa{xintFxPtPowerSeries}|{A}{B}{\coeff}{f}{D}|\etype{\numx\numx} +computes +$\sum_{\text{|n=A|}}^{\text{|n=B|}}|\coeff{n}|\cdot |f|^{\,\text{|n|}}$ with each + term of the series truncated to |D| digits\etype{\Ff\Ff\numx} + after the decimal point. As + usual, |A| and |B| are completely expanded through their inclusion in a + |\numexpr| expression. Regarding |D| it will be similarly be expanded each + time it is used inside an \csa{xintTrunc}. The one-parameter macro |\coeff| + is similarly expanded at the time it is used inside the + computations. Idem for |f|. If |f| itself is some complicated macro it is + thus better to use the variant \csbxint{FxPtPowerSeriesX} which expands it + first and then uses the result of that expansion. + +The current (|1.04|) implementation is: the first power |f^A| is +computed exactly, then \emph{truncated}. Then each successive power is +obtained from the previous one by multiplication by the exact value of +|f|, and truncated. And |\coeff{n}|\raisebox{.5ex}{|.|}|f^n| is obtained +from that by multiplying by |\coeff{n}| (untruncated) and then +truncating. Finally the sum is computed exactly. Apart from that +\csa{xintFxPtPowerSeries} (where |FxPt| means `fixed-point') is like +\csa{xintPowerSeries}. + +There should be a variant for things of the type $\sum c_n \frac {f^n}{n!}$ to +avoid having to compute the factorial from scratch at each coefficient, the same +way \csa{xintFxPtPowerSeries} does not compute |f^n| from scratch at each |n|. +Perhaps in the next package release. + +\def\coeffexp #1{1/\xintFac {#1}[0]}% [0] for faster parsing +\def\f {-1/2[0]}% +\newcount\cnta + +\setlength{\multicolsep}{0pt} + +\begin{multicols}{3}[% +\centeredline{$e^{-\frac12}\approx{}$}]% +\cnta 0 +\noindent\loop +$\xintFxPtPowerSeries {0}{\cnta}{\coeffexp}{\f}{20}$\\ +\ifnum\cnta<19 +\advance\cnta 1 +\repeat\par +\end{multicols} +\dverb|@ +\def\coeffexp #1{1/\xintFac {#1}[0]}% 1/n! +\def\f {-1/2[0]}% [0] for faster input parsing +\cnta 0 % previously declared \count register +\noindent\loop +$\xintFxPtPowerSeries {0}{\cnta}{\coeffexp}{\f}{20}$\\ +\ifnum\cnta<19 \advance\cnta 1 \repeat\par +% One should **not** trust the final digits, as the potential truncation +% errors of up to 10^{-20} per term accumulate and never disappear! (the +% effect is attenuated by the alternating signs in the series). We can +% confirm that the last two digits (of our evaluation of the nineteenth +% partial sum) are wrong via the evaluation with more digits: | + +\centeredline{|\xintFxPtPowerSeries {0}{19}{\coeffexp}{\f}{25}=| +\digitstt{\xintFxPtPowerSeries {0}{19}{\coeffexp}{\f}{25}}} +\edef\z{\xintIrr {\xintPowerSeries {0}{19}{\coeffexp}{\f}}}% + +\texttt{\hyphenchar\font45 }% +It is no difficulty for \xintfracname to compute exactly, with the help +of \csa{xintPowerSeries}, the nineteenth partial sum, and to then give +(the start of) its exact decimal expansion: +\centeredline{|\xintPowerSeries {0}{19}{\coeffexp}{\f}| ${}= + \displaystyle\xintFrac{\z}$% + \vphantom{\vrule height 20pt depth 12pt}}% +\centeredline{${}=\xintTrunc {30}{\z}\dots$} Thus, one should always +estimate a priori how many ending digits are not reliable: if there are +|N| terms and |N| has |k| digits, then digits up to but excluding the +last |k| may usually be trusted. If we are optimistic and the series is +alternating we may even replace |N| with $\sqrt{|N|}$ to get the number |k| +of digits possibly of dubious significance. + + +\subsection{\csbh{xintFxPtPowerSeriesX}}\label{xintFxPtPowerSeriesX} + +%{\small\hspace*{\parindent}New with release |1.04|.\par} + +\noindent\csa{xintFxPtPowerSeriesX}|{A}{B}{\coeff}{\f}{D}|% +\ntype{\numx\numx} +computes, exactly as +\csa{xintFxPtPowerSeries}, the sum of +|\coeff{n}|\raisebox{.5ex}{|.|}|\f^n|\etype{\Ff\Ff\numx} from |n=A| to |n=B| with each term +of the series being \emph{truncated} to |D| digits after the decimal +point. The sole difference is that |\f| is first expanded and it +is the result of this which is used in the computations. + +% Let us illustrate this on the computation of |(1+y)^{5/3}| where +% |1+y=(1+x)^{3/5}| and each of the two binomial series is evaluated with ten +% terms, the results being computed with |8| digits after the decimal point, and +% @|f|<1/10@. + + +Let us illustrate this on the numerical exploration of the identity +\centeredline{|log(1+x) = -log(1/(1+x))|}% +Let |L(h)=log(1+h)|, and |D(h)=L(h)+L(-h/(1+h))|. Theoretically thus, +|D(h)=0| but we shall evaluate |L(h)| and |-h/(1+h)| keeping only 10 +terms of their respective series. We will assume @|h|<0.5@. With only +ten terms kept in the power series we do not have quite 3 digits +precision as @2^10=1024@. So it wouldn't make sense to evaluate things +more precisely than, say circa 5 digits after the decimal points. +\dverb|@ +\cnta 0 +\def\coefflog #1{\the\numexpr\ifodd#1 1\else-1\fi\relax/#1[0]}% (-1)^{n-1}/n +\def\coeffalt #1{\the\numexpr\ifodd#1 -1\else1\fi\relax [0]}% (-1)^n +\loop +\noindent \hbox to 2.5cm {\hss\texttt{D(\the\cnta/100): }}% +\xintAdd {\xintFxPtPowerSeriesX {1}{10}{\coefflog}{\the\cnta [-2]}{5}} + {\xintFxPtPowerSeriesX {1}{10}{\coefflog} + {\xintFxPtPowerSeriesX {1}{10}{\coeffalt}{\the\cnta [-2]}{5}} + {5}}\endgraf +\ifnum\cnta < 49 \advance\cnta 7 \repeat| + +\cnta 0 +\def\coefflog #1{\the\numexpr\ifodd#1 1\else-1\fi\relax/#1[0]}% (-1)^{n-1}/n +\def\coeffalt #1{\the\numexpr\ifodd#1 -1\else1\fi\relax [0]}% (-1)^n + + +\begin{multicols}2 +\loop +\noindent \hbox to 2.5cm {\hss\texttt{D(\the\cnta/100): }}% +\digitstt{\xintAdd {\xintFxPtPowerSeriesX {1}{10}{\coefflog}{\the\cnta [-2]}{5}} + {\xintFxPtPowerSeriesX {1}{10}{\coefflog} + {\xintFxPtPowerSeriesX {1}{10}{\coeffalt}{\the\cnta [-2]}{5}} + {5}}}\endgraf +\ifnum\cnta < 49 \advance\cnta 7 \repeat +\end{multicols} + +Let's say we evaluate functions on |[-1/2,+1/2]| with values more or less also +in |[-1/2,+1/2]| and we want to keep 4 digits of precision. So, roughly we need +at least 14 terms in series like the geometric or log series. Let's make this +15. Then it doesn't make sense to compute intermediate summands with more than 6 +digits precision. So we compute with 6 digits +precision but return only 4 digits (rounded) after the decimal point. +This result with 4 post-decimal points precision is then used as input +to the next evaluation. +\dverb|@ +\loop +\noindent \hbox to 2.5cm {\hss\texttt{D(\the\cnta/100): }}% +\xintRound{4} + {\xintAdd {\xintFxPtPowerSeriesX {1}{15}{\coefflog}{\the\cnta [-2]}{6}} + {\xintFxPtPowerSeriesX {1}{15}{\coefflog} + {\xintRound {4}{\xintFxPtPowerSeriesX {1}{15}{\coeffalt} + {\the\cnta [-2]}{6}}} + {6}}% + }\endgraf +\ifnum\cnta < 49 \advance\cnta 7 \repeat| + +\begin{multicols}2 +\loop +\noindent \hbox to 2.5cm {\hss\texttt{D(\the\cnta/100): }}% +\digitstt{\xintRound{4} + {\xintAdd {\xintFxPtPowerSeriesX {1}{15}{\coefflog}{\the\cnta [-2]}{6}} + {\xintFxPtPowerSeriesX {1}{15}{\coefflog} + {\xintRound {4}{\xintFxPtPowerSeriesX {1}{15}{\coeffalt} + {\the\cnta [-2]}{6}}} + {6}}% + }}\endgraf +\ifnum\cnta < 49 \advance\cnta 7 \repeat +\end{multicols} + + +Not bad... I have cheated a bit: the `four-digits precise' numeric +evaluations were left unrounded in the final addition. However the inner +rounding to four digits worked fine and made the next step faster than +it would have been with longer inputs. The morale is that one should not +use the raw results of \csa{xintFxPtPowerSeriesX} with the |D| digits +with which it was computed, as the last are to be considered garbage. +Rather, one should keep from the output only some smaller number of +digits. This will make further computations faster and not less precise. +I guess there should be some command to do this final truncating, or +better, rounding, at a given number |D'<D| of digits. Maybe for the next +release. + + +\subsection{\csbh{xintFloatPowerSeries}}\label{xintFloatPowerSeries} + +%{\small\hspace*{\parindent}New with |1.08a|.\par} + +\noindent\csa{xintFloatPowerSeries}|[P]{A}{B}{\coeff}{f}|% +\ntype{{\upshape[\numx]}\numx\numx} + computes +$\sum_{\text{|n=A|}}^{\text{|n=B|}}|\coeff{n}|\cdot |f|^{\,\text{|n|}}$ +with a floating point\etype{\Ff\Ff} +precision given by the optional parameter |P| or by the current setting of +|\xintDigits|. + +In the current, preliminary, version, no attempt has been made to try to +guarantee to the final result the precision |P|. Rather, |P| is used for all +intermediate floating point evaluations. So +rounding errors will make some of the last printed digits invalid. The +operations done are first the evaluation of |f^A| using \csa{xintFloatPow}, then +each successive power is obtained from this first one by multiplication by |f| +using \csa{xintFloatMul}, then again with \csa{xintFloatMul} this is multiplied +with |\coeff{n}|, and the sum is done adding one term at a time with +\csa{xintFloatAdd}. To sum up, this is just the naive transformation of +\csa{xintFxPtPowerSeries} from fixed point to floating point. + +\def\coefflog #1{\the\numexpr\ifodd#1 1\else-1\fi\relax/#1[0]}% + +\dverb+@ +\def\coefflog #1{\the\numexpr\ifodd#1 1\else-1\fi\relax/#1[0]}% +\xintFloatPowerSeries [8]{1}{30}{\coefflog}{-1/2[0]}+% +\centeredline{\digitstt{\xintFloatPowerSeries [8]{1}{30}{\coefflog}{-1/2[0]}}} + +\subsection{\csbh{xintFloatPowerSeriesX}}\label{xintFloatPowerSeriesX} + +%{\small\hspace*{\parindent}New with |1.08a|.\par} + +\noindent\csa{xintFloatPowerSeriesX}|[P]{A}{B}{\coeff}{f}|% +\ntype{{\upshape[\numx]}\numx\numx} +is like +\csa{xintFloatPowerSeries} with the difference that |f| is +expanded once\etype{\Ff\Ff} +and for all at the start of the computation, thus allowing +efficient chaining of such series evaluations. +\def\coefflog #1{\the\numexpr\ifodd#1 1\else-1\fi\relax/#1[0]}% + +\dverb+@ +\def\coeffexp #1{1/\xintFac {#1}[0]}% 1/n! (exact, not float) +\def\coefflog #1{\the\numexpr\ifodd#1 1\else-1\fi\relax/#1[0]}% +\xintFloatPowerSeriesX [8]{0}{30}{\coeffexp} + {\xintFloatPowerSeries [8]{1}{30}{\coefflog}{-1/2[0]}}+% +\centeredline{\digitstt{\xintFloatPowerSeriesX [8]{0}{30}{\coeffexp} + {\xintFloatPowerSeries [8]{1}{30}{\coefflog}{-1/2[0]}}}} + + +\subsection{Computing \texorpdfstring{$\log 2$}{log(2)} and \texorpdfstring{$\pi$}{pi}}\label{ssec:Machin} + +In this final section, the use of \csbxint{FxPtPowerSeries} (and +\csbxint{PowerSeries}) will be +illustrated on the (expandable... why make things simple when it is so easy to +make them difficult!) computations of the first digits of the decimal expansion +of the familiar constants $\log 2$ and $\pi$. + +Let us start with $\log 2$. We will get it from this formula (which is +left as an exercise): \centeredline{\digitstt{log(2)=-2\,log(1-13/256)-% + 5\,log(1-1/9)}}% +The number of terms to be kept in the log series, for a desired +precision of |10^{-D}| was roughly estimated without much theoretical +analysis. Computing exactly the partial sums with \csa{xintPowerSeries} +and then printing the truncated values, from |D=0| up to |D=100| showed +that it worked in terms of quality of the approximation. Because of +possible strings of zeroes or nines in the exact decimal expansion (in +the present case of $\log 2$, strings of zeroes around the fourtieth and +the sixtieth decimals), this +does not mean though that all digits printed were always exact. In +the end one always end up having to compute at some higher level of +desired precision to validate the earlier result. + +Then we tried with \csa{xintFxPtPowerSeries}: this is worthwile only for +|D|'s at least 50, as the exact evaluations are faster (with these +short-length |f|'s) for a lower +number of digits. And as expected the degradation in the quality of +approximation was in this range of the order of two or three digits. +This meant roughly that the 3+1=4 ending digits were wrong. Again, we ended +up having to compute with five more digits and compare with the earlier +value to validate it. We use truncation rather than rounding because our +goal is not to obtain the correct rounded decimal expansion but the +correct exact truncated one. + +% 693147180559945309417232121458176568075500134360255254120680009493 + +\dverb|@ +\def\coefflog #1{1/#1[0]}% 1/n +\def\xa {13/256[0]}% we will compute log(1-13/256) +\def\xb {1/9[0]}% we will compute log(1-1/9) +\def\LogTwo #1% +% get log(2)=-2log(1-13/256)- 5log(1-1/9) +{% we want to use \printnumber, hence need something expanding in two steps + % only, so we use here the \romannumeral0 method + \romannumeral0\expandafter\LogTwoDoIt \expandafter + % Nb Terms for 1/9: + {\the\numexpr #1*150/143\expandafter}\expandafter + % Nb Terms for 13/256: + {\the\numexpr #1*100/129\expandafter}\expandafter + % We print #1 digits, but we know the ending ones are garbage + {\the\numexpr #1\relax}% allows #1 to be a count register +}% +\def\LogTwoDoIt #1#2#3% +% #1=nb of terms for 1/9, #2=nb of terms for 13/256, +{% #3=nb of digits for computations, also used for printing + \xinttrunc {#3} % lowercase form to stop the \romannumeral0 expansion! + {\xintAdd + {\xintMul {2}{\xintFxPtPowerSeries {1}{#2}{\coefflog}{\xa}{#3}}} + {\xintMul {5}{\xintFxPtPowerSeries {1}{#1}{\coefflog}{\xb}{#3}}}% + }% +}% +\noindent $\log 2 \approx \LogTwo {60}\dots$\endgraf +\noindent\phantom{$\log 2$}${}\approx{}$\printnumber{\LogTwo {65}}\dots\endgraf +\noindent\phantom{$\log 2$}${}\approx{}$\printnumber{\LogTwo {70}}\dots\endgraf| + +\def\coefflog #1{1/#1[0]}% 1/n +\def\xa {13/256[0]}% we will compute log(1-13/256) +\def\xb {1/9[0]}% we will compute log(1-1/9) +\def\LogTwo #1% get log(2)=-2log(1-13/256)- 5log(1-1/9) with #1 digits precision +{% this #1 may be a count register, if desired + \romannumeral0\expandafter\LogTwoDoIt \expandafter + {\the\numexpr #1*150/143\expandafter}\expandafter % Nb Terms for 1/9 + {\the\numexpr #1*100/129\expandafter}\expandafter % Nb Terms for 13/256 + {\the\numexpr #1\relax }% +}% +\def\LogTwoDoIt #1#2#3% #1=nb of terms for 1/9, #2=nb of terms for 13/256, +{% #3=nb of digits for computations + \xinttrunc {#3} + {\xintAdd + {\xintMul {2}{\xintFxPtPowerSeries {1}{#2}{\coefflog}{\xa}{#3}}} + {\xintMul {5}{\xintFxPtPowerSeries {1}{#1}{\coefflog}{\xb}{#3}}}% + }% +}% + +\noindent $\log 2 \approx {}$\digitstt{\LogTwo {60}\dots}\endgraf +\noindent\phantom{$\log 2$}${}\approx{}$\digitstt{\printnumber{\LogTwo + {65}}\dots}\endgraf +\noindent\phantom{$\log 2$}${}\approx{}$\digitstt{\printnumber{\LogTwo + {70}}\dots}\endgraf + +Here is the code doing an exact evaluation of the partial sums. We have +added a |+1| to the number of digits for estimating the number of terms +to keep from the log series: we experimented that this gets exactly the +first |D| digits, for all values from |D=0| to |D=100|, except in one +case (|D=40|) where the last digit is wrong. For values of |D| +higher than |100| it is more efficient to use the code using +\csa{xintFxPtPowerSeries}. +\dverb|@ +\def\LogTwo #1% get log(2)=-2log(1-13/256)- 5log(1-1/9) +{% + \romannumeral0\expandafter\LogTwoDoIt \expandafter + {\the\numexpr (#1+1)*150/143\expandafter}\expandafter + {\the\numexpr (#1+1)*100/129\expandafter}\expandafter + {\the\numexpr #1\relax}% +}% +\def\LogTwoDoIt #1#2#3% +{% #3=nb of digits for truncating an EXACT partial sum + \xinttrunc {#3} + {\xintAdd + {\xintMul {2}{\xintPowerSeries {1}{#2}{\coefflog}{\xa}}} + {\xintMul {5}{\xintPowerSeries {1}{#1}{\coefflog}{\xb}}}% + }% +}%| + +Let us turn now to Pi, computed with the Machin formula. Again the numbers of +terms to keep in the two |arctg| series were roughly estimated, and some +experimentations showed that removing the last three digits was enough (at least +for |D=0-100| range). And the algorithm does print the correct digits when used +with |D=1000| (to be convinced of that one needs to run it for |D=1000| and +again, say for |D=1010|.) A theoretical analysis could help confirm that this +algorithm always gets better than |10^{-D}| precision, but again, strings of +zeroes or nines encountered in the decimal expansion may falsify the ending +digits, nines may be zeroes (and the last non-nine one should be increased) and +zeroes may be nine (and the last non-zero one should be decreased). + +\hypertarget{MachinCode}{} +\dverb|@ +% pi = 16 Arctg(1/5) - 4 Arctg(1/239) (John Machin's formula) +\def\coeffarctg #1{\the\numexpr\ifodd#1 -1\else1\fi\relax/% + \the\numexpr 2*#1+1\relax [0]}% +% the above computes (-1)^n/(2n+1). +\def\xa {1/25[0]}% 1/5^2, the [0] for (infinitesimally) faster parsing +\def\xb {1/57121[0]}% 1/239^2, the [0] for faster parsing +\def\Machin #1{% \Machin {\mycount} is allowed + \romannumeral0\expandafter\MachinA \expandafter + % number of terms for arctg(1/5): + {\the\numexpr (#1+3)*5/7\expandafter}\expandafter + % number of terms for arctg(1/239): + {\the\numexpr (#1+3)*10/45\expandafter}\expandafter + % do the computations with 3 additional digits: + {\the\numexpr #1+3\expandafter}\expandafter + % allow #1 to be a count register: + {\the\numexpr #1\relax }}% +\def\MachinA #1#2#3#4% +% #4: digits to keep after decimal point for final printing +% #3=#4+3: digits for evaluation of the necessary number of terms +% to be kept in the arctangent series, also used to truncate each +% individual summand. +{\xinttrunc {#4} % lowercase macro to match the initial \romannumeral0. + {\xintSub + {\xintMul {16/5}{\xintFxPtPowerSeries {0}{#1}{\coeffarctg}{\xa}{#3}}} + {\xintMul {4/239}{\xintFxPtPowerSeries {0}{#2}{\coeffarctg}{\xb}{#3}}}% + }}% +\[ \pi = \Machin {60}\dots \]| + +\def\coeffarctg #1{\the\numexpr\ifodd#1 -1\else1\fi\relax/% + \the\numexpr 2*#1+1\relax [0]}% +%\def\coeffarctg #1{\romannumeral0\xintmon{#1}/\the\numexpr 2*#1+1\relax }% +\def\xa {1/25[0]}% 1/5^2, the [0] for faster parsing +\def\xb {1/57121[0]}% 1/239^2, the [0] for faster parsing +\def\Machin #1{% #1 may be a count register, \Machin {\mycount} is allowed + \romannumeral0\expandafter\MachinA \expandafter + % number of terms for arctg(1/5): + {\the\numexpr (#1+3)*5/7\expandafter}\expandafter + % number of terms for arctg(1/239): + {\the\numexpr (#1+3)*10/45\expandafter}\expandafter + % do the computations with 3 additional digits: + {\the\numexpr #1+3\expandafter}\expandafter + % allow #1 to be a count register: + {\the\numexpr #1\relax }}% +\def\MachinA #1#2#3#4% +{\xinttrunc {#4} + {\xintSub + {\xintMul {16/5}{\xintFxPtPowerSeries {0}{#1}{\coeffarctg}{\xa}{#3}}} + {\xintMul{4/239}{\xintFxPtPowerSeries {0}{#2}{\coeffarctg}{\xb}{#3}}}% + }}% +\begin{framed} + \[ \pi = \Machin {60}\dots \] +\end{framed} +Here is a variant|\MachinBis|, +which evaluates the partial sums \emph{exactly} using +\csa{xintPowerSeries}, before their final truncation. No need for a +``|+3|'' then. +\dverb|@ +\def\MachinBis #1{% #1 may be a count register, +% the final result will be truncated to #1 digits post decimal point + \romannumeral0\expandafter\MachinBisA \expandafter + % number of terms for arctg(1/5): + {\the\numexpr #1*5/7\expandafter}\expandafter + % number of terms for arctg(1/239): + {\the\numexpr #1*10/45\expandafter}\expandafter + % allow #1 to be a count register: + {\the\numexpr #1\relax }}% +\def\MachinBisA #1#2#3% +{\xinttrunc {#3} % + {\xintSub + {\xintMul {16/5}{\xintPowerSeries {0}{#1}{\coeffarctg}{\xa}}} + {\xintMul{4/239}{\xintPowerSeries {0}{#2}{\coeffarctg}{\xb}}}% +}}%| + +\def\MachinBis #1{% #1 may be a count register, +% the final result will be truncated to #1 digits post decimal point + \romannumeral0\expandafter\MachinBisA \expandafter + % number of terms for arctg(1/5): + {\the\numexpr #1*5/7\expandafter}\expandafter + % number of terms for arctg(1/239): + {\the\numexpr #1*10/45\expandafter}\expandafter + % allow #1 to be a count register: + {\the\numexpr #1\relax }}% +\def\MachinBisA #1#2#3% +{\xinttrunc {#3} % + {\xintSub + {\xintMul {16/5}{\xintPowerSeries {0}{#1}{\coeffarctg}{\xa}}} + {\xintMul{4/239}{\xintPowerSeries {0}{#2}{\coeffarctg}{\xb}}}% +}}% + +Let us use this variant for a loop showing the build-up of digits: +\dverb|@ + \cnta 0 % previously declared \count register + \loop + \MachinBis{\cnta} \endgraf % Plain's \loop does not accept \par + \ifnum\cnta < 30 \advance\cnta 1 \repeat| + +\begin{multicols}{2} + \cnta 0 % previously declared \count register + \loop \noindent + \centeredline{\digitstt{\MachinBis{\cnta}}}% + \ifnum\cnta < 30 + \advance\cnta 1 \repeat +\end{multicols} + + +\hypertarget{Machin1000}{} +% +You want more digits and have some time? compile this copy of the +\hyperlink{MachinCode}{|\char 92 Machin|} with |etex| (or |pdftex|): +% +\dverb|@ +% Compile with e-TeX extensions enabled (etex, pdftex, ...) +\input xintfrac.sty +\input xintseries.sty +% pi = 16 Arctg(1/5) - 4 Arctg(1/239) (John Machin's formula) +\def\coeffarctg #1{\the\numexpr\ifodd#1 -1\else1\fi\relax/% + \the\numexpr 2*#1+1\relax [0]}% +\def\xa {1/25[0]}% +\def\xb {1/57121[0]}% +\def\Machin #1{% + \romannumeral0\expandafter\MachinA \expandafter + {\the\numexpr (#1+3)*5/7\expandafter}\expandafter + {\the\numexpr (#1+3)*10/45\expandafter}\expandafter + {\the\numexpr #1+3\expandafter}\expandafter + {\the\numexpr #1\relax }}% +\def\MachinA #1#2#3#4% +{\xinttrunc {#4} + {\xintSub + {\xintMul {16/5}{\xintFxPtPowerSeries {0}{#1}{\coeffarctg}{\xa}{#3}}} + {\xintMul {4/239}{\xintFxPtPowerSeries {0}{#2}{\coeffarctg}{\xb}{#3}}}% +}}% +\pdfresettimer +\oodef\Z {\Machin {1000}} +\odef\W {\the\pdfelapsedtime} +\message{\Z} +\message{computed in \xintRound {2}{\W/65536} seconds.} +\bye | + +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. +\footnote{With \texttt{1.09i} and earlier \xintname releases, this used to be + \digitstt{42} seconds; the \texttt{1.09j} division is much faster with small + denominators as occurs here with \digitstt{\char92xa=1/25}, and I believe this + to be the main explanation for the speed gain.} As mentioned in the +introduction, the file \href{http://www.ctan.org/pkg/pi}{pi.tex} by \textsc{D. + Roegel} shows that orders of magnitude faster computations are possible within +\TeX{}, but recall our constraints of complete expandability and be merciful, +please. + + +\textbf{Why truncating rather than rounding?} One of our main competitors +on the market of scientific computing, a canadian product (not +encumbered with expandability constraints, and having barely ever heard +of \TeX{} ;-), prints numbers rounded in the last digit. Why didn't we +follow suit in the macros \csa{xintFxPtPowerSeries} and +\csa{xintFxPtPowerSeriesX}? To round at |D| digits, and excluding a +rewrite or cloning of the division algorithm which anyhow would add to +it some overhead in its final steps, \xintfracname needs to truncate at +|D+1|, then round. And rounding loses information! So, with more time +spent, we obtain a worst result than the one truncated at |D+1| (one +could imagine that additions and so on, done with only |D| digits, cost +less; true, but this is a negligeable effect per summand compared to the +additional cost for this term of having been truncated at |D+1| then +rounded). Rounding is the way to go when setting up algorithms to +evaluate functions destined to be composed one after the other: exact +algebraic operations with many summands and an |f| variable which is a +fraction are costly and create an even bigger fraction; replacing |f| +with a reasonable rounding, and rounding the result, is necessary to +allow arbitrary chaining. + +But, for the +computation of a single constant, we are really interested in the exact +decimal expansion, so we truncate and compute more terms until the +earlier result gets validated. Finally if we do want the rounding we can +always do it on a value computed with |D+1| truncation. + +% \clearpage + +\section{Commands of the \xintcfracname package} +\label{sec:cfrac} + +This package was first included in release |1.04| of the \xintname bundle. + + +\localtableofcontents + + +\subsection{Package overview} + +A \emph{simple} continued fraction has coefficients +|[c0,c1,...,cN]| (usually called partial quotients, but I really +dislike this entrenched terminology), where |c0| is a positive or +negative integer and the others are positive integers. As we will +see it is possible with \xintcfracname to specify the coefficient +function |c:n->cn|. Note that the index then starts at zero as +indicated. With the |amsmath| macro |\cfrac| one can display such a +continued fraction as +\[ c_0 + \cfrac{1}{c_1+\cfrac1{c_2+\cfrac1{c_3+\cfrac1{\ddots}}}}\] +Here is a concrete example: +\[ \xintFrac {208341/66317}=\xintCFrac {208341/66317}\] But the +difference with |amsmath|'s |\cfrac| is that this was input as +\centeredline{|\[ \xintFrac {208341/66317}=\xintCFrac + {208341/66317} \]|} The command \csbxint{CFrac} produces in two +expansion steps the whole thing with the many chained |\cfrac|'s and all +necessary braces, ready to be printed, in math mode. This is \LaTeX{} +only and with the |amsmath| package (we shall mention another method for +Plain \TeX{} users of |amstex|). + +A \emph{generalized} continued fraction has the same structure but +the numerators are not restricted to be ones, and numbers used in +the continued fraction may be arbitrary, also fractions, +irrationals, indeterminates. The \emph{centered} continued +fraction associated to a rational number is an +example: +\[ \xintFrac {915286/188421}=\xintGCFrac {\xintFtoCC {915286/188421}} +=\xintCFrac {915286/188421}\] + \centeredline{|\[ \xintFrac {915286/188421}=\xintGCFrac {\xintFtoCC + {915286/188421}} \]|} +The command \csbxint{GCFrac}, contrarily to +\csbxint{CFrac}, does not compute anything, it just typesets. Here, it is the +command \csbxint{FtoCC} which did the computation of +the centered continued fraction of |f|. Its output has the `inline format' +described in the next paragraph. In the display, we also used \csa{xintCFrac} +(code not shown), for comparison of the two types of continued fractions. + +A generalized continued fraction may be input `inline' as: +\centeredline{|a0+b0/a1+b1/a2+b2/...../a(n-1)+b(n-1)/an|}% +Fractions among the coefficients are allowed but they must be enclosed +within braces. Signed integers may be left without braces (but the |+| +signs are mandatory). Or, they may +be macros expanding (in two steps) to some number or fractional number. +\centeredline{|\xintGCFrac {1+-1/57+\xintPow {-3}{7}/\xintQuo {132}{25}}|} +\[ \xintFrac{\xintGCtoF {1+-1/57+\xintPow {-3}{7}/\xintQuo {132}{25}}}= + \xintGCFrac {1+-1/57+\xintPow {-3}{7}/\xintQuo {132}{25}}\] +The left hand side was obtained with the following code: +\centeredline{|\xintFrac{\xintGCtoF {1+-1/57+\xintPow {-3}{7}/\xintQuo + {132}{25}}}|} +It uses the macro \csbxint{GCtoF} to convert a generalized fraction from the +`inline format' to the fraction it evaluates to. + +A simple continued fraction is a special case of a generalized continued +fraction and may be input as such to macros expecting the `inline format', for +example |-7+1/6+1/19+1/1+1/33|. There is a simpler comma separated format: +\centeredline +{|\xintFrac{\xintCstoF{-7,6,19,1,33}}=\xintCFrac{\xintCstoF{-7,6,19,1,33}}|} +\[ +\xintFrac{\xintCstoF{-7,6,19,1,33}}=\xintCFrac{\xintCstoF{-7,6,19,1,33}}\] This +comma separated format may also be used with fractions among the coefficients: +in that case, computing with \csbxint{FtoCs} from the resulting |f| +its real coefficients will give a new comma separated list +with only integers. This list has no spaces: the spaces in the display below +arise from the math mode processing. +\centeredline{|\xintFrac{1084483/398959}=[\xintFtoCs{1084483/398959}]|} +\[\xintFrac{1084483/398959}=[\xintFtoCs{1084483/398959}]\] +If one prefers other separators, one can use \csbxint{FtoCx} whose first +argument will be the separator to be used. +\centeredline{|\xintFrac{2721/1001}=\xintFtoCx {+1/(}{2721/1001})\cdots)|} +\[\xintFrac{2721/1001}=\xintFtoCx {+1/(}{2721/1001})\cdots)\] +People using Plain \TeX{} and |amstex| can achieve the same effect as +|\xintCFrac| with: +|$$\xintFwOver{2721/1001}=\xintFtoCx {+\cfrac1\\ }{2721/1001}\endcfrac$$| + +Using \csa{xintFtoCx} with first argument an empty pair of braces |{}| will +return the list of the coefficients of the continued fraction of |f|, without +separator, and each one enclosed in a pair of group braces. This can then be +manipulated by the non-expandable macro \csbxint{AssignArray} or the expandable +ones \csbxint{Apply} and \csbxint{ListWithSep}. + +As a shortcut to using \csa{xintFtoCx} with separator |1+/|, there is +\csbxint{FtoGC}: +\centeredline{|2721/1001=\xintFtoGC {2721/1001}|}% +\centeredline{\digitstt{2721/1001=\xintFtoGC {2721/1001}}} +Let us compare in that case with the output of \csbxint{FtoCC}: +\centeredline{|2721/1001=\xintFtoCC {2721/1001}|}% +\centeredline{\digitstt{2721/1001=\xintFtoCC {2721/1001}}} + +The `|\printnumber|' macro which we use to print long numbers can also +be useful on long continued fractions. +\centeredline{|\printnumber{\xintFtoCC {35037018906350720204351049/%|}% +\centeredline{|244241737886197404558180}}|}% +\digitstt{\printnumber{\xintFtoCC {35037018906350720204351049/244241737886197404558180}}}. +If we apply \csbxint{GCtoF} to this generalized continued fraction, we +discover that the original fraction was reducible: +\centeredline{|\xintGCtoF + {143+1/2+...+-1/9}|\digitstt{=\xintGCtoF{143+1/2+1/5+-1/4+-1/4+-1/4+-1/3+1/2+1/2+1/6+-1/22+1/2+1/10+-1/5+-1/11+-1/3+1/4+-1/2+1/2+1/4+-1/2+1/23+1/3+1/8+-1/6+-1/9}}} + +\def\mymacro #1{$\xintFrac{#1}=[\xintFtoCs{#1}]$\vtop to 6pt{}} + +\begingroup +\catcode`^\active +\def^#1^{\hbox{\fontfamily{lmtt}\selectfont #1}}% + +When a generalized continued fraction is built with integers, and +numerators are only |1|'s or |-1|'s, the produced fraction is +irreducible. And if we compute it again with the last sub-fraction +omitted we get another irreducible fraction related to the bigger one by +a Bezout identity. Doing this here we get: +\centeredline{|\xintGCtoF {143+1/2+...+-1/6}|\digitstt{=\xintGCtoF{143+1/2+1/5+-1/4+-1/4+-1/4+-1/3+1/2+1/2+1/6+-1/22+1/2+1/10+-1/5+-1/11+-1/3+1/4+-1/2+1/2+1/4+-1/2+1/23+1/3+1/8+-1/6}}} +and indeed: +\[ \begin{vmatrix} + ^2897319801297630107^ & ^328124887710626729^\\ + ^20197107104701740^ & ^2287346221788023^ + \end{vmatrix} = \mbox{\digitstt{\xintiSub {\xintiMul {2897319801297630107}{2287346221788023}}{\xintiMul{20197107104701740}{328124887710626729}}}}\] + +\endgroup +More generally the various fractions obtained from the truncation of a +continued fraction to its initial terms are called the convergents. The +commands of \xintcfracname such as \csbxint{FtoCv}, \csbxint{FtoCCv}, +and others which compute such convergents, return them as a list of +braced items, with no separator. This list can then be treated either +with \csa{xint\-AssignArray}, or \csa{xintListWithSep}, or any other way +(but then, some \TeX{} programming knowledge will be necessary). Here +is an example: + +\noindent +\centeredline{|$$\xintFrac{915286/188421}\to \xintListWithSep {,}%|}% +\centeredline{|{\xintApply{\xintFrac}{\xintFtoCv{915286/188421}}}$$|} +\[ \xintFrac{915286/188421}\to \xintListWithSep {,} +{\xintApply\xintFrac{\xintFtoCv{915286/188421}}}\] +\centeredline{|$$\xintFrac{915286/188421}\to \xintListWithSep {,}%|}% +\centeredline{|{\xintApply{\xintFrac}{\xintFtoCCv{915286/188421}}}$$|} +\[ \xintFrac{915286/188421}\to \xintListWithSep {,} +{\xintApply\xintFrac{\xintFtoCCv{915286/188421}}}\] We thus see that the +`centered convergents' obtained with \csbxint{FtoCCv} are among the fuller list +of convergents as returned by \csbxint{FtoCv}. + +Here is a more complicated use of \csa{xintApply} +and \csa{xintListWithSep}. We first define a macro which will be applied to each +convergent:\centeredline{|\newcommand{\mymacro}[1]|% + |{$\xintFrac{#1}=[\xintFtoCs{#1}]$\vtop to 6pt{}}|}% +Next, we use the following code: +\centeredline{|$\xintFrac{49171/18089}\to{}$|}% +\centeredline{|\xintListWithSep {, + }{\xintApply{\mymacro}{\xintFtoCv{49171/18089}}}|} +It produces:\par +\noindent$ \xintFrac{49171/18089}\to {}$\xintListWithSep {, + }{\xintApply{\mymacro}{\xintFtoCv{49171/18089}}}. + + +\def\cn #1{\xintiPow {2}{#1}}% + +The macro \csbxint{CntoF} allows to specify the coefficients as +functions of the index. The values to which expand the +coefficient function do not have to be integers. \centeredline{|\def\cn + #1{\xintiPow {2}{#1}}% 2^n|}% + \centeredline{|\[\xintFrac{\xintCntoF {6}{\cn}}=\xintCFrac + [l]{\xintCntoF {6}{\cn}}\]|}% +\[\xintFrac{\xintCntoF {6}{\cn}}=\xintCFrac [l]{\xintCntoF + {6}{\cn}}\] +Notice the use of the optional argument |[l]| to \csa{xintCFrac}. Other +possibilities are |[r]| and (default) |[c]|. +\def\cn #1{\xintPow {2}{-#1}}% +\centeredline{|\def\cn #1{\xintPow {2}{-#1}}% 1/2^n|}% +\centeredline{% +|\[\xintFrac{\xintCntoF {6}{\cn}} = \xintGCFrac [r]{\xintCntoGC {6}{\cn}}|}% +\centeredline{| = [\xintFtoCs {\xintCntoF {6}{\cn}}]\]|}% +\[\xintFrac{\xintCntoF {6}{\cn}}=\xintGCFrac [r]{\xintCntoGC {6}{\cn}}= + [\xintFtoCs {\xintCntoF {6}{\cn}}]\] +We used \csbxint{CntoGC} as we wanted to display also the continued fraction and +not only the fraction returned by \csa{xintCntoF}. + +There are also \csbxint{GCntoF} and \csbxint{GCntoGC} which allow the same for +generalized fractions. The following initial portion of a generalized continued +fraction for $\pi$: +\def\an #1{\the\numexpr 2*#1+1\relax }% +\def\bn #1{\the\numexpr (#1+1)*(#1+1)\relax }% +\[ \xintFrac{\xintDiv {4}{\xintGCntoF {5}{\an}{\bn}}} = + \cfrac{4}{\xintGCFrac{\xintGCntoGC {5}{\an}{\bn}}} = +\xintTrunc {10}{\xintDiv {4}{\xintGCntoF {5}{\an}{\bn}}}\dots\] +was obtained with this code: +\dverb|@ +\def\an #1{\the\numexpr 2*#1+1\relax }% +\def\bn #1{\the\numexpr (#1+1)*(#1+1)\relax }% +\[ \xintFrac{\xintDiv {4}{\xintGCntoF {5}{\an}{\bn}}} = + \cfrac{4}{\xintGCFrac{\xintGCntoGC {5}{\an}{\bn}}} = +\xintTrunc {10}{\xintDiv {4}{\xintGCntoF {5}{\an}{\bn}}}\dots\]| + +We see that the quality of approximation is not fantastic compared to the simple +continued fraction of $\pi$ with about as many terms: +\dverb|@ +\[ \xintFrac{\xintCstoF{3,7,15,1,292,1,1}}= + \xintGCFrac{3+1/7+1/15+1/1+1/292+1/1+1/1}= + \xintTrunc{10}{\xintCstoF{3,7,15,1,292,1,1}}\dots\]| +\[ \xintFrac{\xintCstoF{3,7,15,1,292,1,1}}= +\xintGCFrac{3+1/7+1/15+1/1+1/292+1/1+1/1}= +\xintTrunc{10}{\xintCstoF{3,7,15,1,292,1,1}}\dots\] + +\hypertarget{e-convergents}{To} +conclude this overview of most of the package functionalities, let us explore +the convergents of Euler's number $e$. +\dverb|@ +\def\cn #1{\the\numexpr\ifcase \numexpr #1+3-3*((#1+2)/3)\relax + 1\or1\or2*(#1/3)\fi\relax } +% produces the pattern 1,1,2,1,1,4,1,1,6,1,1,8,... which are the +% coefficients of the simple continued fraction of e-1. +\cnta 0 +\def\mymacro #1{\advance\cnta by 1 + \noindent + \hbox to 3em {\hfil\small\texttt{\the\cnta.} }% + $\xintTrunc {30}{\xintAdd {1[0]}{#1}}\dots= + \xintFrac{\xintAdd {1[0]}{#1}}$}% +\xintListWithSep{\vtop to 6pt{}\vbox to 12pt{}\par} + {\xintApply\mymacro{\xintiCstoCv{\xintCntoCs {35}{\cn}}}}| + +\smallskip The volume of computation is kept minimal by the following steps: +\begin{itemize} +\item a comma separated list of the first 36 coefficients is produced by + \csbxint{CntoCs}, +\item this is then given to \csbxint{iCstoCv} which produces the list of the + convergents (there is also \csbxint{CstoCv}, but our + coefficients being integers we used the infinitesimally + faster \csbxint{iCstoCv}), +\item then the whole list was converted into a sequence of one-line paragraphs, + each convergent becomes the argument to a macro printing it + together with its decimal expansion with 30 digits after the decimal point. +\item A count register |\cnta| was used to give a line count serving as a visual + aid: we could also have done that in an expandable way, but well, let's relax + from time to time\dots +\end{itemize} + + +\def\cn #1{\the\numexpr\ifcase \numexpr #1+3-3*((#1+2)/3)\relax + 1\or1\or2*(#1/3)\fi\relax } +% produces the pattern 1,1,2,1,1,4,1,1,6,1,1,8,... which are the +% coefficients of the simple continued fraction of e-1. +\cnta 0 +\def\mymacro #1{\advance\cnta by 1 + \noindent + \hbox to 3em {\hfil\small\digitstt{\the\cnta.} }% + $\xintTrunc {30}{\xintAdd {1[0]}{#1}}\dots= + \xintFrac{\xintAdd {1[0]}{#1}}$}% +\xintListWithSep{\vtop to 6pt{}\vbox to 12pt{}\par} + {\xintApply\mymacro{\xintiCstoCv{\xintCntoCs {35}{\cn}}}} + +% \def\testmacro #1{\xintTrunc {30}{\xintAdd {1[0]}{#1}}\xintAdd {1[0]}{#1}} +% \pdfresettimer +% \edef\z{\xintApply\testmacro{\xintiCstoCv{\xintCntoCs {35}{\cn}}}} +% (\the\pdfelapsedtime) + + +\smallskip The actual computation of the list of all 36 convergents accounts for +only 8\% of the total time (total time equal to about 5 hundredths of a second +in my testing, on my laptop): another 80\% is occupied with the computation of +the truncated decimal expansions (and the addition of 1 to everything as the +formula gives the continued fraction of $e-1$). One can with no problem compute +much bigger convergents. Let's get the 200th convergent. It turns out to +have the same first 268 digits after the decimal point as $e-1$. Higher +convergents get more and more digits in proportion to their index: the 500th +convergent already gets 799 digits correct! To allow speedy compilation of the +source of this document when the need arises, I limit here to the 200th +convergent (getting the 500th took about 1.2s on my laptop last time I tried, +and the 200th convergent is obtained ten times faster). +\dverb|@ +\oodef\z {\xintCntoF {199}{\cn}}% +\begingroup\parindent 0pt \leftskip 2.5cm +\indent\llap {Numerator = }{\printnumber{\xintNumerator\z}\par +\indent\llap {Denominator = }\printnumber{\xintDenominator\z}\par +\indent\llap {Expansion = }\printnumber{\xintTrunc{268}\z}\dots +\par\endgroup| + +\oodef\z {\xintCntoF {199}{\cn}}% + +\begingroup\parindent 0pt \leftskip 2.5cm +\indent\llap {Numerator = }\digitstt{\printnumber{\xintNumerator\z}}\par +\indent\llap {Denominator = }\digitstt{\printnumber{\xintDenominator\z}}\par +\indent\llap + {Expansion = }\digitstt{\printnumber{\xintTrunc{268}\z}\dots}\par\endgroup + +One can also use a centered continued fraction: we get more digits but there are +also more computations as the numerators may be either +$1$ or $-1$. + +\subsection{\csbh{xintCFrac}}\label{xintCFrac} + +\csa{xintCFrac}|{f}|\ntype{\Ff} is a math-mode only, \LaTeX{} with |amsmath| +only, macro which first computes then displays with the help of |\cfrac| the +simple continued fraction corresponding to the given fraction. It admits an +optional argument which may be |[l]|, |[r]| or (the default) |[c]| to specify +the location of the one's in the numerators of the sub-fractions. Each +coefficient is typeset using the \csbxint{Frac} macro from the \xintfracname +package. This macro is \fexpan dable in the sense that it prepares expandably +the whole expression with the multiple |\cfrac|'s, but it is not completely +expandable naturally. + +\subsection{\csbh{xintGCFrac}}\label{xintGCFrac} + +\csa{xintGCFrac}|{a+b/c+d/e+f/g+h/...}|\etype{f} uses similarly |\cfrac| to +typeset a +generalized continued fraction in inline format. It admits the same optional +argument as \csa{xintCFrac}. +\centeredline{|\[\xintGCFrac {1+\xintPow{1.5}{3}/{1/7}+{-3/5}/\xintFac {6}}\]|} +\[\xintGCFrac {1+\xintPow{1.5}{3}/{1/7}+{-3/5}/\xintFac {6}}\] +As can be seen this is typesetting macro, although it does proceed to the +evaluation of the coefficients themselves. See \csbxint{GCtoF} if you are +impatient to see this fraction computed. Numerators and denominators are made +arguments to the +\csbxint{Frac} macro. + +\subsection{\csbh{xintGCtoGCx}}\label{xintGCtoGCx} +%{\small New with release |1.05|.\par} + + +\csa{xintGCtoGCx}|{sepa}{sepb}{a+b/c+d/e+f/...+x/y}|\etype{nnf} returns the list +of the coefficients of the generalized continued fraction of |f|, each one +within a pair of braces, and separated with the help of |sepa| and |sepb|. Thus +\centeredline{|\xintGCtoGCx :;{1+2/3+4/5+6/7}| gives \xintGCtoGCx + :;{1+2/3+4/5+6/7}} Plain \TeX{}+|amstex| users may be interested in:\par +\dverb|@ +$$\xintGCtoGCx {+\cfrac}{\\}{a+b/...}\endcfrac$$ +$$\xintGCtoGCx {+\cfrac\xintFwOver}{\\\xintFwOver}{a+b/...}\endcfrac$$| + + +\subsection{\csbh{xintFtoCs}}\label{xintFtoCs} + +\csa{xintFtoCs}|{f}|\etype{\Ff} returns the comma separated list of the +coefficients of the simple continued fraction of |f|. +\centeredline{% + |\[ \xintSignedFrac{-5262046/89233} = [\xintFtoCs{-5262046/89233}]\]|}% +\[ \xintSignedFrac{-5262046/89233} = [\xintFtoCs{-5262046/89233}]\] + + +\subsection{\csbh{xintFtoCx}}\label{xintFtoCx} + +\csa{xintFtoCx}|{sep}{f}|\etype{n\Ff} returns the list of the coefficients of +the simple continued fraction of |f|, withing group braces and separated with +the help of |sep|. \centeredline{|$$\xintFtoCx {+\cfrac1\\ }{f}\endcfrac$$|} +will display the continued fraction in |\cfrac| format, with Plain \TeX{} and +|amstex|. + +\subsection{\csbh{xintFtoGC}}\label{xintFtoGC} + +\csa{xintFtoGC}|{f}|\etype{\Ff} does the same as \csa{xintFtoCx}|{+1/}{f}|. Its +output may thus be used in the package macros expecting such an `inline +format'. This continued fraction is a \emph{simple} one, not a +\emph{generalized} one, but as it is produced in the format used for +user input of generalized continued fractions, the macro was called +\csa{xintFtoGC} rather than \csa{xintFtoC} for example. +\centeredline{|566827/208524=\xintFtoGC {566827/208524}|}% +\centeredline{566827/208524=\xintFtoGC {566827/208524}} + +\subsection{\csbh{xintFtoCC}}\label{xintFtoCC} + +\csa{xintFtoCC}|{f}|\etype{\Ff} returns the `centered' continued fraction of +|f|, in `inline format'. \centeredline{|566827/208524=\xintFtoCC + {566827/208524}|}% +\centeredline{566827/208524=\xintFtoCC {566827/208524}} \centeredline{% + |\[\xintFrac{566827/208524} = \xintGCFrac{\xintFtoCC{566827/208524}}\]|}% +\[\xintFrac{566827/208524} = \xintGCFrac{\xintFtoCC{566827/208524}}\] + +\subsection{\csbh{xintFtoCv}}\label{xintFtoCv} + +\csa{xintFtoCv}|{f}|\etype{\Ff} returns the list of the (braced) convergents of +|f|, with no separator. To be treated with \csbxint{AssignArray} or +\csbxint{ListWithSep}. \centeredline{% + |\[\xintListWithSep{\to}{\xintApply\xintFrac{\xintFtoCv{5211/3748}}}\]|}% +\[\xintListWithSep{\to}{\xintApply\xintFrac{\xintFtoCv{5211/3748}}}\] + +\subsection{\csbh{xintFtoCCv}}\label{xintFtoCCv} + +\csa{xintFtoCCv}|{f}|\etype{\Ff} returns the list of the (braced) centered +convergents of |f|, with no separator. To be treated with \csbxint{AssignArray} +or \csbxint{ListWithSep}. \centeredline{% + |\[\xintListWithSep{\to}{\xintApply\xintFrac{\xintFtoCCv{5211/3748}}}\]|}% +\[\xintListWithSep{\to}{\xintApply\xintFrac{\xintFtoCCv{5211/3748}}}\] + +\subsection{\csbh{xintCstoF}}\label{xintCstoF} + +\csa{xintCstoF}|{a,b,c,d,...,z}|\etype{f} computes the fraction corresponding to +the coefficients, which may be fractions or even macros expanding to such +fractions. The final fraction may then be highly reducible. +\centeredline{|\[\xintGCFrac {-1+1/3+1/-5+1/7+1/-9+1/11+1/-13}|}% +\centeredline{|=\xintSignedFrac{\xintCstoF {-1,3,-5,7,-9,11,-13}}|}% +\centeredline{|=\xintSignedFrac{\xintGCtoF + {-1+1/3+1/-5+1/7+1/-9+1/11+1/-13}}\]|}% +\[\xintGCFrac {-1+1/3+1/-5+1/7+1/-9+1/11+1/-13}= +\xintSignedFrac{\xintCstoF {-1,3,-5,7,-9,11,-13}} +=\xintSignedFrac{\xintGCtoF {-1+1/3+1/-5+1/7+1/-9+1/11+1/-13}}\] +\centeredline{|\xintGCFrac{{1/2}+1/{1/3}+1/{1/4}+1/{1/5}}= |}% +\centeredline{| \xintFrac{\xintCstoF {1/2,1/3,1/4,1/5}}|}% +\[\xintGCFrac{{1/2}+1/{1/3}+1/{1/4}+1/{1/5}}= +\xintFrac{\xintCstoF {1/2,1/3,1/4,1/5}}\] A generalized continued fraction may +produce a reducible fraction (\csa{xintCstoF} tries its best not to accumulate +in a silly way superfluous factors but will not do simplifications which would +be obvious to a human, like simplification by 3 in the result above). + +\subsection{\csbh{xintCstoCv}}\label{xintCstoCv} + +\csa{xintCstoCv}|{a,b,c,d,...,z}|\etype{f} returns the list of the corresponding +convergents. It is allowed to use fractions as coefficients (the computed +convergents have then no reason to be the real convergents of the final +fraction). When the coefficients are integers, the convergents are irreducible +fractions, but otherwise it is not necessarily the case. +\centeredline{|\xintListWithSep:{\xintCstoCv{1,2,3,4,5,6}}|}% +\centeredline{\digitstt{\xintListWithSep:{\xintCstoCv{1,2,3,4,5,6}}}} +\centeredline{|\xintListWithSep:{\xintCstoCv{1,1/2,1/3,1/4,1/5,1/6}}|}% +\centeredline{\digitstt{\xintListWithSep:{\xintCstoCv{1,1/2,1/3,1/4,1/5,1/6}}}} +% j'ai retiré les [0] à partir de la version 1.09b, le 3 octobre 2013. +\centeredline{|\[\xintListWithSep{\to}{\xintApply\xintFrac{\xintCstoCv|}% + \centeredline{|{\xintPow {-.3}{-5},7.3/4.57,\xintCstoF{3/4,9,-1/3}}}}\]|}% +\[\xintListWithSep{\to}{\xintApply\xintFrac{\xintCstoCv + {\xintPow {-.3}{-5},7.3/4.57,\xintCstoF{3/4,9,-1/3}}}}\] + + +\subsection{\csbh{xintCstoGC}}\label{xintCstoGC} + +\csa{xintCstoGC}|{a,b,..,z}|\etype{f} transforms a comma separated list (or +something expanding to such a list) into an `inline format' continued fraction +|{a}+1/{b}+1/...+1/{z}|. The coefficients are just copied and put within braces, +without expansion. The output can then be used in \csbxint{GCFrac} for example. +\centeredline{|\[\xintGCFrac {\xintCstoGC {-1,1/2,-1/3,1/4,-1/5}}|}% +\centeredline{|=\xintSignedFrac {\xintCstoF {-1,1/2,-1/3,1/4,-1/5}}\]|}% +\[\xintGCFrac {\xintCstoGC {-1,1/2,-1/3,1/4,-1/5}} = +\xintSignedFrac{\xintCstoF {-1,1/2,-1/3,1/4,-1/5}}\] + +\subsection{\csbh{xintGCtoF}}\label{xintGCtoF} + +\csa{xintGCtoF}|{a+b/c+d/e+f/g+......+v/w+x/y}|\etype{f} computes the fraction +defined by the inline generalized continued fraction. Coefficients may be +fractions but must then be put within braces. They can be macros. The plus signs +are mandatory. \dverb|@ +\[\xintGCFrac {1+\xintPow{1.5}{3}/{1/7}+{-3/5}/\xintFac {6}} = +\xintFrac{\xintGCtoF {1+\xintPow{1.5}{3}/{1/7}+{-3/5}/\xintFac {6}}} = +\xintFrac{\xintIrr{\xintGCtoF + {1+\xintPow{1.5}{3}/{1/7}+{-3/5}/\xintFac {6}}}}\]| +\[\xintGCFrac {1+\xintPow{1.5}{3}/{1/7}+{-3/5}/\xintFac {6}} = +\xintFrac{\xintGCtoF {1+\xintPow{1.5}{3}/{1/7}+{-3/5}/\xintFac {6}}} = +\xintFrac{\xintIrr{\xintGCtoF {1+\xintPow{1.5}{3}/{1/7}+{-3/5}/\xintFac {6}}}}\] +\dverb|@ +\[ \xintGCFrac{{1/2}+{2/3}/{4/5}+{1/2}/{1/5}+{3/2}/{5/3}} = + \xintFrac{\xintGCtoF {{1/2}+{2/3}/{4/5}+{1/2}/{1/5}+{3/2}/{5/3}}} \]| +\[ \xintGCFrac{{1/2}+{2/3}/{4/5}+{1/2}/{1/5}+{3/2}/{5/3}} = + \xintFrac{\xintGCtoF {{1/2}+{2/3}/{4/5}+{1/2}/{1/5}+{3/2}/{5/3}}} \] +The macro tries its best not to accumulate superfluous factor in the +denominators, but doesn't reduce the fraction to irreducible form before +returning it and does not do simplifications which would be obvious to a human. + +\subsection{\csbh{xintGCtoCv}}\label{xintGCtoCv} + +\csa{xintGCtoCv}|{a+b/c+d/e+f/g+......+v/w+x/y}|\etype{f} returns the list of +the corresponding convergents. The coefficients may be fractions, but must then +be inside braces. Or they may be macros, too. + +The convergents will in the general case be reducible. To put them into +irreducible form, one needs one more step, for example it can be done +with |\xintApply\xintIrr|. +\dverb|@ +\[\xintListWithSep{,}{\xintApply\xintFrac + {\xintGCtoCv{3+{-2}/{7/2}+{3/4}/12+{-56}/3}}}\] +\[\xintListWithSep{,}{\xintApply\xintFrac{\xintApply\xintIrr + {\xintGCtoCv{3+{-2}/{7/2}+{3/4}/12+{-56}/3}}}}\]| +\[\xintListWithSep{,}{\xintApply\xintFrac + {\xintGCtoCv{3+{-2}/{7/2}+{3/4}/12+{-56}/3}}}\] +\[\xintListWithSep{,}{\xintApply\xintFrac{\xintApply\xintIrr + {\xintGCtoCv{3+{-2}/{7/2}+{3/4}/12+{-56}/3}}}}\] + +\subsection{\csbh{xintCntoF}}\label{xintCntoF} + +\def\macro #1{\the\numexpr 1+#1*#1\relax} + +\csa{xintCntoF}|{N}{\macro}|\etype{\numx f} computes the fraction |f| having coefficients +|c(j)=\macro{j}| for |j=0,1,...,N|. The |N| parameter is given to a |\numexpr|. +The values of the coefficients, as returned by |\macro| do not have to be +positive, nor integers, and it is thus not necessarily the case that the +original |c(j)| are the true coefficients of the final |f|. \centeredline{% + |\def\macro #1{\the\numexpr 1+#1*#1\relax}\xintCntoF {5}{\macro}|}% +\centeredline{\digitstt{\xintCntoF {5}{\macro}}} + +\subsection{\csbh{xintGCntoF}}\label{xintGCntoF} + +\def\coeffA #1{\the\numexpr #1+4-3*((#1+2)/3)\relax }% +\def\coeffB #1{\xintMON{#1}}% (-1)^n + +\csa{xintGCntoF}|{N}{\macroA}{\macroB}|\etype{\numx ff} returns the fraction |f| +corresponding to the inline generalized continued fraction +|a0+b0/a1+b1/a2+....+b(N-1)/aN|, with |a(j)=\macroA{j}| and |b(j)=\macroB{j}|. +The |N| parameter is given to a |\numexpr|. +\[\xintGCFrac{\xintGCntoGC {6}{\coeffA}{\coeffB}} += \xintFrac{\xintGCntoF {6}{\coeffA}{\coeffB}}\] +There is also \csbxint{GCntoGC} to get the `inline format' continued +fraction. The previous display was obtained with: +\centeredline{|\def\coeffA #1{\the\numexpr #1+4-3*((#1+2)/3)\relax }%|}% +\centeredline{|\def\coeffB #1{\xintMON{#1}}% (-1)^n|}% +\centeredline{|\[\xintGCFrac{\xintGCntoGC {6}{\coeffA}{\coeffB}}|}% +\centeredline{| = \xintFrac{\xintGCntoF {6}{\coeffA}{\coeffB}}\]|} + + +\subsection{\csbh{xintCntoCs}}\label{xintCntoCs} + +\csa{xintCntoCs}|{N}{\macro}|\etype{\numx f} produces the comma separated list +of the corresponding coefficients, from |n=0| to |n=N|. The |N| is given to a +|\numexpr|. \centeredline{% + |\def\macro #1{\the\numexpr 1+#1*#1\relax}|}% +\centeredline{|\xintCntoCs {5}{\macro}|\digitstt{->\xintCntoCs {5}{\macro}}}% +\centeredline{|\[\xintFrac{\xintCntoF {5}{\macro}}=\xintCFrac{\xintCntoF + {5}{\macro}}\]|}% +\[ \xintFrac{\xintCntoF + {5}{\macro}}=\xintCFrac{\xintCntoF {5}{\macro}}\] + +\subsection{\csbh{xintCntoGC}}\label{xintCntoGC} + +\def\macro #1{\the\numexpr\ifodd#1 -1-#1\else1+#1\fi\relax/% + \the\numexpr 1+#1*#1\relax} +% +\csa{xintCntoGC}|{N}{\macro}|\etype{\numx f} evaluates the |c(j)=\macro{j}| from +|j=0| to |j=N| and returns a continued fraction written in inline format: +|{c(0)}+1/{c(1)}+1/...+1/{c(N)}|. The parameter |N| is given to a |\numexpr|. +The coefficients, after expansion, are, as shown, being enclosed in an added +pair of braces, they may thus be fractions. \centeredline{% + |\def\macro #1{\the\numexpr\ifodd#1 -1-#1\else1+#1\fi\relax/%|}% + \centeredline{|\the\numexpr 1+#1*#1\relax}|}% + \centeredline{|\edef\x{\xintCntoGC {5}{\macro}}\meaning\x|}% + \centeredline{\edef\x{\xintCntoGC {5}{\macro}}\digitstt{\meaning\x}}% + \centeredline{|\[\xintGCFrac{\xintCntoGC {5}{\macro}}\]|}% +\[\xintGCFrac{\xintCntoGC {5}{\macro}}\] + +\subsection{\csbh{xintGCntoGC}}\label{xintGCntoGC} + +\csa{xintGCntoGC}|{N}{\macroA}{\macroB}|\etype{\numx ff} evaluates the +coefficients and then returns the corresponding +|{a0}+{b0}/{a1}+{b1}/{a2}+...+{b(N-1)}/{aN}| inline generalized fraction. |N| is +givent to a |\numexpr|. As shown, the coefficients are enclosed into added pairs +of braces, and may thus be fractions. \dverb|@ \def\an #1{\the\numexpr + #1*#1*#1+1\relax}% +\def\bn #1{\the\numexpr \xintiiMON{#1}*(#1+1)\relax}% +$\xintGCntoGC {5}{\an}{\bn}}=\xintGCFrac {\xintGCntoGC {5}{\an}{\bn}} = +\displaystyle\xintFrac {\xintGCntoF {5}{\an}{\bn}}$\par| + +\def\an #1{\the\numexpr #1*#1*#1+1\relax}% +\def\bn #1{\the\numexpr \xintiiMON{#1}*(#1+1)\relax}% +$\xintGCntoGC {5}{\an}{\bn}=\xintGCFrac {\xintGCntoGC {5}{\an}{\bn}} + = \displaystyle\xintFrac {\xintGCntoF {5}{\an}{\bn}}$\par + + + +\subsection{\csbh{xintiCstoF}, \csbh{xintiGCtoF}, \csbh{xint\-iCstoCv}, \csbh{xintiGCtoCv}}\label{xintiCstoF} +\label{xintiGCtoF} +\label{xintiCstoCv} +\label{xintiGCtoCv} + +The same as the corresponding macros without the `i', but for +integer-only input. Infinitesimally faster; to notice the higher +efficiency one would need to use them with an input having (at least) +hundreds of coefficients. + + +\subsection{\csbh{xintGCtoGC}}\label{xintGCtoGC} + +\csa{xintGCtoGC}|{a+b/c+d/e+f/g+......+v/w+x/y}|\etype{f} expands (with the +usual meaning) each one of the coefficients and returns an inline continued +fraction of the same type, each expanded coefficient being enclosed withing +braces. \dverb|@ \edef\x {\xintGCtoGC {1+\xintPow{1.5}{3}/{1/7}+{-3/5}/\xintFac + {6}+\xintCstoF {2,-7,-5}/16}} \meaning\x| + +\edef\x {\xintGCtoGC + {1+\xintPow{1.5}{3}/{1/7}+{-3/5}/\xintFac {6}+\xintCstoF {2,-7,-5}/16}} +\digitstt{\meaning\x} + +To be honest I have, it seems, forgotten why I wrote this macro in the +first place. + +% will be used by the \lverb things + +\def\givesomestretch{% +\fontdimen2\font=0.33333\fontdimen6\font +\fontdimen3\font=0.16666\fontdimen6\font +\fontdimen4\font=0.11111\fontdimen6\font +}% +\def\MacroFont{\ttfamily\small\givesomestretch\hyphenchar\font45 + \baselineskip12pt\relax } + + +\ifnum\NoSourceCode=1 +\bigskip +\begin{framed} + \ttfamily\small\givesomestretch\hyphenchar\font45 This documentation + has been compiled without the source code. To produce the + documentation with the source code included, run "tex xint.dtx" to + generate xint.tex (if not already available), then thrice latex on + xint.tex and finally dvipdfmx on xint.dvi (ignore the dvipdfmx + warnings; see also + \autoref{sec:install}). +\end{framed} +\fi + +\makeatletter +\StopEventually{\end{document}\endinput} + +\def\storedlinecounts {} +\def\StoreCodelineNo #1{\edef\storedlinecounts{% + \unexpanded\expandafter{\storedlinecounts}% + {{#1}{\the\c@CodelineNo}}}\c@CodelineNo\z@ } + +\makeatother + +\newgeometry{hmarginratio=4:3,hscale=0.75} + + +\etocdepthtag.toc {implementation} + +\MakePercentIgnore +% +% \catcode`\<=0 \catcode`\>=11 \catcode`\*=11 \catcode`\/=11 +% \let</dtx>\relax +% \def<*xinttools>{\catcode`\<=12 \catcode`\>=12 \catcode`\*=12 \catcode`\/=12 } +%</dtx> +%<*xinttools> +% \def\MARGEPAGENO{2.5em} +% \section {Package \xinttoolsnameimp implementation} +% \label{sec:toolsimp} +% +% Release |1.09g| splits off |xinttools.sty| from |xint.sty|. +% +% \localtableofcontents +% +% \subsection{Catcodes, \protect\eTeX{} and reload detection} +% +% The method for package identification and reload detection is copied verbatim +% from the packages by \textsc{Heiko Oberdiek} (with some modifications starting +% with release |1.09b|). +% +% The method for catcodes was also inspired by these packages, we proceed +% slightly differently. +% +% Starting with version |1.06| of the package, also |`| must be +% catcode-protected, because we replace everywhere in the code the +% twice-expansion done with |\expandafter| by the systematic use of +% |\romannumeral-`0|. +% +% Starting with version |1.06b| I decide that I suffer from an indigestion of @ +% signs, so I replace them all with underscores |_|, \`a la \LaTeX 3. +% +% Release |1.09b| is more economical: some macros are defined already in +% |xint.sty| (now |xinttools.sty|) and re-used in other modules. All catcode +% changes have been unified and \csa{XINT_storecatcodes} will be used by each +% module to redefine |\XINT_restorecatcodes_endinput| in case catcodes have +% changed in-between the loading of |xint.sty| (now |xinttools.sty|) and the +% module (not very probable but...). +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode95=11 % _ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \expandafter\let\expandafter\x\csname ver@xint.sty\endcsname + \expandafter + \ifx\csname PackageInfo\endcsname\relax + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \else + \def\y#1#2{\PackageInfo{#1}{#2}}% + \fi + \expandafter + \ifx\csname numexpr\endcsname\relax + \y{xinttools}{\numexpr not available, aborting input}% + \aftergroup\endinput + \else + \ifx\x\relax % plain-TeX, first loading + \else + \def\empty {}% + \ifx\x\empty % LaTeX, first loading, + % variable is initialized, but \ProvidesPackage not yet seen + \else + \y{xinttools}{I was already loaded, aborting input}% + \aftergroup\endinput + \fi + \fi + \fi + \def\ChangeCatcodesIfInputNotAborted + {% + \endgroup + \def\XINT_storecatcodes + {% takes care of all, to allow more economical code in modules + \catcode34=\the\catcode34 % " xintbinhex, and 1.09k xintexpr + \catcode63=\the\catcode63 % ? xintexpr + \catcode124=\the\catcode124 % | xintexpr + \catcode38=\the\catcode38 % & xintexpr + \catcode64=\the\catcode64 % @ xintexpr + \catcode33=\the\catcode33 % ! xintexpr + \catcode93=\the\catcode93 % ] -, xintfrac, xintseries, xintcfrac + \catcode91=\the\catcode91 % [ -, xintfrac, xintseries, xintcfrac + \catcode36=\the\catcode36 % $ xintgcd only + \catcode94=\the\catcode94 % ^ + \catcode96=\the\catcode96 % ` + \catcode47=\the\catcode47 % / + \catcode41=\the\catcode41 % ) + \catcode40=\the\catcode40 % ( + \catcode42=\the\catcode42 % * + \catcode43=\the\catcode43 % + + \catcode62=\the\catcode62 % > + \catcode60=\the\catcode60 % < + \catcode58=\the\catcode58 % : + \catcode46=\the\catcode46 % . + \catcode45=\the\catcode45 % - + \catcode44=\the\catcode44 % , + \catcode35=\the\catcode35 % # + \catcode95=\the\catcode95 % _ + \catcode125=\the\catcode125 % } + \catcode123=\the\catcode123 % { + \endlinechar=\the\endlinechar + \catcode13=\the\catcode13 % ^^M + \catcode32=\the\catcode32 % + \catcode61=\the\catcode61\relax % = + }% + \edef\XINT_restorecatcodes_endinput + {% + \XINT_storecatcodes\noexpand\endinput % + }% + \def\XINT_setcatcodes + {% + \catcode61=12 % = + \catcode32=10 % space + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode95=11 % _ (replaces @ everywhere, starting with 1.06b) + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=11 % : (made letter for error cs) + \catcode60=12 % < + \catcode62=12 % > + \catcode43=12 % + + \catcode42=12 % * + \catcode40=12 % ( + \catcode41=12 % ) + \catcode47=12 % / + \catcode96=12 % ` (for ubiquitous \romannumeral-`0 and some \catcode ) + \catcode94=11 % ^ + \catcode36=3 % $ + \catcode91=12 % [ + \catcode93=12 % ] + \catcode33=11 % ! + \catcode64=11 % @ + \catcode38=12 % & + \catcode124=12 % | + \catcode63=11 % ? + \catcode34=12 % " missing from v < 1.09k although needed in xintbinhex + }% + \XINT_setcatcodes + }% +\ChangeCatcodesIfInputNotAborted +\def\XINTsetupcatcodes {% for use by other modules + \edef\XINT_restorecatcodes_endinput + {% + \XINT_storecatcodes\noexpand\endinput % + }% + \XINT_setcatcodes +}% +% \end{macrocode} +% \subsection{Package identification} +% +% Inspired from \textsc{Heiko Oberdiek}'s packages. Modified in |1.09b| to allow +% re-use in the other modules. Also I assume now that if |\ProvidesPackage| +% exists it then does define |\ver@<pkgname>.sty|, code of |HO| for some reason +% escaping me (compatibility with LaTeX 2.09 or other things ??) seems to set +% extra precautions. +% +% |1.09c| uses e-\TeX{} |\ifdefined|. +% \begin{macrocode} +\ifdefined\ProvidesPackage + \let\XINT_providespackage\relax +\else + \def\XINT_providespackage #1#2[#3]% + {\immediate\write-1{Package: #2 #3}% + \expandafter\xdef\csname ver@#2.sty\endcsname{#3}}% +\fi +\XINT_providespackage +\ProvidesPackage {xinttools}% + [2014/02/05 v1.09ka Expandable and non-expandable utilities (jfB)]% +% \end{macrocode} +% \subsection{Token management, constants} +% \lverb|In 1.09e \xint_undef replaced everywhere by \xint_bye. +% Release 1.09h makes most everything \long.| +% \begin{macrocode} +\long\def\xint_gobble_ {}% +\long\def\xint_gobble_i #1{}% +\long\def\xint_gobble_ii #1#2{}% +\long\def\xint_gobble_iii #1#2#3{}% +\long\def\xint_gobble_iv #1#2#3#4{}% +\long\def\xint_gobble_v #1#2#3#4#5{}% +\long\def\xint_gobble_vi #1#2#3#4#5#6{}% +\long\def\xint_gobble_vii #1#2#3#4#5#6#7{}% +\long\def\xint_gobble_viii #1#2#3#4#5#6#7#8{}% +\long\def\xint_firstofone #1{#1}% +\xint_firstofone{\let\XINT_sptoken= } %<- space here! +\long\def\xint_firstoftwo #1#2{#1}% +\long\def\xint_secondoftwo #1#2{#2}% +\long\def\xint_firstoftwo_thenstop #1#2{ #1}% +\long\def\xint_secondoftwo_thenstop #1#2{ #2}% +\def\xint_minus_thenstop { -}% +\long\def\xint_gob_til_R #1\R {}% +\long\def\xint_gob_til_W #1\W {}% +\long\def\xint_gob_til_Z #1\Z {}% +\long\def\xint_bye #1\xint_bye {}% +\let\xint_relax\relax +\def\xint_brelax {\xint_relax }% +\long\def\xint_gob_til_xint_relax #1\xint_relax {}% +\long\def\xint_afterfi #1#2\fi {\fi #1}% +\chardef\xint_c_ 0 +\chardef\xint_c_i 1 % 1.09k did not have it, but needed in \xintSeq +\chardef\xint_c_viii 8 +\newtoks\XINT_toks +% \end{macrocode} +% \subsection{ \csh{xintodef}, \csh{xintgodef}, \csh{odef}} +% \lverb|1.09i. For use in \xintAssign. No parameter text! 1.09j uses \xint... +% rather than \XINT_.... \xintAssign [o] will use the preexisting \odef if there +% was one before xint' loading.| +% \begin{macrocode} +\def\xintodef #1{\expandafter\def\expandafter#1\expandafter }% +\ifdefined\odef\else\let\odef\xintodef\fi +\def\xintgodef {\global\xintodef }% +% \end{macrocode} +% \subsection{ \csh{xintoodef}, \csh{xintgoodef}, \csh{oodef}} +% \lverb|1.09i. Can be prefixed with \global. No parameter text. The alternative +% $\ +% $null \def\oodef #1#{\def\XINT_tmpa{#1}%$\ +% $null $quad $quad $quad \expandafter\expandafter\expandafter\expandafter$\ +% $null $quad $quad $quad \expandafter\expandafter\expandafter\def$\ +% $null $quad $quad $quad \expandafter\expandafter\expandafter\XINT_tmpa$\ +% $null $quad $quad $quad \expandafter\expandafter\expandafter }%$\ +% could not be prefixed by \global. Anyhow, macro parameter tokens would have to +% somehow not be seen by expanded stuff, except if designed for it. +% \xintAssign [oo] (etc...) uses the pre-existing \oodef if there was one. | +% \begin{macrocode} +\def\xintoodef #1{\expandafter\expandafter\expandafter\def + \expandafter\expandafter\expandafter#1% + \expandafter\expandafter\expandafter }% +\ifdefined\oodef\else\let\oodef\xintoodef\fi +\def\xintgoodef {\global\xintoodef }% +% \end{macrocode} +% \subsection{ \csh{xintfdef}, \csh{xintgfdef}, \csh{fdef}} +% \lverb|1.09i. No parameter text! | +% \begin{macrocode} +\def\xintfdef #1#2{\expandafter\def\expandafter#1\expandafter + {\romannumeral-`0#2}}% +\ifdefined\fdef\else\let\fdef\xintfdef\fi +\def\xintgfdef {\global\xintfdef }% should be \global\fdef if \fdef pre-exists? +% \end{macrocode} +% \subsection{ \csh{xintReverseOrder}} +% \lverb|\xintReverseOrder: does NOT expand its argument.| +% \begin{macrocode} +\def\xintReverseOrder {\romannumeral0\xintreverseorder }% +\long\def\xintreverseorder #1% +{% + \XINT_rord_main {}#1% + \xint_relax + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_relax +}% +\long\def\XINT_rord_main #1#2#3#4#5#6#7#8#9% +{% + \xint_bye #9\XINT_rord_cleanup\xint_bye + \XINT_rord_main {#9#8#7#6#5#4#3#2#1}% +}% +\long\edef\XINT_rord_cleanup\xint_bye\XINT_rord_main #1#2\xint_relax +{% + \noexpand\expandafter\space\noexpand\xint_gob_til_xint_relax #1% +}% +% \end{macrocode} +% \subsection{\csh{xintRevWithBraces}} +% \lverb|New with 1.06. Makes the expansion of its argument and then reverses +% the resulting tokens or braced tokens, adding a pair of braces to each (thus, +% maintaining it when it was already there. +% +% As in some other places, 1.09e replaces \Z by \xint_bye, although here it is +% just for coherence of notation as \Z would be perfectly safe. The reason for +% \xint_relax, here and in other locations, is in case #1 expands to nothing, +% the \romannumeral-`0 must be stopped| +% \begin{macrocode} +\def\xintRevWithBraces {\romannumeral0\xintrevwithbraces }% +\def\xintRevWithBracesNoExpand {\romannumeral0\xintrevwithbracesnoexpand }% +\long\def\xintrevwithbraces #1% +{% + \expandafter\XINT_revwbr_loop\expandafter{\expandafter}% + \romannumeral-`0#1\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye +}% +\long\def\xintrevwithbracesnoexpand #1% +{% + \XINT_revwbr_loop {}% + #1\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye +}% +\long\def\XINT_revwbr_loop #1#2#3#4#5#6#7#8#9% +{% + \xint_gob_til_xint_relax #9\XINT_revwbr_finish_a\xint_relax + \XINT_revwbr_loop {{#9}{#8}{#7}{#6}{#5}{#4}{#3}{#2}#1}% +}% +\long\def\XINT_revwbr_finish_a\xint_relax\XINT_revwbr_loop #1#2\xint_bye +{% + \XINT_revwbr_finish_b #2\R\R\R\R\R\R\R\Z #1% +}% +\def\XINT_revwbr_finish_b #1#2#3#4#5#6#7#8\Z +{% + \xint_gob_til_R + #1\XINT_revwbr_finish_c 8% + #2\XINT_revwbr_finish_c 7% + #3\XINT_revwbr_finish_c 6% + #4\XINT_revwbr_finish_c 5% + #5\XINT_revwbr_finish_c 4% + #6\XINT_revwbr_finish_c 3% + #7\XINT_revwbr_finish_c 2% + \R\XINT_revwbr_finish_c 1\Z +}% +\def\XINT_revwbr_finish_c #1#2\Z +{% + \expandafter\expandafter\expandafter + \space + \csname xint_gobble_\romannumeral #1\endcsname +}% +% \end{macrocode} +% \subsection{\csh{xintLength}} +% \lverb|\xintLength does NOT expand its argument.$\ +% 1.09g adds the missing \xintlength, which was previously called \XINT_length, +% and suppresses \XINT_Length$\ +% 1.06: improved code is roughly 20$% faster than the one from earlier +% versions. 1.09a, \xintnum inserted. 1.09e: \Z->\xint_bye as this is called +% from \xintNthElt, and there it was necessary not to use \Z. Later use of \Z +% and \W perfectly safe here.| +% \begin{macrocode} +\def\xintLength {\romannumeral0\xintlength }% +\long\def\xintlength #1% +{% + \XINT_length_loop + {0}#1\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye +}% +\long\def\XINT_length_loop #1#2#3#4#5#6#7#8#9% +{% + \xint_gob_til_xint_relax #9\XINT_length_finish_a\xint_relax + \expandafter\XINT_length_loop\expandafter {\the\numexpr #1+8\relax}% +}% +\def\XINT_length_finish_a\xint_relax + \expandafter\XINT_length_loop\expandafter #1#2\xint_bye +{% + \XINT_length_finish_b #2\W\W\W\W\W\W\W\Z {#1}% +}% +\def\XINT_length_finish_b #1#2#3#4#5#6#7#8\Z +{% + \xint_gob_til_W + #1\XINT_length_finish_c 8% + #2\XINT_length_finish_c 7% + #3\XINT_length_finish_c 6% + #4\XINT_length_finish_c 5% + #5\XINT_length_finish_c 4% + #6\XINT_length_finish_c 3% + #7\XINT_length_finish_c 2% + \W\XINT_length_finish_c 1\Z +}% +\edef\XINT_length_finish_c #1#2\Z #3% + {\noexpand\expandafter\space\noexpand\the\numexpr #3-#1\relax}% +% \end{macrocode} +% \subsection{\csh{xintZapFirstSpaces}} +% \lverb|1.09f, written [2013/11/01].| +% \begin{macrocode} +\def\xintZapFirstSpaces {\romannumeral0\xintzapfirstspaces }% +% \end{macrocode} +% \lverb|defined via an \edef in order to inject space tokens inside.| +% \begin{macrocode} +\long\edef\xintzapfirstspaces #1% + {\noexpand\XINT_zapbsp_a \space #1\space\space\noexpand\xint_bye\xint_relax }% +\xint_firstofone {\long\def\XINT_zapbsp_a #1 } %<- space token here +{% +% \end{macrocode} +% \lverb|If the original #1 started with a space, here #1 will be in fact empty, +% so the effect will be to remove precisely one space from the original, because +% the first two space tokens are matched to the ones of the macro parameter +% text. If the original #1 did not start with a space then the #1 will be this +% original #1, with its added first space, up to the first <sp><sp> found. The +% added initial space will stop later the \romannumeral0. And in +% \xintZapLastSpaces we also carried along a space in order to be able to mix +% tne two codes in \xintZapSpaces. Testing for \emptiness of #1 is NOT done with +% an \if test because #1 may contain \if, \fi things (one could use a +% \detokenize method), and also because xint.sty has a style of its own for +% doing these things...| +% \begin{macrocode} + \XINT_zapbsp_again? #1\xint_bye\XINT_zapbsp_b {#1}% +% \end{macrocode} +% \lverb|The #1 above is thus either empty, or it starts with a (char 32) space +% token followed with a non (char 32) space token and at any rate #1 is +% protected from brace stripping. It is assumed that the initial input does not +% contain space tokens of other than 32 as character code.| +% \begin{macrocode} +}% +\long\def\XINT_zapbsp_again? #1{\xint_bye #1\XINT_zapbsp_again }% +% \end{macrocode} +% \lverb|In the "empty" situation above, here #1=\xint_bye, else #1 could be +% some brace things, but unbracing will anyhow not reveal any \xint_bye. When we +% do below \XINT_zapbsp_again we recall that we have stripped two spaces out of +% <sp><original #1>, so we have one <sp> less in #1, and when we loop we better +% not forget to re-insert one initial <sp>.| +% \begin{macrocode} +\edef\XINT_zapbsp_again\XINT_zapbsp_b #1{\noexpand\XINT_zapbsp_a\space }% +% \end{macrocode} +% \lverb|We now have now gotten rid of the initial spaces, but #1 perhaps extend +% only to some initial chunk which was delimited by <sp><sp>.| +% \begin{macrocode} +\long\def\XINT_zapbsp_b #1#2\xint_relax + {\XINT_zapbsp_end? #2\XINT_zapbsp_e\empty #2{#1}}% +% \end{macrocode} +% \lverb|If the initial chunk up to <sp><sp> (after stripping away the first +% spaces) was maximal, then #2 above is some spaces followed by \xint_bye, so in +% the \XINT_zapbsp_end? below it appears as \xint_bye, else the #1 below will +% not be nor give rise after brace removal to \xint_bye. And then the original +% \xint_bye in #2 will have the effect that all is swallowed and we continue +% with \XINT_zapbsp_e. If the chunk was maximal, then the #2 above contains as +% many space tokens as there were originally at the end.| +% \begin{macrocode} +\long\def\XINT_zapbsp_end? #1{\xint_bye #1\XINT_zapbsp_end }% +% \end{macrocode} +% \lverb|The #2 starts with a space which stops the \romannumeral. +% The #1 contains the same number of space tokens there was originally.| +% \begin{macrocode} +\long\def\XINT_zapbsp_end\XINT_zapbsp_e\empty #1\xint_bye #2{#2#1}% +% \end{macrocode} +% \lverb|& +% Here the initial chunk was not maximal. So we need to get a second piece +% all the way up to \xint_bye, we take this opportunity to remove the two +% initially added ending space tokens. We inserted an \empty to prevent brace +% removal. The \expandafter get rid of the \empty.| +% \begin{macrocode} +\xint_firstofone{\long\def\XINT_zapbsp_e #1 } \xint_bye + {\expandafter\XINT_zapbsp_f \expandafter{#1}}% +% \end{macrocode} +% \lverb|Let's not forget when we glue to reinsert the two intermediate space +% tokens. | +% \begin{macrocode} +\long\edef\XINT_zapbsp_f #1#2{#2\space\space #1}% +% \end{macrocode} +% \subsection{\csh{xintZapLastSpaces}} +% \lverb+1.09f, written [2013/11/01].+ +% \begin{macrocode} +\def\xintZapLastSpaces {\romannumeral0\xintzaplastspaces }% +% \end{macrocode} +% \lverb|Next macro is defined via an \edef for the space tokens.| +% \begin{macrocode} +\long\edef\xintzaplastspaces #1{\noexpand\XINT_zapesp_a {\space}\noexpand\empty + #1\space\space\noexpand\xint_bye \xint_relax}% +% \end{macrocode} +% \lverb|This creates a delimited macro with two space tokens:| +% \begin{macrocode} +\xint_firstofone {\long\def\XINT_zapesp_a #1#2 } %<- second space here + {\expandafter\XINT_zapesp_b\expandafter{#2}{#1}}% +% \end{macrocode} +% \lverb|The \empty from \xintzaplastspaces is to prevent brace removal in the +% #2 above. The \expandafter chain removes it.| +% \begin{macrocode} +\long\def\XINT_zapesp_b #1#2#3\xint_relax + {\XINT_zapesp_end? #3\XINT_zapesp_e {#2#1}\empty #3\xint_relax }% +% \end{macrocode} +% \lverb|& +% When we have reached the ending space tokens, #3 is a bunch of spaces followed +% by \xint_bye. So the #1 below will be \xint_bye. In all other cases #1 can not +% be \xint_bye nor can it give birth to it via brace stripping.| +% \begin{macrocode} +\long\def\XINT_zapesp_end? #1{\xint_bye #1\XINT_zapesp_end }% +% \end{macrocode} +% \lverb|& +% We are done. The #1 here has accumulated all the previous material. It started +% with a space token which stops the \romannumeral0. The reason for the space is +% the recycling of this code in \xintZapSpaces.| +% \begin{macrocode} +\long\def\XINT_zapesp_end\XINT_zapesp_e #1#2\xint_relax {#1}% +% \end{macrocode} +% \lverb|We haven't yet reached the end, so we need to re-inject two space +% tokens after what we have gotten so far. Then we loop. We might wonder why in +% \XINT_zapesp_b we scooped everything up to the end, rather than trying to test +% if the next thing was a bunch of spaces followed by \xint_bye\xint_relax. But +% how can we expandably examine what comes next? if we pick up something as +% undelimited parameter token we risk brace removal and we will never know about +% it so we cannot reinsert correctly; the only way is to gather a delimited +% macro parameter and be sure some token will be inside to forbid brace removal. +% I do not see (so far) any other way than scooping everything up to the end. +% Anyhow, 99$% of the use cases will NOT have <sp><sp> inside!.| +% \begin{macrocode} +\long\edef\XINT_zapesp_e #1{\noexpand \XINT_zapesp_a {#1\space\space}}% +% \end{macrocode} +% \subsection{\csh{xintZapSpaces}} +% \lverb+1.09f, written [2013/11/01].+ +% \begin{macrocode} +\def\xintZapSpaces {\romannumeral0\xintzapspaces }% +% \end{macrocode} +% \lverb|We start like \xintZapStartSpaces.| +% \begin{macrocode} +\long\edef\xintzapspaces #1% + {\noexpand\XINT_zapsp_a \space #1\space\space\noexpand\xint_bye\xint_relax}% +% \end{macrocode} +% \lverb|& +% Once the loop stripping the starting spaces is done, we plug into the +% \xintZapLast$-Spaces code via \XINT_zapesp_b. As our #1 will always have an +% initial space, this is why we arranged code of \xintZapLastSpaces to do the +% same.| +% \begin{macrocode} +\xint_firstofone {\long\def\XINT_zapsp_a #1 } %<- space token here +{% + \XINT_zapsp_again? #1\xint_bye\XINT_zapesp_b {#1}{}% +}% +\long\def\XINT_zapsp_again? #1{\xint_bye #1\XINT_zapsp_again }% +\long\edef\XINT_zapsp_again\XINT_zapesp_b #1#2{\noexpand\XINT_zapsp_a\space }% +% \end{macrocode} +% \subsection{\csh{xintZapSpacesB}} +% \lverb+1.09f, written [2013/11/01].+ +% \begin{macrocode} +\def\xintZapSpacesB {\romannumeral0\xintzapspacesb }% +\long\def\xintzapspacesb #1{\XINT_zapspb_one? #1\xint_relax\xint_relax + \xint_bye\xintzapspaces {#1}}% +\long\def\XINT_zapspb_one? #1#2% + {\xint_gob_til_xint_relax #1\XINT_zapspb_onlyspaces\xint_relax + \xint_gob_til_xint_relax #2\XINT_zapspb_bracedorone\xint_relax + \xint_bye {#1}}% +\def\XINT_zapspb_onlyspaces\xint_relax + \xint_gob_til_xint_relax\xint_relax\XINT_zapspb_bracedorone\xint_relax + \xint_bye #1\xint_bye\xintzapspaces #2{ }% +\long\def\XINT_zapspb_bracedorone\xint_relax + \xint_bye #1\xint_relax\xint_bye\xintzapspaces #2{ #1}% +% \end{macrocode} +% \subsection{\csh{xintCSVtoList}, \csh{xintCSVtoListNonStripped}} +% \lverb|& +% \xintCSVtoList transforms a,b,..,z into {a}{b}...{z}. The comma separated list +% may be a macro which is first expanded (protect the first item with a space if +% it is not to be expanded). First included in release 1.06. Here, use of \Z +% (and \R) perfectly safe. +% +% [2013/11/02]: Starting with 1.09f, automatically filters items through +% \xintZapSpacesB to strip off all spaces around commas, and spaces at the start +% and end of the list. The original is kept as \xintCSVtoListNonStripped, and is +% faster. But ... it doesn't strip spaces.| +% \begin{macrocode} +\def\xintCSVtoList {\romannumeral0\xintcsvtolist }% +\long\def\xintcsvtolist #1{\expandafter\xintApply + \expandafter\xintzapspacesb + \expandafter{\romannumeral0\xintcsvtolistnonstripped{#1}}}% +\def\xintCSVtoListNoExpand {\romannumeral0\xintcsvtolistnoexpand }% +\long\def\xintcsvtolistnoexpand #1{\expandafter\xintApply + \expandafter\xintzapspacesb + \expandafter{\romannumeral0\xintcsvtolistnonstrippednoexpand{#1}}}% +\def\xintCSVtoListNonStripped {\romannumeral0\xintcsvtolistnonstripped }% +\def\xintCSVtoListNonStrippedNoExpand + {\romannumeral0\xintcsvtolistnonstrippednoexpand }% +\long\def\xintcsvtolistnonstripped #1% +{% + \expandafter\XINT_csvtol_loop_a\expandafter + {\expandafter}\romannumeral-`0#1% + ,\xint_bye,\xint_bye,\xint_bye,\xint_bye + ,\xint_bye,\xint_bye,\xint_bye,\xint_bye,\Z +}% +\long\def\xintcsvtolistnonstrippednoexpand #1% +{% + \XINT_csvtol_loop_a + {}#1,\xint_bye,\xint_bye,\xint_bye,\xint_bye + ,\xint_bye,\xint_bye,\xint_bye,\xint_bye,\Z +}% +\long\def\XINT_csvtol_loop_a #1#2,#3,#4,#5,#6,#7,#8,#9,% +{% + \xint_bye #9\XINT_csvtol_finish_a\xint_bye + \XINT_csvtol_loop_b {#1}{{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}}% +}% +\long\def\XINT_csvtol_loop_b #1#2{\XINT_csvtol_loop_a {#1#2}}% +\long\def\XINT_csvtol_finish_a\xint_bye\XINT_csvtol_loop_b #1#2#3\Z +{% + \XINT_csvtol_finish_b #3\R,\R,\R,\R,\R,\R,\R,\Z #2{#1}% +}% +\def\XINT_csvtol_finish_b #1,#2,#3,#4,#5,#6,#7,#8\Z +{% + \xint_gob_til_R + #1\XINT_csvtol_finish_c 8% + #2\XINT_csvtol_finish_c 7% + #3\XINT_csvtol_finish_c 6% + #4\XINT_csvtol_finish_c 5% + #5\XINT_csvtol_finish_c 4% + #6\XINT_csvtol_finish_c 3% + #7\XINT_csvtol_finish_c 2% + \R\XINT_csvtol_finish_c 1\Z +}% +\def\XINT_csvtol_finish_c #1#2\Z +{% + \csname XINT_csvtol_finish_d\romannumeral #1\endcsname +}% +\long\def\XINT_csvtol_finish_dviii #1#2#3#4#5#6#7#8#9{ #9}% +\long\def\XINT_csvtol_finish_dvii #1#2#3#4#5#6#7#8#9{ #9{#1}}% +\long\def\XINT_csvtol_finish_dvi #1#2#3#4#5#6#7#8#9{ #9{#1}{#2}}% +\long\def\XINT_csvtol_finish_dv #1#2#3#4#5#6#7#8#9{ #9{#1}{#2}{#3}}% +\long\def\XINT_csvtol_finish_div #1#2#3#4#5#6#7#8#9{ #9{#1}{#2}{#3}{#4}}% +\long\def\XINT_csvtol_finish_diii #1#2#3#4#5#6#7#8#9{ #9{#1}{#2}{#3}{#4}{#5}}% +\long\def\XINT_csvtol_finish_dii #1#2#3#4#5#6#7#8#9% + { #9{#1}{#2}{#3}{#4}{#5}{#6}}% +\long\def\XINT_csvtol_finish_di #1#2#3#4#5#6#7#8#9% + { #9{#1}{#2}{#3}{#4}{#5}{#6}{#7}}% +% \end{macrocode} +% \subsection{\csh{xintListWithSep}} +% \lverb|& +% \xintListWithSep {\sep}{{a}{b}...{z}} returns a \sep b \sep .... \sep z$\ +% Included in release 1.04. The 'sep' can be \par's: the macro +% xintlistwithsep etc... are all declared long. 'sep' does not have to be a +% single token. It is not expanded. The list may be a macro and it is expanded. +% 1.06 modifies the `feature' of returning sep if the list is empty: the output +% is now empty in that case. (sep was not used for a one element list, but +% strangely it was for a zero-element list). +% +% Use of \Z as delimiter was objectively an error, which I fix here in 1.09e, +% now the code uses \xint_bye.| +% \begin{macrocode} +\def\xintListWithSep {\romannumeral0\xintlistwithsep }% +\def\xintListWithSepNoExpand {\romannumeral0\xintlistwithsepnoexpand }% +\long\def\xintlistwithsep #1#2% + {\expandafter\XINT_lws\expandafter {\romannumeral-`0#2}{#1}}% +\long\def\XINT_lws #1#2{\XINT_lws_start {#2}#1\xint_bye }% +\long\def\xintlistwithsepnoexpand #1#2{\XINT_lws_start {#1}#2\xint_bye }% +\long\def\XINT_lws_start #1#2% +{% + \xint_bye #2\XINT_lws_dont\xint_bye + \XINT_lws_loop_a {#2}{#1}% +}% +\long\def\XINT_lws_dont\xint_bye\XINT_lws_loop_a #1#2{ }% +\long\def\XINT_lws_loop_a #1#2#3% +{% + \xint_bye #3\XINT_lws_end\xint_bye + \XINT_lws_loop_b {#1}{#2#3}{#2}% +}% +\long\def\XINT_lws_loop_b #1#2{\XINT_lws_loop_a {#1#2}}% +\long\def\XINT_lws_end\xint_bye\XINT_lws_loop_b #1#2#3{ #1}% +% \end{macrocode} +% \subsection{\csh{xintNthElt}} +% \lverb|& +% \xintNthElt {i}{{a}{b}...{z}} (or `tokens' abcd...z) returns the i th +% element (one pair of braces removed). The list is first expanded. +% First included in release 1.06. With 1.06a, a value of i = 0 (or negative) +% makes the macro return the length. This is different from \xintLen which is +% for numbers (checks sign) and different from \xintLength which does not first +% expand its argument. With 1.09b, only i=0 gives the length, negative values +% return the i th element from the end. 1.09c has some slightly less quick +% initial preparation (if #2 is very long, not good to have it twice), I wanted +% to respect the noexpand directive in all cases, and the alternative would be +% to define more macros. +% +% At some point I turned the \W's into \xint_relax's but forgot to modify +% accordingly \XINT_nthelt_finish. So in case the index is larger than the +% number of items the macro returned was an \xint_relax token rather than +% nothing. Fixed in 1.09e. I also take the opportunity of this fix to replace +% uses of \Z by \xint_bye. (and as a result I must do the change also in +% \XINT_length_loop and related macros). +% | +% \begin{macrocode} +\def\xintNthElt {\romannumeral0\xintnthelt }% +\def\xintNthEltNoExpand {\romannumeral0\xintntheltnoexpand }% +\def\xintnthelt #1% +{% + \expandafter\XINT_nthelt_a\expandafter {\the\numexpr #1}% +}% +\def\xintntheltnoexpand #1% +{% + \expandafter\XINT_ntheltnoexpand_a\expandafter {\the\numexpr #1}% +}% +\long\def\XINT_nthelt_a #1#2% +{% + \ifnum #1<0 + \xint_afterfi{\expandafter\XINT_nthelt_c\expandafter + {\romannumeral0\xintrevwithbraces {#2}}{-#1}}% + \else + \xint_afterfi{\expandafter\XINT_nthelt_c\expandafter + {\romannumeral-`0#2}{#1}}% + \fi +}% +\long\def\XINT_ntheltnoexpand_a #1#2% +{% + \ifnum #1<0 + \xint_afterfi{\expandafter\XINT_nthelt_c\expandafter + {\romannumeral0\xintrevwithbracesnoexpand {#2}}{-#1}}% + \else + \xint_afterfi{\expandafter\XINT_nthelt_c\expandafter + {#2}{#1}}% + \fi +}% +\long\def\XINT_nthelt_c #1#2% +{% + \ifnum #2>\xint_c_ + \expandafter\XINT_nthelt_loop_a + \else + \expandafter\XINT_length_loop + \fi {#2}#1\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye +}% +\def\XINT_nthelt_loop_a #1% +{% + \ifnum #1>\xint_c_viii + \expandafter\XINT_nthelt_loop_b + \else + \expandafter\XINT_nthelt_getit + \fi + {#1}% +}% +\long\def\XINT_nthelt_loop_b #1#2#3#4#5#6#7#8#9% +{% + \xint_gob_til_xint_relax #9\XINT_nthelt_silentend\xint_relax + \expandafter\XINT_nthelt_loop_a\expandafter{\the\numexpr #1-8}% +}% +\def\XINT_nthelt_silentend #1\xint_bye { }% +\def\XINT_nthelt_getit #1% +{% + \expandafter\expandafter\expandafter\XINT_nthelt_finish + \csname xint_gobble_\romannumeral\numexpr#1-1\endcsname +}% +\long\edef\XINT_nthelt_finish #1#2\xint_bye + {\noexpand\xint_gob_til_xint_relax #1\noexpand\expandafter\space + \noexpand\xint_gobble_iii\xint_relax\space #1}% +% \end{macrocode} +% \subsection{\csh{xintApply}} +% \lverb|& +% \xintApply {\macro}{{a}{b}...{z}} returns {\macro{a}}...{\macro{b}} +% where each instance of \macro is ff-expanded. The list is first +% expanded and may thus be a macro. Introduced with release 1.04. +% +% Modified in 1.09e to not use \Z but rather \xint_bye.| +% \begin{macrocode} +\def\xintApply {\romannumeral0\xintapply }% +\def\xintApplyNoExpand {\romannumeral0\xintapplynoexpand }% +\long\def\xintapply #1#2% +{% + \expandafter\XINT_apply\expandafter {\romannumeral-`0#2}% + {#1}% +}% +\long\def\XINT_apply #1#2{\XINT_apply_loop_a {}{#2}#1\xint_bye }% +\long\def\xintapplynoexpand #1#2{\XINT_apply_loop_a {}{#1}#2\xint_bye }% +\long\def\XINT_apply_loop_a #1#2#3% +{% + \xint_bye #3\XINT_apply_end\xint_bye + \expandafter + \XINT_apply_loop_b + \expandafter {\romannumeral-`0#2{#3}}{#1}{#2}% +}% +\long\def\XINT_apply_loop_b #1#2{\XINT_apply_loop_a {#2{#1}}}% +\long\def\XINT_apply_end\xint_bye\expandafter\XINT_apply_loop_b + \expandafter #1#2#3{ #2}% +% \end{macrocode} +% \subsection{\csh{xintApplyUnbraced}} +% \lverb|& +% \xintApplyUnbraced {\macro}{{a}{b}...{z}} returns \macro{a}...\macro{z} +% where each instance of \macro is expanded using \romannumeral-`0. The second +% argument may be a macro as it is first expanded itself (fully). No braces +% are added: this allows for example a non-expandable \def in \macro, without +% having to do \gdef. The list is first expanded. Introduced with release 1.06b. +% Define \macro to start with a space if it is not expandable or its execution +% should be delayed only when all of \macro{a}...\macro{z} is ready. +% +% Modified in 1.09e to use \xint_bye rather than \Z.| +% \begin{macrocode} +\def\xintApplyUnbraced {\romannumeral0\xintapplyunbraced }% +\def\xintApplyUnbracedNoExpand {\romannumeral0\xintapplyunbracednoexpand }% +\long\def\xintapplyunbraced #1#2% +{% + \expandafter\XINT_applyunbr\expandafter {\romannumeral-`0#2}% + {#1}% +}% +\long\def\XINT_applyunbr #1#2{\XINT_applyunbr_loop_a {}{#2}#1\xint_bye }% +\long\def\xintapplyunbracednoexpand #1#2% + {\XINT_applyunbr_loop_a {}{#1}#2\xint_bye }% +\long\def\XINT_applyunbr_loop_a #1#2#3% +{% + \xint_bye #3\XINT_applyunbr_end\xint_bye + \expandafter\XINT_applyunbr_loop_b + \expandafter {\romannumeral-`0#2{#3}}{#1}{#2}% +}% +\long\def\XINT_applyunbr_loop_b #1#2{\XINT_applyunbr_loop_a {#2#1}}% +\long\def\XINT_applyunbr_end\xint_bye\expandafter\XINT_applyunbr_loop_b + \expandafter #1#2#3{ #2}% +% \end{macrocode} +% \subsection{\csh{xintSeq}} +% \lverb|1.09c. Without the optional argument puts stress on the input stack, +% should not be used to generated thousands of terms then. Here also, let's use +% \xint_bye rather than \Z as delimiter (1.09e; necessary change as #1 is used +% prior to being expanded, thus \Z might very well arise here as a macro).| +% \begin{macrocode} +\def\xintSeq {\romannumeral0\xintseq }% +\def\xintseq #1{\XINT_seq_chkopt #1\xint_bye }% +\def\XINT_seq_chkopt #1% +{% + \ifx [#1\expandafter\XINT_seq_opt + \else\expandafter\XINT_seq_noopt + \fi #1% +}% +\def\XINT_seq_noopt #1\xint_bye #2% +{% + \expandafter\XINT_seq\expandafter + {\the\numexpr#1\expandafter}\expandafter{\the\numexpr #2}% +}% +\def\XINT_seq #1#2% +{% + \ifcase\ifnum #1=#2 0\else\ifnum #2>#1 1\else -1\fi\fi\space + \expandafter\xint_firstoftwo_thenstop + \or + \expandafter\XINT_seq_p + \else + \expandafter\XINT_seq_n + \fi + {#2}{#1}% +}% +\def\XINT_seq_p #1#2% +{% + \ifnum #1>#2 + \expandafter\expandafter\expandafter\XINT_seq_p + \else + \expandafter\XINT_seq_e + \fi + \expandafter{\the\numexpr #1-\xint_c_i}{#2}{#1}% +}% +\def\XINT_seq_n #1#2% +{% + \ifnum #1<#2 + \expandafter\expandafter\expandafter\XINT_seq_n + \else + \expandafter\XINT_seq_e + \fi + \expandafter{\the\numexpr #1+\xint_c_i}{#2}{#1}% +}% +\def\XINT_seq_e #1#2#3{ }% +\def\XINT_seq_opt [\xint_bye #1]#2#3% +{% + \expandafter\XINT_seqo\expandafter + {\the\numexpr #2\expandafter}\expandafter + {\the\numexpr #3\expandafter}\expandafter + {\the\numexpr #1}% +}% +\def\XINT_seqo #1#2% +{% + \ifcase\ifnum #1=#2 0\else\ifnum #2>#1 1\else -1\fi\fi\space + \expandafter\XINT_seqo_a + \or + \expandafter\XINT_seqo_pa + \else + \expandafter\XINT_seqo_na + \fi + {#1}{#2}% +}% +\def\XINT_seqo_a #1#2#3{ {#1}}% +\def\XINT_seqo_o #1#2#3#4{ #4}% +\def\XINT_seqo_pa #1#2#3% +{% + \ifcase\ifnum #3=\xint_c_ 0\else\ifnum #3>\xint_c_ 1\else -1\fi\fi\space + \expandafter\XINT_seqo_o + \or + \expandafter\XINT_seqo_pb + \else + \xint_afterfi{\expandafter\space\xint_gobble_iv}% + \fi + {#1}{#2}{#3}{{#1}}% +}% +\def\XINT_seqo_pb #1#2#3% +{% + \expandafter\XINT_seqo_pc\expandafter{\the\numexpr #1+#3}{#2}{#3}% +}% +\def\XINT_seqo_pc #1#2% +{% + \ifnum #1>#2 + \expandafter\XINT_seqo_o + \else + \expandafter\XINT_seqo_pd + \fi + {#1}{#2}% +}% +\def\XINT_seqo_pd #1#2#3#4{\XINT_seqo_pb {#1}{#2}{#3}{#4{#1}}}% +\def\XINT_seqo_na #1#2#3% +{% + \ifcase\ifnum #3=\xint_c_ 0\else\ifnum #3>\xint_c_ 1\else -1\fi\fi\space + \expandafter\XINT_seqo_o + \or + \xint_afterfi{\expandafter\space\xint_gobble_iv}% + \else + \expandafter\XINT_seqo_nb + \fi + {#1}{#2}{#3}{{#1}}% +}% +\def\XINT_seqo_nb #1#2#3% +{% + \expandafter\XINT_seqo_nc\expandafter{\the\numexpr #1+#3}{#2}{#3}% +}% +\def\XINT_seqo_nc #1#2% +{% + \ifnum #1<#2 + \expandafter\XINT_seqo_o + \else + \expandafter\XINT_seqo_nd + \fi + {#1}{#2}% +}% +\def\XINT_seqo_nd #1#2#3#4{\XINT_seqo_nb {#1}{#2}{#3}{#4{#1}}}% +% \end{macrocode} +%\subsection{\csh{xintloop}, \csh{xintbreakloop}, \csh{xintbreakloopanddo}, +% \csh{xintloopskiptonext}} +% \lverb|1.09g [2013/11/22]. Made long with 1.09h.| +% \begin{macrocode} +\long\def\xintloop #1#2\repeat {#1#2\xintloop_again\fi\xint_gobble_i {#1#2}}% +\long\def\xintloop_again\fi\xint_gobble_i #1{\fi + #1\xintloop_again\fi\xint_gobble_i {#1}}% +\long\def\xintbreakloop #1\xintloop_again\fi\xint_gobble_i #2{}% +\long\def\xintbreakloopanddo #1#2\xintloop_again\fi\xint_gobble_i #3{#1}% +\long\def\xintloopskiptonext #1\xintloop_again\fi\xint_gobble_i #2{% + #2\xintloop_again\fi\xint_gobble_i {#2}}% +% \end{macrocode} +% \subsection{\csh{xintiloop}, \csh{xintiloopindex}, \csh{xintouteriloopindex}, +% \csh{xintbreakiloop}, \csh{xintbreakiloopanddo}, \csh{xintiloopskiptonext}, +% \csh{xintiloopskipandredo}} +% \lverb|1.09g [2013/11/22]. Made long with 1.09h.| +% \begin{macrocode} +\def\xintiloop [#1+#2]{% + \expandafter\xintiloop_a\the\numexpr #1\expandafter.\the\numexpr #2.}% +\long\def\xintiloop_a #1.#2.#3#4\repeat{% + #3#4\xintiloop_again\fi\xint_gobble_iii {#1}{#2}{#3#4}}% +\def\xintiloop_again\fi\xint_gobble_iii #1#2{% + \fi\expandafter\xintiloop_again_b\the\numexpr#1+#2.#2.}% +\long\def\xintiloop_again_b #1.#2.#3{% + #3\xintiloop_again\fi\xint_gobble_iii {#1}{#2}{#3}}% +\long\def\xintbreakiloop #1\xintiloop_again\fi\xint_gobble_iii #2#3#4{}% +\long\def\xintbreakiloopanddo + #1.#2\xintiloop_again\fi\xint_gobble_iii #3#4#5{#1}% +\long\def\xintiloopindex #1\xintiloop_again\fi\xint_gobble_iii #2% + {#2#1\xintiloop_again\fi\xint_gobble_iii {#2}}% +\long\def\xintouteriloopindex #1\xintiloop_again + #2\xintiloop_again\fi\xint_gobble_iii #3% + {#3#1\xintiloop_again #2\xintiloop_again\fi\xint_gobble_iii {#3}}% +\long\def\xintiloopskiptonext #1\xintiloop_again\fi\xint_gobble_iii #2#3{% + \expandafter\xintiloop_again_b \the\numexpr#2+#3.#3.}% +\long\def\xintiloopskipandredo #1\xintiloop_again\fi\xint_gobble_iii #2#3#4{% + #4\xintiloop_again\fi\xint_gobble_iii {#2}{#3}{#4}}% +% \end{macrocode} +% \subsection{\csh{XINT\_xflet}} +% \lverb|1.09e [2013/10/29]: we expand fully unbraced tokens and swallow arising +% space tokens until the dust settles. For treating cases +% {<blank>\x<blank>\y...}, with guaranteed expansion of the \x (which may itself +% give space tokens), a simpler approach is possible with doubled +% \romannumeral-`0, this is what I first did, but it had the feature that +% <sptoken><sptoken>\x would not expand the \x. At any rate, <sptoken>'s before +% the list terminator z were all correctly moved out of the way, hence the stuff +% was robust for use in (the then current versions of) \xintApplyInline and +% \xintFor. Although *two* space tokens would need devilishly prepared input, +% nevertheless I decided to also survive that, so here the method is a bit more +% complicated. But it simplifies things on the caller side.| +% \begin{macrocode} +\def\XINT_xflet #1% +{% + \def\XINT_xflet_macro {#1}\XINT_xflet_zapsp +}% +\def\XINT_xflet_zapsp +{% + \expandafter\futurelet\expandafter\XINT_token + \expandafter\XINT_xflet_sp?\romannumeral-`0% +}% +\def\XINT_xflet_sp? +{% + \ifx\XINT_token\XINT_sptoken + \expandafter\XINT_xflet_zapsp + \else\expandafter\XINT_xflet_zapspB + \fi +}% +\def\XINT_xflet_zapspB +{% + \expandafter\futurelet\expandafter\XINT_tokenB + \expandafter\XINT_xflet_spB?\romannumeral-`0% +}% +\def\XINT_xflet_spB? +{% + \ifx\XINT_tokenB\XINT_sptoken + \expandafter\XINT_xflet_zapspB + \else\expandafter\XINT_xflet_eq? + \fi +}% +\def\XINT_xflet_eq? +{% + \ifx\XINT_token\XINT_tokenB + \expandafter\XINT_xflet_macro + \else\expandafter\XINT_xflet_zapsp + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintApplyInline}} +% \lverb|& +% 1.09a: \xintApplyInline\macro{{a}{b}...{z}} has the same effect as executing +% \macro{a} and then applying again \xintApplyInline to the shortened list +% {{b}...{z}} until +% nothing is left. This is a non-expandable command which will result in +% quicker code than using +% \xintApplyUnbraced. It expands (fully) its second (list) argument +% first, which may thus be encapsulated in a macro. +% +% Release 1.09c has a new \xintApplyInline: the new version, while not +% expandable, is designed to survive when the applied macro closes a group, as +% is the case in alignemnts when it contains a $& or \\. It uses catcode 3 Z as +% list terminator. Don't use it among the list items. +% +% 1.09d: the bug which was discovered in \xintFor* regarding space tokens at the +% very end of the item list also was in \xintApplyInline. The new version will +% expand unbraced item elements and this is in fact convenient to simulate +% insertion of lists in others. +% +% 1.09e: the applied macro is allowed to be long, with items (or the first fixed +% arguments of he macro, passed together with it as #1 to \xintApplyInline) +% containing explicit \par's. (1.09g: some missing \long's added) +% +% 1.09f: terminator used to be z, now Z (still catcode 3). +%| +% \begin{macrocode} +\catcode`Z 3 +\long\def\xintApplyInline #1#2% +{% + \long\expandafter\def\expandafter\XINT_inline_macro + \expandafter ##\expandafter 1\expandafter {#1{##1}}% + \XINT_xflet\XINT_inline_b #2Z% this Z has catcode 3 +}% +\def\XINT_inline_b +{% + \ifx\XINT_token Z\expandafter\xint_gobble_i + \else\expandafter\XINT_inline_d\fi +}% +\long\def\XINT_inline_d #1% +{% + \long\def\XINT_item{{#1}}\XINT_xflet\XINT_inline_e +}% +\def\XINT_inline_e +{% + \ifx\XINT_token Z\expandafter\XINT_inline_w + \else\expandafter\XINT_inline_f\fi +}% +\def\XINT_inline_f +{% + \expandafter\XINT_inline_g\expandafter{\XINT_inline_macro {##1}}% +}% +\long\def\XINT_inline_g #1% +{% + \expandafter\XINT_inline_macro\XINT_item + \long\def\XINT_inline_macro ##1{#1}\XINT_inline_d +}% +\def\XINT_inline_w #1% +{% + \expandafter\XINT_inline_macro\XINT_item +}% +% \end{macrocode} +% \subsection{\csh{xintFor}, +% \csh{xintFor*}, \csh{xintBreakFor}, \csh{xintBreakForAndDo}} +% \lverb|1.09c [2013/10/09]: a new kind of loop which uses macro parameters +% #1, #2, #3, #4 rather than macros; while not expandable it survives executing +% code closing groups, like what happens in an alignment with the $& character. +% When inserted in a macro for later use, the # character must be doubled. +% +% The non-star variant works on a csv list, which it expands once, the +% star variant works on a token list, expanded fully. +% +% 1.09d: [2013/10/22] \xintFor* crashed when a space token was at the very end +% of the list. It is crucial in this code to not let the ending Z be picked up +% as a macro parameter without knowing in advance that it is its turn. So, we +% conscientiously clean out of the way space tokens, but also we ff-expand with +% \romannumeral-`0 (unbraced) items, a process which may create new space +% tokens, so it is iterated. As unbraced items are expanded, it is easy to +% simulate insertion of a list in another. +% Unbraced items consecutive to an even (non-zero) number of space tokens will +% not get expanded. +% +% 1.09e: [2013/10/29] does this better, no difference between an even or odd +% number of explicit consecutive space tokens. Normal situations anyhow only +% create at most one space token, but well. There was a feature in \xintFor (not +% \xintFor*) from 1.09c that it treated an empty list as a list with one, empty, +% item. This feature is kept in 1.09e, knowingly... Also, macros are made long, +% hence the iterated text may contain \par and also the looped over items. I +% thought about providing some macro expanding to the loop count, but as the +% \xintFor is not expandable anyhow, there is no loss of generality if the +% iterated commands do themselves the bookkeeping using a count or a LaTeX +% counter, and deal with nesting or other problems. I can't do *everything*! +% +% 1.09e adds \XINT_forever with \xintintegers, \xintdimensions, \xintrationals +% and \xintBreakFor, \xintBreakForAndDo, \xintifForFirst, \xintifForLast. On +% this occasion \xint_firstoftwo and \xint_secondoftwo are made long. +% +% 1.09f: rewrites large parts of \xintFor code in order to filter the comma +% separated list via \xintCSVtoList which gets rid of spaces. Compatibility +% with \XINT_forever, the necessity to prevent unwanted brace stripping, and +% shared code with \xintFor*, make this all a delicate balancing act. The #1 in +% \XINT_for_forever? has an initial space token which serves two purposes: +% preventing brace stripping, and stopping the expansion made by \xintcsvtolist. +% If the \XINT_forever branch is taken, the added space will not be a problem +% there. +% +% 1.09f rewrites (2013/11/03) the code which now allows all macro parameters +% from #1 to #9 in \xintFor, \xintFor*, and \XINT_forever. +% +% The 1.09f \xintFor and \xintFor* modified the value of \count 255 +% which was silly, 1.09g used \XINT_count, but requiring a \count only +% for that was also silly, 1.09h just uses \numexpr (all of that was only to +% get rid simply of a possibly space in #2...). +% +% 1.09ka [2014/02/05] corrects the following bug: \xintBreakFor and +% \xintBreakForAndDo could not be used in the last iteration.| +% \begin{macrocode} +\def\XINT_tmpa #1#2{\ifnum #2<#1 \xint_afterfi {{#########2}}\fi}% +\def\XINT_tmpb #1#2{\ifnum #1<#2 \xint_afterfi {{#########2}}\fi}% +\def\XINT_tmpc #1% +{% + \expandafter\edef \csname XINT_for_left#1\endcsname + {\xintApplyUnbraced {\XINT_tmpa #1}{123456789}}% + \expandafter\edef \csname XINT_for_right#1\endcsname + {\xintApplyUnbraced {\XINT_tmpb #1}{123456789}}% +}% +\xintApplyInline \XINT_tmpc {123456789}% +\long\def\xintBreakFor #1Z{}% +\long\def\xintBreakForAndDo #1#2Z{#1}% +\def\xintFor {\let\xintifForFirst\xint_firstoftwo + \futurelet\XINT_token\XINT_for_ifstar }% +\def\XINT_for_ifstar {\ifx\XINT_token*\expandafter\XINT_forx + \else\expandafter\XINT_for \fi }% +\catcode`U 3 % with numexpr +\catcode`V 3 % with xintfrac.sty (xint.sty not enough) +\catcode`D 3 % with dimexpr +% \def\XINT_flet #1% +% {% +% \def\XINT_flet_macro {#1}\XINT_flet_zapsp +% }% +\def\XINT_flet_zapsp +{% + \futurelet\XINT_token\XINT_flet_sp? +}% +\def\XINT_flet_sp? +{% + \ifx\XINT_token\XINT_sptoken + \xint_afterfi{\expandafter\XINT_flet_zapsp\romannumeral0}% + \else\expandafter\XINT_flet_macro + \fi +}% +\long\def\XINT_for #1#2in#3#4#5% +{% + \expandafter\XINT_toks\expandafter + {\expandafter\XINT_for_d\the\numexpr #2\relax {#5}}% + \def\XINT_flet_macro {\expandafter\XINT_for_forever?\space}% + \expandafter\XINT_flet_zapsp #3Z% +}% +\def\XINT_for_forever? #1Z% +{% + \ifx\XINT_token U\XINT_to_forever\fi + \ifx\XINT_token V\XINT_to_forever\fi + \ifx\XINT_token D\XINT_to_forever\fi + \expandafter\the\expandafter\XINT_toks\romannumeral0\xintcsvtolist {#1}Z% +}% +\def\XINT_to_forever\fi #1\xintcsvtolist #2{\fi \XINT_forever #2}% +\long\def\XINT_forx *#1#2in#3#4#5% +{% + \expandafter\XINT_toks\expandafter + {\expandafter\XINT_forx_d\the\numexpr #2\relax {#5}}% + \XINT_xflet\XINT_forx_forever? #3Z% +}% +\def\XINT_forx_forever? +{% + \ifx\XINT_token U\XINT_to_forxever\fi + \ifx\XINT_token V\XINT_to_forxever\fi + \ifx\XINT_token D\XINT_to_forxever\fi + \XINT_forx_empty? +}% +\def\XINT_to_forxever\fi #1\XINT_forx_empty? {\fi \XINT_forever }% +\catcode`U 11 +\catcode`D 11 +\catcode`V 11 +\def\XINT_forx_empty? +{% + \ifx\XINT_token Z\expandafter\xintBreakFor\fi + \the\XINT_toks +}% +\long\def\XINT_for_d #1#2#3% +{% + \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#2}% + \XINT_toks {{#3}}% + \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname + \the\XINT_toks \csname XINT_for_right#1\endcsname }% + \XINT_toks {\XINT_x\let\xintifForFirst\xint_secondoftwo\XINT_for_d #1{#2}}% + \futurelet\XINT_token\XINT_for_last? +}% +\long\def\XINT_forx_d #1#2#3% +{% + \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#2}% + \XINT_toks {{#3}}% + \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname + \the\XINT_toks \csname XINT_for_right#1\endcsname }% + \XINT_toks {\XINT_x\let\xintifForFirst\xint_secondoftwo\XINT_forx_d #1{#2}}% + \XINT_xflet\XINT_for_last? +}% +\def\XINT_for_last? +{% + \let\xintifForLast\xint_secondoftwo + \ifx\XINT_token Z\let\xintifForLast\xint_firstoftwo + \xint_afterfi{\xintBreakForAndDo{\XINT_x\xint_gobble_i Z}}\fi + \the\XINT_toks +}% +% \end{macrocode} +% \subsection{\csh{XINT\_forever}, \csh{xintintegers}, \csh{xintdimensions}, \csh{xintrationals}} +% \lverb|New with 1.09e. But this used inadvertently \xintiadd/\xintimul which +% have the unnecessary \xintnum overhead. Changed in 1.09f to use +% \xintiiadd/\xintiimul which do not have this overhead. Also 1.09f has +% \xintZapSpacesB which helps getting rid of spaces for the \xintrationals case +% (the other cases end up inside a \numexpr, or \dimexpr, so not necessary).| +% \begin{macrocode} +\catcode`U 3 +\catcode`D 3 +\catcode`V 3 +\let\xintegers U% +\let\xintintegers U% +\let\xintdimensions D% +\let\xintrationals V% +\def\XINT_forever #1% +{% + \expandafter\XINT_forever_a + \csname XINT_?expr_\ifx#1UU\else\ifx#1DD\else V\fi\fi a\expandafter\endcsname + \csname XINT_?expr_\ifx#1UU\else\ifx#1DD\else V\fi\fi i\expandafter\endcsname + \csname XINT_?expr_\ifx#1UU\else\ifx#1DD\else V\fi\fi \endcsname +}% +\catcode`U 11 +\catcode`D 11 +\catcode`V 11 +\def\XINT_?expr_Ua #1#2% + {\expandafter{\expandafter\numexpr\the\numexpr #1\expandafter\relax + \expandafter\relax\expandafter}% + \expandafter{\the\numexpr #2}}% +\def\XINT_?expr_Da #1#2% + {\expandafter{\expandafter\dimexpr\number\dimexpr #1\expandafter\relax + \expandafter s\expandafter p\expandafter\relax\expandafter}% + \expandafter{\number\dimexpr #2}}% +\catcode`Z 11 +\def\XINT_?expr_Va #1#2% +{% + \expandafter\XINT_?expr_Vb\expandafter + {\romannumeral-`0\xintrawwithzeros{\xintZapSpacesB{#2}}}% + {\romannumeral-`0\xintrawwithzeros{\xintZapSpacesB{#1}}}% +}% +\catcode`Z 3 +\def\XINT_?expr_Vb #1#2{\expandafter\XINT_?expr_Vc #2.#1.}% +\def\XINT_?expr_Vc #1/#2.#3/#4.% +{% + \xintifEq {#2}{#4}% + {\XINT_?expr_Vf {#3}{#1}{#2}}% + {\expandafter\XINT_?expr_Vd\expandafter + {\romannumeral0\xintiimul {#2}{#4}}% + {\romannumeral0\xintiimul {#1}{#4}}% + {\romannumeral0\xintiimul {#2}{#3}}% + }% +}% +\def\XINT_?expr_Vd #1#2#3{\expandafter\XINT_?expr_Ve\expandafter {#2}{#3}{#1}}% +\def\XINT_?expr_Ve #1#2{\expandafter\XINT_?expr_Vf\expandafter {#2}{#1}}% +\def\XINT_?expr_Vf #1#2#3{{#2/#3}{{0}{#1}{#2}{#3}}}% +\def\XINT_?expr_Ui {{\numexpr 1\relax}{1}}% +\def\XINT_?expr_Di {{\dimexpr 0pt\relax}{65536}}% +\def\XINT_?expr_Vi {{1/1}{0111}}% +\def\XINT_?expr_U #1#2% + {\expandafter{\expandafter\numexpr\the\numexpr #1+#2\relax\relax}{#2}}% +\def\XINT_?expr_D #1#2% + {\expandafter{\expandafter\dimexpr\the\numexpr #1+#2\relax sp\relax}{#2}}% +\def\XINT_?expr_V #1#2{\XINT_?expr_Vx #2}% +\def\XINT_?expr_Vx #1#2% +{% + \expandafter\XINT_?expr_Vy\expandafter + {\romannumeral0\xintiiadd {#1}{#2}}{#2}% +}% +\def\XINT_?expr_Vy #1#2#3#4% +{% + \expandafter{\romannumeral0\xintiiadd {#3}{#1}/#4}{{#1}{#2}{#3}{#4}}% +}% +\def\XINT_forever_a #1#2#3#4% +{% + \ifx #4[\expandafter\XINT_forever_opt_a + \else\expandafter\XINT_forever_b + \fi #1#2#3#4% +}% +\def\XINT_forever_b #1#2#3Z{\expandafter\XINT_forever_c\the\XINT_toks #2#3}% +\long\def\XINT_forever_c #1#2#3#4#5% + {\expandafter\XINT_forever_d\expandafter #2#4#5{#3}Z}% +\def\XINT_forever_opt_a #1#2#3[#4+#5]#6Z% +{% + \expandafter\expandafter\expandafter + \XINT_forever_opt_c\expandafter\the\expandafter\XINT_toks + \romannumeral-`0#1{#4}{#5}#3% +}% +\long\def\XINT_forever_opt_c #1#2#3#4#5#6{\XINT_forever_d #2{#4}{#5}#6{#3}Z}% +\long\def\XINT_forever_d #1#2#3#4#5% +{% + \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#5}% + \XINT_toks {{#2}}% + \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname + \the\XINT_toks \csname XINT_for_right#1\endcsname }% + \XINT_x + \let\xintifForFirst\xint_secondoftwo + \expandafter\XINT_forever_d\expandafter #1\romannumeral-`0#4{#2}{#3}#4{#5}% +}% +% \end{macrocode} +% \subsection{\csh{xintForpair}, \csh{xintForthree}, \csh{xintForfour}} +% \lverb|1.09c: I don't know yet if {a}{b} is better for the user or worse than +% (a,b). I prefer the former. I am not very motivated to deal with spaces in the +% (a,b) approach which is the one (currently) followed here. +% +% [2013/11/02] 1.09f: I may not have been very motivated in 1.09c, but since +% then I developped the \xintZapSpaces/\xintZapSpacesB tools (much to my +% satisfaction). Based on this, and better parameter texts, \xintForpair and its +% cousins now handle spaces very satisfactorily (this relies partly on the new +% \xintCSVtoList which makes use of \xintZapSpacesB). Does not share code with +% \xintFor anymore. +% +% [2013/11/03] 1.09f: \xintForpair extended to accept #1#2, #2#3 etc... up to +% #8#9, \xintForthree, #1#2#3 up to #7#8#9, \xintForfour id. | +% \begin{macrocode} +\catcode`j 3 +\long\def\xintForpair #1#2#3in#4#5#6% +{% + \let\xintifForFirst\xint_firstoftwo + \XINT_toks {\XINT_forpair_d #2{#6}}% + \expandafter\the\expandafter\XINT_toks #4jZ% +}% +\long\def\XINT_forpair_d #1#2#3(#4)#5% +{% + \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#2}% + \XINT_toks \expandafter{\romannumeral0\xintcsvtolist{ #4}}% + \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname + \the\XINT_toks \csname XINT_for_right\the\numexpr#1+1\endcsname}% + \let\xintifForLast\xint_secondoftwo + \ifx #5j\expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo + \fi + {\let\xintifForLast\xint_firstoftwo + \xintBreakForAndDo {\XINT_x \xint_gobble_i Z}}% + \XINT_x + \let\xintifForFirst\xint_secondoftwo\XINT_forpair_d #1{#2}% +}% +\long\def\xintForthree #1#2#3in#4#5#6% +{% + \let\xintifForFirst\xint_firstoftwo + \XINT_toks {\XINT_forthree_d #2{#6}}% + \expandafter\the\expandafter\XINT_toks #4jZ% +}% +\long\def\XINT_forthree_d #1#2#3(#4)#5% +{% + \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#2}% + \XINT_toks \expandafter{\romannumeral0\xintcsvtolist{ #4}}% + \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname + \the\XINT_toks \csname XINT_for_right\the\numexpr#1+2\endcsname}% + \let\xintifForLast\xint_secondoftwo + \ifx #5j\expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo + \fi + {\let\xintifForLast\xint_firstoftwo + \xintBreakForAndDo {\XINT_x \xint_gobble_i Z}}% + \XINT_x + \let\xintifForFirst\xint_secondoftwo\XINT_forthree_d #1{#2}% +}% +\long\def\xintForfour #1#2#3in#4#5#6% +{% + \let\xintifForFirst\xint_firstoftwo + \XINT_toks {\XINT_forfour_d #2{#6}}% + \expandafter\the\expandafter\XINT_toks #4jZ% +}% +\long\def\XINT_forfour_d #1#2#3(#4)#5% +{% + \long\def\XINT_y ##1##2##3##4##5##6##7##8##9{#2}% + \XINT_toks \expandafter{\romannumeral0\xintcsvtolist{ #4}}% + \long\edef\XINT_x {\noexpand\XINT_y \csname XINT_for_left#1\endcsname + \the\XINT_toks \csname XINT_for_right\the\numexpr#1+3\endcsname}% + \let\xintifForLast\xint_secondoftwo + \ifx #5j\expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo + \fi + {\let\xintifForLast\xint_firstoftwo + \xintBreakForAndDo {\XINT_x \xint_gobble_i Z}}% + \XINT_x + \let\xintifForFirst\xint_secondoftwo\XINT_forfour_d #1{#2}% +}% +\catcode`Z 11 +\catcode`j 11 +% \end{macrocode} +% \subsection{\csh{xintAssign}, \csh{xintAssignArray}, \csh{xintDigitsOf}} +% \lverb|& +% \xintAssign {a}{b}..{z}\to\A\B...\Z,$\ +% \xintAssignArray {a}{b}..{z}\to\U +% +% version 1.01 corrects an oversight in 1.0 related to the value of +% \escapechar at the time of using \xintAssignArray or \xintRelaxArray +% These macros are non-expandable. +% +% In version 1.05a I suddenly see some incongruous \expandafter's in (what is +% called now) \XINT_assignarray_end_c, which I remove. +% +% Release 1.06 modifies the macros created by \xintAssignArray to feed their +% argument to a \numexpr. Release 1.06a detects an incredible typo in 1.01, (bad +% copy-paste from +% \xintRelaxArray) which caused \xintAssignArray to use #1 rather than the #2 as +% in the correct earlier 1.0 version!!! This went through undetected because +% \xint_arrayname, although weird, was still usable: the probability to +% overwrite something was almost zero. The bug got finally revealed doing +% \xintAssignArray {}{}{}\to\Stuff. +% +% With release 1.06b an empty argument (or expanding to empty) to +% \xintAssignArray is ok. +% +% 1.09h simplifies the coding of \xintAssignArray (no more _end_a, _end_b, +% etc...), and no use of a \count register anymore, and uses \xintiloop in +% \xintRelaxArray. Furthermore, macros are made long. +% +% 1.09i allows an optional parameter \xintAssign [oo] for example, then \oodef +% rather than \edef is used. Idem for \xintAssignArray. However in the latter +% case, the global variant is not available, one should use \globaldefs for +% that. +% +% 1.09j: I decide that the default behavior of \xintAssign should be to use +% \def, not \edef when assigning to a cs an item of the list. This is a +% breaking change but I don't think anybody on earth is using xint anyhow. +% Also use of the optional parameter was broken if it was [], [g], [e], [x] as +% the corresponding \XINT_... macros had not been defined (in the initial +% version I did not have the XINT_ prefix; then I added it in case \oodef was +% pre-existing and thus was not redefined by the package which instead had +% \XINT_oodef, now \xintoodef.)| +% \begin{macrocode} +\def\xintAssign{\def\XINT_flet_macro {\XINT_assign_fork}\XINT_flet_zapsp }% +\def\XINT_assign_fork +{% + \let\XINT_assign_def\def + \ifx\XINT_token[\expandafter\XINT_assign_opt + \else\expandafter\XINT_assign_a + \fi +}% +\def\XINT_assign_opt [#1]% +{% + \ifcsname #1def\endcsname + \expandafter\let\expandafter\XINT_assign_def \csname #1def\endcsname + \else + \expandafter\let\expandafter\XINT_assign_def \csname xint#1def\endcsname + \fi + \XINT_assign_a +}% +\long\def\XINT_assign_a #1\to +{% + \expandafter\XINT_assign_b\romannumeral-`0#1{}\to +}% +\long\def\XINT_assign_b #1% attention to the # at the beginning of next line +#{% + \def\xint_temp {#1}% + \ifx\empty\xint_temp + \expandafter\XINT_assign_c + \else + \expandafter\XINT_assign_d + \fi +}% +\long\def\XINT_assign_c #1#2\to #3% +{% + \XINT_assign_def #3{#1}% + \def\xint_temp {#2}% + \unless\ifx\empty\xint_temp\xint_afterfi{\XINT_assign_b #2\to }\fi +}% +\def\XINT_assign_d #1\to #2% normally #1 is {} here. +{% + \expandafter\XINT_assign_def\expandafter #2\expandafter{\xint_temp}% +}% +\def\xintRelaxArray #1% +{% + \edef\XINT_restoreescapechar {\escapechar\the\escapechar\relax}% + \escapechar -1 + \expandafter\def\expandafter\xint_arrayname\expandafter {\string #1}% + \XINT_restoreescapechar + \xintiloop [\csname\xint_arrayname 0\endcsname+-1] + \global + \expandafter\let\csname\xint_arrayname\xintiloopindex\endcsname\relax + \ifnum \xintiloopindex > \xint_c_ + \repeat + \global\expandafter\let\csname\xint_arrayname 00\endcsname\relax + \global\let #1\relax +}% +\def\xintAssignArray{\def\XINT_flet_macro {\XINT_assignarray_fork}% + \XINT_flet_zapsp }% +\def\XINT_assignarray_fork +{% + \let\XINT_assignarray_def\def + \ifx\XINT_token[\expandafter\XINT_assignarray_opt + \else\expandafter\XINT_assignarray + \fi +}% +\def\XINT_assignarray_opt [#1]% +{% + \ifcsname #1def\endcsname + \expandafter\let\expandafter\XINT_assignarray_def \csname #1def\endcsname + \else + \expandafter\let\expandafter\XINT_assignarray_def + \csname xint#1def\endcsname + \fi + \XINT_assignarray +}% +\long\def\XINT_assignarray #1\to #2% +{% + \edef\XINT_restoreescapechar {\escapechar\the\escapechar\relax }% + \escapechar -1 + \expandafter\def\expandafter\xint_arrayname\expandafter {\string #2}% + \XINT_restoreescapechar + \def\xint_itemcount {0}% + \expandafter\XINT_assignarray_loop \romannumeral-`0#1\xint_relax + \csname\xint_arrayname 00\expandafter\endcsname + \csname\xint_arrayname 0\expandafter\endcsname + \expandafter {\xint_arrayname}#2% +}% +\long\def\XINT_assignarray_loop #1% +{% + \def\xint_temp {#1}% + \ifx\xint_brelax\xint_temp + \expandafter\def\csname\xint_arrayname 0\expandafter\endcsname + \expandafter{\the\numexpr\xint_itemcount}% + \expandafter\expandafter\expandafter\XINT_assignarray_end + \else + \expandafter\def\expandafter\xint_itemcount\expandafter + {\the\numexpr\xint_itemcount+\xint_c_i}% + \expandafter\XINT_assignarray_def + \csname\xint_arrayname\xint_itemcount\expandafter\endcsname + \expandafter{\xint_temp }% + \expandafter\XINT_assignarray_loop + \fi +}% +\def\XINT_assignarray_end #1#2#3#4% +{% + \def #4##1% + {% + \romannumeral0\expandafter #1\expandafter{\the\numexpr ##1}% + }% + \def #1##1% + {% + \ifnum ##1<\xint_c_ + \xint_afterfi {\xintError:ArrayIndexIsNegative\space }% + \else + \xint_afterfi {% + \ifnum ##1>#2 + \xint_afterfi {\xintError:ArrayIndexBeyondLimit\space }% + \else\xint_afterfi + {\expandafter\expandafter\expandafter\space\csname #3##1\endcsname}% + \fi}% + \fi + }% +}% +\let\xintDigitsOf\xintAssignArray +\let\XINT_tmpa\relax \let\XINT_tmpb\relax \let\XINT_tmpc\relax +\XINT_restorecatcodes_endinput% +% \end{macrocode} +%\catcode`\<=0 \catcode`\>=11 \catcode`\*=11 \catcode`\/=11 +%\let</xinttools>\relax +%\def<*xint>{\catcode`\<=12 \catcode`\>=12 \catcode`\*=12 \catcode`\/=12 } +%</xinttools> +%<*xint> +% +% \StoreCodelineNo {xinttools} +% +% \section{Package \xintnameimp implementation} +% \label{sec:xintimp} +% +% With release |1.09a| all macros doing arithmetic operations and a few more +% 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. Simplifies the +% discussion in the documentation too. +% +% \localtableofcontents +% +% \subsection{Catcodes, \protect\eTeX{} and reload detection} +% +% The code for reload detection is copied from \textsc{Heiko +% Oberdiek}'s packages, and adapted here to check for previous +% loading of the master \xintname package. +% +% The method for catcodes is slightly different, but still +% directly inspired by these packages. +% +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \def\space { }% + \let\z\endgroup + \expandafter\let\expandafter\x\csname ver@xint.sty\endcsname + \expandafter\let\expandafter\w\csname ver@xinttools.sty\endcsname + \expandafter + \ifx\csname PackageInfo\endcsname\relax + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \else + \def\y#1#2{\PackageInfo{#1}{#2}}% + \fi + \expandafter + \ifx\csname numexpr\endcsname\relax + \y{xint}{\numexpr not available, aborting input}% + \aftergroup\endinput + \else + \ifx\x\relax % plain-TeX, first loading of xint.sty + \ifx\w\relax % but xinttools.sty not yet loaded. + \y{xint}{now issuing \string\input\space xinttools.sty}% + \def\z{\endgroup\input xinttools.sty\relax}% + \fi + \else + \def\empty {}% + \ifx\x\empty % LaTeX, first loading, + % variable is initialized, but \ProvidesPackage not yet seen + \ifx\w\relax % xinttools.sty not yet loaded. + \y{xint}{now issuing \string\RequirePackage{xinttools}}% + \def\z{\endgroup\RequirePackage{xinttools}}% + \fi + \else + \y{xint}{I was already loaded, aborting input}% + \aftergroup\endinput + \fi + \fi + \fi +\z% +% \end{macrocode} +% \subsection{Confirmation of \xinttoolsnameimp loading} +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \ifdefined\PackageInfo + \def\y#1#2{\PackageInfo{#1}{#2}}% + \else + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \fi + \def\empty {}% + \expandafter\let\expandafter\w\csname ver@xinttools.sty\endcsname + \ifx\w\relax % Plain TeX, user gave a file name at the prompt + \y{xint}{Loading of package xinttools failed, aborting input}% + \aftergroup\endinput + \fi + \ifx\w\empty % LaTeX, user gave a file name at the prompt + \y{xint}{Loading of package xinttools failed, aborting input}% + \aftergroup\endinput + \fi +\endgroup% +% \end{macrocode} +% \subsection{Catcodes} +% \begin{macrocode} +\XINTsetupcatcodes% +% \end{macrocode} +% \subsection{Package identification} +% \begin{macrocode} +\XINT_providespackage +\ProvidesPackage{xint}% + [2014/02/05 v1.09ka Expandable operations on long numbers (jfB)]% +% \end{macrocode} +% \subsection{Token management, constants} +% \begin{macrocode} +\long\def\xint_firstofthree #1#2#3{#1}% +\long\def\xint_secondofthree #1#2#3{#2}% +\long\def\xint_thirdofthree #1#2#3{#3}% +\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}% +\def\xint_gob_til_zero #10{}% +\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_UDzerominusfork #10-#2#3\krof {#2}% +\def\xint_UDsignsfork #1--#2#3\krof {#2}% +% \chardef\xint_c_ 0 % already done in xinttools +% \chardef\xint_c_i 1 % already done in xinttools +\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 % will be done in xintfrac +% \chardef\xinf_c_vii 7 % will be done in xintfrac +% \chardef\xint_c_viii 8 % already done in xinttools +\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 +% \end{macrocode} +% \subsection{\csh{xintRev}} +% \lverb|& +% \xintRev: expands fully its argument \romannumeral-`0, and checks the sign. +% 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.| +% \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 +}% +% \end{macrocode} +% \subsection{\csh{xintLen}} +% \lverb|\xintLen is ONLY for (possibly long) integers. Gets extended to +% fractions by xintfrac.sty| +% \begin{macrocode} +\def\xintLen {\romannumeral0\xintlen }% +\def\xintlen #1% +{% + \expandafter\XINT_len_fork + \romannumeral0\xintnum{#1}\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye +}% +\def\XINT_Len #1% variant which does not expand via \xintnum. +{% + \romannumeral0\XINT_len_fork + #1\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\xint_bye +}% +\def\XINT_len_fork #1% +{% + \expandafter\XINT_length_loop + \xint_UDsignfork + #1{{0}}% + -{{0}#1}% + \krof +}% +% \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 | +% \begin{macrocode} +\def\XINT_RQ #1#2#3#4#5#6#7#8#9% +{% + \xint_gob_til_R #9\XINT_RQ_end_a\R\XINT_RQ {#9#8#7#6#5#4#3#2#1}% +}% +\def\XINT_RQ_end_a\R\XINT_RQ #1#2\Z +{% + \XINT_RQ_end_b #1\Z +}% +\def\XINT_RQ_end_b #1#2#3#4#5#6#7#8% +{% + \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% +}% +\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_SQ #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}% +}% +\def\XINT_SQ_end_a\R\XINT_SQ #1#2\Z +{% + \XINT_SQ_end_b #1\Z +}% +\def\XINT_SQ_end_b #1#2#3#4#5#6#7% +{% + \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}% +\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{XINT\_cuz}} +% \begin{macrocode} +\edef\xint_cleanupzeros_andstop #1#2#3#4% +{% + \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4\relax +}% +\def\xint_cleanupzeros_nostop #1#2#3#4% +{% + \the\numexpr #1#2#3#4\relax +}% +\def\XINT_rev_andcuz #1% +{% + \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 +}% +% \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| +% \begin{macrocode} +\def\XINT_cuz #1% +{% + \XINT_cuz_loop #1\W\W\W\W\W\W\W\Z% +}% +\def\XINT_cuz_loop #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}% +}% +\def\xint_cuz_end_a #1\XINT_cuz_check_a #2% +{% + \xint_cuz_end_b #2% +}% +\edef\xint_cuz_end_b #1#2#3#4#5\Z +{% + \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4\relax +}% +\def\xint_cuz_end_A \Z\XINT_cuz_check_a #1{ 0}% +\def\XINT_cuz_check_a #1% +{% + \expandafter\XINT_cuz_check_b\the\numexpr #1\relax +}% +\def\XINT_cuz_check_b #1% +{% + \xint_gob_til_zero #1\xint_cuz_backtoloop 0\XINT_cuz_stop #1% +}% +\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{xintIsOne}} +% \lverb|& +% Added in 1.03. Attention: \XINT_isOne does not do any expansion. Release 1.09a +% defines \xintIsOne which is more user-friendly. Will be modified if xintfrac +% is loaded. | +% \begin{macrocode} +\def\xintIsOne {\romannumeral0\xintisone }% +\def\xintisone #1{\expandafter\XINT_isone\romannumeral0\xintnum{#1}\W\Z }% +\def\XINT_isOne #1{\romannumeral0\XINT_isone #1\W\Z }% +\def\XINT_isone #1#2% +{% + \xint_gob_til_one #1\XINT_isone_b 1% + \expandafter\space\expandafter 0\xint_gob_til_Z #2% +}% +\def\XINT_isone_b #1\xint_gob_til_Z #2% +{% + \xint_gob_til_W #2\XINT_isone_yes \W + \expandafter\space\expandafter 0\xint_gob_til_Z +}% +\def\XINT_isone_yes #1\Z { 1}% +% \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).| +% \begin{macrocode} +\def\xintiNum {\romannumeral0\xintinum }% +\def\xintinum #1% +{% + \expandafter\XINT_num_loop + \romannumeral-`0#1\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\Z +}% +\let\xintNum\xintiNum \let\xintnum\xintinum +\def\XINT_num #1% +{% + \XINT_num_loop #1\xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\Z +}% +\def\XINT_num_loop #1#2#3#4#5#6#7#8% +{% + \xint_gob_til_xint_relax #8\XINT_num_end\xint_relax + \XINT_num_NumEight #1#2#3#4#5#6#7#8% +}% +\edef\XINT_num_end\xint_relax\XINT_num_NumEight #1\xint_relax #2\Z +{% + \noexpand\expandafter\space\noexpand\the\numexpr #1+0\relax +}% +\def\XINT_num_NumEight #1#2#3#4#5#6#7#8% +{% + \ifnum \numexpr #1#2#3#4#5#6#7#8+0= 0 + \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{xintSgn}, \csh{xintiiSgn}, \csh{XINT\_Sgn}, \csh{XINT\_cntSgn}} +% \lverb|& +% Changed in 1.05. Earlier code was unnecessarily strange. 1.09a with \xintnum +% +% 1.09i defines \XINT_Sgn and \XINT_cntSgn (was \XINT__Sgn in 1.09i) for reasons +% of internal optimizations| +% \begin{macrocode} +\def\xintiiSgn {\romannumeral0\xintiisgn }% +\def\xintiisgn #1% +{% + \expandafter\XINT_sgn \romannumeral-`0#1\Z% +}% +\def\xintSgn {\romannumeral0\xintsgn }% +\def\xintsgn #1% +{% + \expandafter\XINT_sgn \romannumeral0\xintnum{#1}\Z% +}% +\def\XINT_sgn #1#2\Z +{% + \xint_UDzerominusfork + #1-{ 0}% + 0#1{ -1}% + 0-{ 1}% + \krof +}% +\def\XINT_Sgn #1#2\Z +{% + \xint_UDzerominusfork + #1-{0}% + 0#1{-1}% + 0-{1}% + \krof +}% +\def\XINT_cntSgn #1#2\Z +{% + \xint_UDzerominusfork + #1-\z@ + 0#1\m@ne + 0-\@ne + \krof +}% +% \end{macrocode} +% \subsection{\csh{xintBool}, \csh{xintToggle}} +% \lverb|1.09c| +% \begin{macrocode} +\def\xintBool #1{\romannumeral-`0% + \csname if#1\endcsname\expandafter1\else\expandafter0\fi }% +\def\xintToggle #1{\romannumeral-`0\iftoggle{#1}{1}{0}}% +% \end{macrocode} +% \subsection{\csh{xintSgnFork}} +% \lverb|Expandable three-way fork added in 1.07. The argument #1 must expand +% to -1,0 or 1. 1.09i has _afterstop, renamed _thenstop later, for efficiency.| +% \begin{macrocode} +\def\xintSgnFork {\romannumeral0\xintsgnfork }% +\def\xintsgnfork #1% +{% + \ifcase #1 \expandafter\xint_secondofthree_thenstop + \or\expandafter\xint_thirdofthree_thenstop + \else\expandafter\xint_firstofthree_thenstop + \fi +}% +% \end{macrocode} +% \subsection{\csh{XINT\_cntSgnFork}} +% \lverb|1.09i. Used internally, #1 must expand to \m@ne, \z@, or \@ne or +% equivalent. Does not insert a space token to stop a romannumeral0 expansion.| +% \begin{macrocode} +\def\XINT_cntSgnFork #1% +{% + \ifcase #1\expandafter\xint_secondofthree + \or\expandafter\xint_thirdofthree + \else\expandafter\xint_firstofthree + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintifSgn}} +% \lverb|Expandable three-way fork added in 1.09a. Branches expandably +% depending on whether <0, =0, >0. Choice of branch guaranteed in two steps. +% +% The use of \romannumeral0\xintsgn rather than \xintSgn is for matters related +% to the transformation of the ternary operator : in \xintNewExpr. I hope I have +% explained there the details because right now off hand I can't recall why. +% +% 1.09i has \xint_firstofthreeafterstop (now _thenstop) etc for faster +% expansion.| +% \begin{macrocode} +\def\xintifSgn {\romannumeral0\xintifsgn }% +\def\xintifsgn #1% +{% + \ifcase \romannumeral0\xintsgn{#1} + \expandafter\xint_secondofthree_thenstop + \or\expandafter\xint_thirdofthree_thenstop + \else\expandafter\xint_firstofthree_thenstop + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintifZero}, \csh{xintifNotZero}} +% \lverb|& +% Expandable two-way fork added in 1.09a. Branches expandably depending on +% whether the argument is zero (branch A) or not (branch B). 1.09i restyling. By +% the way it appears (not thoroughly tested, though) that \if tests are faster +% than \ifnum tests. | +% \begin{macrocode} +\def\xintifZero {\romannumeral0\xintifzero }% +\def\xintifzero #1% +{% + \if0\xintSgn{#1}% + \expandafter\xint_firstoftwo_thenstop + \else + \expandafter\xint_secondoftwo_thenstop + \fi +}% +\def\xintifNotZero {\romannumeral0\xintifnotzero }% +\def\xintifnotzero #1% +{% + \if0\xintSgn{#1}% + \expandafter\xint_secondoftwo_thenstop + \else + \expandafter\xint_firstoftwo_thenstop + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintifOne}} +% \lverb|added in 1.09i.| +% \begin{macrocode} +\def\xintifOne {\romannumeral0\xintifone }% +\def\xintifone #1% +{% + \if1\xintIsOne{#1}% + \expandafter\xint_firstoftwo_thenstop + \else + \expandafter\xint_secondoftwo_thenstop + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintifTrueAelseB}, \csh{xint\-ifFalseAelseB}} +% \lverb|1.09i. Warning, \xintifTrueFalse, \xintifTrue deprecated, to be +% removed| +% \begin{macrocode} +\let\xintifTrueAelseB\xintifNotZero +\let\xintifFalseAelseB\xintifZero +\let\xintifTrue\xintifNotZero +\let\xintifTrueFalse\xintifNotZero +% \end{macrocode} +% \subsection{\csh{xintifCmp}} +% \lverb|& +% 1.09e +% \xintifCmp {n}{m}{if n<m}{if n=m}{if n>m}.| +% \begin{macrocode} +\def\xintifCmp {\romannumeral0\xintifcmp }% +\def\xintifcmp #1#2% +{% + \ifcase\xintCmp {#1}{#2} + \expandafter\xint_secondofthree_thenstop + \or\expandafter\xint_thirdofthree_thenstop + \else\expandafter\xint_firstofthree_thenstop + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintifEq}} +% \lverb|& +% 1.09a +% \xintifEq {n}{m}{YES if n=m}{NO if n<>m}.| +% \begin{macrocode} +\def\xintifEq {\romannumeral0\xintifeq }% +\def\xintifeq #1#2% +{% + \if0\xintCmp{#1}{#2}% + \expandafter\xint_firstoftwo_thenstop + \else\expandafter\xint_secondoftwo_thenstop + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintifGt}} +% \lverb|& +% 1.09a \xintifGt {n}{m}{YES if n>m}{NO if n<=m}.| +% \begin{macrocode} +\def\xintifGt {\romannumeral0\xintifgt }% +\def\xintifgt #1#2% +{% + \if1\xintCmp{#1}{#2}% + \expandafter\xint_firstoftwo_thenstop + \else\expandafter\xint_secondoftwo_thenstop + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintifLt}} +% \lverb|& +% 1.09a \xintifLt {n}{m}{YES if n<m}{NO if n>=m}. Restyled in 1.09i| +% \begin{macrocode} +\def\xintifLt {\romannumeral0\xintiflt }% +\def\xintiflt #1#2% +{% + \ifnum\xintCmp{#1}{#2}<\xint_c_ + \expandafter\xint_firstoftwo_thenstop + \else \expandafter\xint_secondoftwo_thenstop + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintifOdd}} +% \lverb|1.09e. Restyled in 1.09i.| +% \begin{macrocode} +\def\xintifOdd {\romannumeral0\xintifodd }% +\def\xintifodd #1% +{% + \if\xintOdd{#1}1% + \expandafter\xint_firstoftwo_thenstop + \else + \expandafter\xint_secondoftwo_thenstop + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintOpp}} +% \lverb|\xintnum added in 1.09a| +% \begin{macrocode} +\def\xintiiOpp {\romannumeral0\xintiiopp }% +\def\xintiiopp #1% +{% + \expandafter\XINT_opp \romannumeral-`0#1% +}% +\def\xintiOpp {\romannumeral0\xintiopp }% +\def\xintiopp #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% +{% + \xint_UDzerominusfork + #1-{ 0}% zero + 0#1{ }% negative + 0-{ -#1}% positive + \krof +}% +% \end{macrocode} +% \subsection{\csh{xintAbs}} +% \lverb|Release 1.09a has now \xintiabs which does \xintnum (contrarily to some +% other i-macros, but similarly as \xintiAdd etc...) and this is +% inherited by DecSplit, by Sqr, and macros of xintgcd.sty.| +% \begin{macrocode} +\def\xintiiAbs {\romannumeral0\xintiiabs }% +\def\xintiiabs #1% +{% + \expandafter\XINT_abs \romannumeral-`0#1% +}% +\def\xintiAbs {\romannumeral0\xintiabs }% +\def\xintiabs #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% +{% + \xint_UDsignfork + #1{ }% + -{ #1}% + \krof +}% +% \end{macrocode} +% \lverb|& +% -----------------------------------------------------------------$\ +% -----------------------------------------------------------------$\ +% ARITHMETIC OPERATIONS: ADDITION, SUBTRACTION, SUMS, +% MULTIPLICATION, PRODUCTS, FACTORIAL, POWERS, EUCLIDEAN DIVISION. +% +% 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 I: \XINT_add_A +% +% 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} +% \lverb|Addition II: \XINT_addr_A.$\ +% 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} +% \lverb|ADDITION III, \XINT_addm_A$\ +% 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} +% \lverb|ADDITION IV, variante \XINT_addp_A$\ +% 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.| +% \begin{macrocode} +\def\XINT_addp_A #1#2#3#4#5#6% +{% + \xint_gob_til_W #3\xint_addp_az\W + \XINT_addp_AB #1{#3#4#5#6}{#2}% +}% +\def\xint_addp_az\W\XINT_addp_AB #1#2% +{% + \XINT_addp_AC_checkcarry #1% +}% +\def\XINT_addp_AC_checkcarry #1% +{% + \xint_gob_til_zero #1\xint_addp_AC_nocarry 0\XINT_addp_C +}% +\def\xint_addp_AC_nocarry 0\XINT_addp_C +{% + \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 +}% +\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_addp_ABEA #1#2#3#4#5#6#7% +{% + \XINT_addp_A #2{#7#6#5#4#3}%<-- attention on met donc \`a droite +}% +\def\XINT_addp_C #1#2#3#4#5% +{% + \xint_gob_til_W + #5\xint_addp_cw + #4\xint_addp_cx + #3\xint_addp_cy + #2\xint_addp_cz + \W\XINT_addp_CD {#5#4#3#2}{#1}% +}% +\def\XINT_addp_CD #1% +{% + \expandafter\XINT_addp_CC\the\numexpr 1+10#1\relax +}% +\def\XINT_addp_CC #1#2#3#4#5#6#7% +{% + \XINT_addp_AC_checkcarry #2{#7#6#5#4#3}% +}% +\def\xint_addp_cw + #1\xint_addp_cx + #2\xint_addp_cy + #3\xint_addp_cz + \W\XINT_addp_CD +{% + \expandafter\XINT_addp_CDw\the\numexpr \xint_c_i+10#1#2#3\relax +}% +\def\XINT_addp_CDw #1#2#3#4#5#6% +{% + \xint_gob_til_zeros_iv #2#3#4#5\XINT_addp_endDw_zeros + 0000\XINT_addp_endDw #2#3#4#5% +}% +\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 +{% + \expandafter\XINT_addp_CDx\the\numexpr \xint_c_i+100#1#2\relax +}% +\def\XINT_addp_CDx #1#2#3#4#5#6% +{% + \xint_gob_til_zeros_iv #2#3#4#5\XINT_addp_endDx_zeros + 0000\XINT_addp_endDx #2#3#4#5% +}% +\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 +{% + \expandafter\XINT_addp_CDy\the\numexpr \xint_c_i+1000#1\relax +}% +\def\XINT_addp_CDy #1#2#3#4#5#6% +{% + \xint_gob_til_zeros_iv #2#3#4#5\XINT_addp_endDy_zeros + 0000\XINT_addp_endDy #2#3#4#5% +}% +\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% +{% + \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}% +}% +\def\XINT_addp_G #1#2% +{% + \XINT_addp_F {#2#1}% +}% +\def\xint_addp_Gw + #1\xint_addp_Gx + #2\xint_addp_Gy + #3\xint_addp_Gz + \W\XINT_addp_G #4% +{% + \xint_gob_til_zeros_iv #3#2#10\XINT_addp_endGw_zeros + 0000\XINT_addp_endGw #3#2#10% +}% +\def\XINT_addp_endGw_zeros 0000\XINT_addp_endGw 0000#1\X\Y\Z{ #1}% +\def\XINT_addp_endGw #1#2#3#4#5\X\Y\Z{ #5#1#2#3#4}% +\def\xint_addp_Gx + #1\xint_addp_Gy + #2\xint_addp_Gz + \W\XINT_addp_G #3% +{% + \xint_gob_til_zeros_iv #2#100\XINT_addp_endGx_zeros + 0000\XINT_addp_endGx #2#100% +}% +\def\XINT_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% +{% + \xint_gob_til_zeros_iv #1000\XINT_addp_endGy_zeros + 0000\XINT_addp_endGy #1000% +}% +\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{xintAdd}} +% \lverb|Release 1.09a has \xintnum added into \xintiAdd.| +% \begin{macrocode} +\def\xintiiAdd {\romannumeral0\xintiiadd }% +\def\xintiiadd #1% +{% + \expandafter\xint_iiadd\expandafter{\romannumeral-`0#1}% +}% +\def\xint_iiadd #1#2% +{% + \expandafter\XINT_add_fork \romannumeral-`0#2\Z #1\Z +}% +\def\xintiAdd {\romannumeral0\xintiadd }% +\def\xintiadd #1% +{% + \expandafter\xint_add\expandafter{\romannumeral0\xintnum{#1}}% +}% +\def\xint_add #1#2% +{% + \expandafter\XINT_add_fork \romannumeral0\xintnum{#2}\Z #1\Z +}% +\let\xintAdd\xintiAdd \let\xintadd\xintiadd +\def\XINT_Add #1#2{\romannumeral0\XINT_add_fork #2\Z #1\Z }% +\def\XINT_add #1#2{\XINT_add_fork #2\Z #1\Z }% +% \end{macrocode} +% \lverb|ADDITION +% Ici #1#2 vient du *deuxième* argument de \xintAdd et #3#4 donc du *premier* +% [algo plus efficace lorsque le premier est plus long que le second]| +% \begin{macrocode} +\def\XINT_add_fork #1#2\Z #3#4\Z +{% + \xint_UDzerofork + #1\XINT_add_secondiszero + #3\XINT_add_firstiszero + 0 + {\xint_UDsignsfork + #1#3\XINT_add_minusminus % #1 = #3 = - + #1-\XINT_add_minusplus % #1 = - + #3-\XINT_add_plusminus % #3 = - + --\XINT_add_plusplus + \krof }% + \krof + {#2}{#4}#1#3% +}% +\def\XINT_add_secondiszero #1#2#3#4{ #4#2}% +\def\XINT_add_firstiszero #1#2#3#4{ #3#1}% +% \end{macrocode} +% \lverb|#1 vient du *deuxième* et #2 vient du *premier*| +% \begin{macrocode} +\def\XINT_add_minusminus #1#2#3#4% +{% + \expandafter\xint_minus_thenstop% + \romannumeral0\XINT_add_pre {#2}{#1}% +}% +\def\XINT_add_minusplus #1#2#3#4% +{% + \XINT_sub_pre {#4#2}{#1}% +}% +\def\XINT_add_plusminus #1#2#3#4% +{% + \XINT_sub_pre {#3#1}{#2}% +}% +\def\XINT_add_plusplus #1#2#3#4% +{% + \XINT_add_pre {#4#2}{#3#1}% +}% +\def\XINT_add_pre #1% +{% + \expandafter\XINT_add_pre_b\expandafter + {\romannumeral0\XINT_RQ {}#1\R\R\R\R\R\R\R\R\Z }% +}% +\def\XINT_add_pre_b #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 +}% +% \end{macrocode} +% \subsection{\csh{xintSub}} +% \lverb|Release 1.09a has \xintnum added into \xintiSub.| +% \begin{macrocode} +\def\xintiiSub {\romannumeral0\xintiisub }% +\def\xintiisub #1% +{% + \expandafter\xint_iisub\expandafter{\romannumeral-`0#1}% +}% +\def\xint_iisub #1#2% +{% + \expandafter\XINT_sub_fork \romannumeral-`0#2\Z #1\Z +}% +\def\xintiSub {\romannumeral0\xintisub }% +\def\xintisub #1% +{% + \expandafter\xint_sub\expandafter{\romannumeral0\xintnum{#1}}% +}% +\def\xint_sub #1#2% +{% + \expandafter\XINT_sub_fork \romannumeral0\xintnum{#2}\Z #1\Z +}% +\def\XINT_Sub #1#2{\romannumeral0\XINT_sub_fork #2\Z #1\Z }% +\def\XINT_sub #1#2{\XINT_sub_fork #2\Z #1\Z }% +\let\xintSub\xintiSub \let\xintsub\xintisub +% \end{macrocode} +% \lverb|& +% SOUSTRACTION +% #3#4-#1#2: +% #3#4 vient du *premier* +% #1#2 vient du *second*| +% \begin{macrocode} +\def\XINT_sub_fork #1#2\Z #3#4\Z +{% + \xint_UDsignsfork + #1#3\XINT_sub_minusminus + #1-\XINT_sub_minusplus % attention, #3=0 possible + #3-\XINT_sub_plusminus % attention, #1=0 possible + --{\xint_UDzerofork + #1\XINT_sub_secondiszero + #3\XINT_sub_firstiszero + 0\XINT_sub_plusplus + \krof }% + \krof + {#2}{#4}#1#3% +}% +\def\XINT_sub_secondiszero #1#2#3#4{ #4#2}% +\def\XINT_sub_firstiszero #1#2#3#4{ -#3#1}% +\def\XINT_sub_plusplus #1#2#3#4% +{% + \XINT_sub_pre {#4#2}{#3#1}% +}% +\def\XINT_sub_minusminus #1#2#3#4% +{% + \XINT_sub_pre {#1}{#2}% +}% +\def\XINT_sub_minusplus #1#2#3#4% +{% + \xint_gob_til_zero #4\xint_sub_mp0\XINT_add_pre {#4#2}{#1}% +}% +\def\xint_sub_mp0\XINT_add_pre #1#2{ #2}% +\def\XINT_sub_plusminus #1#2#3#4% +{% + \xint_gob_til_zero #3\xint_sub_pm0\expandafter\xint_minus_thenstop% + \romannumeral0\XINT_add_pre {#2}{#3#1}% +}% +\def\xint_sub_pm #1\XINT_add_pre #2#3{ -#2}% +\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% +{% + \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.% +}% +% \end{macrocode} +% \lverb|ON PRODUIT LE RÉSULTAT DANS LE BON ORDRE| +% \begin{macrocode} +\def\XINT_sub_backtoA #1#2#3.#4% +{% + \XINT_sub_A #2{#3#4}% +}% +\def\xint_sub_bz + \W\XINT_sub_onestep #1#2#3#4#5#6#7% +{% + \xint_UDzerofork + #1\XINT_sub_C % une retenue + 0\XINT_sub_D % pas de retenue + \krof + {#7}#2#3#4#5% +}% +\def\XINT_sub_D #1#2\W\X\Y\Z +{% + \expandafter + \xint_cleanupzeros_andstop + \romannumeral0% + \XINT_rord_main {}#2% + \xint_relax + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_relax + #1% +}% +\def\XINT_sub_C #1#2#3#4#5% +{% + \xint_gob_til_W + #2\xint_sub_cz + \W\XINT_sub_AC_onestep {#5#4#3#2}{#1}% +}% +\def\XINT_sub_AC_onestep #1% +{% + \expandafter\XINT_sub_backtoC\the\numexpr 11#1-\xint_c_i.% +}% +\def\XINT_sub_backtoC #1#2#3.#4% +{% + \XINT_sub_AC_checkcarry #2{#3#4}% la retenue va \^etre examin\'ee +}% +\def\XINT_sub_AC_checkcarry #1% +{% + \xint_gob_til_one #1\xint_sub_AC_nocarry 1\XINT_sub_C +}% +\def\xint_sub_AC_nocarry 1\XINT_sub_C #1#2\W\X\Y\Z +{% + \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 +}% +\def\xint_sub_cz\W\XINT_sub_AC_onestep #1% +{% + \XINT_cuz +}% +\def\xint_sub_az\W\XINT_sub_B #1#2#3#4#5#6#7% +{% + \xint_gob_til_W + #4\xint_sub_ez + \W\XINT_sub_Eenter #1{#3}#4#5#6#7% +}% +% \end{macrocode} +% \lverb|le premier nombre continue, le résultat sera < 0.| +% \begin{macrocode} +\def\XINT_sub_Eenter #1#2% +{% + \expandafter + \XINT_sub_E\expandafter1\expandafter{\expandafter}% + \romannumeral0% + \XINT_rord_main {}#2% + \xint_relax + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_relax + \W\X\Y\Z #1% +}% +\def\XINT_sub_E #1#2#3#4#5#6% +{% + \xint_gob_til_W #3\xint_sub_F\W + \XINT_sub_Eonestep #1{#6#5#4#3}{#2}% +}% +\def\XINT_sub_Eonestep #1#2% +{% + \expandafter\XINT_sub_backtoE\the\numexpr 109999-#2+#1.% +}% +\def\XINT_sub_backtoE #1#2#3.#4% +{% + \XINT_sub_E #2{#3#4}% +}% +\def\xint_sub_F\W\XINT_sub_Eonestep #1#2#3#4% +{% + \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}% +}% +\def\XINT_sub_DD {\expandafter\xint_minus_thenstop\romannumeral0\XINT_sub_D }% +\def\XINT_sub_Fdec #1#2#3#4#5#6% +{% + \xint_gob_til_W #3\xint_sub_Fdec_finish\W + \XINT_sub_Fdec_onestep #1{#6#5#4#3}{#2}% +}% +\def\XINT_sub_Fdec_onestep #1#2% +{% + \expandafter\XINT_sub_backtoFdec\the\numexpr 11#2+#1-\xint_c_i.% +}% +\def\XINT_sub_backtoFdec #1#2#3.#4% +{% + \XINT_sub_Fdec #2{#3#4}% +}% +\def\xint_sub_Fdec_finish\W\XINT_sub_Fdec_onestep #1#2% +{% + \expandafter\xint_minus_thenstop\romannumeral0\XINT_cuz +}% +\def\XINT_sub_Finc #1#2#3#4#5#6% +{% + \xint_gob_til_W #3\xint_sub_Finc_finish\W + \XINT_sub_Finc_onestep #1{#6#5#4#3}{#2}% +}% +\def\XINT_sub_Finc_onestep #1#2% +{% + \expandafter\XINT_sub_backtoFinc\the\numexpr 10#2+#1.% +}% +\def\XINT_sub_backtoFinc #1#2#3.#4% +{% + \XINT_sub_Finc #2{#3#4}% +}% +\def\xint_sub_Finc_finish\W\XINT_sub_Finc_onestep #1#2#3% +{% + \xint_UDzerofork + #1{\expandafter\expandafter\expandafter + \xint_minus_thenstop\xint_cleanupzeros_nostop}% + 0{ -1}% + \krof + #3% +}% +\def\xint_sub_ez\W\XINT_sub_Eenter #1% +{% + \xint_UDzerofork + #1\XINT_sub_K % il y a une retenue + 0\XINT_sub_L % pas de retenue + \krof +}% +\def\XINT_sub_L #1\W\X\Y\Z {\XINT_cuz_loop #1\W\W\W\W\W\W\W\Z }% +\def\XINT_sub_K #1% +{% + \expandafter + \XINT_sub_KK\expandafter1\expandafter{\expandafter}% + \romannumeral0% + \XINT_rord_main {}#1% + \xint_relax + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_relax +}% +\def\XINT_sub_KK #1#2#3#4#5#6% +{% + \xint_gob_til_W #3\xint_sub_KK_finish\W + \XINT_sub_KK_onestep #1{#6#5#4#3}{#2}% +}% +\def\XINT_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 +}% +% \end{macrocode} +% \subsection{\csh{xintCmp}} +% \lverb|Release 1.09a has \xintnum inserted into \xintCmp. Unnecessary +% \xintiCmp suppressed in 1.09f.| +% \begin{macrocode} +\def\xintCmp {\romannumeral0\xintcmp }% +\def\xintcmp #1% +{% + \expandafter\xint_cmp\expandafter{\romannumeral0\xintnum{#1}}% +}% +\def\xint_cmp #1#2% +{% + \expandafter\XINT_cmp_fork \romannumeral0\xintnum{#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_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 }% + \krof + {#2}{#4}#1#3% +}% +\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% +{% + \XINT_cmp_pre {#4#2}{#3#1}% +}% +\def\XINT_cmp_minusminus #1#2#3#4% +{% + \XINT_cmp_pre {#1}{#2}% +}% +\def\XINT_cmp_pre #1% +{% + \expandafter\XINT_cmp_pre_b\expandafter + {\romannumeral0\XINT_RQ {}#1\R\R\R\R\R\R\R\R\Z }% +}% +\def\XINT_cmp_pre_b #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 +}% +% \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% +{% + \xint_gob_til_W #4\xint_cmp_az\W + \XINT_cmp_B #1{#4#5#6#7}{#2}#3\W\X\Y\Z +}% +\def\XINT_cmp_B #1#2#3#4#5#6#7% +{% + \xint_gob_til_W#4\xint_cmp_bz\W + \XINT_cmp_onestep #1#2{#7#6#5#4}{#3}% +}% +\def\XINT_cmp_onestep #1#2#3#4#5#6% +{% + \expandafter\XINT_cmp_backtoA\the\numexpr 11#5#4#3#2-#6+#1-\xint_c_i.% +}% +\def\XINT_cmp_backtoA #1#2#3.#4% +{% + \XINT_cmp_A #2{#3#4}% +}% +\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% +{% + \xint_gob_til_W #4\xint_cmp_ez\W + \XINT_cmp_Eenter #1{#3}#4#5#6#7% +}% +\def\XINT_cmp_Eenter #1\Z { -1}% +\def\xint_cmp_ez\W\XINT_cmp_Eenter #1% +{% + \xint_UDzerofork + #1\XINT_cmp_K % il y a une retenue + 0\XINT_cmp_L % pas de retenue + \krof +}% +\def\XINT_cmp_K #1\Z { -1}% +\def\XINT_cmp_L #1{\XINT_OneIfPositive_main #1}% +\def\XINT_OneIfPositive #1% +{% + \XINT_OneIfPositive_main #1\W\X\Y\Z% +}% +\def\XINT_OneIfPositive_main #1#2#3#4% +{% + \xint_gob_til_Z #4\xint_OneIfPositive_terminated\Z + \XINT_OneIfPositive_onestep #1#2#3#4% +}% +\def\xint_OneIfPositive_terminated\Z\XINT_OneIfPositive_onestep\W\X\Y\Z { 0}% +\def\XINT_OneIfPositive_onestep #1#2#3#4% +{% + \expandafter\XINT_OneIfPositive_check\the\numexpr #1#2#3#4\relax +}% +\def\XINT_OneIfPositive_check #1% +{% + \xint_gob_til_zero #1\xint_OneIfPositive_backtomain 0% + \XINT_OneIfPositive_finish #1% +}% +\def\XINT_OneIfPositive_finish #1\W\X\Y\Z{ 1}% +\def\xint_OneIfPositive_backtomain 0\XINT_OneIfPositive_finish 0% + {\XINT_OneIfPositive_main }% +% \end{macrocode} +% \subsection{\csh{xintEq}, \csh{xintGt}, \csh{xintLt}} +% \lverb|1.09a.| +% \begin{macrocode} +\def\xintEq {\romannumeral0\xinteq }% +\def\xinteq #1#2{\xintifeq{#1}{#2}{1}{0}}% +\def\xintGt {\romannumeral0\xintgt }% +\def\xintgt #1#2{\xintifgt{#1}{#2}{1}{0}}% +\def\xintLt {\romannumeral0\xintlt }% +\def\xintlt #1#2{\xintiflt{#1}{#2}{1}{0}}% +% \end{macrocode} +% \subsection{\csh{xintIsZero}, \csh{xintIsNotZero}} +% \lverb|1.09a. restyled in 1.09i.| +% \begin{macrocode} +\def\xintIsZero {\romannumeral0\xintiszero }% +\def\xintiszero #1{\if0\xintSgn{#1}\xint_afterfi{ 1}\else\xint_afterfi{ 0}\fi}% +\def\xintIsNotZero {\romannumeral0\xintisnotzero }% +\def\xintisnotzero + #1{\if0\xintSgn{#1}\xint_afterfi{ 0}\else\xint_afterfi{ 1}\fi}% +% \end{macrocode} +% \subsection{\csh{xintIsTrue}, \csh{xintNot}, \csh{xintIsFalse}} +% \lverb|1.09c| +% \begin{macrocode} +\let\xintIsTrue\xintIsNotZero +\let\xintNot\xintIsZero +\let\xintIsFalse\xintIsZero +% \end{macrocode} +% \subsection{\csh{xintAND}, \csh{xintOR}, \csh{xintXOR}} +% \lverb|1.09a. Embarrasing bugs in \xintAND and \xintOR which inserted a space +% token corrected in 1.09i. \xintxor restyled with \if (faster) in 1.09i| +% \begin{macrocode} +\def\xintAND {\romannumeral0\xintand }% +\def\xintand #1#2{\if0\xintSgn{#1}\expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo\fi + { 0}{\xintisnotzero{#2}}}% +\def\xintOR {\romannumeral0\xintor }% +\def\xintor #1#2{\if0\xintSgn{#1}\expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo\fi + {\xintisnotzero{#2}}{ 1}}% +\def\xintXOR {\romannumeral0\xintxor }% +\def\xintxor #1#2{\if\xintIsZero{#1}\xintIsZero{#2}% + \xint_afterfi{ 0}\else\xint_afterfi{ 1}\fi }% +% \end{macrocode} +% \subsection{\csh{xintANDof}} +% \lverb|New with 1.09a. \xintANDof works also with an empty list.| +% \begin{macrocode} +\def\xintANDof {\romannumeral0\xintandof }% +\def\xintandof #1{\expandafter\XINT_andof_a\romannumeral-`0#1\relax }% +\def\XINT_andof_a #1{\expandafter\XINT_andof_b\romannumeral-`0#1\Z }% +\def\XINT_andof_b #1% + {\xint_gob_til_relax #1\XINT_andof_e\relax\XINT_andof_c #1}% +\def\XINT_andof_c #1\Z + {\xintifTrueAelseB {#1}{\XINT_andof_a}{\XINT_andof_no}}% +\def\XINT_andof_no #1\relax { 0}% +\def\XINT_andof_e #1\Z { 1}% +% \end{macrocode} +% \subsection{\csh{xintORof}} +% \lverb|New with 1.09a. Works also with an empty list.| +% \begin{macrocode} +\def\xintORof {\romannumeral0\xintorof }% +\def\xintorof #1{\expandafter\XINT_orof_a\romannumeral-`0#1\relax }% +\def\XINT_orof_a #1{\expandafter\XINT_orof_b\romannumeral-`0#1\Z }% +\def\XINT_orof_b #1% + {\xint_gob_til_relax #1\XINT_orof_e\relax\XINT_orof_c #1}% +\def\XINT_orof_c #1\Z + {\xintifTrueAelseB {#1}{\XINT_orof_yes}{\XINT_orof_a}}% +\def\XINT_orof_yes #1\relax { 1}% +\def\XINT_orof_e #1\Z { 0}% +% \end{macrocode} +% \subsection{\csh{xintXORof}} +% \lverb|New with 1.09a. Works with an empty list, too. \XINT_xorof_c more +% efficient in 1.09i| +% \begin{macrocode} +\def\xintXORof {\romannumeral0\xintxorof }% +\def\xintxorof #1{\expandafter\XINT_xorof_a\expandafter + 0\romannumeral-`0#1\relax }% +\def\XINT_xorof_a #1#2{\expandafter\XINT_xorof_b\romannumeral-`0#2\Z #1}% +\def\XINT_xorof_b #1% + {\xint_gob_til_relax #1\XINT_xorof_e\relax\XINT_xorof_c #1}% +\def\XINT_xorof_c #1\Z #2% + {\xintifTrueAelseB {#1}{\if #20\xint_afterfi{\XINT_xorof_a 1}% + \else\xint_afterfi{\XINT_xorof_a 0}\fi}% + {\XINT_xorof_a #2}% + }% +\def\XINT_xorof_e #1\Z #2{ #2}% +% \end{macrocode} +% \subsection{\csh{xintGeq}} +% \lverb|& +% Release 1.09a has \xintnum added into \xintGeq. Unused and useless \xintiGeq +% removed in 1.09e. +% PLUS GRAND OU ÉGAL +% attention compare les **valeurs absolues**| +% \begin{macrocode} +\def\xintGeq {\romannumeral0\xintgeq }% +\def\xintgeq #1% +{% + \expandafter\xint_geq\expandafter {\romannumeral0\xintnum{#1}}% +}% +\def\xint_geq #1#2% +{% + \expandafter\XINT_geq_fork \romannumeral0\xintnum{#2}\Z #1\Z +}% +\def\XINT_Geq #1#2{\romannumeral0\XINT_geq_fork #2\Z #1\Z }% +% \end{macrocode} +% \lverb|& +% PLUS GRAND OU ÉGAL +% ATTENTION, TESTE les VALEURS ABSOLUES| +% \begin{macrocode} +\def\XINT_geq_fork #1#2\Z #3#4\Z +{% + \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 }% + \krof + {#2}{#4}#1#3% +}% +\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% +{% + \expandafter\XINT_geq_pre_b\expandafter + {\romannumeral0\XINT_RQ {}#1\R\R\R\R\R\R\R\R\Z }% +}% +\def\XINT_geq_pre_b #1#2% +{% + \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 +}% +% \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% +{% + \xint_gob_til_W #4\xint_geq_az\W + \XINT_geq_B #1{#4#5#6#7}{#2}#3\W\X\Y\Z +}% +\def\XINT_geq_B #1#2#3#4#5#6#7% +{% + \xint_gob_til_W #4\xint_geq_bz\W + \XINT_geq_onestep #1#2{#7#6#5#4}{#3}% +}% +\def\XINT_geq_onestep #1#2#3#4#5#6% +{% + \expandafter\XINT_geq_backtoA\the\numexpr 11#5#4#3#2-#6+#1-\xint_c_i.% +}% +\def\XINT_geq_backtoA #1#2#3.#4% +{% + \XINT_geq_A #2{#3#4}% +}% +\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% +{% + \xint_gob_til_W #4\xint_geq_ez\W + \XINT_geq_Eenter #1% +}% +\def\XINT_geq_Eenter #1\W\X\Y\Z { 0}% +\def\xint_geq_ez\W\XINT_geq_Eenter #1% +{% + \xint_UDzerofork + #1{ 0} % il y a une retenue + 0{ 1} % pas de retenue + \krof +}% +% \end{macrocode} +% \subsection{\csh{xintMax}} +% \lverb|& +% The rationale is that it is more efficient than using \xintCmp. +% 1.03 makes the code a tiny bit slower but easier to re-use for fractions. +% Note: actually since 1.08a code for fractions does not all reduce to these +% entry points, so perhaps I should revert the changes made in 1.03. Release +% 1.09a has \xintnum added into \xintiMax.| +% \begin{macrocode} +\def\xintiMax {\romannumeral0\xintimax }% +\def\xintimax #1% +{% + \expandafter\xint_max\expandafter {\romannumeral0\xintnum{#1}}% +}% +\let\xintMax\xintiMax \let\xintmax\xintimax +\def\xint_max #1#2% +{% + \expandafter\XINT_max_pre\expandafter {\romannumeral0\xintnum{#2}}{#1}% +}% +\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} +% \lverb|& +% #3#4 vient du *premier*, +% #1#2 vient du *second*| +% \begin{macrocode} +\def\XINT_max_fork #1#2\Z #3#4\Z +{% + \xint_UDsignsfork + #1#3\XINT_max_minusminus % A < 0, B < 0 + #1-\XINT_max_minusplus % B < 0, A >= 0 + #3-\XINT_max_plusminus % A < 0, B >= 0 + --{\xint_UDzerosfork + #1#3\XINT_max_zerozero % A = B = 0 + #10\XINT_max_zeroplus % B = 0, A > 0 + #30\XINT_max_pluszero % A = 0, B > 0 + 00\XINT_max_plusplus % A, B > 0 + \krof }% + \krof + {#2}{#4}#1#3% +}% +% \end{macrocode} +% \lverb|& +% A = #4#2, B = #3#1| +% \begin{macrocode} +\def\XINT_max_zerozero #1#2#3#4{\xint_firstoftwo_thenstop }% +\def\XINT_max_zeroplus #1#2#3#4{\xint_firstoftwo_thenstop }% +\def\XINT_max_pluszero #1#2#3#4{\xint_secondoftwo_thenstop }% +\def\XINT_max_minusplus #1#2#3#4{\xint_firstoftwo_thenstop }% +\def\XINT_max_plusminus #1#2#3#4{\xint_secondoftwo_thenstop }% +\def\XINT_max_plusplus #1#2#3#4% +{% + \ifodd\XINT_Geq {#4#2}{#3#1} + \expandafter\xint_firstoftwo_thenstop + \else + \expandafter\xint_secondoftwo_thenstop + \fi +}% +% \end{macrocode} +% \lverb+#3=-, #4=-, #1 = |B| = -B, #2 = |A| = -A+ +% \begin{macrocode} +\def\XINT_max_minusminus #1#2#3#4% +{% + \ifodd\XINT_Geq {#1}{#2} + \expandafter\xint_firstoftwo_thenstop + \else + \expandafter\xint_secondoftwo_thenstop + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintMaxof}} +% \lverb|New with 1.09a.| +% \begin{macrocode} +\def\xintiMaxof {\romannumeral0\xintimaxof }% +\def\xintimaxof #1{\expandafter\XINT_imaxof_a\romannumeral-`0#1\relax }% +\def\XINT_imaxof_a #1{\expandafter\XINT_imaxof_b\romannumeral0\xintnum{#1}\Z }% +\def\XINT_imaxof_b #1\Z #2% + {\expandafter\XINT_imaxof_c\romannumeral-`0#2\Z {#1}\Z}% +\def\XINT_imaxof_c #1% + {\xint_gob_til_relax #1\XINT_imaxof_e\relax\XINT_imaxof_d #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{xintMin}} +% \lverb|\xintnum added New with 1.09a.| +% \begin{macrocode} +\def\xintiMin {\romannumeral0\xintimin }% +\def\xintimin #1% +{% + \expandafter\xint_min\expandafter {\romannumeral0\xintnum{#1}}% +}% +\let\xintMin\xintiMin \let\xintmin\xintimin +\def\xint_min #1#2% +{% + \expandafter\XINT_min_pre\expandafter {\romannumeral0\xintnum{#2}}{#1}% +}% +\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} +% \lverb|& +% #3#4 vient du *premier*, +% #1#2 vient du *second*| +% \begin{macrocode} +\def\XINT_min_fork #1#2\Z #3#4\Z +{% + \xint_UDsignsfork + #1#3\XINT_min_minusminus % A < 0, B < 0 + #1-\XINT_min_minusplus % B < 0, A >= 0 + #3-\XINT_min_plusminus % A < 0, B >= 0 + --{\xint_UDzerosfork + #1#3\XINT_min_zerozero % A = B = 0 + #10\XINT_min_zeroplus % B = 0, A > 0 + #30\XINT_min_pluszero % A = 0, B > 0 + 00\XINT_min_plusplus % A, B > 0 + \krof }% + \krof + {#2}{#4}#1#3% +}% +% \end{macrocode} +% \lverb|& +% A = #4#2, B = #3#1| +% \begin{macrocode} +\def\XINT_min_zerozero #1#2#3#4{\xint_firstoftwo_thenstop }% +\def\XINT_min_zeroplus #1#2#3#4{\xint_secondoftwo_thenstop }% +\def\XINT_min_pluszero #1#2#3#4{\xint_firstoftwo_thenstop }% +\def\XINT_min_minusplus #1#2#3#4{\xint_secondoftwo_thenstop }% +\def\XINT_min_plusminus #1#2#3#4{\xint_firstoftwo_thenstop }% +\def\XINT_min_plusplus #1#2#3#4% +{% + \ifodd\XINT_Geq {#4#2}{#3#1} + \expandafter\xint_secondoftwo_thenstop + \else + \expandafter\xint_firstoftwo_thenstop + \fi +}% +% \end{macrocode} +% \lverb+#3=-, #4=-, #1 = |B| = -B, #2 = |A| = -A+ +% \begin{macrocode} +\def\XINT_min_minusminus #1#2#3#4% +{% + \ifodd\XINT_Geq {#1}{#2} + \expandafter\xint_secondoftwo_thenstop + \else + \expandafter\xint_firstoftwo_thenstop + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintMinof}} +% \lverb|1.09a| +% \begin{macrocode} +\def\xintiMinof {\romannumeral0\xintiminof }% +\def\xintiminof #1{\expandafter\XINT_iminof_a\romannumeral-`0#1\relax }% +\def\XINT_iminof_a #1{\expandafter\XINT_iminof_b\romannumeral0\xintnum{#1}\Z }% +\def\XINT_iminof_b #1\Z #2% + {\expandafter\XINT_iminof_c\romannumeral-`0#2\Z {#1}\Z}% +\def\XINT_iminof_c #1% + {\xint_gob_til_relax #1\XINT_iminof_e\relax\XINT_iminof_d #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{xintSum}} +% \lverb|& +% \xintSum {{a}{b}...{z}}$\ +% \xintSumExpr {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 +% \z expands to a list of braced terms (prior only \xintSum {\z} or \xintSum \z +% was possible). +% +% 1.09a does NOT add the \xintnum overhead. 1.09h renames \xintiSum to +% \xintiiSum to correctly reflect this.| +% \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}}% +% \end{macrocode} +% \subsection{\csh{xintMul}} +% \lverb|1.09a adds \xintnum| +% \begin{macrocode} +\def\xintiiMul {\romannumeral0\xintiimul }% +\def\xintiimul #1% +{% + \expandafter\xint_iimul\expandafter {\romannumeral-`0#1}% +}% +\def\xint_iimul #1#2% +{% + \expandafter\XINT_mul_fork \romannumeral-`0#2\Z #1\Z +}% +\def\xintiMul {\romannumeral0\xintimul }% +\def\xintimul #1% +{% + \expandafter\xint_mul\expandafter {\romannumeral0\xintnum{#1}}% +}% +\def\xint_mul #1#2% +{% + \expandafter\XINT_mul_fork \romannumeral0\xintnum{#2}\Z #1\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 +{% + \xint_UDzerofork + #1\XINT_mul_zero + #3\XINT_mul_zero + 0{\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 }% + \krof + {#2}{#4}% +}% +\def\XINT_mul_zero #1#2{ 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 +}% +\def\XINT_mul_choice_compare #1#2% +{% + \ifnum #1>#2 + \expandafter \XINT_mul_choice_i + \else + \expandafter \XINT_mul_choice_ii + \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} +% \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.| +% \begin{macrocode} +\def\XINT_mul_Mr #1% +{% + \expandafter\XINT_mul_Mr_checkifzeroorone\expandafter{\the\numexpr #1}% +}% +\def\XINT_mul_Mr_checkifzeroorone #1% +{% + \ifcase #1 + \expandafter\XINT_mul_Mr_zero + \or + \expandafter\XINT_mul_Mr_one + \else + \expandafter\XINT_mul_Nr + \fi + {0000}{}{#1}% +}% +\def\XINT_mul_Mr_zero #1\Z\Z\Z\Z { 0000}% +\def\XINT_mul_Mr_one #1#2#3#4\Z\Z\Z\Z { #4}% +\def\XINT_mul_Nr #1#2#3#4#5#6#7% +{% + \xint_gob_til_Z #4\xint_mul_pr\Z\XINT_mul_Pr {#1}{#3}{#7#6#5#4}{#2}{#3}% +}% +\def\XINT_mul_Pr #1#2#3% +{% + \expandafter\XINT_mul_Lr\the\numexpr \xint_c_x^viii+#1+#2*#3\relax +}% +\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}% +% \end{macrocode} +% \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*. | +% \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} +% \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% +{% + \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 +}% +\def\XINT_mul_compute #1#2#3\Z\Z\Z\Z +{% + \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 +}% +% \end{macrocode} +% \lverb|& +% Ici, le deuxième nombre se termine. Fin du calcul. On utilise la variante +% \XINT_addm_A de l'addition car on sait que le deuxième terme est au moins +% aussi long que le premier. Lorsque le multiplicateur avait longueur 4n, la +% dernière addition a fourni le résultat à l'envers, il faut donc encore le +% renverser. | +% \begin{macrocode} +\def\XINT_mul_finish_a\W\XINT_mul_compute #1% +{% + \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 +{% + \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 +}% +\def\XINT_mul_finish_cii + \W\XINT_mul_finish_ciii #1\W\W #2#3\Z\Z\Z\Z \W\W +{% + \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 +}% +\def\XINT_mul_finish_ci #1\XINT_mul_finish_ciii #2\W\W\W #3#4\Z\Z\Z\Z \W +{% + \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}% +}% +% \end{macrocode} +% \lverb|& +% Variante de la Multiplication$\ +% \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.| +% \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% +{% + \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% +}% +\def\XINT_mulr_finish_ciii #1\W #2#3\Z\Z\Z\Z \W\W\W +{% + \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 +}% +\def\XINT_mulr_finish_cii + \W\XINT_mulr_finish_ciii #1\W\W #2#3\Z\Z\Z\Z \W\W +{% + \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 +}% +\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_mulr_finish_c #1\XINT_mulr_finish_ciii \W\W\W\W #2#3\Z\Z\Z\Z { #2}% +% \end{macrocode} +% \subsection{\csh{xintSqr}} +% \begin{macrocode} +\def\xintiiSqr {\romannumeral0\xintiisqr }% +\def\xintiisqr #1% +{% + \expandafter\XINT_sqr\expandafter {\romannumeral0\xintiiabs{#1}}% +}% +\def\xintiSqr {\romannumeral0\xintisqr }% +\def\xintisqr #1% +{% + \expandafter\XINT_sqr\expandafter {\romannumeral0\xintiabs{#1}}% +}% +\let\xintSqr\xintiSqr \let\xintsqr\xintisqr +\def\XINT_sqr #1% +{% + \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 +}% +% \end{macrocode} +% \subsection{\csh{xintPrd}} +% \lverb|& +% \xintPrd {{a}...{z}}$\ +% \xintPrdExpr {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 +% 1.02 version was changed to be more efficient on big products, where the new +% term is small compared to what has been computed so far (the power algorithm +% now has its own product routine). +% +% Finally, the 1.03 version just simplifies everything as the multiplication now +% decides what is best, with the price of a little overhead. So the code has +% been dramatically reduced here. +% +% In 1.03 I also modify the way \xintPrd and \xintPrdExpr ...\relax are +% related. Now \xintPrdExpr \z \relax is accepted input when \z expands +% to a list of braced terms (prior only \xintPrd {\z} or \xintPrd \z was +% possible). +% +% In 1.06a I suddenly decide that \xintProductExpr was a silly name, and as the +% package is new and certainly not used, I decide I may just switch to +% \xintPrdExpr which I should have used from the beginning. +% +% 1.09a does NOT add the \xintnum overhead. 1.09h renames \xintiPrd to +% \xintiiPrd to correctly reflect this.| +% \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}% +\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 +}% +% \end{macrocode} +% \subsection{\csh{xintPow}} +% \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).| +% \begin{macrocode} +\def\xintiiPow {\romannumeral0\xintiipow }% +\def\xintiipow #1% +{% + \expandafter\xint_pow\romannumeral-`0#1\Z% +}% +\def\xintiPow {\romannumeral0\xintipow }% +\def\xintipow #1% +{% + \expandafter\xint_pow\romannumeral0\xintnum{#1}\Z% +}% +\let\xintPow\xintiPow \let\xintpow\xintipow +\def\xint_pow #1#2\Z +{% + \xint_UDsignfork + #1\XINT_pow_Aneg + -\XINT_pow_Anonneg + \krof + #1{#2}% +}% +\def\XINT_pow_Aneg #1#2#3% +{% + \expandafter\XINT_pow_Aneg_\expandafter{\the\numexpr #3}{#2}% +}% +\def\XINT_pow_Aneg_ #1% +{% + \ifodd #1 + \expandafter\XINT_pow_Aneg_Bodd + \fi + \XINT_pow_Anonneg_ {#1}% +}% +\def\XINT_pow_Aneg_Bodd #1% +{% + \expandafter\XINT_opp\romannumeral0\XINT_pow_Anonneg_ +}% +% \end{macrocode} +% \lverb|B = #3, faire le xpxp. Modified with 1.06: use of \numexpr.| +% \begin{macrocode} +\def\XINT_pow_Anonneg #1#2#3% +{% + \expandafter\XINT_pow_Anonneg_\expandafter {\the\numexpr #3}{#1#2}% +}% +% \end{macrocode} +% \lverb+#1 = B, #2 = |A|+ +% \begin{macrocode} +\def\XINT_pow_Anonneg_ #1#2% +{% + \ifcase\XINT_Cmp {#2}{1} + \expandafter\XINT_pow_AisOne + \or + \expandafter\XINT_pow_AatleastTwo + \else + \expandafter\XINT_pow_AisZero + \fi + {#1}{#2}% +}% +\def\XINT_pow_AisOne #1#2{ 1}% +% \end{macrocode} +% \lverb|#1 = B| +% \begin{macrocode} +\def\XINT_pow_AisZero #1#2% +{% + \ifcase\XINT_cntSgn #1\Z + \xint_afterfi { 1}% + \or + \xint_afterfi { 0}% + \else + \xint_afterfi {\xintError:DivisionByZero\space 0}% + \fi +}% +\def\XINT_pow_AatleastTwo #1% +{% + \ifcase\XINT_cntSgn #1\Z + \expandafter\XINT_pow_BisZero + \or + \expandafter\XINT_pow_checkBsize + \else + \expandafter\XINT_pow_BisNegative + \fi + {#1}% +}% +\edef\XINT_pow_BisNegative #1#2% + {\noexpand\xintError:FractionRoundedToZero\space 0}% +\def\XINT_pow_BisZero #1#2{ 1}% +% \end{macrocode} +% \lverb|B = #1 > 0, A = #2 > 1. 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 + \else + \expandafter\XINT_pow_loopI + \fi + {#1}% +}% +\edef\XINT_pow_BtooBig #1#2{\noexpand\xintError:ExponentTooBig\space 0}% +\def\XINT_pow_loopI #1% +{% + \ifnum #1=\xint_c_i\XINT_pow_Iend\fi + \ifodd #1 + \expandafter\XINT_pow_loopI_odd + \else + \expandafter\XINT_pow_loopI_even + \fi + {#1}% +}% +\edef\XINT_pow_Iend\fi #1\fi #2#3{\noexpand\fi\space #3}% +\def\XINT_pow_loopI_even #1#2% +{% + \expandafter\XINT_pow_loopI\expandafter + {\the\numexpr #1/\xint_c_ii\expandafter}\expandafter + {\romannumeral0\xintiisqr {#2}}% +}% +\def\XINT_pow_loopI_odd #1#2% +{% + \expandafter\XINT_pow_loopI_odda\expandafter + {\romannumeral0\XINT_RQ {}#2\R\R\R\R\R\R\R\R\Z }{#1}{#2}% +}% +\def\XINT_pow_loopI_odda #1#2#3% +{% + \expandafter\XINT_pow_loopII\expandafter + {\the\numexpr #2/\xint_c_ii-\xint_c_i\expandafter}\expandafter + {\romannumeral0\xintiisqr {#3}}{#1}% +}% +\def\XINT_pow_loopII #1% +{% + \ifnum #1 = \xint_c_i\XINT_pow_IIend\fi + \ifodd #1 + \expandafter\XINT_pow_loopII_odd + \else + \expandafter\XINT_pow_loopII_even + \fi + {#1}% +}% +\def\XINT_pow_loopII_even #1#2% +{% + \expandafter\XINT_pow_loopII\expandafter + {\the\numexpr #1/\xint_c_ii\expandafter}\expandafter + {\romannumeral0\xintiisqr {#2}}% +}% +\def\XINT_pow_loopII_odd #1#2#3% +{% + \expandafter\XINT_pow_loopII_odda\expandafter + {\romannumeral0\XINT_mulr_enter #3\Z\Z\Z\Z #2\W\W\W\W}{#1}{#2}% +}% +\def\XINT_pow_loopII_odda #1#2#3% +{% + \expandafter\XINT_pow_loopII\expandafter + {\the\numexpr #2/\xint_c_ii-\xint_c_i\expandafter}\expandafter + {\romannumeral0\xintiisqr {#3}}{#1}% +}% +\def\XINT_pow_IIend\fi #1\fi #2#3#4% +{% + \fi\XINT_mul_enter #4\Z\Z\Z\Z #3\W\W\W\W +}% +% \end{macrocode} +% \subsection{\csh{xintDivision}, \csh{xintQuo}, \csh{xintRem}} +% \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 \xintDivision, like all other routines in xint (except +% \xintSeq without optional parameter) still does not impact the input save +% stack. One can have a produced quotient longer than 4x5000=20000 digits, and +% no need to worry about \xintTrunc, \xintRound, \xintFloat, \xintFloatSqrt, +% etc... and all other places using the division. +% +% However outputting to a file (which is basically the only thing one can do, +% multiplying out two 20000 digits numbers already takes hours, for 100000 it +% would be days if not weeks) 100000 digits is slow... the truncation routine +% will add 100000 zeros (circa) and then trim them four by four. Definitely I +% should do a routine XTrunc which will work by blocks of say 64, and +% furthermore, being destined to be used in and \edef or a \write, it could be +% much more efficient as it could simply be based on tail loop, which so far +% nothing in xint does because I want things to expand fully under +% \romannumeral-`0 (and don't imagine inserting chains of thousands of +% \expandafter's...) in order to be nestable. Inside \xintexpr such style of +% tail recursion leaving downstream things should definitely be implemented for +% the routines for which it is possible as things get expanded inside +% \csname..\endcsname. I don't do yet anything like this for 1.09j. | +% \begin{macrocode} +\def\xintiiQuo {\romannumeral0\xintiiquo }% +\def\xintiiRem {\romannumeral0\xintiirem }% +\def\xintiiquo {\expandafter\xint_firstoftwo_thenstop + \romannumeral0\xintiidivision }% +\def\xintiirem {\expandafter\xint_secondoftwo_thenstop + \romannumeral0\xintiidivision }% +\def\xintQuo {\romannumeral0\xintquo }% +\def\xintRem {\romannumeral0\xintrem }% +\def\xintquo {\expandafter\xint_firstoftwo_thenstop + \romannumeral0\xintdivision }% +\def\xintrem {\expandafter\xint_secondoftwo_thenstop + \romannumeral0\xintdivision }% +% \end{macrocode} +% \lverb|#1 = A, #2 = B. On calcule le quotient et le reste dans la division +% euclidienne de A par B.| +% \begin{macrocode} +\def\xintiiDivision {\romannumeral0\xintiidivision }% +\def\xintiidivision #1% +{% + \expandafter\xint_iidivision\expandafter {\romannumeral-`0#1}% +}% +\def\xint_iidivision #1#2% +{% + \expandafter\XINT_div_fork \romannumeral-`0#2\Z #1\Z +}% +\def\xintDivision {\romannumeral0\xintdivision }% +\def\xintdivision #1% +{% + \expandafter\xint_division\expandafter {\romannumeral0\xintnum{#1}}% +}% +\def\xint_division #1#2% +{% + \expandafter\XINT_div_fork \romannumeral0\xintnum{#2}\Z #1\Z +}% +% \end{macrocode} +% \lverb|#1#2 = 2e input = diviseur = B. +% #3#4 = 1er input = divisé = A.| +% \begin{macrocode} +\def\XINT_div_fork #1#2\Z #3#4\Z +{% + \xint_UDzerofork + #1\XINT_div_BisZero + #3\XINT_div_AisZero + 0{\xint_UDsignfork + #1\XINT_div_BisNegative % B < 0 + #3\XINT_div_AisNegative % A < 0, B > 0 + -\XINT_div_plusplus % B > 0, A > 0 + \krof }% + \krof + {#2}{#4}#1#3% #1#2=B, #3#4=A +}% +\edef\XINT_div_BisZero #1#2#3#4{\noexpand\xintError:DivisionByZero\space {0}{0}}% +\def\XINT_div_AisZero #1#2#3#4{ {0}{0}}% +% \end{macrocode} +% \lverb|& +% jusqu'à présent c'est facile.$\ +% minusplus signifie B < 0, A > 0$\ +% plusminus signifie B > 0, A < 0$\ +% Ici #3#1 correspond au diviseur B et #4#2 au divisé A. +% +% Cases with B<0 or especially A<0 are treated sub-optimally in terms of +% post-processing, things get reversed which could have been produced directly +% in the wanted order, but A,B>0 is given priority for optimization. I should +% revise the next few macros, definitely.| +% \begin{macrocode} +\def\XINT_div_plusplus #1#2#3#4{\XINT_div_prepare {#3#1}{#4#2}}% +% \end{macrocode} +% \lverb|B = #3#1 < 0, A non nul positif ou négatif| +% \begin{macrocode} +\def\XINT_div_BisNegative #1#2#3#4% +{% + \expandafter\XINT_div_BisNegative_b + \romannumeral0\XINT_div_fork #1\Z #4#2\Z +}% +\edef\XINT_div_BisNegative_b #1% +{% + \noexpand\expandafter\space\noexpand\expandafter + {\noexpand\romannumeral0\noexpand\XINT_opp #1}% +}% +% \end{macrocode} +% \lverb|B = #3#1 > 0, A =-#2< 0| +% \begin{macrocode} +\def\XINT_div_AisNegative #1#2#3#4% +{% + \expandafter\XINT_div_AisNegative_b + \romannumeral0\XINT_div_prepare {#3#1}{#2}{#3#1}% +}% +\def\XINT_div_AisNegative_b #1#2% +{% + \if0\XINT_Sgn #2\Z + \expandafter \XINT_div_AisNegative_Rzero + \else + \expandafter \XINT_div_AisNegative_Rpositive + \fi + {#1}{#2}% +}% +% \end{macrocode} +% \lverb|en #3 on a une copie de B (à l'endroit)| +% \begin{macrocode} +\edef\XINT_div_AisNegative_Rzero #1#2#3% +{% + \noexpand\expandafter\space\noexpand\expandafter + {\noexpand\romannumeral0\noexpand\XINT_opp #1}{0}% +}% +% \end{macrocode} +% \lverb!#1 = quotient, #2 = reste, #3 = diviseur initial (à l'endroit) +% remplace Reste par B - Reste, après avoir remplacé Q par -(Q+1) +% de sorte que la formule a = qb + r, 0<= r < |b| est valable! +% \begin{macrocode} +\def\XINT_div_AisNegative_Rpositive #1% +{% + \expandafter \XINT_div_AisNegative_Rpositive_b \expandafter + {\romannumeral0\xintiiopp{\xintInc {#1}}}% +}% +\def\XINT_div_AisNegative_Rpositive_b #1#2#3% +{% + \expandafter \xint_exchangetwo_keepbraces_thenstop \expandafter + {\romannumeral0\XINT_sub {#3}{#2}}{#1}% +}% +% \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 +}% +\def\XINT_div_prepareB_aa #1% +{% + \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}% +}% +% \end{macrocode} +% \lverb|B=1 and B=2 treated specially.| +% \begin{macrocode} +\def\XINT_div_prepareB_onedigit #1#2% +{% + \ifcase#2 + \or\expandafter\XINT_div_BisOne + \or\expandafter\XINT_div_BisTwo + \else\expandafter\XINT_div_prepareB_e + \fi {000}{0}{4}{#2}% +}% +\def\XINT_div_BisOne #1#2#3#4#5{ {#5}{0}}% +\def\XINT_div_BisTwo #1#2#3#4#5% +{% + \expandafter\expandafter\expandafter\XINT_div_BisTwo_a + \ifodd\xintiiLDg{#5} \expandafter1\else \expandafter0\fi {#5}% +}% +\edef\XINT_div_BisTwo_a #1#2% +{% + \noexpand\expandafter\space\noexpand\expandafter + {\noexpand\romannumeral0\noexpand\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% +{% + \csname XINT_div_prepareB_d\romannumeral\numexpr#1-#2\endcsname + {#1}% +}% +\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% +{% + \ifnum#3=\xint_c_iv\expandafter\XINT_div_prepareLittleB_f + \else\expandafter\XINT_div_prepareB_f + \fi + #4#1{#3}{#2}{#1}% +}% +% \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_prepareLittleB_f #1#{% + \expandafter\XINT_div_prepareB_g \the\numexpr #1/\xint_c_ii.{}.{}.{#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% +{% + \XINT_div_prepareA_a {#8#7}{#5}{{#1}{#2}{#4}}{#3}{#6}% +}% +% \end{macrocode} +% \lverb|A, K, {x'yx}, B«c» | +% \begin{macrocode} +\def\XINT_div_prepareA_a #1% +{% + \expandafter\XINT_div_prepareA_b\expandafter + {\romannumeral0\xintlength {#1}}{#1}% +}% +% \end{macrocode} +% \lverb|L0, A, K, {x'yx}, B«c»| +% \begin{macrocode} +\def\XINT_div_prepareA_b #1% +{% + \expandafter\XINT_div_prepareA_c\expandafter + {\the\numexpr \xint_c_iv*((#1+\xint_c_i)/\xint_c_iv)}{#1}% +}% +% \end{macrocode} +% \lverb|L, L0, A, K, {x'yx}, B, «c»| +% \begin{macrocode} +\def\XINT_div_prepareA_c #1#2% +{% + \csname XINT_div_prepareA_d\romannumeral\numexpr #1-#2\endcsname + {#1}% +}% +\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% +{% + \XINT_div_start_a {#2}{#4}{#1#3}#5% +}% +% \end{macrocode} +% \lverb|L, K, A, x',y,x, B, «c» (avec y{}x{} au lieu de x'yxB dans la +% variante little)| +% \begin{macrocode} +\def\XINT_div_start_a #1#2% +{% + \ifnum #2=\xint_c_iv \expandafter\XINT_div_little_b + \else + \ifnum #1 < #2 + \expandafter\expandafter\expandafter\XINT_div_III_aa + \else + \expandafter\expandafter\expandafter\XINT_div_start_b + \fi + \fi + {#1}{#2}% +}% +% \end{macrocode} +% \lverb|L, K, A, x',y,x, B, «c».| +% \begin{macrocode} +\def\XINT_div_III_aa #1#2#3#4#5#6#7% +{% + \expandafter\expandafter\expandafter + \XINT_div_III_b\xint_cleanupzeros_nostop #3.{0000}% +}% +% \end{macrocode} +% \lverb|R.Q«c».| +% \begin{macrocode} +\def\XINT_div_III_b #1% +{% + \if0#1% + \expandafter\XINT_div_III_bRzero + \else + \expandafter\XINT_div_III_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}% +}% +% \end{macrocode} +% \lverb|L, K, A, x',y,x, B, «c»->K.A.x{LK{x'y}x}B«c»| +% \begin{macrocode} +\def\XINT_div_start_b #1#2#3#4#5#6% +{% + \XINT_div_start_c {#2}.#3.{#6}{{#1}{#2}{{#4}{#5}}{#6}}% +}% +% \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% +{% + \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}% +% \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.| +% \begin{macrocode} +\def\XINT_div_start_d #1#2.#3.#4#5#6% +{% + \XINT_div_I_a {#1}{#4}{#2}{#6}{0000}#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» | +% \begin{macrocode} +\def\XINT_div_I_a #1#2% +{% + \expandafter\XINT_div_I_b\the\numexpr #1/#2.{#1}{#2}% +}% +\def\XINT_div_I_b #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»| +% \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_c #1.#2#3% +{% + \expandafter\XINT_div_I_da\the\numexpr #2-#1*#3.#1.% +}% +% \end{macrocode} +% \lverb|r.q.alpha, B, q0, L, K, {x'y}, x, alpha', BQ«c»| +% \begin{macrocode} +\def\XINT_div_I_da #1.% +{% + \ifnum #1>\xint_c_ix + \expandafter\XINT_div_I_dP + \else + \ifnum #1<\xint_c_ + \expandafter\expandafter\expandafter\XINT_div_I_dN + \else + \expandafter\expandafter\expandafter\XINT_div_I_db + \fi + \fi +}% +\def\XINT_div_I_dN #1.% +{% + \expandafter\XINT_div_I_dP\the\numexpr #1-\xint_c_i.% +}% +\def\XINT_div_I_db #1.#2#3% #1=q=un chiffre, #2=alpha, #3=B +{% + \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}% +}% +\def\XINT_div_I_dc #1#2% +{% + \if-#1% s'arranger pour que si négatif on ait renvoyé 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}% +}% +% \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% +{% + \expandafter\XINT_div_I_f \the\numexpr \xint_c_x^iv+#2+#5{#1}% +}% +% \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»| +% \begin{macrocode} +\def\XINT_div_I_dP #1.#2#3#4% +{% + \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 }}% +}% +% \end{macrocode} +% \lverb|1#1#2#3#4=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»| +% \begin{macrocode} +\def\XINT_div_I_g #1#2#3#4#5#6#7#8#9% +{% + \ifnum#3=#4 + \expandafter\XINT_div_III_ab + \else + \expandafter\XINT_div_I_h + \fi + {#5}#2.#7.{{#5}{#6}{#4}{#3}}{#8}{#9#1}% +}% +% \end{macrocode} +% \lverb|{x'y}alpha.alpha'.{{x'y}xKL}B{Qq}«c» -> R sans leading zeros.{Qq}«c»| +% \begin{macrocode} +\def\XINT_div_III_ab #1#2.#3.#4#5% +{% + \expandafter\XINT_div_III_b + \romannumeral0\XINT_cuz_loop #2#3\W\W\W\W\W\W\W\Z.% +}% +% \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»| +% \begin{macrocode} +\def\XINT_div_I_h #1.#2#3#4#5#6.#7#8% +{% + \XINT_div_II_b #1#2#3#4#5.{#8}{#7}{#6}{#8}% +}% +% \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 | +% \begin{macrocode} +\def\XINT_div_II_b #1#2#3#4#5#6#7#8#9% +{% + \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}% +}% +% \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»| +% \begin{macrocode} +\def\XINT_div_II_skipc 0000\XINT_div_II_c #1#2#3#4#5.#6#7% +{% + \XINT_div_II_k #7{#4#5}{#6}{0000}% +}% +% \end{macrocode} +% \lverb|x'ya->1qx'yalpha.B, {{x'y},x,K,L}, nouveau alpha',B, Q«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% +}% +% \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» | +% \begin{macrocode} +\def\XINT_div_II_d 1#1#2#3#4#5#6#7.#8% +{% + \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}% +}% +% \end{macrocode} +% \lverb|alpha.x',y,B,q1, {{x'y},x,K,L}, alpha', B, Q«c»| +% \begin{macrocode} +\def\XINT_div_II_e #1#2#3#4% +{% + \xint_gob_til_zeros_iv #1#2#3#4\XINT_div_II_skipf 0000% + \XINT_div_II_f #1#2#3#4% +}% +% \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»| +% \begin{macrocode} +\def\XINT_div_II_skipf 0000\XINT_div_II_f 0000#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»| +% \begin{macrocode} +\def\XINT_div_II_f #1#2#3#4#5#6#7#8#9.% +{% + \XINT_div_II_fa {#1#2#3#4#5#6#7#8}{#1#2#3#4#5#6#7#8#9}% +}% +\def\XINT_div_II_fa #1#2#3#4% +{% + \expandafter\XINT_div_II_g\expandafter + {\the\numexpr (#1+#4)/#3-\xint_c_i}{#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» | +% \begin{macrocode} +\def\XINT_div_II_g #1#2#3#4% +{% + \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}% +}% +% \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»| +% \begin{macrocode} +\def\XINT_div_II_h 1#1#2#3#4#5#6#7% +{% + \XINT_div_II_k #7{#5}{#6}{#1#2#3#4}% +}% +% \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»| +% \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.% +}% +\def\XINT_div_II_l #1.#2#3#4#5#6#7#8#9% +{% + \XINT_div_II_m {{#1}{#2}{{#3}{#4}}{#5}}{#5}{#6#7#8#9}#6#7#8#9% +}% +% \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» | +% \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| +% \begin{macrocode} +\def\XINT_div_little_b #1#2#3#4#5#6#7% +{% + \XINT_div_little_c #3.{{#4}{#6}}{#1}% +}% +% \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% +{% + \XINT_div_littleI_a {#1#2#3#4}#6{#7}{#5}% +}% +% \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.| +% \begin{macrocode} +\def\XINT_div_littleI_a #1#2#3% +{% + \expandafter\XINT_div_littleI_b + \the\numexpr (#1+#2)/#3-\xint_c_i{#1}{#2}{#3}% +}% +% \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».| +% \begin{macrocode} +\def\XINT_div_littleI_b #1% +{% + \xint_gob_til_zero #1\XINT_div_littleI_skip 0\XINT_div_littleI_c #1% +}% +\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% +{% + \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}}% +}% +% \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% +{% + \ifnum#1=\xint_c_iv + \expandafter\XINT_div_littleIII_ab + \else + \expandafter\XINT_div_littleII_b + \fi {#1}% +}% +% \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% +{% + \expandafter\XINT_div_III_b\the\numexpr #2#3.% +}% +% \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% +{% + \expandafter\XINT_div_littleII_c\expandafter {\the\numexpr #1-\xint_c_iv}% +}% +% \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% +{% + \XINT_div_littleII_d {#2#3#4#5#6}#8{#1}{#7}% +}% +\def\XINT_div_littleII_d #1#2#3% +{% + \expandafter\XINT_div_littleII_e\the\numexpr (#1+#2)/#3+\xint_c_ixixixix.% + {#1}{#2}{#3}% +}% +% \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% +{% + \expandafter\expandafter\expandafter\XINT_div_littleII_f + \expandafter\xint_gobble_i\the\numexpr \xint_c_x^iv+#2-#1*#4.% + {#1}{{#3}{#4}}% +}% +% \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% +{% + \XINT_div_littleII_a {#4}{#1}#5.{#3}{#6#2}% +}% +% \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éjà renversé, #2 se développe en qB +{% + \expandafter\XINT_div_sub_xpxp_b #2\W\X\Y\Z #1\W\X\Y\Z +}% +\def\XINT_div_sub_xpxp_b +{% + \XINT_div_sub_A 1{}% +}% +\def\XINT_div_sub_A #1#2#3#4#5#6% +{% + \xint_gob_til_W #3\xint_div_sub_az\W + \XINT_div_sub_B #1{#3#4#5#6}{#2}% +}% +\def\XINT_div_sub_B #1#2#3#4\W\X\Y\Z #5#6#7#8% +{% + \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 +}% +\def\XINT_div_sub_onestep #1#2#3#4#5#6% +{% + \expandafter\XINT_div_sub_backtoA + \the\numexpr 11#6-#5#4#3#2+#1-\xint_c_i.% +}% +\def\XINT_div_sub_backtoA #1#2#3.#4% +{% + \XINT_div_sub_A #2{#3#4}% +}% +% \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% +{% + \xint_gob_til_W #3\xint_div_sub_cz\W + \XINT_div_sub_C_onestep #1{#6#5#4#3}{#2}% +}% +\def\XINT_div_sub_C_onestep #1#2% +{% + \expandafter\XINT_div_sub_backtoC \the\numexpr 11#2+#1-\xint_c_i.% +}% +\def\XINT_div_sub_backtoC #1#2#3.#4% +{% + \XINT_div_sub_C #2{#3#4}% +}% +% \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 -| +% \begin{macrocode} +\def\xint_div_sub_cz\W\XINT_div_sub_C_onestep #1#2% +{% + \if#10% retenue + \expandafter\xint_div_sub_neg + \else\expandafter\xint_div_sub_ok + \fi +}% +\def\xint_div_sub_neg #1{ -}% +\def\xint_div_sub_ok #1{ #1}% +% \end{macrocode} +% \lverb|& +% & +% -----------------------------------------------------------------$\ +% -----------------------------------------------------------------$\ +% DECIMAL OPERATIONS: FIRST DIGIT, LASTDIGIT, ODDNESS, +% MULTIPLICATION BY TEN, QUOTIENT BY TEN, QUOTIENT OR +% MULTIPLICATION BY POWER OF TEN, SPLIT OPERATION.| +% \subsection{\csh{xintFDg}} +% \lverb|& +% FIRST DIGIT. Code simplified in 1.05. +% And prepared for redefinition by xintfrac to parse through \xintNum. Version +% 1.09a inserts the \xintnum already here.| +% \begin{macrocode} +\def\xintiiFDg {\romannumeral0\xintiifdg }% +\def\xintiifdg #1% +{% + \expandafter\XINT_fdg \romannumeral-`0#1\W\Z +}% +\def\xintFDg {\romannumeral0\xintfdg }% +\def\xintfdg #1% +{% + \expandafter\XINT_fdg \romannumeral0\xintnum{#1}\W\Z +}% +\def\XINT_FDg #1{\romannumeral0\XINT_fdg #1\W\Z }% +\def\XINT_fdg #1#2#3\Z +{% + \xint_UDzerominusfork + #1-{ 0}% zero + 0#1{ #2}% negative + 0-{ #1}% positive + \krof +}% +% \end{macrocode} +% \subsection{\csh{xintLDg}} +% \lverb|& +% LAST DIGIT. Simplified in 1.05. And prepared for extension by xintfrac +% to parse through \xintNum. Release 1.09a adds the \xintnum already here, +% and this propagates to \xintOdd, etc... 1.09e The \xintiiLDg is for +% defining \xintiiOdd which is used once (currently) elsewhere .| +% \begin{macrocode} +\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 +}% +\def\XINT_ldg_ #1#2\Z{ #1}% +% \end{macrocode} +% \subsection{\csh{xintMON}, \csh{xintMMON}} +% \lverb|& +% MINUS ONE TO THE POWER N and (-1)^{N-1}| +% \begin{macrocode} +\def\xintiiMON {\romannumeral0\xintiimon }% +\def\xintiimon #1% +{% + \ifodd\xintiiLDg {#1} + \xint_afterfi{ -1}% + \else + \xint_afterfi{ 1}% + \fi +}% +\def\xintiiMMON {\romannumeral0\xintiimmon }% +\def\xintiimmon #1% +{% + \ifodd\xintiiLDg {#1} + \xint_afterfi{ 1}% + \else + \xint_afterfi{ -1}% + \fi +}% +\def\xintMON {\romannumeral0\xintmon }% +\def\xintmon #1% +{% + \ifodd\xintLDg {#1} + \xint_afterfi{ -1}% + \else + \xint_afterfi{ 1}% + \fi +}% +\def\xintMMON {\romannumeral0\xintmmon }% +\def\xintmmon #1% +{% + \ifodd\xintLDg {#1} + \xint_afterfi{ 1}% + \else + \xint_afterfi{ -1}% + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintOdd}} +% \lverb|1.05 has \xintiOdd, whereas \xintOdd parses through \xintNum. +% Inadvertently, 1.09a redefined \xintiLDg so \xintiOdd also parsed through +% \xintNum. Anyway, having a \xintOdd and a \xintiOdd was silly. Removed in +% 1.09f | +% \begin{macrocode} +\def\xintiiOdd {\romannumeral0\xintiiodd }% +\def\xintiiodd #1% +{% + \ifodd\xintiiLDg{#1} + \xint_afterfi{ 1}% + \else + \xint_afterfi{ 0}% + \fi +}% +\def\xintOdd {\romannumeral0\xintodd }% +\def\xintodd #1% +{% + \ifodd\xintLDg{#1} + \xint_afterfi{ 1}% + \else + \xint_afterfi{ 0}% + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintDSL}} +% \lverb|& +% DECIMAL SHIFT LEFT (=MULTIPLICATION PAR 10)| +% \begin{macrocode} +\def\xintDSL {\romannumeral0\xintdsl }% +\def\xintdsl #1% +{% + \expandafter\XINT_dsl \romannumeral-`0#1\Z +}% +\def\XINT_DSL #1{\romannumeral0\XINT_dsl #1\Z }% +\def\XINT_dsl #1% +{% + \xint_gob_til_zero #1\xint_dsl_zero 0\XINT_dsl_ #1% +}% +\def\xint_dsl_zero 0\XINT_dsl_ 0#1\Z { 0}% +\def\XINT_dsl_ #1\Z { #10}% +% \end{macrocode} +% \subsection{\csh{xintDSR}} +% \lverb|& +% DECIMAL SHIFT RIGHT (=DIVISION PAR 10). Release 1.06b which replaced all @'s +% by +% underscores left undefined the \xint_minus used in \XINT_dsr_b, and this bug +% was fixed only later in release 1.09b| +% \begin{macrocode} +\def\xintDSR {\romannumeral0\xintdsr }% +\def\xintdsr #1% +{% + \expandafter\XINT_dsr_a\expandafter {\romannumeral-`0#1}\W\Z +}% +\def\XINT_DSR #1{\romannumeral0\XINT_dsr_a {#1}\W\Z }% +\def\XINT_dsr_a +{% + \expandafter\XINT_dsr_b\romannumeral0\xintreverseorder +}% +\def\XINT_dsr_b #1#2#3\Z +{% + \xint_gob_til_W #2\xint_dsr_onedigit\W + \xint_gob_til_minus #2\xint_dsr_onedigit-% + \expandafter\XINT_dsr_removew + \romannumeral0\xintreverseorder {#2#3}% +}% +\def\xint_dsr_onedigit #1\xintreverseorder #2{ 0}% +\def\XINT_dsr_removew #1\W { }% +% \end{macrocode} +% \subsection{\csh{xintDSH}, \csh{xintDSHr}} +% \lverb+DECIMAL SHIFTS \xintDSH {x}{A}$\ +% si x <= 0, fait A -> A.10^(|x|). v1.03 corrige l'oversight pour A=0.$\ +% si x > 0, et A >=0, fait A -> quo(A,10^(x))$\ +% si x > 0, et A < 0, fait A -> -quo(-A,10^(x))$\ +% (donc pour x > 0 c'est comme DSR itéré x fois)$\ +% \xintDSHr donne le `reste' (si x<=0 donne zéro). +% +% Release 1.06 now feeds x to a \numexpr first. I will have to revise this code +% at some point.+ +% \begin{macrocode} +\def\xintDSHr {\romannumeral0\xintdshr }% +\def\xintdshr #1% +{% + \expandafter\XINT_dshr_checkxpositive \the\numexpr #1\relax\Z +}% +\def\XINT_dshr_checkxpositive #1% +{% + \xint_UDzerominusfork + 0#1\XINT_dshr_xzeroorneg + #1-\XINT_dshr_xzeroorneg + 0-\XINT_dshr_xpositive + \krof #1% +}% +\def\XINT_dshr_xzeroorneg #1\Z #2{ 0}% +\def\XINT_dshr_xpositive #1\Z +{% + \expandafter\xint_secondoftwo_thenstop\romannumeral0\xintdsx {#1}% +}% +\def\xintDSH {\romannumeral0\xintdsh }% +\def\xintdsh #1#2% +{% + \expandafter\xint_dsh\expandafter {\romannumeral-`0#2}{#1}% +}% +\def\xint_dsh #1#2% +{% + \expandafter\XINT_dsh_checksignx \the\numexpr #2\relax\Z {#1}% +}% +\def\XINT_dsh_checksignx #1% +{% + \xint_UDzerominusfork + #1-\XINT_dsh_xiszero + 0#1\XINT_dsx_xisNeg_checkA % on passe direct dans DSx + 0-{\XINT_dsh_xisPos #1}% + \krof +}% +\def\XINT_dsh_xiszero #1\Z #2{ #2}% +\def\XINT_dsh_xisPos #1\Z #2% +{% + \expandafter\xint_firstoftwo_thenstop + \romannumeral0\XINT_dsx_checksignA #2\Z {#1}% via DSx +}% +% \end{macrocode} +% \subsection{\csh{xintDSx}} +% \lverb+Je fais cette routine pour la version 1.01, après modification de +% \xintDecSplit. Dorénavant \xintDSx fera appel à \xintDecSplit et de même +% \xintDSH fera appel à \xintDSx. J'ai donc supprimé entièrement l'ancien code +% de \xintDSH et re-écrit entièrement celui de \xintDecSplit pour x positif. +% +% --> Attention le cas x=0 est traité dans la même catégorie que x > 0 <--$\ +% si x < 0, fait A -> A.10^(|x|)$\ +% si x >= 0, et A >=0, fait A -> {quo(A,10^(x))}{rem(A,10^(x))}$\ +% si x >= 0, et A < 0, d'abord on calcule {quo(-A,10^(x))}{rem(-A,10^(x))}$\ +% puis, si le premier n'est pas nul on lui donne le signe -$\ +% si le premier est nul on donne le signe - au second. +% +% On peut donc toujours reconstituer l'original A par 10^x Q \pm R +% où il faut prendre le signe plus si Q est positif ou nul et le signe moins si +% Q est strictement négatif. +% +% Release 1.06 has a faster and more compactly coded \XINT_dsx_zeroloop. +% Also, x is now given to a \numexpr. The earlier code should be then +% simplified, but I leave as is for the time being. +% +% Release 1.07 modified the coding of \XINT_dsx_zeroloop, to avoid impacting the +% input stack. Indeed the truncating, rounding, and conversion to float routines +% all use internally \XINT_dsx_zeroloop (via \XINT_dsx_addzerosnofuss), and they +% were thus roughly limited to generating N = 8 times the input save stack size +% digits. On TL2012 and TL2013, this means 40000 = 8x5000 digits. Although +% generating more than 40000 digits is more like a one shot thing, I wanted to +% open the possibility of outputting tens of thousands of digits to faile, thus +% I re-organized \XINT_dsx_zeroloop. +% +% January 5, 2014: but it is only with the new division implementation of 1.09j +% and also with its special \xintXTrunc routine that the possibility mentioned +% in the last paragraph has become a concrete one in terms of computation time.+ +% \begin{macrocode} +\def\xintDSx {\romannumeral0\xintdsx }% +\def\xintdsx #1#2% +{% + \expandafter\xint_dsx\expandafter {\romannumeral-`0#2}{#1}% +}% +\def\xint_dsx #1#2% +{% + \expandafter\XINT_dsx_checksignx \the\numexpr #2\relax\Z {#1}% +}% +\def\XINT_DSx #1#2{\romannumeral0\XINT_dsx_checksignx #1\Z {#2}}% +\def\XINT_dsx #1#2{\XINT_dsx_checksignx #1\Z {#2}}% +\def\XINT_dsx_checksignx #1% +{% + \xint_UDzerominusfork + #1-\XINT_dsx_xisZero + 0#1\XINT_dsx_xisNeg_checkA + 0-{\XINT_dsx_xisPos #1}% + \krof +}% +\def\XINT_dsx_xisZero #1\Z #2{ {#2}{0}}% attention comme x > 0 +\def\XINT_dsx_xisNeg_checkA #1\Z #2% +{% + \XINT_dsx_xisNeg_checkA_ #2\Z {#1}% +}% +\def\XINT_dsx_xisNeg_checkA_ #1#2\Z #3% +{% + \xint_gob_til_zero #1\XINT_dsx_xisNeg_Azero 0% + \XINT_dsx_xisNeg_checkx {#3}{#3}{}\Z {#1#2}% +}% +\def\XINT_dsx_xisNeg_Azero #1\Z #2{ 0}% +\def\XINT_dsx_xisNeg_checkx #1% +{% + \ifnum #1>1000000 + \xint_afterfi + {\xintError:TooBigDecimalShift + \expandafter\space\expandafter 0\xint_gobble_iv }% + \else + \expandafter \XINT_dsx_zeroloop + \fi +}% +\def\XINT_dsx_addzerosnofuss #1{\XINT_dsx_zeroloop {#1}{}\Z }% +\def\XINT_dsx_zeroloop #1#2% +{% + \ifnum #1<\xint_c_ix \XINT_dsx_exita\fi + \expandafter\XINT_dsx_zeroloop\expandafter + {\the\numexpr #1-\xint_c_viii}{#200000000}% +}% +\def\XINT_dsx_exita\fi\expandafter\XINT_dsx_zeroloop +{% + \fi\expandafter\XINT_dsx_exitb +}% +\def\XINT_dsx_exitb #1#2% +{% + \expandafter\expandafter\expandafter + \XINT_dsx_addzeros\csname xint_gobble_\romannumeral -#1\endcsname #2% +}% +\def\XINT_dsx_addzeros #1\Z #2{ #2#1}% +\def\XINT_dsx_xisPos #1\Z #2% +{% + \XINT_dsx_checksignA #2\Z {#1}% +}% +\def\XINT_dsx_checksignA #1% +{% + \xint_UDzerominusfork + #1-\XINT_dsx_AisZero + 0#1\XINT_dsx_AisNeg + 0-{\XINT_dsx_AisPos #1}% + \krof +}% +\def\XINT_dsx_AisZero #1\Z #2{ {0}{0}}% +\def\XINT_dsx_AisNeg #1\Z #2% +{% + \expandafter\XINT_dsx_AisNeg_dosplit_andcheckfirst + \romannumeral0\XINT_split_checksizex {#2}{#1}% +}% +\def\XINT_dsx_AisNeg_dosplit_andcheckfirst #1% +{% + \XINT_dsx_AisNeg_checkiffirstempty #1\Z +}% +\def\XINT_dsx_AisNeg_checkiffirstempty #1% +{% + \xint_gob_til_Z #1\XINT_dsx_AisNeg_finish_zero\Z + \XINT_dsx_AisNeg_finish_notzero #1% +}% +\def\XINT_dsx_AisNeg_finish_zero\Z + \XINT_dsx_AisNeg_finish_notzero\Z #1% +{% + \expandafter\XINT_dsx_end + \expandafter {\romannumeral0\XINT_num {-#1}}{0}% +}% +\def\XINT_dsx_AisNeg_finish_notzero #1\Z #2% +{% + \expandafter\XINT_dsx_end + \expandafter {\romannumeral0\XINT_num {#2}}{-#1}% +}% +\def\XINT_dsx_AisPos #1\Z #2% +{% + \expandafter\XINT_dsx_AisPos_finish + \romannumeral0\XINT_split_checksizex {#2}{#1}% +}% +\def\XINT_dsx_AisPos_finish #1#2% +{% + \expandafter\XINT_dsx_end + \expandafter {\romannumeral0\XINT_num {#2}}% + {\romannumeral0\XINT_num {#1}}% +}% +\edef\XINT_dsx_end #1#2% +{% + \noexpand\expandafter\space\noexpand\expandafter{#2}{#1}% +}% +% \end{macrocode} +% \subsection{\csh{xintDecSplit}, \csh{xintDecSplitL}, \csh{xintDecSplitR}} +% \lverb!DECIMAL SPLIT +% +% The macro \xintDecSplit {x}{A} first replaces A with |A| (*) +% This macro cuts the number into two pieces L and R. The concatenation LR +% always reproduces |A|, and R may be empty or have leading zeros. The +% position of the cut is specified by the first argument x. If x is zero or +% positive the cut location is x slots to the left of the right end of the +% number. If x becomes equal to or larger than the length of the number then L +% becomes empty. If x is negative the location of the cut is |x| slots to the +% right of the left end of the number. +% +% (*) warning: this may change in a future version. Only the behavior +% for A non-negative is guaranteed to remain the same. +% +% v1.05a: \XINT_split_checksizex does not compute the length anymore, rather the +% error will be from a \numexpr; but the limit of 999999999 does not make much +% sense. +% +% v1.06: Improvements in \XINT_split_fromleft_loop, \XINT_split_fromright_loop +% and related macros. More readable coding, speed gains. +% Also, I now feed immediately a \numexpr with x. Some simplifications should +% probably be made to the code, which is kept as is for the time being. +% +% 1.09e pays attention to the use of xintiabs which acquired in 1.09a the +% xintnum overhead. So xintiiabs rather without that overhead. +% ! +% \begin{macrocode} +\def\xintDecSplitL {\romannumeral0\xintdecsplitl }% +\def\xintDecSplitR {\romannumeral0\xintdecsplitr }% +\def\xintdecsplitl +{% + \expandafter\xint_firstoftwo_thenstop + \romannumeral0\xintdecsplit +}% +\def\xintdecsplitr +{% + \expandafter\xint_secondoftwo_thenstop + \romannumeral0\xintdecsplit +}% +\def\xintDecSplit {\romannumeral0\xintdecsplit }% +\def\xintdecsplit #1#2% +{% + \expandafter \xint_split \expandafter + {\romannumeral0\xintiiabs {#2}}{#1}% fait expansion de A +}% +\def\xint_split #1#2% +{% + \expandafter\XINT_split_checksizex\expandafter{\the\numexpr #2}{#1}% +}% +\def\XINT_split_checksizex #1% 999999999 is anyhow very big, could be reduced +{% + \ifnum\numexpr\XINT_Abs{#1}>999999999 + \xint_afterfi {\xintError:TooBigDecimalSplit\XINT_split_bigx }% + \else + \expandafter\XINT_split_xfork + \fi + #1\Z +}% +\def\XINT_split_bigx #1\Z #2% +{% + \ifcase\XINT_cntSgn #1\Z + \or \xint_afterfi { {}{#2}}% positive big x + \else + \xint_afterfi { {#2}{}}% negative big x + \fi +}% +\def\XINT_split_xfork #1% +{% + \xint_UDzerominusfork + #1-\XINT_split_zerosplit + 0#1\XINT_split_fromleft + 0-{\XINT_split_fromright #1}% + \krof +}% +\def\XINT_split_zerosplit #1\Z #2{ {#2}{}}% +\def\XINT_split_fromleft #1\Z #2% +{% + \XINT_split_fromleft_loop {#1}{}#2\W\W\W\W\W\W\W\W\Z +}% +\def\XINT_split_fromleft_loop #1% +{% + \ifnum #1<\xint_c_viii\XINT_split_fromleft_exita\fi + \expandafter\XINT_split_fromleft_loop_perhaps\expandafter + {\the\numexpr #1-\xint_c_viii\expandafter}\XINT_split_fromleft_eight +}% +\def\XINT_split_fromleft_eight #1#2#3#4#5#6#7#8#9{#9{#1#2#3#4#5#6#7#8#9}}% +\def\XINT_split_fromleft_loop_perhaps #1#2% +{% + \xint_gob_til_W #2\XINT_split_fromleft_toofar\W + \XINT_split_fromleft_loop {#1}% +}% +\def\XINT_split_fromleft_toofar\W\XINT_split_fromleft_loop #1#2#3\Z +{% + \XINT_split_fromleft_toofar_b #2\Z +}% +\def\XINT_split_fromleft_toofar_b #1\W #2\Z { {#1}{}}% +\def\XINT_split_fromleft_exita\fi + \expandafter\XINT_split_fromleft_loop_perhaps\expandafter #1#2% + {\fi \XINT_split_fromleft_exitb #1}% +\def\XINT_split_fromleft_exitb\the\numexpr #1-\xint_c_viii\expandafter +{% + \csname XINT_split_fromleft_endsplit_\romannumeral #1\endcsname +}% +\def\XINT_split_fromleft_endsplit_ #1#2\W #3\Z { {#1}{#2}}% +\def\XINT_split_fromleft_endsplit_i #1#2% + {\XINT_split_fromleft_checkiftoofar #2{#1#2}}% +\def\XINT_split_fromleft_endsplit_ii #1#2#3% + {\XINT_split_fromleft_checkiftoofar #3{#1#2#3}}% +\def\XINT_split_fromleft_endsplit_iii #1#2#3#4% + {\XINT_split_fromleft_checkiftoofar #4{#1#2#3#4}}% +\def\XINT_split_fromleft_endsplit_iv #1#2#3#4#5% + {\XINT_split_fromleft_checkiftoofar #5{#1#2#3#4#5}}% +\def\XINT_split_fromleft_endsplit_v #1#2#3#4#5#6% + {\XINT_split_fromleft_checkiftoofar #6{#1#2#3#4#5#6}}% +\def\XINT_split_fromleft_endsplit_vi #1#2#3#4#5#6#7% + {\XINT_split_fromleft_checkiftoofar #7{#1#2#3#4#5#6#7}}% +\def\XINT_split_fromleft_endsplit_vii #1#2#3#4#5#6#7#8% + {\XINT_split_fromleft_checkiftoofar #8{#1#2#3#4#5#6#7#8}}% +\def\XINT_split_fromleft_checkiftoofar #1#2#3\W #4\Z +{% + \xint_gob_til_W #1\XINT_split_fromleft_wenttoofar\W + \space {#2}{#3}% +}% +\def\XINT_split_fromleft_wenttoofar\W\space #1% +{% + \XINT_split_fromleft_wenttoofar_b #1\Z +}% +\def\XINT_split_fromleft_wenttoofar_b #1\W #2\Z { {#1}}% +\def\XINT_split_fromright #1\Z #2% +{% + \expandafter \XINT_split_fromright_a \expandafter + {\romannumeral0\xintreverseorder {#2}}{#1}{#2}% +}% +\def\XINT_split_fromright_a #1#2% +{% + \XINT_split_fromright_loop {#2}{}#1\W\W\W\W\W\W\W\W\Z +}% +\def\XINT_split_fromright_loop #1% +{% + \ifnum #1<\xint_c_viii\XINT_split_fromright_exita\fi + \expandafter\XINT_split_fromright_loop_perhaps\expandafter + {\the\numexpr #1-\xint_c_viii\expandafter }\XINT_split_fromright_eight +}% +\def\XINT_split_fromright_eight #1#2#3#4#5#6#7#8#9{#9{#9#8#7#6#5#4#3#2#1}}% +\def\XINT_split_fromright_loop_perhaps #1#2% +{% + \xint_gob_til_W #2\XINT_split_fromright_toofar\W + \XINT_split_fromright_loop {#1}% +}% +\def\XINT_split_fromright_toofar\W\XINT_split_fromright_loop #1#2#3\Z { {}}% +\def\XINT_split_fromright_exita\fi + \expandafter\XINT_split_fromright_loop_perhaps\expandafter #1#2% + {\fi \XINT_split_fromright_exitb #1}% +\def\XINT_split_fromright_exitb\the\numexpr #1-\xint_c_viii\expandafter +{% + \csname XINT_split_fromright_endsplit_\romannumeral #1\endcsname +}% +\edef\XINT_split_fromright_endsplit_ #1#2\W #3\Z #4% +{% + \noexpand\expandafter\space\noexpand\expandafter + {\noexpand\romannumeral0\noexpand\xintreverseorder {#2}}{#1}% +}% +\def\XINT_split_fromright_endsplit_i #1#2% + {\XINT_split_fromright_checkiftoofar #2{#2#1}}% +\def\XINT_split_fromright_endsplit_ii #1#2#3% + {\XINT_split_fromright_checkiftoofar #3{#3#2#1}}% +\def\XINT_split_fromright_endsplit_iii #1#2#3#4% + {\XINT_split_fromright_checkiftoofar #4{#4#3#2#1}}% +\def\XINT_split_fromright_endsplit_iv #1#2#3#4#5% + {\XINT_split_fromright_checkiftoofar #5{#5#4#3#2#1}}% +\def\XINT_split_fromright_endsplit_v #1#2#3#4#5#6% + {\XINT_split_fromright_checkiftoofar #6{#6#5#4#3#2#1}}% +\def\XINT_split_fromright_endsplit_vi #1#2#3#4#5#6#7% + {\XINT_split_fromright_checkiftoofar #7{#7#6#5#4#3#2#1}}% +\def\XINT_split_fromright_endsplit_vii #1#2#3#4#5#6#7#8% + {\XINT_split_fromright_checkiftoofar #8{#8#7#6#5#4#3#2#1}}% +\def\XINT_split_fromright_checkiftoofar #1% +{% + \xint_gob_til_W #1\XINT_split_fromright_wenttoofar\W + \XINT_split_fromright_endsplit_ +}% +\def\XINT_split_fromright_wenttoofar\W\XINT_split_fromright_endsplit_ #1\Z #2% + { {}{#2}}% +% \end{macrocode} +% \subsection{\csh{xintDouble}} +% \lverb|v1.08| +% \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 +}% +\def\XINT_dbl #1% +{% + \xint_UDzerominusfork + #1-\XINT_dbl_zero + 0#1\XINT_dbl_neg + 0-{\XINT_dbl_pos #1}% + \krof +}% +\def\XINT_dbl_zero #1\Z \W\W\W\W\W\W\W { 0}% +\def\XINT_dbl_neg + {\expandafter\xint_minus_thenstop\romannumeral0\XINT_dbl_pos }% +\def\XINT_dbl_pos +{% + \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% +{% + \XINT_dbl_a {#2#3#4#5#6#7#8#9}{#1}% +}% +\def\XINT_dbl_end_a #1+#2+#3\relax #4% +{% + \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 +}% +% \end{macrocode} +% \subsection{\csh{xintHalf}} +% \lverb!v1.08! +% \begin{macrocode} +\def\xintHalf {\romannumeral0\xinthalf }% +\def\xinthalf #1% +{% + \expandafter\XINT_half\romannumeral-`0#1% + \R\R\R\R\R\R\R\Z \W\W\W\W\W\W\W +}% +\def\XINT_half #1% +{% + \xint_UDzerominusfork + #1-\XINT_half_zero + 0#1\XINT_half_neg + 0-{\XINT_half_pos #1}% + \krof +}% +\def\XINT_half_zero #1\Z \W\W\W\W\W\W\W { 0}% +\def\XINT_half_neg {\expandafter\XINT_opp\romannumeral0\XINT_half_pos }% +\def\XINT_half_pos {\expandafter\XINT_half_a\romannumeral0\XINT_SQ {}}% +\def\XINT_half_a #1#2#3#4#5#6#7#8% +{% + \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% +{% + \XINT_half_c {#2#3#4#5#6#7#8#9}{#1}% +}% +\def\XINT_half_end_a #1\W #2\relax #3% +{% + \xint_gob_til_zero #1\XINT_half_end_b 0\space #1#3% +}% +\edef\XINT_half_end_b 0\space 0#1#2#3#4#5#6#7% +{% + \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5#6#7\relax +}% +% \end{macrocode} +% \subsection{\csh{xintDec}} +% \lverb!v1.08! +% \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 +}% +\def\XINT_dec #1% +{% + \xint_UDzerominusfork + #1-\XINT_dec_zero + 0#1\XINT_dec_neg + 0-{\XINT_dec_pos #1}% + \krof +}% +\def\XINT_dec_zero #1\W\W\W\W\W\W\W\W { -1}% +\def\XINT_dec_neg + {\expandafter\xint_minus_thenstop\romannumeral0\XINT_inc_pos }% +\def\XINT_dec_pos +{% + \expandafter\XINT_dec_a \expandafter{\expandafter}% + \romannumeral0\XINT_OQ {}% +}% +\def\XINT_dec_a #1#2#3#4#5#6#7#8#9% +{% + \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% +}% +\edef\XINT_dec_cleanup #1#2#3#4#5#6#7#8% + {\noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5#6#7#8\relax }% +% \end{macrocode} +% \subsection{\csh{xintInc}} +% \lverb!v1.08! +% \begin{macrocode} +\def\xintInc {\romannumeral0\xintinc }% +\def\xintinc #1% +{% + \expandafter\XINT_inc\romannumeral-`0#1% + \R\R\R\R\R\R\R\R\Z \W\W\W\W\W\W\W\W +}% +\def\XINT_inc #1% +{% + \xint_UDzerominusfork + #1-\XINT_inc_zero + 0#1\XINT_inc_neg + 0-{\XINT_inc_pos #1}% + \krof +}% +\def\XINT_inc_zero #1\W\W\W\W\W\W\W\W { 1}% +\def\XINT_inc_neg {\expandafter\XINT_opp\romannumeral0\XINT_dec_pos }% +\def\XINT_inc_pos +{% + \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{\csh{xintiSqrt}, \csh{xintiSquareRoot}} +% \lverb|v1.08. 1.09a uses \xintnum. +% +% Some overhead was added inadvertently in 1.09a to inner routines when +% \xintiquo and \xintidivision were also promoted to use \xintnum; release 1.09f +% thus uses \xintiiquo and \xintiidivision xhich avoid this \xintnum overhead. +% +% 1.09j replaced the previous long \ifcase from \XINT_sqrt_c by some nested +% \ifnum's.| +% \begin{macrocode} +\def\xintiSqrt {\romannumeral0\xintisqrt }% +\def\xintisqrt + {\expandafter\XINT_sqrt_post\romannumeral0\xintisquareroot }% +\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\xintiSquareRoot {\romannumeral0\xintisquareroot }% +\def\xintisquareroot #1% + {\expandafter\XINT_sqrt_checkin\romannumeral0\xintnum{#1}\Z}% +\def\XINT_sqrt_checkin #1% +{% + \xint_UDzerominusfork + #1-\XINT_sqrt_iszero + 0#1\XINT_sqrt_isneg + 0-{\XINT_sqrt #1}% + \krof +}% +\def\XINT_sqrt_iszero #1\Z { 1.}% +\edef\XINT_sqrt_isneg #1\Z {\noexpand\xintError:RootOfNegative\space 1.}% +\def\XINT_sqrt #1\Z +{% + \expandafter\XINT_sqrt_start\expandafter + {\romannumeral0\xintlength {#1}}{#1}% +}% +\def\XINT_sqrt_start #1% +{% + \ifnum #1<\xint_c_x + \expandafter\XINT_sqrt_small_a + \else + \expandafter\XINT_sqrt_big_a + \fi + {#1}% +}% +\def\XINT_sqrt_small_a #1{\XINT_sqrt_a {#1}\XINT_sqrt_small_d }% +\def\XINT_sqrt_big_a #1{\XINT_sqrt_a {#1}\XINT_sqrt_big_d }% +\def\XINT_sqrt_a #1% +{% + \ifodd #1 + \expandafter\XINT_sqrt_bB + \else + \expandafter\XINT_sqrt_bA + \fi + {#1}% +}% +\def\XINT_sqrt_bA #1#2#3% +{% + \XINT_sqrt_bA_b #3\Z #2{#1}{#3}% +}% +\def\XINT_sqrt_bA_b #1#2#3\Z +{% + \XINT_sqrt_c {#1#2}% +}% +\def\XINT_sqrt_bB #1#2#3% +{% + \XINT_sqrt_bB_b #3\Z #2{#1}{#3}% +}% +\def\XINT_sqrt_bB_b #1#2\Z +{% + \XINT_sqrt_c #1% +}% +\def\XINT_sqrt_c #1#2% +{% + \expandafter #2\expandafter + {\the\numexpr\ifnum #1>\xint_c_iii + \ifnum #1>\xint_c_viii + \ifnum #1>15 \ifnum #1>24 \ifnum #1>35 + \ifnum #1>48 \ifnum #1>63 \ifnum #1>80 + 10\else 9\fi \else 8\fi \else 7\fi \else 6\fi + \else 5\fi \else 4\fi \else 3\fi \else 2\fi \relax }% +}% +\def\XINT_sqrt_small_d #1#2% +{% + \expandafter\XINT_sqrt_small_e\expandafter + {\the\numexpr #1\ifcase \numexpr #2/\xint_c_ii-\xint_c_i\relax + \or 0\or 00\or 000\or 0000\fi }% +}% +\def\XINT_sqrt_small_e #1#2% +{% + \expandafter\XINT_sqrt_small_f\expandafter {\the\numexpr #1*#1-#2}{#1}% +}% +\def\XINT_sqrt_small_f #1#2% +{% + \expandafter\XINT_sqrt_small_g\expandafter + {\the\numexpr ((#1+#2)/(\xint_c_ii*#2))-\xint_c_i}{#1}{#2}% +}% +\def\XINT_sqrt_small_g #1% +{% + \ifnum #1>\xint_c_ + \expandafter\XINT_sqrt_small_h + \else + \expandafter\XINT_sqrt_small_end + \fi + {#1}% +}% +\def\XINT_sqrt_small_h #1#2#3% +{% + \expandafter\XINT_sqrt_small_f\expandafter + {\the\numexpr #2-\xint_c_ii*#1*#3+#1*#1\expandafter}\expandafter + {\the\numexpr #3-#1}% +}% +\def\XINT_sqrt_small_end #1#2#3{ {#3}{#2}}% +\def\XINT_sqrt_big_d #1#2% +{% + \ifodd #2 + \expandafter\expandafter\expandafter\XINT_sqrt_big_eB + \else + \expandafter\expandafter\expandafter\XINT_sqrt_big_eA + \fi + \expandafter {\the\numexpr #2/\xint_c_ii }{#1}% +}% +\def\XINT_sqrt_big_eA #1#2#3% +{% + \XINT_sqrt_big_eA_a #3\Z {#2}{#1}{#3}% +}% +\def\XINT_sqrt_big_eA_a #1#2#3#4#5#6#7#8#9\Z +{% + \XINT_sqrt_big_eA_b {#1#2#3#4#5#6#7#8}% +}% +\def\XINT_sqrt_big_eA_b #1#2% +{% + \expandafter\XINT_sqrt_big_f + \romannumeral0\XINT_sqrt_small_e {#2000}{#1}{#1}% +}% +\def\XINT_sqrt_big_eB #1#2#3% +{% + \XINT_sqrt_big_eB_a #3\Z {#2}{#1}{#3}% +}% +\def\XINT_sqrt_big_eB_a #1#2#3#4#5#6#7#8#9% +{% + \XINT_sqrt_big_eB_b {#1#2#3#4#5#6#7#8#9}% +}% +\def\XINT_sqrt_big_eB_b #1#2\Z #3% +{% + \expandafter\XINT_sqrt_big_f + \romannumeral0\XINT_sqrt_small_e {#30000}{#1}{#1}% +}% +\def\XINT_sqrt_big_f #1#2#3#4% +{% + \expandafter\XINT_sqrt_big_f_a\expandafter + {\the\numexpr #2+#3\expandafter}\expandafter + {\romannumeral0\XINT_dsx_addzerosnofuss + {\numexpr #4-\xint_c_iv\relax}{#1}}{#4}% +}% +\def\XINT_sqrt_big_f_a #1#2#3#4% +{% + \expandafter\XINT_sqrt_big_g\expandafter + {\romannumeral0\xintiisub + {\XINT_dsx_addzerosnofuss + {\numexpr \xint_c_ii*#3-\xint_c_viii\relax}{#1}}{#4}}% + {#2}{#3}% +}% +\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}% +}% +\def\XINT_sqrt_big_j #1% +{% + \if0\XINT_Sgn #1\Z + \expandafter \XINT_sqrt_big_end + \else \expandafter \XINT_sqrt_big_k + \fi {#1}% +}% +\def\XINT_sqrt_big_k #1#2#3% +{% + \expandafter\XINT_sqrt_big_l\expandafter + {\romannumeral0\xintiisub {#3}{#1}}% + {\romannumeral0\xintiiadd {#2}{\xintiiSqr {#1}}}% +}% +\def\XINT_sqrt_big_l #1#2% +{% + \expandafter\XINT_sqrt_big_g\expandafter + {#2}{#1}% +}% +\def\XINT_sqrt_big_end #1#2#3#4{ {#3}{#2}}% +% \end{macrocode} +% \subsection{\csh{xintIsTrue:csv}} +% \lverb|1.09c. For use by \xinttheboolexpr.(inside \csname, no need for a +% \romannumeral here). The macros may well be defined already here. I +% make no advertisement because I have inserted no space parsing in the +% :csv macros, as they will be used only with privately created comma +% separated lists, having no space naturally. Nevertheless they exist +% and can be used.| +% \begin{macrocode} +\def\xintIsTrue:csv #1{\expandafter\XINT_istrue:_a\romannumeral-`0#1,,^}% +\def\XINT_istrue:_a {\XINT_istrue:_b {}}% +\def\XINT_istrue:_b #1#2,% + {\expandafter\XINT_istrue:_c\romannumeral-`0#2,{#1}}% +\def\XINT_istrue:_c #1{\if #1,\expandafter\XINT_:_f + \else\expandafter\XINT_istrue:_d\fi #1}% +\def\XINT_istrue:_d #1,% + {\expandafter\XINT_istrue:_e\romannumeral0\xintisnotzero {#1},}% +\def\XINT_istrue:_e #1,#2{\XINT_istrue:_b {#2,#1}}% +\def\XINT_:_f ,#1#2^{\xint_gobble_i #1}% +% \end{macrocode} +% \subsection{\csh{xintANDof:csv}} +% \lverb|1.09a. For use by \xintexpr (inside \csname, no need for a +% \romannumeral here).| +% \begin{macrocode} +\def\xintANDof:csv #1{\expandafter\XINT_andof:_a\romannumeral-`0#1,,^}% +\def\XINT_andof:_a {\expandafter\XINT_andof:_b\romannumeral-`0}% +\def\XINT_andof:_b #1{\if #1,\expandafter\XINT_andof:_e + \else\expandafter\XINT_andof:_c\fi #1}% +\def\XINT_andof:_c #1,{\xintifTrueAelseB {#1}{\XINT_andof:_a}{\XINT_andof:_no}}% +\def\XINT_andof:_no #1^{0}% +\def\XINT_andof:_e #1^{1}% works with empty list +% \end{macrocode} +% \subsection{\csh{xintORof:csv}} +% \lverb|1.09a. For use by \xintexpr.| +% \begin{macrocode} +\def\xintORof:csv #1{\expandafter\XINT_orof:_a\romannumeral-`0#1,,^}% +\def\XINT_orof:_a {\expandafter\XINT_orof:_b\romannumeral-`0}% +\def\XINT_orof:_b #1{\if #1,\expandafter\XINT_orof:_e + \else\expandafter\XINT_orof:_c\fi #1}% +\def\XINT_orof:_c #1,{\xintifTrueAelseB{#1}{\XINT_orof:_yes}{\XINT_orof:_a}}% +\def\XINT_orof:_yes #1^{1}% +\def\XINT_orof:_e #1^{0}% works with empty list +% \end{macrocode} +% \subsection{\csh{xintXORof:csv}} +% \lverb|1.09a. For use by \xintexpr (inside a \csname..\endcsname).| +% \begin{macrocode} +\def\xintXORof:csv #1{\expandafter\XINT_xorof:_a\expandafter + 0\romannumeral-`0#1,,^}% +\def\XINT_xorof:_a #1#2,{\expandafter\XINT_xorof:_b\romannumeral-`0#2,#1}% +\def\XINT_xorof:_b #1{\if #1,\expandafter\XINT_:_e + \else\expandafter\XINT_xorof:_c\fi #1}% +\def\XINT_xorof:_c #1,#2% + {\xintifTrueAelseB {#1}{\if #20\xint_afterfi{\XINT_xorof:_a 1}% + \else\xint_afterfi{\XINT_xorof:_a 0}\fi}% + {\XINT_xorof:_a #2}% + }% +\def\XINT_:_e ,#1#2^{#1}% allows empty list +% \end{macrocode} +% \subsection{\csh{xintiMaxof:csv}} +% \lverb|1.09i. For use by \xintiiexpr.| +% \begin{macrocode} +\def\xintiMaxof:csv #1{\expandafter\XINT_imaxof:_b\romannumeral-`0#1,,}% +\def\XINT_imaxof:_b #1,#2,{\expandafter\XINT_imaxof:_c\romannumeral-`0#2,{#1},}% +\def\XINT_imaxof:_c #1{\if #1,\expandafter\XINT_of:_e + \else\expandafter\XINT_imaxof:_d\fi #1}% +\def\XINT_imaxof:_d #1,{\expandafter\XINT_imaxof:_b\romannumeral0\xintimax {#1}}% +\def\XINT_of:_e ,#1,{#1}% +\let\xintMaxof:csv\xintiMaxof:csv +% \end{macrocode} +% \subsection{\csh{xintiMinof:csv}} +% \lverb|1.09i. For use by \xintiiexpr.| +% \begin{macrocode} +\def\xintiMinof:csv #1{\expandafter\XINT_iminof:_b\romannumeral-`0#1,,}% +\def\XINT_iminof:_b #1,#2,{\expandafter\XINT_iminof:_c\romannumeral-`0#2,{#1},}% +\def\XINT_iminof:_c #1{\if #1,\expandafter\XINT_of:_e + \else\expandafter\XINT_iminof:_d\fi #1}% +\def\XINT_iminof:_d #1,{\expandafter\XINT_iminof:_b\romannumeral0\xintimin {#1}}% +\let\xintMinof:csv\xintiMinof:csv +% \end{macrocode} +% \subsection{\csh{xintiiSum:csv}} +% \lverb|1.09i. For use by \xintiiexpr.| +% \begin{macrocode} +\def\xintiiSum:csv #1{\expandafter\XINT_iisum:_a\romannumeral-`0#1,,^}% +\def\XINT_iisum:_a {\XINT_iisum:_b {0}}% +\def\XINT_iisum:_b #1#2,{\expandafter\XINT_iisum:_c\romannumeral-`0#2,{#1}}% +\def\XINT_iisum:_c #1{\if #1,\expandafter\XINT_:_e + \else\expandafter\XINT_iisum:_d\fi #1}% +\def\XINT_iisum:_d #1,#2{\expandafter\XINT_iisum:_b\expandafter + {\romannumeral0\xintiiadd {#2}{#1}}}% +\let\xintSum:csv\xintiiSum:csv +% \end{macrocode} +% \subsection{\csh{xintiiPrd:csv}} +% \lverb|1.09i. For use by \xintiiexpr.| +% \begin{macrocode} +\def\xintiiPrd:csv #1{\expandafter\XINT_iiprd:_a\romannumeral-`0#1,,^}% +\def\XINT_iiprd:_a {\XINT_iiprd:_b {1}}% +\def\XINT_iiprd:_b #1#2,{\expandafter\XINT_iiprd:_c\romannumeral-`0#2,{#1}}% +\def\XINT_iiprd:_c #1{\if #1,\expandafter\XINT_:_e + \else\expandafter\XINT_iiprd:_d\fi #1}% +\def\XINT_iiprd:_d #1,#2{\expandafter\XINT_iiprd:_b\expandafter + {\romannumeral0\xintiimul {#2}{#1}}}% +\let\xintPrd:csv\xintiiPrd:csv +\XINT_restorecatcodes_endinput% +% \end{macrocode} +%\catcode`\<=0 \catcode`\>=11 \catcode`\*=11 \catcode`\/=11 +%\let</xint>\relax +%\def<*xintbinhex>{\catcode`\<=12 \catcode`\>=12 \catcode`\*=12 \catcode`\/=12 } +%</xint> +%<*xintbinhex> +% +% \StoreCodelineNo {xint} +% +% \section{Package \xintbinhexnameimp implementation} +% \label{sec:binheximp} +% +% The commenting is currently (\docdate) very sparse. +% +% \localtableofcontents +% \subsection{Catcodes, \protect\eTeX{} and reload detection} +% +% The code for reload detection is copied from \textsc{Heiko +% Oberdiek}'s packages, and adapted here to check for previous +% loading of the master \xintname package. +% +% The method for catcodes is slightly different, but still +% directly inspired by these packages. +% +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \def\space { }% + \let\z\endgroup + \expandafter\let\expandafter\x\csname ver@xintbinhex.sty\endcsname + \expandafter\let\expandafter\w\csname ver@xint.sty\endcsname + \expandafter + \ifx\csname PackageInfo\endcsname\relax + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \else + \def\y#1#2{\PackageInfo{#1}{#2}}% + \fi + \expandafter + \ifx\csname numexpr\endcsname\relax + \y{xintbinhex}{\numexpr not available, aborting input}% + \aftergroup\endinput + \else + \ifx\x\relax % plain-TeX, first loading of xintbinhex.sty + \ifx\w\relax % but xint.sty not yet loaded. + \y{xintbinhex}{now issuing \string\input\space xint.sty}% + \def\z{\endgroup\input xint.sty\relax}% + \fi + \else + \def\empty {}% + \ifx\x\empty % LaTeX, first loading, + % variable is initialized, but \ProvidesPackage not yet seen + \ifx\w\relax % xint.sty not yet loaded. + \y{xintbinhex}{now issuing \string\RequirePackage{xint}}% + \def\z{\endgroup\RequirePackage{xint}}% + \fi + \else + \y{xintbinhex}{I was already loaded, aborting input}% + \aftergroup\endinput + \fi + \fi + \fi +\z% +% \end{macrocode} +% \subsection{Confirmation of \xintnameimp loading} +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \ifdefined\PackageInfo + \def\y#1#2{\PackageInfo{#1}{#2}}% + \else + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \fi + \def\empty {}% + \expandafter\let\expandafter\w\csname ver@xint.sty\endcsname + \ifx\w\relax % Plain TeX, user gave a file name at the prompt + \y{xintbinhex}{Loading of package xint failed, aborting input}% + \aftergroup\endinput + \fi + \ifx\w\empty % LaTeX, user gave a file name at the prompt + \y{xintbinhex}{Loading of package xint failed, aborting input}% + \aftergroup\endinput + \fi +\endgroup% +% \end{macrocode} +% \subsection{Catcodes} +% \begin{macrocode} +\XINTsetupcatcodes% +% \end{macrocode} +% \subsection{Package identification} +% \begin{macrocode} +\XINT_providespackage +\ProvidesPackage{xintbinhex}% + [2014/02/05 v1.09ka 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 done in xint.sty +% \chardef\xint_c_ii^vi 64 % already done 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_x^v \xint_c_x^v 100000 +\newcount\xint_c_x^ix \xint_c_x^ix 1000000000 +\def\XINT_tmpa #1{% + \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 + 8\or 9\or A\or B\or C\or D\or E\or F\fi}}% +\xintApplyInline\XINT_tmpa + {{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}{13}{14}{15}}% +\def\XINT_tmpa #1{% + \expandafter\edef\csname XINT_sdtb_#1\endcsname + {\ifcase #1 + 0000\or 0001\or 0010\or 0011\or 0100\or 0101\or 0110\or 0111\or + 1000\or 1001\or 1010\or 1011\or 1100\or 1101\or 1110\or 1111\fi}}% +\xintApplyInline\XINT_tmpa + {{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}{13}{14}{15}}% +\let\XINT_tmpa\relax +\expandafter\def\csname XINT_sbtd_0000\endcsname {0}% +\expandafter\def\csname XINT_sbtd_0001\endcsname {1}% +\expandafter\def\csname XINT_sbtd_0010\endcsname {2}% +\expandafter\def\csname XINT_sbtd_0011\endcsname {3}% +\expandafter\def\csname XINT_sbtd_0100\endcsname {4}% +\expandafter\def\csname XINT_sbtd_0101\endcsname {5}% +\expandafter\def\csname XINT_sbtd_0110\endcsname {6}% +\expandafter\def\csname XINT_sbtd_0111\endcsname {7}% +\expandafter\def\csname XINT_sbtd_1000\endcsname {8}% +\expandafter\def\csname XINT_sbtd_1001\endcsname {9}% +\expandafter\def\csname XINT_sbtd_1010\endcsname {10}% +\expandafter\def\csname XINT_sbtd_1011\endcsname {11}% +\expandafter\def\csname XINT_sbtd_1100\endcsname {12}% +\expandafter\def\csname XINT_sbtd_1101\endcsname {13}% +\expandafter\def\csname XINT_sbtd_1110\endcsname {14}% +\expandafter\def\csname XINT_sbtd_1111\endcsname {15}% +\expandafter\let\csname XINT_sbth_0000\expandafter\endcsname + \csname XINT_sbtd_0000\endcsname +\expandafter\let\csname XINT_sbth_0001\expandafter\endcsname + \csname XINT_sbtd_0001\endcsname +\expandafter\let\csname XINT_sbth_0010\expandafter\endcsname + \csname XINT_sbtd_0010\endcsname +\expandafter\let\csname XINT_sbth_0011\expandafter\endcsname + \csname XINT_sbtd_0011\endcsname +\expandafter\let\csname XINT_sbth_0100\expandafter\endcsname + \csname XINT_sbtd_0100\endcsname +\expandafter\let\csname XINT_sbth_0101\expandafter\endcsname + \csname XINT_sbtd_0101\endcsname +\expandafter\let\csname XINT_sbth_0110\expandafter\endcsname + \csname XINT_sbtd_0110\endcsname +\expandafter\let\csname XINT_sbth_0111\expandafter\endcsname + \csname XINT_sbtd_0111\endcsname +\expandafter\let\csname XINT_sbth_1000\expandafter\endcsname + \csname XINT_sbtd_1000\endcsname +\expandafter\let\csname XINT_sbth_1001\expandafter\endcsname + \csname XINT_sbtd_1001\endcsname +\expandafter\def\csname XINT_sbth_1010\endcsname {A}% +\expandafter\def\csname XINT_sbth_1011\endcsname {B}% +\expandafter\def\csname XINT_sbth_1100\endcsname {C}% +\expandafter\def\csname XINT_sbth_1101\endcsname {D}% +\expandafter\def\csname XINT_sbth_1110\endcsname {E}% +\expandafter\def\csname XINT_sbth_1111\endcsname {F}% +\expandafter\def\csname XINT_shtb_0\endcsname {0000}% +\expandafter\def\csname XINT_shtb_1\endcsname {0001}% +\expandafter\def\csname XINT_shtb_2\endcsname {0010}% +\expandafter\def\csname XINT_shtb_3\endcsname {0011}% +\expandafter\def\csname XINT_shtb_4\endcsname {0100}% +\expandafter\def\csname XINT_shtb_5\endcsname {0101}% +\expandafter\def\csname XINT_shtb_6\endcsname {0110}% +\expandafter\def\csname XINT_shtb_7\endcsname {0111}% +\expandafter\def\csname XINT_shtb_8\endcsname {1000}% +\expandafter\def\csname XINT_shtb_9\endcsname {1001}% +\def\XINT_shtb_A {1010}% +\def\XINT_shtb_B {1011}% +\def\XINT_shtb_C {1100}% +\def\XINT_shtb_D {1101}% +\def\XINT_shtb_E {1110}% +\def\XINT_shtb_F {1111}% +\def\XINT_shtb_G {}% +\def\XINT_smallhex #1% +{% + \expandafter\XINT_smallhex_a\expandafter + {\the\numexpr (#1+\xint_c_viii)/\xint_c_xvi-\xint_c_i}{#1}% +}% +\def\XINT_smallhex_a #1#2% +{% + \csname XINT_sdth_#1\expandafter\expandafter\expandafter\endcsname + \csname XINT_sdth_\the\numexpr #2-\xint_c_xvi*#1\endcsname +}% +\def\XINT_smallbin #1% +{% + \expandafter\XINT_smallbin_a\expandafter + {\the\numexpr (#1+\xint_c_viii)/\xint_c_xvi-\xint_c_i}{#1}% +}% +\def\XINT_smallbin_a #1#2% +{% + \csname XINT_sdtb_#1\expandafter\expandafter\expandafter\endcsname + \csname XINT_sdtb_\the\numexpr #2-\xint_c_xvi*#1\endcsname +}% +% \end{macrocode} +% \subsection{\csh{xintDecToHex}, \csh{xintDecToBin}} +% \lverb!v1.08! +% \begin{macrocode} +\def\xintDecToHex {\romannumeral0\xintdectohex }% +\def\xintdectohex #1% + {\expandafter\XINT_dth_checkin\romannumeral-`0#1\W\W\W\W \T}% +\def\XINT_dth_checkin #1% +{% + \xint_UDsignfork + #1\XINT_dth_N + -{\XINT_dth_P #1}% + \krof +}% +\def\XINT_dth_N {\expandafter\xint_minus_thenstop\romannumeral0\XINT_dth_P }% +\def\XINT_dth_P {\expandafter\XINT_dth_III\romannumeral-`0\XINT_dtbh_I {0.}}% +\def\xintDecToBin {\romannumeral0\xintdectobin }% +\def\xintdectobin #1% + {\expandafter\XINT_dtb_checkin\romannumeral-`0#1\W\W\W\W \T }% +\def\XINT_dtb_checkin #1% +{% + \xint_UDsignfork + #1\XINT_dtb_N + -{\XINT_dtb_P #1}% + \krof +}% +\def\XINT_dtb_N {\expandafter\xint_minus_thenstop\romannumeral0\XINT_dtb_P }% +\def\XINT_dtb_P {\expandafter\XINT_dtb_III\romannumeral-`0\XINT_dtbh_I {0.}}% +\def\XINT_dtbh_I #1#2#3#4#5% +{% + \xint_gob_til_W #5\XINT_dtbh_II_a\W\XINT_dtbh_I_a {}{#2#3#4#5}#1\Z.% +}% +\def\XINT_dtbh_II_a\W\XINT_dtbh_I_a #1#2{\XINT_dtbh_II_b #2}% +\def\XINT_dtbh_II_b #1#2#3#4% +{% + \xint_gob_til_W + #1\XINT_dtbh_II_c + #2\XINT_dtbh_II_ci + #3\XINT_dtbh_II_cii + \W\XINT_dtbh_II_ciii #1#2#3#4% +}% +\def\XINT_dtbh_II_c \W\XINT_dtbh_II_ci + \W\XINT_dtbh_II_cii + \W\XINT_dtbh_II_ciii \W\W\W\W {{}}% +\def\XINT_dtbh_II_ci #1\XINT_dtbh_II_ciii #2\W\W\W + {\XINT_dtbh_II_d {}{#2}{0}}% +\def\XINT_dtbh_II_cii\W\XINT_dtbh_II_ciii #1#2\W\W + {\XINT_dtbh_II_d {}{#1#2}{00}}% +\def\XINT_dtbh_II_ciii #1#2#3\W + {\XINT_dtbh_II_d {}{#1#2#3}{000}}% +\def\XINT_dtbh_I_a #1#2#3.% +{% + \xint_gob_til_Z #3\XINT_dtbh_I_z\Z + \expandafter\XINT_dtbh_I_b\the\numexpr #2+#30000.{#1}% +}% +\def\XINT_dtbh_I_b #1.% +{% + \expandafter\XINT_dtbh_I_c\the\numexpr + (#1+\xint_c_ii^xv)/\xint_c_ii^xvi-\xint_c_i.#1.% +}% +\def\XINT_dtbh_I_c #1.#2.% +{% + \expandafter\XINT_dtbh_I_d\expandafter + {\the\numexpr #2-\xint_c_ii^xvi*#1}{#1}% +}% +\def\XINT_dtbh_I_d #1#2#3{\XINT_dtbh_I_a {#3#1.}{#2}}% +\def\XINT_dtbh_I_z\Z\expandafter\XINT_dtbh_I_b\the\numexpr #1+#2.% +{% + \ifnum #1=\xint_c_ \expandafter\XINT_dtbh_I_end_zb\fi + \XINT_dtbh_I_end_za {#1}% +}% +\def\XINT_dtbh_I_end_za #1#2{\XINT_dtbh_I {#2#1.}}% +\def\XINT_dtbh_I_end_zb\XINT_dtbh_I_end_za #1#2{\XINT_dtbh_I {#2}}% +\def\XINT_dtbh_II_d #1#2#3#4.% +{% + \xint_gob_til_Z #4\XINT_dtbh_II_z\Z + \expandafter\XINT_dtbh_II_e\the\numexpr #2+#4#3.{#1}{#3}% +}% +\def\XINT_dtbh_II_e #1.% +{% + \expandafter\XINT_dtbh_II_f\the\numexpr + (#1+\xint_c_ii^xv)/\xint_c_ii^xvi-\xint_c_i.#1.% +}% +\def\XINT_dtbh_II_f #1.#2.% +{% + \expandafter\XINT_dtbh_II_g\expandafter + {\the\numexpr #2-\xint_c_ii^xvi*#1}{#1}% +}% +\def\XINT_dtbh_II_g #1#2#3{\XINT_dtbh_II_d {#3#1.}{#2}}% +\def\XINT_dtbh_II_z\Z\expandafter\XINT_dtbh_II_e\the\numexpr #1+#2.% +{% + \ifnum #1=\xint_c_ \expandafter\XINT_dtbh_II_end_zb\fi + \XINT_dtbh_II_end_za {#1}% +}% +\def\XINT_dtbh_II_end_za #1#2#3{{}#2#1.\Z.}% +\def\XINT_dtbh_II_end_zb\XINT_dtbh_II_end_za #1#2#3{{}#2\Z.}% +\def\XINT_dth_III #1#2.% +{% + \xint_gob_til_Z #2\XINT_dth_end\Z + \expandafter\XINT_dth_III\expandafter + {\romannumeral-`0\XINT_dth_small #2.#1}% +}% +\def\XINT_dth_small #1.% +{% + \expandafter\XINT_smallhex\expandafter + {\the\numexpr (#1+\xint_c_ii^vii)/\xint_c_ii^viii-\xint_c_i\expandafter}% + \romannumeral-`0\expandafter\XINT_smallhex\expandafter + {\the\numexpr + #1-((#1+\xint_c_ii^vii)/\xint_c_ii^viii-\xint_c_i)*\xint_c_ii^viii}% +}% +\def\XINT_dth_end\Z\expandafter\XINT_dth_III\expandafter #1#2\T +{% + \XINT_dth_end_b #1% +}% +\def\XINT_dth_end_b #1.{\XINT_dth_end_c }% +\def\XINT_dth_end_c #1{\xint_gob_til_zero #1\XINT_dth_end_d 0\space #1}% +\def\XINT_dth_end_d 0\space 0#1% +{% + \xint_gob_til_zero #1\XINT_dth_end_e 0\space #1% +}% +\def\XINT_dth_end_e 0\space 0#1% +{% + \xint_gob_til_zero #1\XINT_dth_end_f 0\space #1% +}% +\def\XINT_dth_end_f 0\space 0{ }% +\def\XINT_dtb_III #1#2.% +{% + \xint_gob_til_Z #2\XINT_dtb_end\Z + \expandafter\XINT_dtb_III\expandafter + {\romannumeral-`0\XINT_dtb_small #2.#1}% +}% +\def\XINT_dtb_small #1.% +{% + \expandafter\XINT_smallbin\expandafter + {\the\numexpr (#1+\xint_c_ii^vii)/\xint_c_ii^viii-\xint_c_i\expandafter}% + \romannumeral-`0\expandafter\XINT_smallbin\expandafter + {\the\numexpr + #1-((#1+\xint_c_ii^vii)/\xint_c_ii^viii-\xint_c_i)*\xint_c_ii^viii}% +}% +\def\XINT_dtb_end\Z\expandafter\XINT_dtb_III\expandafter #1#2\T +{% + \XINT_dtb_end_b #1% +}% +\def\XINT_dtb_end_b #1.{\XINT_dtb_end_c }% +\def\XINT_dtb_end_c #1#2#3#4#5#6#7#8% +{% + \expandafter\XINT_dtb_end_d\the\numexpr #1#2#3#4#5#6#7#8\relax +}% +\edef\XINT_dtb_end_d #1#2#3#4#5#6#7#8#9% +{% + \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5#6#7#8#9\relax +}% +% \end{macrocode} +% \subsection{\csh{xintHexToDec}} +% \lverb!v1.08! +% \begin{macrocode} +\def\xintHexToDec {\romannumeral0\xinthextodec }% +\def\xinthextodec #1% + {\expandafter\XINT_htd_checkin\romannumeral-`0#1\W\W\W\W \T }% +\def\XINT_htd_checkin #1% +{% + \xint_UDsignfork + #1\XINT_htd_neg + -{\XINT_htd_I {0000}#1}% + \krof +}% +\def\XINT_htd_neg {\expandafter\xint_minus_thenstop + \romannumeral0\XINT_htd_I {0000}}% +\def\XINT_htd_I #1#2#3#4#5% +{% + \xint_gob_til_W #5\XINT_htd_II_a\W + \XINT_htd_I_a {}{"#2#3#4#5}#1\Z\Z\Z\Z +}% +\def\XINT_htd_II_a \W\XINT_htd_I_a #1#2{\XINT_htd_II_b #2}% +\def\XINT_htd_II_b "#1#2#3#4% +{% + \xint_gob_til_W + #1\XINT_htd_II_c + #2\XINT_htd_II_ci + #3\XINT_htd_II_cii + \W\XINT_htd_II_ciii #1#2#3#4% +}% +\def\XINT_htd_II_c \W\XINT_htd_II_ci + \W\XINT_htd_II_cii + \W\XINT_htd_II_ciii \W\W\W\W #1\Z\Z\Z\Z\T +{% + \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 +}% +\def\XINT_htd_II_ci #1\XINT_htd_II_ciii + #2\W\W\W {\XINT_htd_II_d {}{"#2}{\xint_c_xvi}}% +\def\XINT_htd_II_cii\W\XINT_htd_II_ciii + #1#2\W\W {\XINT_htd_II_d {}{"#1#2}{\xint_c_ii^viii}}% +\def\XINT_htd_II_ciii #1#2#3\W {\XINT_htd_II_d {}{"#1#2#3}{\xint_c_ii^xii}}% +\def\XINT_htd_I_a #1#2#3#4#5#6% +{% + \xint_gob_til_Z #3\XINT_htd_I_end_a\Z + \expandafter\XINT_htd_I_b\the\numexpr + #2+\xint_c_ii^xvi*#6#5#4#3+\xint_c_x^ix\relax {#1}% +}% +\def\XINT_htd_I_b 1#1#2#3#4#5#6#7#8#9{\XINT_htd_I_c {#1#2#3#4#5}{#9#8#7#6}}% +\def\XINT_htd_I_c #1#2#3{\XINT_htd_I_a {#3#2}{#1}}% +\def\XINT_htd_I_end_a\Z\expandafter\XINT_htd_I_b\the\numexpr #1+#2\relax +{% + \expandafter\XINT_htd_I_end_b\the\numexpr \xint_c_x^v+#1\relax +}% +\def\XINT_htd_I_end_b 1#1#2#3#4#5% +{% + \xint_gob_til_zero #1\XINT_htd_I_end_bz0% + \XINT_htd_I_end_c #1#2#3#4#5% +}% +\def\XINT_htd_I_end_c #1#2#3#4#5#6{\XINT_htd_I {#6#5#4#3#2#1000}}% +\def\XINT_htd_I_end_bz0\XINT_htd_I_end_c 0#1#2#3#4% +{% + \xint_gob_til_zeros_iv #1#2#3#4\XINT_htd_I_end_bzz 0000% + \XINT_htd_I_end_D {#4#3#2#1}% +}% +\def\XINT_htd_I_end_D #1#2{\XINT_htd_I {#2#1}}% +\def\XINT_htd_I_end_bzz 0000\XINT_htd_I_end_D #1{\XINT_htd_I }% +\def\XINT_htd_II_d #1#2#3#4#5#6#7% +{% + \xint_gob_til_Z #4\XINT_htd_II_end_a\Z + \expandafter\XINT_htd_II_e\the\numexpr + #2+#3*#7#6#5#4+\xint_c_x^viii\relax {#1}{#3}% +}% +\def\XINT_htd_II_e 1#1#2#3#4#5#6#7#8{\XINT_htd_II_f {#1#2#3#4}{#5#6#7#8}}% +\def\XINT_htd_II_f #1#2#3{\XINT_htd_II_d {#2#3}{#1}}% +\def\XINT_htd_II_end_a\Z\expandafter\XINT_htd_II_e + \the\numexpr #1+#2\relax #3#4\T +{% + \XINT_htd_II_end_b #1#3% +}% +\edef\XINT_htd_II_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 +}% +% \end{macrocode} +% \subsection{\csh{xintBinToDec}} +% \lverb!v1.08! +% \begin{macrocode} +\def\xintBinToDec {\romannumeral0\xintbintodec }% +\def\xintbintodec #1{\expandafter\XINT_btd_checkin + \romannumeral-`0#1\W\W\W\W\W\W\W\W \T }% +\def\XINT_btd_checkin #1% +{% + \xint_UDsignfork + #1\XINT_btd_neg + -{\XINT_btd_I {000000}#1}% + \krof +}% +\def\XINT_btd_neg {\expandafter\xint_minus_thenstop + \romannumeral0\XINT_btd_I {000000}}% +\def\XINT_btd_I #1#2#3#4#5#6#7#8#9% +{% + \xint_gob_til_W #9\XINT_btd_II_a {#2#3#4#5#6#7#8#9}\W + \XINT_btd_I_a {}{\csname XINT_sbtd_#2#3#4#5\endcsname*\xint_c_xvi+% + \csname XINT_sbtd_#6#7#8#9\endcsname}% + #1\Z\Z\Z\Z\Z\Z +}% +\def\XINT_btd_II_a #1\W\XINT_btd_I_a #2#3{\XINT_btd_II_b #1}% +\def\XINT_btd_II_b #1#2#3#4#5#6#7#8% +{% + \xint_gob_til_W + #1\XINT_btd_II_c + #2\XINT_btd_II_ci + #3\XINT_btd_II_cii + #4\XINT_btd_II_ciii + #5\XINT_btd_II_civ + #6\XINT_btd_II_cv + #7\XINT_btd_II_cvi + \W\XINT_btd_II_cvii #1#2#3#4#5#6#7#8% +}% +\def\XINT_btd_II_c #1\XINT_btd_II_cvii \W\W\W\W\W\W\W\W #2\Z\Z\Z\Z\Z\Z\T +{% + \expandafter\XINT_btd_II_c_end + \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 +}% +\edef\XINT_btd_II_c_end #1#2#3#4#5#6% +{% + \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5#6\relax +}% +\def\XINT_btd_II_ci #1\XINT_btd_II_cvii #2\W\W\W\W\W\W\W + {\XINT_btd_II_d {}{#2}{\xint_c_ii }}% +\def\XINT_btd_II_cii #1\XINT_btd_II_cvii #2\W\W\W\W\W\W + {\XINT_btd_II_d {}{\csname XINT_sbtd_00#2\endcsname }{\xint_c_iv }}% +\def\XINT_btd_II_ciii #1\XINT_btd_II_cvii #2\W\W\W\W\W + {\XINT_btd_II_d {}{\csname XINT_sbtd_0#2\endcsname }{\xint_c_viii }}% +\def\XINT_btd_II_civ #1\XINT_btd_II_cvii #2\W\W\W\W + {\XINT_btd_II_d {}{\csname XINT_sbtd_#2\endcsname}{\xint_c_xvi }}% +\def\XINT_btd_II_cv #1\XINT_btd_II_cvii #2#3#4#5#6\W\W\W +{% + \XINT_btd_II_d {}{\csname XINT_sbtd_#2#3#4#5\endcsname*\xint_c_ii+% + #6}{\xint_c_ii^v }% +}% +\def\XINT_btd_II_cvi #1\XINT_btd_II_cvii #2#3#4#5#6#7\W\W +{% + \XINT_btd_II_d {}{\csname XINT_sbtd_#2#3#4#5\endcsname*\xint_c_iv+% + \csname XINT_sbtd_00#6#7\endcsname}{\xint_c_ii^vi }% +}% +\def\XINT_btd_II_cvii #1#2#3#4#5#6#7\W +{% + \XINT_btd_II_d {}{\csname XINT_sbtd_#1#2#3#4\endcsname*\xint_c_viii+% + \csname XINT_sbtd_0#5#6#7\endcsname}{\xint_c_ii^vii }% +}% +\def\XINT_btd_II_d #1#2#3#4#5#6#7#8#9% +{% + \xint_gob_til_Z #4\XINT_btd_II_end_a\Z + \expandafter\XINT_btd_II_e\the\numexpr + #2+(\xint_c_x^ix+#3*#9#8#7#6#5#4)\relax {#1}{#3}% +}% +\def\XINT_btd_II_e 1#1#2#3#4#5#6#7#8#9{\XINT_btd_II_f {#1#2#3}{#4#5#6#7#8#9}}% +\def\XINT_btd_II_f #1#2#3{\XINT_btd_II_d {#2#3}{#1}}% +\def\XINT_btd_II_end_a\Z\expandafter\XINT_btd_II_e + \the\numexpr #1+(#2\relax #3#4\T +{% + \XINT_btd_II_end_b #1#3% +}% +\edef\XINT_btd_II_end_b #1#2#3#4#5#6#7#8#9% +{% + \noexpand\expandafter\space\noexpand\the\numexpr #1#2#3#4#5#6#7#8#9\relax +}% +\def\XINT_btd_I_a #1#2#3#4#5#6#7#8% +{% + \xint_gob_til_Z #3\XINT_btd_I_end_a\Z + \expandafter\XINT_btd_I_b\the\numexpr + #2+\xint_c_ii^viii*#8#7#6#5#4#3+\xint_c_x^ix\relax {#1}% +}% +\def\XINT_btd_I_b 1#1#2#3#4#5#6#7#8#9{\XINT_btd_I_c {#1#2#3}{#9#8#7#6#5#4}}% +\def\XINT_btd_I_c #1#2#3{\XINT_btd_I_a {#3#2}{#1}}% +\def\XINT_btd_I_end_a\Z\expandafter\XINT_btd_I_b + \the\numexpr #1+\xint_c_ii^viii #2\relax +{% + \expandafter\XINT_btd_I_end_b\the\numexpr 1000+#1\relax +}% +\def\XINT_btd_I_end_b 1#1#2#3% +{% + \xint_gob_til_zeros_iii #1#2#3\XINT_btd_I_end_bz 000% + \XINT_btd_I_end_c #1#2#3% +}% +\def\XINT_btd_I_end_c #1#2#3#4{\XINT_btd_I {#4#3#2#1000}}% +\def\XINT_btd_I_end_bz 000\XINT_btd_I_end_c 000{\XINT_btd_I }% +% \end{macrocode} +% \subsection{\csh{xintBinToHex}} +% \lverb!v1.08! +% \begin{macrocode} +\def\xintBinToHex {\romannumeral0\xintbintohex }% +\def\xintbintohex #1% +{% + \expandafter\XINT_bth_checkin + \romannumeral0\expandafter\XINT_num_loop + \romannumeral-`0#1\xint_relax\xint_relax + \xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\Z + \R\R\R\R\R\R\R\R\Z \W\W\W\W\W\W\W\W +}% +\def\XINT_bth_checkin #1% +{% + \xint_UDsignfork + #1\XINT_bth_N + -{\XINT_bth_P #1}% + \krof +}% +\def\XINT_bth_N {\expandafter\xint_minus_thenstop\romannumeral0\XINT_bth_P }% +\def\XINT_bth_P {\expandafter\XINT_bth_I\expandafter{\expandafter}% + \romannumeral0\XINT_OQ {}}% +\def\XINT_bth_I #1#2#3#4#5#6#7#8#9% +{% + \xint_gob_til_W #9\XINT_bth_end_a\W + \expandafter\expandafter\expandafter + \XINT_bth_I + \expandafter\expandafter\expandafter + {\csname XINT_sbth_#9#8#7#6\expandafter\expandafter\expandafter\endcsname + \csname XINT_sbth_#5#4#3#2\endcsname #1}% +}% +\def\XINT_bth_end_a\W \expandafter\expandafter\expandafter + \XINT_bth_I \expandafter\expandafter\expandafter #1% +{% + \XINT_bth_end_b #1% +}% +\def\XINT_bth_end_b #1\endcsname #2\endcsname #3% +{% + \xint_gob_til_zero #3\XINT_bth_end_z 0\space #3% +}% +\def\XINT_bth_end_z0\space 0{ }% +% \end{macrocode} +% \subsection{\csh{xintHexToBin}} +% \lverb!v1.08! +% \begin{macrocode} +\def\xintHexToBin {\romannumeral0\xinthextobin }% +\def\xinthextobin #1% +{% + \expandafter\XINT_htb_checkin\romannumeral-`0#1GGGGGGGG\T +}% +\def\XINT_htb_checkin #1% +{% + \xint_UDsignfork + #1\XINT_htb_N + -{\XINT_htb_P #1}% + \krof +}% +\def\XINT_htb_N {\expandafter\xint_minus_thenstop\romannumeral0\XINT_htb_P }% +\def\XINT_htb_P {\XINT_htb_I_a {}}% +\def\XINT_htb_I_a #1#2#3#4#5#6#7#8#9% +{% + \xint_gob_til_G #9\XINT_htb_II_a G% + \expandafter\expandafter\expandafter + \XINT_htb_I_b + \expandafter\expandafter\expandafter + {\csname XINT_shtb_#2\expandafter\expandafter\expandafter\endcsname + \csname XINT_shtb_#3\expandafter\expandafter\expandafter\endcsname + \csname XINT_shtb_#4\expandafter\expandafter\expandafter\endcsname + \csname XINT_shtb_#5\expandafter\expandafter\expandafter\endcsname + \csname XINT_shtb_#6\expandafter\expandafter\expandafter\endcsname + \csname XINT_shtb_#7\expandafter\expandafter\expandafter\endcsname + \csname XINT_shtb_#8\expandafter\expandafter\expandafter\endcsname + \csname XINT_shtb_#9\endcsname }{#1}% +}% +\def\XINT_htb_I_b #1#2{\XINT_htb_I_a {#2#1}}% +\def\XINT_htb_II_a G\expandafter\expandafter\expandafter\XINT_htb_I_b +{% + \expandafter\expandafter\expandafter \XINT_htb_II_b +}% +\def\XINT_htb_II_b #1#2#3\T +{% + \XINT_num_loop #2#1% + \xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\Z +}% +% \end{macrocode} +% \subsection{\csh{xintCHexToBin}} +% \lverb!v1.08! +% \begin{macrocode} +\def\xintCHexToBin {\romannumeral0\xintchextobin }% +\def\xintchextobin #1% +{% + \expandafter\XINT_chtb_checkin\romannumeral-`0#1% + \R\R\R\R\R\R\R\R\Z \W\W\W\W\W\W\W\W +}% +\def\XINT_chtb_checkin #1% +{% + \xint_UDsignfork + #1\XINT_chtb_N + -{\XINT_chtb_P #1}% + \krof +}% +\def\XINT_chtb_N {\expandafter\xint_minus_thenstop\romannumeral0\XINT_chtb_P }% +\def\XINT_chtb_P {\expandafter\XINT_chtb_I\expandafter{\expandafter}% + \romannumeral0\XINT_OQ {}}% +\def\XINT_chtb_I #1#2#3#4#5#6#7#8#9% +{% + \xint_gob_til_W #9\XINT_chtb_end_a\W + \expandafter\expandafter\expandafter + \XINT_chtb_I + \expandafter\expandafter\expandafter + {\csname XINT_shtb_#9\expandafter\expandafter\expandafter\endcsname + \csname XINT_shtb_#8\expandafter\expandafter\expandafter\endcsname + \csname XINT_shtb_#7\expandafter\expandafter\expandafter\endcsname + \csname XINT_shtb_#6\expandafter\expandafter\expandafter\endcsname + \csname XINT_shtb_#5\expandafter\expandafter\expandafter\endcsname + \csname XINT_shtb_#4\expandafter\expandafter\expandafter\endcsname + \csname XINT_shtb_#3\expandafter\expandafter\expandafter\endcsname + \csname XINT_shtb_#2\endcsname + #1}% +}% +\def\XINT_chtb_end_a\W\expandafter\expandafter\expandafter + \XINT_chtb_I\expandafter\expandafter\expandafter #1% +{% + \XINT_chtb_end_b #1% + \xint_relax\xint_relax\xint_relax\xint_relax + \xint_relax\xint_relax\xint_relax\xint_relax\Z +}% +\def\XINT_chtb_end_b #1\W#2\W#3\W#4\W#5\W#6\W#7\W#8\W\endcsname +{% + \XINT_num_loop +}% +\XINT_restorecatcodes_endinput% +% \end{macrocode} +%\catcode`\<=0 \catcode`\>=11 \catcode`\*=11 \catcode`\/=11 +%\let</xintbinhex>\relax +%\def<*xintgcd>{\catcode`\<=12 \catcode`\>=12 \catcode`\*=12 \catcode`\/=12 } +%</xintbinhex> +%<*xintgcd> +% +% \StoreCodelineNo {xintbinhex} +% +% \section{Package \xintgcdnameimp implementation} +% \label{sec:gcdimp} +% +% The commenting is currently (\docdate) very sparse. Release |1.09h| has +% modified a bit the |\xintTypesetEuclideAlgorithm| and +% |\xintTypesetBezoutAlgorithm| layout with respect to line indentation in +% particular. And they use the \xinttoolsnameimp |\xintloop| rather than the +% Plain \TeX{} or \LaTeX{}'s |\loop|. +% +% \localtableofcontents +% \subsection{Catcodes, \protect\eTeX{} and reload detection} +% +% The code for reload detection is copied from \textsc{Heiko +% Oberdiek}'s packages, and adapted here to check for previous +% loading of the master \xintname package. +% +% The method for catcodes is slightly different, but still +% directly inspired by these packages. +% +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \def\space { }% + \let\z\endgroup + \expandafter\let\expandafter\x\csname ver@xintgcd.sty\endcsname + \expandafter\let\expandafter\w\csname ver@xint.sty\endcsname + \expandafter + \ifx\csname PackageInfo\endcsname\relax + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \else + \def\y#1#2{\PackageInfo{#1}{#2}}% + \fi + \expandafter + \ifx\csname numexpr\endcsname\relax + \y{xintgcd}{\numexpr not available, aborting input}% + \aftergroup\endinput + \else + \ifx\x\relax % plain-TeX, first loading of xintgcd.sty + \ifx\w\relax % but xint.sty not yet loaded. + \y{xintgcd}{now issuing \string\input\space xint.sty}% + \def\z{\endgroup\input xint.sty\relax}% + \fi + \else + \def\empty {}% + \ifx\x\empty % LaTeX, first loading, + % variable is initialized, but \ProvidesPackage not yet seen + \ifx\w\relax % xint.sty not yet loaded. + \y{xintgcd}{now issuing \string\RequirePackage{xint}}% + \def\z{\endgroup\RequirePackage{xint}}% + \fi + \else + \y{xintgcd}{I was already loaded, aborting input}% + \aftergroup\endinput + \fi + \fi + \fi +\z% +% \end{macrocode} +% \subsection{Confirmation of \xintnameimp loading} +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \ifdefined\PackageInfo + \def\y#1#2{\PackageInfo{#1}{#2}}% + \else + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \fi + \def\empty {}% + \expandafter\let\expandafter\w\csname ver@xint.sty\endcsname + \ifx\w\relax % Plain TeX, user gave a file name at the prompt + \y{xintgcd}{Loading of package xint failed, aborting input}% + \aftergroup\endinput + \fi + \ifx\w\empty % LaTeX, user gave a file name at the prompt + \y{xintgcd}{Loading of package xint failed, aborting input}% + \aftergroup\endinput + \fi +\endgroup% +% \end{macrocode} +% \subsection{Catcodes} +% \begin{macrocode} +\XINTsetupcatcodes% +% \end{macrocode} +% \subsection{Package identification} +% \begin{macrocode} +\XINT_providespackage +\ProvidesPackage{xintgcd}% + [2014/02/05 v1.09ka Euclide algorithm with xint package (jfB)]% +% \end{macrocode} +% \subsection{\csh{xintGCD}} +% The macros of |1.09a| benefits from the |\xintnum| which has been inserted +% inside |\xintiabs| in \xintname; +% this is a little overhead but is more convenient for the +% user and also makes it easier to use into |\xintexpr|essions. +% \begin{macrocode} +\def\xintGCD {\romannumeral0\xintgcd }% +\def\xintgcd #1% +{% + \expandafter\XINT_gcd\expandafter{\romannumeral0\xintiabs {#1}}% +}% +\def\XINT_gcd #1#2% +{% + \expandafter\XINT_gcd_fork\romannumeral0\xintiabs {#2}\Z #1\Z +}% +% \end{macrocode} +% \lverb|& +% Ici #3#4=A, #1#2=B| +% \begin{macrocode} +\def\XINT_gcd_fork #1#2\Z #3#4\Z +{% + \xint_UDzerofork + #1\XINT_gcd_BisZero + #3\XINT_gcd_AisZero + 0\XINT_gcd_loop + \krof + {#1#2}{#3#4}% +}% +\def\XINT_gcd_AisZero #1#2{ #1}% +\def\XINT_gcd_BisZero #1#2{ #2}% +\def\XINT_gcd_CheckRem #1#2\Z +{% + \xint_gob_til_zero #1\xint_gcd_end0\XINT_gcd_loop {#1#2}% +}% +\def\xint_gcd_end0\XINT_gcd_loop #1#2{ #2}% +% \end{macrocode} +% \lverb|#1=B, #2=A| +% \begin{macrocode} +\def\XINT_gcd_loop #1#2% +{% + \expandafter\expandafter\expandafter + \XINT_gcd_CheckRem + \expandafter\xint_secondoftwo + \romannumeral0\XINT_div_prepare {#1}{#2}\Z + {#1}% +}% +% \end{macrocode} +% \subsection{\csh{xintGCDof}} +% \lverb|New with 1.09a. I also tried an optimization (not working two by two) +% which I thought was clever but +% it seemed to be less efficient ...| +% \begin{macrocode} +\def\xintGCDof {\romannumeral0\xintgcdof }% +\def\xintgcdof #1{\expandafter\XINT_gcdof_a\romannumeral-`0#1\relax }% +\def\XINT_gcdof_a #1{\expandafter\XINT_gcdof_b\romannumeral-`0#1\Z }% +\def\XINT_gcdof_b #1\Z #2{\expandafter\XINT_gcdof_c\romannumeral-`0#2\Z {#1}\Z}% +\def\XINT_gcdof_c #1{\xint_gob_til_relax #1\XINT_gcdof_e\relax\XINT_gcdof_d #1}% +\def\XINT_gcdof_d #1\Z {\expandafter\XINT_gcdof_b\romannumeral0\xintgcd {#1}}% +\def\XINT_gcdof_e #1\Z #2\Z { #2}% +% \end{macrocode} +% \subsection{\csh{xintLCM}} +% \lverb|New with 1.09a. Inadvertent use of \xintiQuo which was promoted at the +% same time to add the \xintnum overhead. So with 1.09f \xintiiQuo without the +% overhead.| +% \begin{macrocode} +\def\xintLCM {\romannumeral0\xintlcm}% +\def\xintlcm #1% +{% + \expandafter\XINT_lcm\expandafter{\romannumeral0\xintiabs {#1}}% +}% +\def\XINT_lcm #1#2% +{% + \expandafter\XINT_lcm_fork\romannumeral0\xintiabs {#2}\Z #1\Z +}% +\def\XINT_lcm_fork #1#2\Z #3#4\Z +{% + \xint_UDzerofork + #1\XINT_lcm_BisZero + #3\XINT_lcm_AisZero + 0\expandafter + \krof + \XINT_lcm_notzero\expandafter{\romannumeral0\XINT_gcd_loop {#1#2}{#3#4}}% + {#1#2}{#3#4}% +}% +\def\XINT_lcm_AisZero #1#2#3#4#5{ 0}% +\def\XINT_lcm_BisZero #1#2#3#4#5{ 0}% +\def\XINT_lcm_notzero #1#2#3{\xintiimul {#2}{\xintiiQuo{#3}{#1}}}% +% \end{macrocode} +% \subsection{\csh{xintLCMof}} +% \lverb|New with 1.09a| +% \begin{macrocode} +\def\xintLCMof {\romannumeral0\xintlcmof }% +\def\xintlcmof #1{\expandafter\XINT_lcmof_a\romannumeral-`0#1\relax }% +\def\XINT_lcmof_a #1{\expandafter\XINT_lcmof_b\romannumeral-`0#1\Z }% +\def\XINT_lcmof_b #1\Z #2{\expandafter\XINT_lcmof_c\romannumeral-`0#2\Z {#1}\Z}% +\def\XINT_lcmof_c #1{\xint_gob_til_relax #1\XINT_lcmof_e\relax\XINT_lcmof_d #1}% +\def\XINT_lcmof_d #1\Z {\expandafter\XINT_lcmof_b\romannumeral0\xintlcm {#1}}% +\def\XINT_lcmof_e #1\Z #2\Z { #2}% +% \end{macrocode} +% \subsection{\csh{xintBezout}} +% \lverb|1.09a inserts use of \xintnum| +% \begin{macrocode} +\def\xintBezout {\romannumeral0\xintbezout }% +\def\xintbezout #1% +{% + \expandafter\xint_bezout\expandafter {\romannumeral0\xintnum{#1}}% +}% +\def\xint_bezout #1#2% +{% + \expandafter\XINT_bezout_fork \romannumeral0\xintnum{#2}\Z #1\Z +}% +% \end{macrocode} +% \lverb|#3#4 = A, #1#2=B| +% \begin{macrocode} +\def\XINT_bezout_fork #1#2\Z #3#4\Z +{% + \xint_UDzerosfork + #1#3\XINT_bezout_botharezero + #10\XINT_bezout_secondiszero + #30\XINT_bezout_firstiszero + 00{\xint_UDsignsfork + #1#3\XINT_bezout_minusminus % A < 0, B < 0 + #1-\XINT_bezout_minusplus % A > 0, B < 0 + #3-\XINT_bezout_plusminus % A < 0, B > 0 + --\XINT_bezout_plusplus % A > 0, B > 0 + \krof }% + \krof + {#2}{#4}#1#3{#3#4}{#1#2}% #1#2=B, #3#4=A +}% +\edef\XINT_bezout_botharezero #1#2#3#4#5#6% +{% + \noexpand\xintError:NoBezoutForZeros + \space {0}{0}{0}{0}{0}% +}% +% \end{macrocode} +% \lverb|& +% attention première entrée doit être ici (-1)^n donc 1$\ +% #4#2 = 0 = A, B = #3#1| +% \begin{macrocode} +\def\XINT_bezout_firstiszero #1#2#3#4#5#6% +{% + \xint_UDsignfork + #3{ {0}{#3#1}{0}{1}{#1}}% + -{ {0}{#3#1}{0}{-1}{#1}}% + \krof +}% +% \end{macrocode} +% \lverb|#4#2 = A, B = #3#1 = 0| +% \begin{macrocode} +\def\XINT_bezout_secondiszero #1#2#3#4#5#6% +{% + \xint_UDsignfork + #4{ {#4#2}{0}{-1}{0}{#2}}% + -{ {#4#2}{0}{1}{0}{#2}}% + \krof +}% +% \end{macrocode} +% \lverb|#4#2= A < 0, #3#1 = B < 0| +% \begin{macrocode} +\def\XINT_bezout_minusminus #1#2#3#4% +{% + \expandafter\XINT_bezout_mm_post + \romannumeral0\XINT_bezout_loop_a 1{#1}{#2}1001% +}% +\def\XINT_bezout_mm_post #1#2% +{% + \expandafter\XINT_bezout_mm_postb\expandafter + {\romannumeral0\xintiiopp{#2}}{\romannumeral0\xintiiopp{#1}}% +}% +\def\XINT_bezout_mm_postb #1#2% +{% + \expandafter\XINT_bezout_mm_postc\expandafter {#2}{#1}% +}% +\edef\XINT_bezout_mm_postc #1#2#3#4#5% +{% + \space {#4}{#5}{#1}{#2}{#3}% +}% +% \end{macrocode} +% \lverb|minusplus #4#2= A > 0, B < 0| +% \begin{macrocode} +\def\XINT_bezout_minusplus #1#2#3#4% +{% + \expandafter\XINT_bezout_mp_post + \romannumeral0\XINT_bezout_loop_a 1{#1}{#4#2}1001% +}% +\def\XINT_bezout_mp_post #1#2% +{% + \expandafter\XINT_bezout_mp_postb\expandafter + {\romannumeral0\xintiiopp {#2}}{#1}% +}% +\edef\XINT_bezout_mp_postb #1#2#3#4#5% +{% + \space {#4}{#5}{#2}{#1}{#3}% +}% +% \end{macrocode} +% \lverb|plusminus A < 0, B > 0| +% \begin{macrocode} +\def\XINT_bezout_plusminus #1#2#3#4% +{% + \expandafter\XINT_bezout_pm_post + \romannumeral0\XINT_bezout_loop_a 1{#3#1}{#2}1001% +}% +\def\XINT_bezout_pm_post #1% +{% + \expandafter \XINT_bezout_pm_postb \expandafter + {\romannumeral0\xintiiopp{#1}}% +}% +\edef\XINT_bezout_pm_postb #1#2#3#4#5% +{% + \space {#4}{#5}{#1}{#2}{#3}% +}% +% \end{macrocode} +% \lverb|plusplus| +% \begin{macrocode} +\def\XINT_bezout_plusplus #1#2#3#4% +{% + \expandafter\XINT_bezout_pp_post + \romannumeral0\XINT_bezout_loop_a 1{#3#1}{#4#2}1001% +}% +% \end{macrocode} +% \lverb|la parité (-1)^N est en #1, et on la jette ici.| +% \begin{macrocode} +\edef\XINT_bezout_pp_post #1#2#3#4#5% +{% + \space {#4}{#5}{#1}{#2}{#3}% +}% +% \end{macrocode} +% \lverb|& +% n = 0: 1BAalpha(0)beta(0)alpha(-1)beta(-1)$\ +% n général: +% {(-1)^n}{r(n-1)}{r(n-2)}{alpha(n-1)}{beta(n-1)}{alpha(n-2)}{beta(n-2)}$\ +% #2 = B, #3 = A| +% \begin{macrocode} +\def\XINT_bezout_loop_a #1#2#3% +{% + \expandafter\XINT_bezout_loop_b + \expandafter{\the\numexpr -#1\expandafter }% + \romannumeral0\XINT_div_prepare {#2}{#3}{#2}% +}% +% \end{macrocode} +% \lverb|& +% Le q(n) a ici une existence éphémère, dans le version Bezout Algorithm +% il faudra le conserver. On voudra à la fin +% {{q(n)}{r(n)}{alpha(n)}{beta(n)}}. +% De plus ce n'est plus (-1)^n que l'on veut mais n. (ou dans un autre ordre)$\ +% {-(-1)^n}{q(n)}{r(n)}{r(n-1)}{alpha(n-1)}{beta(n-1)}{alpha(n-2)}{beta(n-2)}| +% \begin{macrocode} +\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}}% + {#1}{#3}{#4}{#5}{#6}% +}% +% \end{macrocode} +% \lverb|{alpha(n)}{->beta(n)}{-(-1)^n}{r(n)}{r(n-1)}{alpha(n-1)}{beta(n-1)}| +% \begin{macrocode} +\def\XINT_bezout_loop_c #1#2% +{% + \expandafter \XINT_bezout_loop_d \expandafter + {#2}{#1}% +}% +% \end{macrocode} +% \lverb|{beta(n)}{alpha(n)}{(-1)^(n+1)}{r(n)}{r(n-1)}{alpha(n-1)}{beta(n-1)}| +% \begin{macrocode} +\def\XINT_bezout_loop_d #1#2#3#4#5% +{% + \XINT_bezout_loop_e #4\Z {#3}{#5}{#2}{#1}% +}% +% \end{macrocode} +% \lverb|r(n)\Z {(-1)^(n+1)}{r(n-1)}{alpha(n)}{beta(n)}{alpha(n-1)}{beta(n-1)}| +% \begin{macrocode} +\def\XINT_bezout_loop_e #1#2\Z +{% + \xint_gob_til_zero #1\xint_bezout_loop_exit0\XINT_bezout_loop_f + {#1#2}% +}% +% \end{macrocode} +% \lverb|{r(n)}{(-1)^(n+1)}{r(n-1)}{alpha(n)}{beta(n)}{alpha(n-1)}{beta(n-1)}| +% \begin{macrocode} +\def\XINT_bezout_loop_f #1#2% +{% + \XINT_bezout_loop_a {#2}{#1}% +}% +% \end{macrocode} +% \lverb|{(-1)^(n+1)}{r(n)}{r(n-1)}{alpha(n)}{beta(n)}{alpha(n-1)}{beta(n-1)} +% et itération| +% \begin{macrocode} +\def\xint_bezout_loop_exit0\XINT_bezout_loop_f #1#2% +{% + \ifcase #2 + \or \expandafter\XINT_bezout_exiteven + \else\expandafter\XINT_bezout_exitodd + \fi +}% +\edef\XINT_bezout_exiteven #1#2#3#4#5% +{% + \space {#5}{#4}{#1}% +}% +\edef\XINT_bezout_exitodd #1#2#3#4#5% +{% + \space {-#5}{-#4}{#1}% +}% +% \end{macrocode} +% \subsection{\csh{xintEuclideAlgorithm}} +% \lverb|& +% Pour Euclide: +% {N}{A}{D=r(n)}{B}{q1}{r1}{q2}{r2}{q3}{r3}....{qN}{rN=0}$\ +% u<2n> = u<2n+3>u<2n+2> + u<2n+4> à la n ième étape| +% \begin{macrocode} +\def\xintEuclideAlgorithm {\romannumeral0\xinteuclidealgorithm }% +\def\xinteuclidealgorithm #1% +{% + \expandafter \XINT_euc \expandafter{\romannumeral0\xintiabs {#1}}% +}% +\def\XINT_euc #1#2% +{% + \expandafter\XINT_euc_fork \romannumeral0\xintiabs {#2}\Z #1\Z +}% +% \end{macrocode} +% \lverb|Ici #3#4=A, #1#2=B| +% \begin{macrocode} +\def\XINT_euc_fork #1#2\Z #3#4\Z +{% + \xint_UDzerofork + #1\XINT_euc_BisZero + #3\XINT_euc_AisZero + 0\XINT_euc_a + \krof + {0}{#1#2}{#3#4}{{#3#4}{#1#2}}{}\Z +}% +% \end{macrocode} +% \lverb|& +% Le {} pour protéger {{A}{B}} si on s'arrête après une étape (B divise +% A). +% On va renvoyer:$\ +% {N}{A}{D=r(n)}{B}{q1}{r1}{q2}{r2}{q3}{r3}....{qN}{rN=0}| +% \begin{macrocode} +\def\XINT_euc_AisZero #1#2#3#4#5#6{ {1}{0}{#2}{#2}{0}{0}}% +\def\XINT_euc_BisZero #1#2#3#4#5#6{ {1}{0}{#3}{#3}{0}{0}}% +% \end{macrocode} +% \lverb|& +% {n}{rn}{an}{{qn}{rn}}...{{A}{B}}{}\Z$\ +% a(n) = r(n-1). Pour n=0 on a juste {0}{B}{A}{{A}{B}}{}\Z$\ +% \XINT_div_prepare {u}{v} divise v par u| +% \begin{macrocode} +\def\XINT_euc_a #1#2#3% +{% + \expandafter\XINT_euc_b + \expandafter {\the\numexpr #1+1\expandafter }% + \romannumeral0\XINT_div_prepare {#2}{#3}{#2}% +}% +% \end{macrocode} +% \lverb|{n+1}{q(n+1)}{r(n+1)}{rn}{{qn}{rn}}...| +% \begin{macrocode} +\def\XINT_euc_b #1#2#3#4% +{% + \XINT_euc_c #3\Z {#1}{#3}{#4}{{#2}{#3}}% +}% +% \end{macrocode} +% \lverb|r(n+1)\Z {n+1}{r(n+1)}{r(n)}{{q(n+1)}{r(n+1)}}{{qn}{rn}}...$\ +% Test si r(n+1) est nul.| +% \begin{macrocode} +\def\XINT_euc_c #1#2\Z +{% + \xint_gob_til_zero #1\xint_euc_end0\XINT_euc_a +}% +% \end{macrocode} +% \lverb|& +% {n+1}{r(n+1)}{r(n)}{{q(n+1)}{r(n+1)}}...{}\Z +% Ici r(n+1) = 0. On arrête on se prépare à inverser +% {n+1}{0}{r(n)}{{q(n+1)}{r(n+1)}}.....{{q1}{r1}}{{A}{B}}{}\Z$\ +% On veut renvoyer: {N=n+1}{A}{D=r(n)}{B}{q1}{r1}{q2}{r2}{q3}{r3}....{qN}{rN=0}| +% \begin{macrocode} +\def\xint_euc_end0\XINT_euc_a #1#2#3#4\Z% +{% + \expandafter\xint_euc_end_ + \romannumeral0% + \XINT_rord_main {}#4{{#1}{#3}}% + \xint_relax + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_relax +}% +\edef\xint_euc_end_ #1#2#3% +{% + \space {#1}{#3}{#2}% +}% +% \end{macrocode} +% \subsection{\csh{xintBezoutAlgorithm}} +% \lverb|& +% Pour Bezout: objectif, renvoyer$\ +% {N}{A}{0}{1}{D=r(n)}{B}{1}{0}{q1}{r1}{alpha1=q1}{beta1=1}$\ +% {q2}{r2}{alpha2}{beta2}....{qN}{rN=0}{alphaN=A/D}{betaN=B/D}$\ +% alpha0=1, beta0=0, alpha(-1)=0, beta(-1)=1| +% \begin{macrocode} +\def\xintBezoutAlgorithm {\romannumeral0\xintbezoutalgorithm }% +\def\xintbezoutalgorithm #1% +{% + \expandafter \XINT_bezalg \expandafter{\romannumeral0\xintiabs {#1}}% +}% +\def\XINT_bezalg #1#2% +{% + \expandafter\XINT_bezalg_fork \romannumeral0\xintiabs {#2}\Z #1\Z +}% +% \end{macrocode} +% \lverb|Ici #3#4=A, #1#2=B| +% \begin{macrocode} +\def\XINT_bezalg_fork #1#2\Z #3#4\Z +{% + \xint_UDzerofork + #1\XINT_bezalg_BisZero + #3\XINT_bezalg_AisZero + 0\XINT_bezalg_a + \krof + 0{#1#2}{#3#4}1001{{#3#4}{#1#2}}{}\Z +}% +\def\XINT_bezalg_AisZero #1#2#3\Z{ {1}{0}{0}{1}{#2}{#2}{1}{0}{0}{0}{0}{1}}% +\def\XINT_bezalg_BisZero #1#2#3#4\Z{ {1}{0}{0}{1}{#3}{#3}{1}{0}{0}{0}{0}{1}}% +% \end{macrocode} +% \lverb|& +% pour préparer l'étape n+1 il faut +% {n}{r(n)}{r(n-1)}{alpha(n)}{beta(n)}{alpha(n-1)}{beta(n-1)}& +% {{q(n)}{r(n)}{alpha(n)}{beta(n)}}... +% division de #3 par #2| +% \begin{macrocode} +\def\XINT_bezalg_a #1#2#3% +{% + \expandafter\XINT_bezalg_b + \expandafter {\the\numexpr #1+1\expandafter }% + \romannumeral0\XINT_div_prepare {#2}{#3}{#2}% +}% +% \end{macrocode} +% \lverb|& +% {n+1}{q(n+1)}{r(n+1)}{r(n)}{alpha(n)}{beta(n)}{alpha(n-1)}{beta(n-1)}...| +% \begin{macrocode} +\def\XINT_bezalg_b #1#2#3#4#5#6#7#8% +{% + \expandafter\XINT_bezalg_c\expandafter + {\romannumeral0\xintiiadd {\xintiiMul {#6}{#2}}{#8}}% + {\romannumeral0\xintiiadd {\xintiiMul {#5}{#2}}{#7}}% + {#1}{#2}{#3}{#4}{#5}{#6}% +}% +% \end{macrocode} +% \lverb|& +% {beta(n+1)}{alpha(n+1)}{n+1}{q(n+1)}{r(n+1)}{r(n)}{alpha(n)}{beta(n}}| +% \begin{macrocode} +\def\XINT_bezalg_c #1#2#3#4#5#6% +{% + \expandafter\XINT_bezalg_d\expandafter {#2}{#3}{#4}{#5}{#6}{#1}% +}% +% \end{macrocode} +% \lverb|{alpha(n+1)}{n+1}{q(n+1)}{r(n+1)}{r(n)}{beta(n+1)}| +% \begin{macrocode} +\def\XINT_bezalg_d #1#2#3#4#5#6#7#8% +{% + \XINT_bezalg_e #4\Z {#2}{#4}{#5}{#1}{#6}{#7}{#8}{{#3}{#4}{#1}{#6}}% +}% +% \end{macrocode} +% \lverb|r(n+1)\Z {n+1}{r(n+1)}{r(n)}{alpha(n+1)}{beta(n+1)}$\ +% {alpha(n)}{beta(n)}{q,r,alpha,beta(n+1)}$\ +% Test si r(n+1) est nul.| +% \begin{macrocode} +\def\XINT_bezalg_e #1#2\Z +{% + \xint_gob_til_zero #1\xint_bezalg_end0\XINT_bezalg_a +}% +% \end{macrocode} +% \lverb|& +% Ici r(n+1) = 0. On arrête on se prépare à inverser.$\ +% {n+1}{r(n+1)}{r(n)}{alpha(n+1)}{beta(n+1)}{alpha(n)}{beta(n)}$\ +% {q,r,alpha,beta(n+1)}...{{A}{B}}{}\Z$\ +% On veut renvoyer$\ +% {N}{A}{0}{1}{D=r(n)}{B}{1}{0}{q1}{r1}{alpha1=q1}{beta1=1}$\ +% {q2}{r2}{alpha2}{beta2}....{qN}{rN=0}{alphaN=A/D}{betaN=B/D}| +% \begin{macrocode} +\def\xint_bezalg_end0\XINT_bezalg_a #1#2#3#4#5#6#7#8\Z +{% + \expandafter\xint_bezalg_end_ + \romannumeral0% + \XINT_rord_main {}#8{{#1}{#3}}% + \xint_relax + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_relax +}% +% \end{macrocode} +% \lverb|& +% {N}{D}{A}{B}{q1}{r1}{alpha1=q1}{beta1=1}{q2}{r2}{alpha2}{beta2}$\ +% ....{qN}{rN=0}{alphaN=A/D}{betaN=B/D}$\ +% On veut renvoyer$\ +% {N}{A}{0}{1}{D=r(n)}{B}{1}{0}{q1}{r1}{alpha1=q1}{beta1=1}$\ +% {q2}{r2}{alpha2}{beta2}....{qN}{rN=0}{alphaN=A/D}{betaN=B/D}| +% \begin{macrocode} +\edef\xint_bezalg_end_ #1#2#3#4% +{% + \space {#1}{#3}{0}{1}{#2}{#4}{1}{0}% +}% +% \end{macrocode} +% \subsection{\csh{xintTypesetEuclideAlgorithm}} +% \lverb|& +% TYPESETTING +% +% Organisation: +% +% {N}{A}{D}{B}{q1}{r1}{q2}{r2}{q3}{r3}....{qN}{rN=0}$\ +% \U1 = N = nombre d'étapes, \U3 = PGCD, \U2 = A, \U4=B +% q1 = \U5, q2 = \U7 --> qn = \U<2n+3>, rn = \U<2n+4> +% bn = rn. B = r0. A=r(-1) +% +% r(n-2) = q(n)r(n-1)+r(n) (n e étape) +% +% \U{2n} = \U{2n+3} \times \U{2n+2} + \U{2n+4}, n e étape. +% (avec n entre 1 et N) +% +% 1.09h uses \xintloop, and \par rather than \endgraf; and \par rather than +% \hfill\break| +% \begin{macrocode} +\def\xintTypesetEuclideAlgorithm #1#2% +{% l'algo remplace #1 et #2 par |#1| et |#2| + \par + \begingroup + \xintAssignArray\xintEuclideAlgorithm {#1}{#2}\to\U + \edef\A{\U2}\edef\B{\U4}\edef\N{\U1}% + \setbox 0 \vbox{\halign {$##$\cr \A\cr \B \cr}}% + \count 255 1 + \xintloop + \indent\hbox to \wd 0 {\hfil$\U{\numexpr 2*\count255\relax}$}% + ${} = \U{\numexpr 2*\count255 + 3\relax} + \times \U{\numexpr 2*\count255 + 2\relax} + + \U{\numexpr 2*\count255 + 4\relax}$% + \ifnum \count255 < \N + \par + \advance \count255 1 + \repeat + \endgroup +}% +% \end{macrocode} +% \subsection{\csh{xintTypesetBezoutAlgorithm}} +% \lverb|& +% Pour Bezout on a: +% {N}{A}{0}{1}{D=r(n)}{B}{1}{0}{q1}{r1}{alpha1=q1}{beta1=1}$\ +% {q2}{r2}{alpha2}{beta2}....{qN}{rN=0}{alphaN=A/D}{betaN=B/D}% +% Donc 4N+8 termes: +% U1 = N, U2= A, U5=D, U6=B, q1 = U9, qn = U{4n+5}, n au moins 1$\ +% rn = U{4n+6}, n au moins -1$\ +% alpha(n) = U{4n+7}, n au moins -1$\ +% beta(n) = U{4n+8}, n au moins -1 +% +% 1.09h uses \xintloop, and \par rather than \endgraf; and no more \parindent0pt +% | +% \begin{macrocode} +\def\xintTypesetBezoutAlgorithm #1#2% +{% + \par + \begingroup + \xintAssignArray\xintBezoutAlgorithm {#1}{#2}\to\BEZ + \edef\A{\BEZ2}\edef\B{\BEZ6}\edef\N{\BEZ1}% A = |#1|, B = |#2| + \setbox 0 \vbox{\halign {$##$\cr \A\cr \B \cr}}% + \count255 1 + \xintloop + \indent\hbox to \wd 0 {\hfil$\BEZ{4*\count255 - 2}$}% + ${} = \BEZ{4*\count255 + 5} + \times \BEZ{4*\count255 + 2} + + \BEZ{4*\count255 + 6}$\hfill\break + \hbox to \wd 0 {\hfil$\BEZ{4*\count255 +7}$}% + ${} = \BEZ{4*\count255 + 5} + \times \BEZ{4*\count255 + 3} + + \BEZ{4*\count255 - 1}$\hfill\break + \hbox to \wd 0 {\hfil$\BEZ{4*\count255 +8}$}% + ${} = \BEZ{4*\count255 + 5} + \times \BEZ{4*\count255 + 4} + + \BEZ{4*\count255 }$ + \par + \ifnum \count255 < \N + \advance \count255 1 + \repeat + \edef\U{\BEZ{4*\N + 4}}% + \edef\V{\BEZ{4*\N + 3}}% + \edef\D{\BEZ5}% + \ifodd\N + $\U\times\A - \V\times \B = -\D$% + \else + $\U\times\A - \V\times\B = \D$% + \fi + \par + \endgroup +}% +% \end{macrocode} +% \subsection{\csh{xintGCDof:csv}} +% \lverb|1.09a. For use by \xintexpr.| +% \begin{macrocode} +\def\xintGCDof:csv #1{\expandafter\XINT_gcdof:_b\romannumeral-`0#1,,}% +\def\XINT_gcdof:_b #1,#2,{\expandafter\XINT_gcdof:_c\romannumeral-`0#2,{#1},}% +\def\XINT_gcdof:_c #1{\if #1,\expandafter\XINT_of:_e + \else\expandafter\XINT_gcdof:_d\fi #1}% +\def\XINT_gcdof:_d #1,{\expandafter\XINT_gcdof:_b\romannumeral0\xintgcd {#1}}% +% \end{macrocode} +% \subsection{\csh{xintLCMof:csv}} +% \lverb|1.09a. For use by \xintexpr.| +% \begin{macrocode} +\def\xintLCMof:csv #1{\expandafter\XINT_lcmof:_a\romannumeral-`0#1,,}% +\def\XINT_lcmof:_a #1,#2,{\expandafter\XINT_lcmof:_c\romannumeral-`0#2,{#1},}% +\def\XINT_lcmof:_c #1{\if#1,\expandafter\XINT_of:_e + \else\expandafter\XINT_lcmof:_d\fi #1}% +\def\XINT_lcmof:_d #1,{\expandafter\XINT_lcmof:_a\romannumeral0\xintlcm {#1}}% +\XINT_restorecatcodes_endinput% +% \end{macrocode} +%\catcode`\<=0 \catcode`\>=11 \catcode`\*=11 \catcode`\/=11 +%\let</xintgcd>\relax +%\def<*xintfrac>{\catcode`\<=12 \catcode`\>=12 \catcode`\*=12 \catcode`\/=12 } +%</xintgcd> +%<*xintfrac> +% +% \StoreCodelineNo {xintgcd} +% +% \section{Package \xintfracnameimp implementation} +% \label{sec:fracimp} +% +% The commenting is currently (\docdate) very sparse. +% +% \localtableofcontents +% \subsection{Catcodes, \protect\eTeX{} and reload detection} +% +% The code for reload detection is copied from \textsc{Heiko +% Oberdiek}'s packages, and adapted here to check for previous +% loading of the master \xintname package. +% +% The method for catcodes is slightly different, but still +% directly inspired by these packages. +% +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \def\space { }% + \let\z\endgroup + \expandafter\let\expandafter\x\csname ver@xintfrac.sty\endcsname + \expandafter\let\expandafter\w\csname ver@xint.sty\endcsname + \expandafter + \ifx\csname PackageInfo\endcsname\relax + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \else + \def\y#1#2{\PackageInfo{#1}{#2}}% + \fi + \expandafter + \ifx\csname numexpr\endcsname\relax + \y{xintfrac}{\numexpr not available, aborting input}% + \aftergroup\endinput + \else + \ifx\x\relax % plain-TeX, first loading of xintfrac.sty + \ifx\w\relax % but xint.sty not yet loaded. + \y{xintfrac}{now issuing \string\input\space xint.sty}% + \def\z{\endgroup\input xint.sty\relax}% + \fi + \else + \def\empty {}% + \ifx\x\empty % LaTeX, first loading, + % variable is initialized, but \ProvidesPackage not yet seen + \ifx\w\relax % xint.sty not yet loaded. + \y{xintfrac}{now issuing \string\RequirePackage{xint}}% + \def\z{\endgroup\RequirePackage{xint}}% + \fi + \else + \y{xintfrac}{I was already loaded, aborting input}% + \aftergroup\endinput + \fi + \fi + \fi +\z% +% \end{macrocode} +% \subsection{Confirmation of \xintnameimp loading} +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \ifdefined\PackageInfo + \def\y#1#2{\PackageInfo{#1}{#2}}% + \else + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \fi + \def\empty {}% + \expandafter\let\expandafter\w\csname ver@xint.sty\endcsname + \ifx\w\relax % Plain TeX, user gave a file name at the prompt + \y{xintfrac}{Loading of package xint failed, aborting input}% + \aftergroup\endinput + \fi + \ifx\w\empty % LaTeX, user gave a file name at the prompt + \y{xintfrac}{Loading of package xint failed, aborting input}% + \aftergroup\endinput + \fi +\endgroup% +% \end{macrocode} +% \subsection{Catcodes} +% \begin{macrocode} +\XINTsetupcatcodes% +% \end{macrocode} +% \subsection{Package identification} +% \begin{macrocode} +\XINT_providespackage +\ProvidesPackage{xintfrac}% + [2014/02/05 v1.09ka Expandable operations on fractions (jfB)]% +\chardef\xint_c_vi 6 +\chardef\xint_c_vii 7 +\chardef\xint_c_xviii 18 +% \end{macrocode} +% \subsection{\csh{xintLen}} +% \begin{macrocode} +\def\xintLen {\romannumeral0\xintlen }% +\def\xintlen #1% +{% + \expandafter\XINT_flen\romannumeral0\XINT_infrac {#1}% +}% +\def\XINT_flen #1#2#3% +{% + \expandafter\space + \the\numexpr -1+\XINT_Abs {#1}+\XINT_Len {#2}+\XINT_Len {#3}\relax +}% +% \end{macrocode} +% \subsection{\csh{XINT\_lenrord\_loop}} +% \begin{macrocode} +\def\XINT_lenrord_loop #1#2#3#4#5#6#7#8#9% +{% faire \romannumeral-`0\XINT_lenrord_loop 0{}#1\Z\W\W\W\W\W\W\W\Z + \xint_gob_til_W #9\XINT_lenrord_W\W + \expandafter\XINT_lenrord_loop\expandafter + {\the\numexpr #1+7}{#9#8#7#6#5#4#3#2}% +}% +\def\XINT_lenrord_W\W\expandafter\XINT_lenrord_loop\expandafter #1#2#3\Z +{% + \expandafter\XINT_lenrord_X\expandafter {#1}#2\Z +}% +\def\XINT_lenrord_X #1#2\Z +{% + \XINT_lenrord_Y #2\R\R\R\R\R\R\T {#1}% +}% +\def\XINT_lenrord_Y #1#2#3#4#5#6#7#8\T +{% + \xint_gob_til_W + #7\XINT_lenrord_Z \xint_c_viii + #6\XINT_lenrord_Z \xint_c_vii + #5\XINT_lenrord_Z \xint_c_vi + #4\XINT_lenrord_Z \xint_c_v + #3\XINT_lenrord_Z \xint_c_iv + #2\XINT_lenrord_Z \xint_c_iii + \W\XINT_lenrord_Z \xint_c_ii \Z +}% +\def\XINT_lenrord_Z #1#2\Z #3% retourne: {longueur}renverse\Z +{% + \expandafter{\the\numexpr #3-#1\relax}% +}% +% \end{macrocode} +% \subsection{\csh{XINT\_outfrac}} +% \lverb|& +% 1.06a version now outputs 0/1[0] and not 0[0] in case of zero. More generally +% all macros have been checked in xintfrac, xintseries, xintcfrac, to make sure +% the output format for fractions was always A/B[n]. (except \xintIrr, +% \xintJrr, \xintRawWithZeros) +% +% The problem with statements like those in the previous paragraph is that it is +% hard to maintain consistencies across relases. | +% \begin{macrocode} +\def\XINT_outfrac #1#2#3% +{% + \ifcase\XINT_cntSgn #3\Z + \expandafter \XINT_outfrac_divisionbyzero + \or + \expandafter \XINT_outfrac_P + \else + \expandafter \XINT_outfrac_N + \fi + {#2}{#3}[#1]% +}% +\def\XINT_outfrac_divisionbyzero #1#2{\xintError:DivisionByZero\space #1/0}% +\edef\XINT_outfrac_P #1#2% +{% + \noexpand\if0\noexpand\XINT_Sgn #1\noexpand\Z + \noexpand\expandafter\noexpand\XINT_outfrac_Zero + \noexpand\fi + \space #1/#2% +}% +\def\XINT_outfrac_Zero #1[#2]{ 0/1[0]}% +\def\XINT_outfrac_N #1#2% +{% + \expandafter\XINT_outfrac_N_a\expandafter + {\romannumeral0\XINT_opp #2}{\romannumeral0\XINT_opp #1}% +}% +\def\XINT_outfrac_N_a #1#2% +{% + \expandafter\XINT_outfrac_P\expandafter {#2}{#1}% +}% +% \end{macrocode} +% \subsection{\csh{XINT\_inFrac}} +% \lverb|Extended in 1.07 to accept scientific notation on input. With lowercase +% e only. The \xintexpr parser does accept uppercase E also.| +% \begin{macrocode} +\def\XINT_inFrac {\romannumeral0\XINT_infrac }% +\def\XINT_infrac #1% +{% + \expandafter\XINT_infrac_ \romannumeral-`0#1[\W]\Z\T +}% +\def\XINT_infrac_ #1[#2#3]#4\Z +{% + \xint_UDwfork + #2\XINT_infrac_A + \W\XINT_infrac_B + \krof + #1[#2#3]#4% +}% +\def\XINT_infrac_A #1[\W]\T +{% + \XINT_frac #1/\W\Z +}% +\def\XINT_infrac_B #1% +{% + \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}% + \krof + #3\Z #1\Z +}% +\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}}% +% \end{macrocode} +% \subsection{\csh{XINT\_frac}} +% \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 | +% \begin{macrocode} +\def\XINT_frac #1/#2#3\Z +{% + \xint_UDwfork + #2\XINT_frac_A + \W{\expandafter\XINT_frac_U \romannumeral-`0#2}% + \krof + #3e\W\Z #1e\W\Z +}% +\def\XINT_frac_U #1e#2#3\Z +{% + \xint_UDwfork + #2\XINT_frac_Ua + \W{\XINT_frac_Ub #2}% + \krof + #3\Z #1\Z +}% +\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 +{% + \xint_UDwfork + #2\XINT_frac_Ba + \W{\XINT_frac_Bb #2}% + \krof + #3\Z #1\Z +}% +\def\XINT_frac_Ba \Z #1\Z {\XINT_frac_T {0}{#1}}% +\def\XINT_frac_Bb #1.\W\Z #2\Z +{% + \expandafter \XINT_frac_T \expandafter + {\romannumeral0\xintlength {#1}}{#2#1}% +}% +\def\XINT_frac_A e\W\Z {\XINT_frac_T {0}{1}{0}}% +\def\XINT_frac_T #1#2#3#4e#5#6\Z +{% + \xint_UDwfork + #5\XINT_frac_Ta + \W{\XINT_frac_Tb #5}% + \krof + #6\Z #4\Z {#1}{#2}{#3}% +}% +\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 +{% + \xint_UDwfork + #2\XINT_frac_Ca + \W{\XINT_frac_Cb #2}% + \krof + #3\Z #1\Z +}% +\def\XINT_frac_Ca \Z #1\Z {\XINT_frac_D {0}{#1}}% +\def\XINT_frac_Cb #1.\W\Z #2\Z +{% + \expandafter\XINT_frac_D\expandafter + {\romannumeral0\xintlength {#1}}{#2#1}% +}% +\def\XINT_frac_D #1#2#3#4#5#6% +{% + \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 }% +}% +\def\XINT_frac_E #1#2#3% +{% + \expandafter \XINT_frac_F #3\Z {#2}{#1}% +}% +\def\XINT_frac_F #1% +{% + \xint_UDzerominusfork + #1-\XINT_frac_Gdivisionbyzero + 0#1\XINT_frac_Gneg + 0-{\XINT_frac_Gpos #1}% + \krof +}% +\edef\XINT_frac_Gdivisionbyzero #1\Z #2#3% +{% + \noexpand\xintError:DivisionByZero\space {0}{#2}{0}% +}% +\def\XINT_frac_Gneg #1\Z #2#3% +{% + \expandafter\XINT_frac_H \expandafter{\romannumeral0\XINT_opp #2}{#3}{#1}% +}% +\def\XINT_frac_H #1#2{ {#2}{#1}}% +\def\XINT_frac_Gpos #1\Z #2#3{ {#3}{#2}{#1}}% +% \end{macrocode} +% \subsection{\csh{XINT\_factortens}, \csh{XINT\_cuz\_cnt}} +% \begin{macrocode} +\def\XINT_factortens #1% +{% + \expandafter\XINT_cuz_cnt_loop\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 + \R\R\R\R\R\R\R\R\Z +}% +\def\XINT_cuz_cnt #1% +{% + \XINT_cuz_cnt_loop {}#1\R\R\R\R\R\R\R\R\Z +}% +\def\XINT_cuz_cnt_loop #1#2#3#4#5#6#7#8#9% +{% + \xint_gob_til_R #9\XINT_cuz_cnt_toofara \R + \expandafter\XINT_cuz_cnt_checka\expandafter + {\the\numexpr #1+8\relax}{#2#3#4#5#6#7#8#9}% +}% +\def\XINT_cuz_cnt_toofara\R + \expandafter\XINT_cuz_cnt_checka\expandafter #1#2% +{% + \XINT_cuz_cnt_toofarb {#1}#2% +}% +\def\XINT_cuz_cnt_toofarb #1#2\Z {\XINT_cuz_cnt_toofarc #2\Z {#1}}% +\def\XINT_cuz_cnt_toofarc #1#2#3#4#5#6#7#8% +{% + \xint_gob_til_R #2\XINT_cuz_cnt_toofard 7% + #3\XINT_cuz_cnt_toofard 6% + #4\XINT_cuz_cnt_toofard 5% + #5\XINT_cuz_cnt_toofard 4% + #6\XINT_cuz_cnt_toofard 3% + #7\XINT_cuz_cnt_toofard 2% + #8\XINT_cuz_cnt_toofard 1% + \Z #1#2#3#4#5#6#7#8% +}% +\def\XINT_cuz_cnt_toofard #1#2\Z #3\R #4\Z #5% +{% + \expandafter\XINT_cuz_cnt_toofare + \the\numexpr #3\relax \R\R\R\R\R\R\R\R\Z + {\the\numexpr #5-#1\relax}\R\Z +}% +\def\XINT_cuz_cnt_toofare #1#2#3#4#5#6#7#8% +{% + \xint_gob_til_R #2\XINT_cuz_cnt_stopc 1% + #3\XINT_cuz_cnt_stopc 2% + #4\XINT_cuz_cnt_stopc 3% + #5\XINT_cuz_cnt_stopc 4% + #6\XINT_cuz_cnt_stopc 5% + #7\XINT_cuz_cnt_stopc 6% + #8\XINT_cuz_cnt_stopc 7% + \Z #1#2#3#4#5#6#7#8% +}% +\def\XINT_cuz_cnt_checka #1#2% +{% + \expandafter\XINT_cuz_cnt_checkb\the\numexpr #2\relax \Z {#1}% +}% +\def\XINT_cuz_cnt_checkb #1% +{% + \xint_gob_til_zero #1\expandafter\XINT_cuz_cnt_loop\xint_gob_til_Z + 0\XINT_cuz_cnt_stopa #1% +}% +\def\XINT_cuz_cnt_stopa #1\Z +{% + \XINT_cuz_cnt_stopb #1\R\R\R\R\R\R\R\R\Z % +}% +\def\XINT_cuz_cnt_stopb #1#2#3#4#5#6#7#8#9% +{% + \xint_gob_til_R #2\XINT_cuz_cnt_stopc 1% + #3\XINT_cuz_cnt_stopc 2% + #4\XINT_cuz_cnt_stopc 3% + #5\XINT_cuz_cnt_stopc 4% + #6\XINT_cuz_cnt_stopc 5% + #7\XINT_cuz_cnt_stopc 6% + #8\XINT_cuz_cnt_stopc 7% + #9\XINT_cuz_cnt_stopc 8% + \Z #1#2#3#4#5#6#7#8#9% +}% +\def\XINT_cuz_cnt_stopc #1#2\Z #3\R #4\Z #5% +{% + \expandafter\XINT_cuz_cnt_stopd\expandafter + {\the\numexpr #5-#1}#3% +}% +\def\XINT_cuz_cnt_stopd #1#2\R #3\Z +{% + \expandafter\space\expandafter + {\romannumeral0\XINT_rord_main {}#2% + \xint_relax + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_relax }{#1}% +}% +% \end{macrocode} +% \subsection{\csh{xintRaw}} +% \lverb|& +% 1.07: this macro simply prints in a user readable form the fraction after its +% initial scanning. Useful when put inside braces in an \xintexpr, when the +% input is not yet in the A/B[n] form.| +% \begin{macrocode} +\def\xintRaw {\romannumeral0\xintraw }% +\def\xintraw +{% + \expandafter\XINT_raw\romannumeral0\XINT_infrac +}% +\def\XINT_raw #1#2#3{ #2/#3[#1]}% +% \end{macrocode} +% \subsection{\csh{xintPRaw}} +% \lverb|& +% 1.09b: these [n]'s and especially the possible /1 are truly annoying at +% times.| +% \begin{macrocode} +\def\xintPRaw {\romannumeral0\xintpraw }% +\def\xintpraw +{% + \expandafter\XINT_praw\romannumeral0\XINT_infrac +}% +\def\XINT_praw #1% +{% + \ifnum #1=\xint_c_ \expandafter\XINT_praw_a\fi \XINT_praw_A {#1}% +}% +\def\XINT_praw_A #1#2#3% +{% + \if\XINT_isOne{#3}1\expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo + \fi { #2[#1]}{ #2/#3[#1]}% +}% +\def\XINT_praw_a\XINT_praw_A #1#2#3% +{% + \if\XINT_isOne{#3}1\expandafter\xint_firstoftwo + \else\expandafter\xint_secondoftwo + \fi { #2}{ #2/#3}% +}% +% \end{macrocode} +% \subsection{\csh{xintRawWithZeros}} +% \lverb|& +% This was called \xintRaw in versions earlier than 1.07| +% \begin{macrocode} +\def\xintRawWithZeros {\romannumeral0\xintrawwithzeros }% +\def\xintrawwithzeros +{% + \expandafter\XINT_rawz\romannumeral0\XINT_infrac +}% +\def\XINT_rawz #1% +{% + \ifcase\XINT_cntSgn #1\Z + \expandafter\XINT_rawz_Ba + \or + \expandafter\XINT_rawz_A + \else + \expandafter\XINT_rawz_Ba + \fi + {#1}% +}% +\def\XINT_rawz_A #1#2#3{\xint_dsh {#2}{-#1}/#3}% +\def\XINT_rawz_Ba #1#2#3{\expandafter\XINT_rawz_Bb + \expandafter{\romannumeral0\xint_dsh {#3}{#1}}{#2}}% +\def\XINT_rawz_Bb #1#2{ #2/#1}% +% \end{macrocode} +% \subsection{\csh{xintFloor}} +% \lverb|1.09a| +% \begin{macrocode} +\def\xintFloor {\romannumeral0\xintfloor }% +\def\xintfloor #1{\expandafter\XINT_floor + \romannumeral0\xintrawwithzeros {#1}.}% +\def\XINT_floor #1/#2.{\xintiiquo {#1}{#2}}% +% \end{macrocode} +% \subsection{\csh{xintCeil}} +% \lverb|1.09a| +% \begin{macrocode} +\def\xintCeil {\romannumeral0\xintceil }% +\def\xintceil #1{\xintiiopp {\xintFloor {\xintOpp{#1}}}}% +% \end{macrocode} +% \subsection{\csh{xintNumerator}} +% \begin{macrocode} +\def\xintNumerator {\romannumeral0\xintnumerator }% +\def\xintnumerator +{% + \expandafter\XINT_numer\romannumeral0\XINT_infrac +}% +\def\XINT_numer #1% +{% + \ifcase\XINT_cntSgn #1\Z + \expandafter\XINT_numer_B + \or + \expandafter\XINT_numer_A + \else + \expandafter\XINT_numer_B + \fi + {#1}% +}% +\def\XINT_numer_A #1#2#3{\xint_dsh {#2}{-#1}}% +\def\XINT_numer_B #1#2#3{ #2}% +% \end{macrocode} +% \subsection{\csh{xintDenominator}} +% \begin{macrocode} +\def\xintDenominator {\romannumeral0\xintdenominator }% +\def\xintdenominator +{% + \expandafter\XINT_denom\romannumeral0\XINT_infrac +}% +\def\XINT_denom #1% +{% + \ifcase\XINT_cntSgn #1\Z + \expandafter\XINT_denom_B + \or + \expandafter\XINT_denom_A + \else + \expandafter\XINT_denom_B + \fi + {#1}% +}% +\def\XINT_denom_A #1#2#3{ #3}% +\def\XINT_denom_B #1#2#3{\xint_dsh {#3}{#1}}% +% \end{macrocode} +% \subsection{\csh{xintFrac}} +% \begin{macrocode} +\def\xintFrac {\romannumeral0\xintfrac }% +\def\xintfrac #1% +{% + \expandafter\XINT_fracfrac_A\romannumeral0\XINT_infrac {#1}% +}% +\def\XINT_fracfrac_A #1{\XINT_fracfrac_B #1\Z }% +\catcode`^=7 +\def\XINT_fracfrac_B #1#2\Z +{% + \xint_gob_til_zero #1\XINT_fracfrac_C 0\XINT_fracfrac_D {10^{#1#2}}% +}% +\def\XINT_fracfrac_C 0\XINT_fracfrac_D #1#2#3% +{% + \if1\XINT_isOne {#3}% + \xint_afterfi {\expandafter\xint_firstoftwo_thenstop\xint_gobble_ii }% + \fi + \space + \frac {#2}{#3}% +}% +\def\XINT_fracfrac_D #1#2#3% +{% + \if1\XINT_isOne {#3}\XINT_fracfrac_E\fi + \space + \frac {#2}{#3}#1% +}% +\def\XINT_fracfrac_E \fi\space\frac #1#2{\fi \space #1\cdot }% +% \end{macrocode} +% \subsection{\csh{xintSignedFrac}} +% \begin{macrocode} +\def\xintSignedFrac {\romannumeral0\xintsignedfrac }% +\def\xintsignedfrac #1% +{% + \expandafter\XINT_sgnfrac_a\romannumeral0\XINT_infrac {#1}% +}% +\def\XINT_sgnfrac_a #1#2% +{% + \XINT_sgnfrac_b #2\Z {#1}% +}% +\def\XINT_sgnfrac_b #1% +{% + \xint_UDsignfork + #1\XINT_sgnfrac_N + -{\XINT_sgnfrac_P #1}% + \krof +}% +\def\XINT_sgnfrac_P #1\Z #2% +{% + \XINT_fracfrac_A {#2}{#1}% +}% +\def\XINT_sgnfrac_N +{% + \expandafter\xint_minus_thenstop\romannumeral0\XINT_sgnfrac_P +}% +% \end{macrocode} +% \subsection{\csh{xintFwOver}} +% \begin{macrocode} +\def\xintFwOver {\romannumeral0\xintfwover }% +\def\xintfwover #1% +{% + \expandafter\XINT_fwover_A\romannumeral0\XINT_infrac {#1}% +}% +\def\XINT_fwover_A #1{\XINT_fwover_B #1\Z }% +\def\XINT_fwover_B #1#2\Z +{% + \xint_gob_til_zero #1\XINT_fwover_C 0\XINT_fwover_D {10^{#1#2}}% +}% +\catcode`^=11 +\def\XINT_fwover_C #1#2#3#4#5% +{% + \if0\XINT_isOne {#5}\xint_afterfi { {#4\over #5}}% + \else\xint_afterfi { #4}% + \fi +}% +\def\XINT_fwover_D #1#2#3% +{% + \if0\XINT_isOne {#3}\xint_afterfi { {#2\over #3}}% + \else\xint_afterfi { #2\cdot }% + \fi + #1% +}% +% \end{macrocode} +% \subsection{\csh{xintSignedFwOver}} +% \begin{macrocode} +\def\xintSignedFwOver {\romannumeral0\xintsignedfwover }% +\def\xintsignedfwover #1% +{% + \expandafter\XINT_sgnfwover_a\romannumeral0\XINT_infrac {#1}% +}% +\def\XINT_sgnfwover_a #1#2% +{% + \XINT_sgnfwover_b #2\Z {#1}% +}% +\def\XINT_sgnfwover_b #1% +{% + \xint_UDsignfork + #1\XINT_sgnfwover_N + -{\XINT_sgnfwover_P #1}% + \krof +}% +\def\XINT_sgnfwover_P #1\Z #2% +{% + \XINT_fwover_A {#2}{#1}% +}% +\def\XINT_sgnfwover_N +{% + \expandafter\xint_minus_thenstop\romannumeral0\XINT_sgnfwover_P +}% +% \end{macrocode} +% \subsection{\csh{xintREZ}} +% \begin{macrocode} +\def\xintREZ {\romannumeral0\xintrez }% +\def\xintrez +{% + \expandafter\XINT_rez_A\romannumeral0\XINT_infrac +}% +\def\XINT_rez_A #1#2% +{% + \XINT_rez_AB #2\Z {#1}% +}% +\def\XINT_rez_AB #1% +{% + \xint_UDzerominusfork + #1-\XINT_rez_zero + 0#1\XINT_rez_neg + 0-{\XINT_rez_B #1}% + \krof +}% +\def\XINT_rez_zero #1\Z #2#3{ 0/1[0]}% +\def\XINT_rez_neg {\expandafter\xint_minus_thenstop\romannumeral0\XINT_rez_B }% +\def\XINT_rez_B #1\Z +{% + \expandafter\XINT_rez_C\romannumeral0\XINT_factortens {#1}% +}% +\def\XINT_rez_C #1#2#3#4% +{% + \expandafter\XINT_rez_D\romannumeral0\XINT_factortens {#4}{#3}{#2}{#1}% +}% +\def\XINT_rez_D #1#2#3#4#5% +{% + \expandafter\XINT_rez_E\expandafter + {\the\numexpr #3+#4-#2}{#1}{#5}% +}% +\def\XINT_rez_E #1#2#3{ #3/#2[#1]}% +% \end{macrocode} +% \subsection{\csh{xintE}} +% \lverb|1.07: The fraction is the first argument contrarily to \xintTrunc and +% \xintRound. +% +% \xintfE (1.07) and \xintiE (1.09i) are for \xintexpr and cousins. It is quite +% annoying that \numexpr does not know how to deal correctly with a minus sign - +% as prefix: \numexpr -(1)\relax is illegal! (one can do \numexpr 0-(1)\relax). +% +% the 1.07 \xintE puts directly its second argument in a \numexpr. The \xintfE +% first uses \xintNum on it, this is necessary for use in \xintexpr. (but +% one cannot use directly infix notation in the second argument of \xintfE) +% +% 1.09i also adds \xintFloatE and modifies \XINTinFloatfE, although currently +% the latter is only used from \xintfloatexpr hence always with \XINTdigits, it +% comes equipped with its first argument withing brackets as the other +% \XINTinFloat... macros. | +% \begin{macrocode} +\def\xintE {\romannumeral0\xinte }% +\def\xinte #1% +{% + \expandafter\XINT_e \romannumeral0\XINT_infrac {#1}% +}% +\def\XINT_e #1#2#3#4% +{% + \expandafter\XINT_e_end\expandafter{\the\numexpr #1+#4}{#2}{#3}% +}% +\def\XINT_e_end #1#2#3{ #2/#3[#1]}% +\def\xintfE {\romannumeral0\xintfe }% +\def\xintfe #1% +{% + \expandafter\XINT_fe \romannumeral0\XINT_infrac {#1}% +}% +\def\XINT_fe #1#2#3#4% +{% + \expandafter\XINT_e_end\expandafter{\the\numexpr #1+\xintNum{#4}}{#2}{#3}% +}% +\def\xintFloatE {\romannumeral0\xintfloate }% +\def\xintfloate #1{\XINT_floate_chkopt #1\Z }% +\def\XINT_floate_chkopt #1% +{% + \ifx [#1\expandafter\XINT_floate_opt + \else\expandafter\XINT_floate_noopt + \fi #1% +}% +\def\XINT_floate_noopt #1\Z +{% + \expandafter\XINT_floate_a\expandafter\XINTdigits + \romannumeral0\XINT_infrac {#1}% +}% +\def\XINT_floate_opt [\Z #1]#2% +{% + \expandafter\XINT_floate_a\expandafter + {\the\numexpr #1\expandafter}\romannumeral0\XINT_infrac {#2}% +}% +\def\XINT_floate_a #1#2#3#4#5% +{% + \expandafter\expandafter\expandafter\XINT_float_a + \expandafter\xint_exchangetwo_keepbraces\expandafter + {\the\numexpr #2+#5}{#1}{#3}{#4}\XINT_float_Q +}% +\def\XINTinFloatfE {\romannumeral0\XINTinfloatfe }% +\def\XINTinfloatfe [#1]#2% +{% + \expandafter\XINT_infloatfe_a\expandafter + {\the\numexpr #1\expandafter}\romannumeral0\XINT_infrac {#2}% +}% +\def\XINT_infloatfe_a #1#2#3#4#5% +{% + \expandafter\expandafter\expandafter\XINT_infloat_a + \expandafter\xint_exchangetwo_keepbraces\expandafter + {\the\numexpr #2+\xintNum{#5}}{#1}{#3}{#4}\XINT_infloat_Q +}% +\def\xintiE {\romannumeral0\xintie }% for \xintiiexpr only +\def\xintie #1% +{% + \expandafter\XINT_ie \romannumeral0\XINT_infrac {#1}% allows 3.123e3 +}% +\def\XINT_ie #1#2#3#4% assumes #3=1 and uses \xint_dsh with its \numexpr +{% + \xint_dsh {#2}{0-(#1+#4)}% could have \xintNum{#4} for a bit more general +}% +% \end{macrocode} +% \subsection{\csh{xintIrr}} +% \lverb|& +% 1.04 fixes a buggy \xintIrr {0}. +% 1.05 modifies the initial parsing and post-processing to use \xintrawwithzeros +% and to +% more quickly deal with an input denominator equal to 1. 1.08 version does +% not remove a /1 denominator.| +% \begin{macrocode} +\def\xintIrr {\romannumeral0\xintirr }% +\def\xintirr #1% +{% + \expandafter\XINT_irr_start\romannumeral0\xintrawwithzeros {#1}\Z +}% +\def\XINT_irr_start #1#2/#3\Z +{% + \if0\XINT_isOne {#3}% + \xint_afterfi + {\xint_UDsignfork + #1\XINT_irr_negative + -{\XINT_irr_nonneg #1}% + \krof}% + \else + \xint_afterfi{\XINT_irr_denomisone #1}% + \fi + #2\Z {#3}% +}% +\def\XINT_irr_denomisone #1\Z #2{ #1/1}% changed in 1.08 +\def\XINT_irr_negative #1\Z #2{\XINT_irr_D #1\Z #2\Z \xint_minus_thenstop}% +\def\XINT_irr_nonneg #1\Z #2{\XINT_irr_D #1\Z #2\Z \space}% +\def\XINT_irr_D #1#2\Z #3#4\Z +{% + \xint_UDzerosfork + #3#1\XINT_irr_indeterminate + #30\XINT_irr_divisionbyzero + #10\XINT_irr_zero + 00\XINT_irr_loop_a + \krof + {#3#4}{#1#2}{#3#4}{#1#2}% +}% +\def\XINT_irr_indeterminate #1#2#3#4#5{\xintError:NaN\space 0/0}% +\def\XINT_irr_divisionbyzero #1#2#3#4#5{\xintError:DivisionByZero #5#2/0}% +\def\XINT_irr_zero #1#2#3#4#5{ 0/1}% changed in 1.08 +\def\XINT_irr_loop_a #1#2% +{% + \expandafter\XINT_irr_loop_d + \romannumeral0\XINT_div_prepare {#1}{#2}{#1}% +}% +\def\XINT_irr_loop_d #1#2% +{% + \XINT_irr_loop_e #2\Z +}% +\def\XINT_irr_loop_e #1#2\Z +{% + \xint_gob_til_zero #1\xint_irr_loop_exit0\XINT_irr_loop_a {#1#2}% +}% +\def\xint_irr_loop_exit0\XINT_irr_loop_a #1#2#3#4% +{% + \expandafter\XINT_irr_loop_exitb\expandafter + {\romannumeral0\xintiiquo {#3}{#2}}% + {\romannumeral0\xintiiquo {#4}{#2}}% +}% +\def\XINT_irr_loop_exitb #1#2% +{% + \expandafter\XINT_irr_finish\expandafter {#2}{#1}% +}% +\def\XINT_irr_finish #1#2#3{#3#1/#2}% changed in 1.08 +% \end{macrocode} +% \subsection{\csh{xintNum}} +% \lverb|& +% This extension of the xint original xintNum is added in 1.05, as a +% synonym to +% \xintIrr, but raising an error when the input does not evaluate to an integer. +% Usable with not too much overhead on integer input as \xintIrr +% checks quickly for a denominator equal to 1 (which will be put there by the +% \XINT_infrac called by \xintrawwithzeros). This way, macros such as \xintQuo +% can be +% modified with minimal overhead to accept fractional input as long as it +% evaluates to an integer. | +% \begin{macrocode} +\def\xintNum {\romannumeral0\xintnum }% +\def\xintnum #1{\expandafter\XINT_intcheck\romannumeral0\xintirr {#1}\Z }% +\edef\XINT_intcheck #1/#2\Z +{% + \noexpand\if 0\noexpand\XINT_isOne {#2}\noexpand\xintError:NotAnInteger + \noexpand\fi\space #1% +}% +% \end{macrocode} +% \subsection{\csh{xintifInt}} +% \lverb|1.09e. xintfrac.sty only.| +% \begin{macrocode} +\def\xintifInt {\romannumeral0\xintifint }% +\def\xintifint #1{\expandafter\XINT_ifint\romannumeral0\xintirr {#1}\Z }% +\def\XINT_ifint #1/#2\Z +{% + \if\XINT_isOne {#2}1% + \expandafter\xint_firstoftwo_thenstop + \else + \expandafter\xint_secondoftwo_thenstop + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintJrr}} +% \lverb|& +% Modified similarly as \xintIrr in release 1.05. 1.08 version does +% not remove a /1 denominator.| +% \begin{macrocode} +\def\xintJrr {\romannumeral0\xintjrr }% +\def\xintjrr #1% +{% + \expandafter\XINT_jrr_start\romannumeral0\xintrawwithzeros {#1}\Z +}% +\def\XINT_jrr_start #1#2/#3\Z +{% + \if0\XINT_isOne {#3}\xint_afterfi + {\xint_UDsignfork + #1\XINT_jrr_negative + -{\XINT_jrr_nonneg #1}% + \krof}% + \else + \xint_afterfi{\XINT_jrr_denomisone #1}% + \fi + #2\Z {#3}% +}% +\def\XINT_jrr_denomisone #1\Z #2{ #1/1}% changed in 1.08 +\def\XINT_jrr_negative #1\Z #2{\XINT_jrr_D #1\Z #2\Z \xint_minus_thenstop }% +\def\XINT_jrr_nonneg #1\Z #2{\XINT_jrr_D #1\Z #2\Z \space}% +\def\XINT_jrr_D #1#2\Z #3#4\Z +{% + \xint_UDzerosfork + #3#1\XINT_jrr_indeterminate + #30\XINT_jrr_divisionbyzero + #10\XINT_jrr_zero + 00\XINT_jrr_loop_a + \krof + {#3#4}{#1#2}1001% +}% +\def\XINT_jrr_indeterminate #1#2#3#4#5#6#7{\xintError:NaN\space 0/0}% +\def\XINT_jrr_divisionbyzero #1#2#3#4#5#6#7{\xintError:DivisionByZero #7#2/0}% +\def\XINT_jrr_zero #1#2#3#4#5#6#7{ 0/1}% changed in 1.08 +\def\XINT_jrr_loop_a #1#2% +{% + \expandafter\XINT_jrr_loop_b + \romannumeral0\XINT_div_prepare {#1}{#2}{#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}}% + {#2}{#3}{#4}{#5}% +}% +\def\XINT_jrr_loop_c #1#2% +{% + \expandafter \XINT_jrr_loop_d \expandafter{#2}{#1}% +}% +\def\XINT_jrr_loop_d #1#2#3#4% +{% + \XINT_jrr_loop_e #3\Z {#4}{#2}{#1}% +}% +\def\XINT_jrr_loop_e #1#2\Z +{% + \xint_gob_til_zero #1\xint_jrr_loop_exit0\XINT_jrr_loop_a {#1#2}% +}% +\def\xint_jrr_loop_exit0\XINT_jrr_loop_a #1#2#3#4#5#6% +{% + \XINT_irr_finish {#3}{#4}% +}% +% \end{macrocode} +% \subsection{\csh{xintTFrac}} +% \lverb|1.09i, for frac in \xintexpr. And \xintFrac is already assigned. T for +% truncation. However, potentially not very efficient with numbers in scientific +% notations, with big exponents. Will have to think it again some day. I +% hesitated how to call the macro. Same convention as in maple, but some people +% reserve fractional part to x - floor(x). Also, not clear if I had to make it +% negative (or zero) if x < 0, or rather always positive. There should be in +% fact such a thing for each rounding function, trunc, round, floor, ceil. | +% \begin{macrocode} +\def\xintTFrac {\romannumeral0\xinttfrac }% +\def\xinttfrac #1% + {\expandafter\XINT_tfrac_fork\romannumeral0\xintrawwithzeros {#1}\Z }% +\def\XINT_tfrac_fork #1% +{% + \xint_UDzerominusfork + #1-\XINT_tfrac_zero + 0#1\XINT_tfrac_N + 0-{\XINT_tfrac_P #1}% + \krof +}% +\def\XINT_tfrac_zero #1\Z { 0/1[0]}% +\def\XINT_tfrac_N {\expandafter\XINT_opp\romannumeral0\XINT_tfrac_P }% +\def\XINT_tfrac_P #1/#2\Z +{% + \expandafter\XINT_rez_AB\romannumeral0\xintiirem{#1}{#2}\Z {0}{#2}% +}% +% \end{macrocode} +% \subsection{\csh{XINTinFloatFrac}} +% \lverb|1.09i, for frac in \xintfloatexpr. This version computes +% exactly from the input the fractional part and then only converts it +% into a float with the asked-for number of digits. I will have to think +% it again some day, certainly. | +% \begin{macrocode} +\def\XINTinFloatFrac {\romannumeral0\XINTinfloatfrac }% +\def\XINTinfloatfrac [#1]#2% +{% + \expandafter\XINT_infloatfrac_a\expandafter + {\romannumeral0\xinttfrac{#2}}{#1}% +}% +\def\XINT_infloatfrac_a #1#2{\XINTinFloat [#2]{#1}}% +% \end{macrocode} +% \subsection{\csh{xintTrunc}, \csh{xintiTrunc}} +% \lverb|& +% Modified in 1.06 to give the first argument to a \numexpr. +% +% 1.09f fixes the overhead added in 1.09a to some inner routines when \xintiquo +% was redefined to use \xintnum. Now uses \xintiiquo, rather. +% +% 1.09j: minor improvements, \XINT_trunc_E was very strange and defined two +% never occuring branches; also, optimizes the call to the division routine, and +% the zero loops.| +% \begin{macrocode} +\def\xintTrunc {\romannumeral0\xinttrunc }% +\def\xintiTrunc {\romannumeral0\xintitrunc }% +\def\xinttrunc #1% +{% + \expandafter\XINT_trunc\expandafter {\the\numexpr #1}% +}% +\def\XINT_trunc #1#2% +{% + \expandafter\XINT_trunc_G + \romannumeral0\expandafter\XINT_trunc_A + \romannumeral0\XINT_infrac {#2}{#1}{#1}% +}% +\def\xintitrunc #1% +{% + \expandafter\XINT_itrunc\expandafter {\the\numexpr #1}% +}% +\def\XINT_itrunc #1#2% +{% + \expandafter\XINT_itrunc_G + \romannumeral0\expandafter\XINT_trunc_A + \romannumeral0\XINT_infrac {#2}{#1}{#1}% +}% +\def\XINT_trunc_A #1#2#3#4% +{% + \expandafter\XINT_trunc_checkifzero + \expandafter{\the\numexpr #1+#4}#2\Z {#3}% +}% +\def\XINT_trunc_checkifzero #1#2#3\Z +{% + \xint_gob_til_zero #2\XINT_trunc_iszero0\XINT_trunc_B {#1}{#2#3}% +}% +\def\XINT_trunc_iszero0\XINT_trunc_B #1#2#3{ 0\Z 0}% +\def\XINT_trunc_B #1% +{% + \ifcase\XINT_cntSgn #1\Z + \expandafter\XINT_trunc_D + \or + \expandafter\XINT_trunc_D + \else + \expandafter\XINT_trunc_C + \fi + {#1}% +}% +\def\XINT_trunc_C #1#2#3% +{% + \expandafter\XINT_trunc_CE\expandafter + {\romannumeral0\XINT_dsx_zeroloop {-#1}{}\Z {#3}}{#2}% +}% +\def\XINT_trunc_CE #1#2{\XINT_trunc_E #2.{#1}}% +\def\XINT_trunc_D #1#2% +{% + \expandafter\XINT_trunc_E + \romannumeral0\XINT_dsx_zeroloop {#1}{}\Z {#2}.% +}% +\def\XINT_trunc_E #1% +{% + \xint_UDsignfork + #1\XINT_trunc_Fneg + -{\XINT_trunc_Fpos #1}% + \krof +}% +\def\XINT_trunc_Fneg #1.#2{\expandafter\xint_firstoftwo_thenstop + \romannumeral0\XINT_div_prepare {#2}{#1}\Z \xint_minus_thenstop}% +\def\XINT_trunc_Fpos #1.#2{\expandafter\xint_firstoftwo_thenstop + \romannumeral0\XINT_div_prepare {#2}{#1}\Z \space }% +\def\XINT_itrunc_G #1#2\Z #3#4% +{% + \xint_gob_til_zero #1\XINT_trunc_zero 0#3#1#2% +}% +\def\XINT_trunc_zero 0#1#20{ 0}% +\def\XINT_trunc_G #1\Z #2#3% +{% + \xint_gob_til_zero #2\XINT_trunc_zero 0% + \expandafter\XINT_trunc_H\expandafter + {\the\numexpr\romannumeral0\xintlength {#1}-#3}{#3}{#1}#2% +}% +\def\XINT_trunc_H #1#2% +{% + \ifnum #1 > \xint_c_ + \xint_afterfi {\XINT_trunc_Ha {#2}}% + \else + \xint_afterfi {\XINT_trunc_Hb {-#1}}% -0,--1,--2, .... + \fi +}% +\def\XINT_trunc_Ha +{% + \expandafter\XINT_trunc_Haa\romannumeral0\xintdecsplit +}% +\def\XINT_trunc_Haa #1#2#3% +{% + #3#1.#2% +}% +\def\XINT_trunc_Hb #1#2#3% +{% + \expandafter #3\expandafter0\expandafter.% + \romannumeral0\XINT_dsx_zeroloop {#1}{}\Z {}#2% #1=-0 autorisé ! +}% +% \end{macrocode} +% \subsection{\csh{xintRound}, \csh{xintiRound}} +% \lverb|Modified in 1.06 to give the first argument to a \numexpr.| +% \begin{macrocode} +\def\xintRound {\romannumeral0\xintround }% +\def\xintiRound {\romannumeral0\xintiround }% +\def\xintround #1% +{% + \expandafter\XINT_round\expandafter {\the\numexpr #1}% +}% +\def\XINT_round +{% + \expandafter\XINT_trunc_G\romannumeral0\XINT_round_A +}% +\def\xintiround #1% +{% + \expandafter\XINT_iround\expandafter {\the\numexpr #1}% +}% +\def\XINT_iround +{% + \expandafter\XINT_itrunc_G\romannumeral0\XINT_round_A +}% +\def\XINT_round_A #1#2% +{% + \expandafter\XINT_round_B + \romannumeral0\expandafter\XINT_trunc_A + \romannumeral0\XINT_infrac {#2}{\the\numexpr #1+1\relax}{#1}% +}% +\def\XINT_round_B #1\Z +{% + \expandafter\XINT_round_C + \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 + \Z +}% +\def\XINT_round_C #1% +{% + \ifnum #1<5 + \expandafter\XINT_round_Daa + \else + \expandafter\XINT_round_Dba + \fi +}% +\def\XINT_round_Daa #1% +{% + \xint_gob_til_Z #1\XINT_round_Daz\Z \XINT_round_Da #1% +}% +\def\XINT_round_Daz\Z \XINT_round_Da \Z { 0\Z }% +\def\XINT_round_Da #1\Z +{% + \XINT_rord_main {}#1% + \xint_relax + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_bye\xint_bye\xint_bye\xint_bye + \xint_relax \Z +}% +\def\XINT_round_Dba #1% +{% + \xint_gob_til_Z #1\XINT_round_Dbz\Z \XINT_round_Db #1% +}% +\def\XINT_round_Dbz\Z \XINT_round_Db \Z { 1\Z }% +\def\XINT_round_Db #1\Z +{% + \XINT_addm_A 0{}1000\W\X\Y\Z #1000\W\X\Y\Z \Z +}% +% \end{macrocode} +% \subsection{\csh{xintXTrunc}} +% \lverb|1.09j [2014/01/06] This is completely expandable but not f-expandable. +% Designed be used inside an \edef or a \write, if one is interested in getting +% tens of thousands of digits from the decimal expansion of some fraction... it +% is not worth using it rather than \xintTrunc if for less than *hundreds* of +% digits. For efficiency it clones part of the preparatory division macros, as +% the same denominator will be used again and again. The D parameter which says +% how many digits to keep after decimal mark must be at least 1 (and it is +% forcefully set to such a value if found negative or zero, to avoid an eternal +% loop). +% +% For reasons of efficiency I try to use the shortest possible denominator, so +% if the fraction is A/B[N], I want to use B. For N at least zero, just +% immediately replace A by A.10^N. The first division then may be a little +% longish but the next ones will be fast (if B is not too big). For N<0, this is +% a bit more complicated. I thought somewhat about this, and I would need a +% rather complicated approach going through a long division algorithm, forcing +% me to essentially clone the actual division with some differences; a side +% thing is that as this would use blocks of four digits I would have a hard time +% allowing a non-multiple of four number of post decimal mark digits. +% +% Thus, for N<0, another method is followed. First the euclidean division +% A/B=Q+R/B is done. The number of digits of Q is M. If |N|\leq D, we launch +% inside a \csname the routine for obtaining D-|N| next digits (this may impact +% TeX's memory if D is very big), call them T. We then need to position the +% decimal mark D slots from the right of QT, which has length M+D-|N|, hence |N| +% slots from the right of Q. We thus avoid having to work will the T, as D may +% be very very big (\xintXTrunc's only goal is to make it possible to learn by +% hearts decimal expansions with thousands of digits). We can use the +% \xintDecSplit for that on Q . Computing the length M of Q was a more or less +% unavoidable step. If |N|>D, the \csname step is skipped we need to remove the +% 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 thinsg +% and I even do an \xintnum to ensure a 0 if something comes out empty from +% \xintDecSplit).| +% \begin{macrocode} +\def\xintXTrunc #1#2% +{% + \expandafter\XINT_xtrunc_a\expandafter + {\the\numexpr #1\expandafter}\romannumeral0\xintraw {#2}% +}% +\def\XINT_xtrunc_a #1% +{% + \expandafter\XINT_xtrunc_b\expandafter + {\the\numexpr\ifnum#1<\xint_c_i \xint_c_i-\fi #1}% +}% +\def\XINT_xtrunc_b #1% +{% + \expandafter\XINT_xtrunc_c\expandafter + {\the\numexpr (#1+\xint_c_ii^v)/\xint_c_ii^vi-\xint_c_i}{#1}% +}% +\def\XINT_xtrunc_c #1#2% +{% + \expandafter\XINT_xtrunc_d\expandafter + {\the\numexpr #2-\xint_c_ii^vi*#1}{#1}{#2}% +}% +\def\XINT_xtrunc_d #1#2#3#4/#5[#6]% +{% + \XINT_xtrunc_e #4.{#6}{#5}{#3}{#2}{#1}% +}% +% #1=numerator.#2=N,#3=B,#4=D,#5=Blocs,#6=extra +\def\XINT_xtrunc_e #1% +{% + \xint_UDzerominusfork + #1-\XINT_xtrunc_zero + 0#1\XINT_xtrunc_N + 0-{\XINT_xtrunc_P #1}% + \krof +}% +\def\XINT_xtrunc_zero .#1#2#3#4#5% +{% + 0.\romannumeral0\expandafter\XINT_dsx_zeroloop\expandafter + {\the\numexpr #5}{}\Z {}% + \xintiloop [#4+-1] + \ifnum \xintiloopindex>\xint_c_ + 0000000000000000000000000000000000000000000000000000000000000000% + \repeat +}% +\def\XINT_xtrunc_N {-\XINT_xtrunc_P }% +\def\XINT_xtrunc_P #1.#2% +{% + \ifnum #2<\xint_c_ + \expandafter\XINT_xtrunc_negN_Q + \else + \expandafter\XINT_xtrunc_Q + \fi {#2}{#1}.% +}% +\def\XINT_xtrunc_negN_Q #1#2.#3#4#5#6% +{% + \expandafter\XINT_xtrunc_negN_R + \romannumeral0\XINT_div_prepare {#3}{#2}{#3}{#1}{#4}% +}% +% #1=Q, #2=R, #3=B, #4=N<0, #5=D +\def\XINT_xtrunc_negN_R #1#2#3#4#5% +{% + \expandafter\XINT_xtrunc_negN_S\expandafter + {\the\numexpr -#4}{#5}{#2}{#3}{#1}% +}% +\def\XINT_xtrunc_negN_S #1#2% +{% + \expandafter\XINT_xtrunc_negN_T\expandafter + {\the\numexpr #2-#1}{#1}{#2}% +}% +\def\XINT_xtrunc_negN_T #1% +{% + \ifnum \xint_c_<#1 + \expandafter\XINT_xtrunc_negNA + \else + \expandafter\XINT_xtrunc_negNW + \fi {#1}% +}% +% #1=D-|N|>0, #2=|N|, #3=D, #4=R, #5=B, #6=Q +\def\XINT_xtrunc_unlock #10.{ }% +\def\XINT_xtrunc_negNA #1#2#3#4#5#6% +{% + \expandafter\XINT_xtrunc_negNB\expandafter + {\romannumeral0\expandafter\expandafter\expandafter + \XINT_xtrunc_unlock\expandafter\string + \csname\XINT_xtrunc_b {#1}#4/#5[0]\expandafter\endcsname + \expandafter}\expandafter + {\the\numexpr\xintLength{#6}-#2}{#6}% +}% +\def\XINT_xtrunc_negNB #1#2#3{\XINT_xtrunc_negNC {#2}{#3}#1}% +\def\XINT_xtrunc_negNC #1% +{% + \ifnum \xint_c_ < #1 + \expandafter\XINT_xtrunc_negNDa + \else + \expandafter\XINT_xtrunc_negNE + \fi {#1}% +}% +\def\XINT_xtrunc_negNDa #1#2% +{% + \expandafter\XINT_xtrunc_negNDb% + \romannumeral0\XINT_split_fromleft_loop {#1}{}#2\W\W\W\W\W\W\W\W\Z +}% +\def\XINT_xtrunc_negNDb #1#2{#1.#2}% +\def\XINT_xtrunc_negNE #1#2% +{% + 0.\romannumeral0\XINT_dsx_zeroloop {-#1}{}\Z {}#2% +}% +% #1=D-|N|<=0, #2=|N|, #3=D, #4=R, #5=B, #6=Q +\def\XINT_xtrunc_negNW #1#2#3#4#5#6% +{% + \expandafter\XINT_xtrunc_negNX\expandafter + {\romannumeral0\xintnum{\xintDecSplitL {-#1}{#6}}}{#3}% +}% +\def\XINT_xtrunc_negNX #1#2% +{% + \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 + {\the\numexpr #7}{}\Z {}% + \xintiloop [#6+-1] + \ifnum \xintiloopindex>\xint_c_ + 0000000000000000000000000000000000000000000000000000000000000000% + \repeat +}% +\def\XINT_xtrunc_BisTwo #1#2#3#4#5#6#7% +{% + \xintHalf {#5}.\ifodd\xintiiLDg{#5} 5\else 0\fi + \romannumeral0\expandafter\XINT_dsx_zeroloop\expandafter + {\the\numexpr #7-\xint_c_i}{}\Z {}% + \xintiloop [#6+-1] + \ifnum \xintiloopindex>\xint_c_ + 0000000000000000000000000000000000000000000000000000000000000000% + \repeat +}% +\def\XINT_xtrunc_prepareB_PaBa #1#2% +{% + \expandafter\XINT_xtrunc_Pa\expandafter + {\romannumeral0\XINT_xtrunc_prepareB_a {#1}{#2}}% +}% +\def\XINT_xtrunc_prepareB_a #1% +{% + \expandafter\XINT_xtrunc_prepareB_c\expandafter + {\the\numexpr \xint_c_iv*((#1+\xint_c_i)/\xint_c_iv)}{#1}% +}% +\def\XINT_xtrunc_prepareB_c #1#2% +{% + \csname XINT_xtrunc_prepareB_d\romannumeral\numexpr#1-#2\endcsname + {#1}% +}% +\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% +{% + \expandafter\XINT_xtrunc_Pa\expandafter + {\romannumeral0\XINT_xtrunc_prepareB_e {#1}{#2}{#3}{#4}}% +}% +\def\XINT_xtrunc_prepareB_e #1#2#3#4% +{% + \ifnum#3=\xint_c_iv\expandafter\XINT_xtrunc_prepareLittleB_f + \else\expandafter\XINT_xtrunc_prepareB_f + \fi + #4#1{#3}{#2}{#1}% +}% +\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_prepareLittleB_f #1#{% + \expandafter\space\expandafter + \XINT_div_prepareB_g \the\numexpr #1/\xint_c_ii.{}.{}.{#1}% +}% +\def\XINT_xtrunc_Pa #1#2% +{% + \expandafter\XINT_xtrunc_Pb\romannumeral0#1{#2}{#1}% +}% +\def\XINT_xtrunc_Pb #1#2#3#4{#1.\XINT_xtrunc_A {#4}{#2}{#3}}% +\def\XINT_xtrunc_A #1% +{% + \unless\ifnum #1>\xint_c_ \XINT_xtrunc_transition\fi + \expandafter\XINT_xtrunc_B\expandafter{\the\numexpr #1-\xint_c_i}% +}% +\def\XINT_xtrunc_B #1#2#3% +{% + \expandafter\XINT_xtrunc_D\romannumeral0#3% + {#20000000000000000000000000000000000000000000000000000000000000000}% + {#1}{#3}% +}% +\def\XINT_xtrunc_D #1#2#3% +{% + \romannumeral0\expandafter\XINT_dsx_zeroloop\expandafter + {\the\numexpr \xint_c_ii^vi-\xintLength{#1}}{}\Z {}#1% + \XINT_xtrunc_A {#3}{#2}% +}% +\def\XINT_xtrunc_transition\fi + \expandafter\XINT_xtrunc_B\expandafter #1#2#3#4% +{% + \fi + \ifnum #4=\xint_c_ \XINT_xtrunc_abort\fi + \expandafter\XINT_xtrunc_x\expandafter + {\romannumeral0\XINT_dsx_zeroloop {#4}{}\Z {#2}}{#3}{#4}% +}% +\def\XINT_xtrunc_x #1#2% +{% + \expandafter\XINT_xtrunc_y\romannumeral0#2{#1}% +}% +\def\XINT_xtrunc_y #1#2#3% +{% + \romannumeral0\expandafter\XINT_dsx_zeroloop\expandafter + {\the\numexpr #3-\xintLength{#1}}{}\Z {}#1% +}% +\def\XINT_xtrunc_abort\fi\expandafter\XINT_xtrunc_x\expandafter #1#2#3{\fi}% +% \end{macrocode} +% \subsection{\csh{xintDigits}} +% \lverb|& +% The mathchardef used to be called \XINT_digits, but for reasons originating in +% \xintNewExpr, release 1.09a uses \XINTdigits without underscore.| +% \begin{macrocode} +\mathchardef\XINTdigits 16 +\def\xintDigits #1#2% + {\afterassignment \xint_gobble_i \mathchardef\XINTdigits=}% +\def\xinttheDigits {\number\XINTdigits }% +% \end{macrocode} +% \subsection{\csh{xintFloat}} +% \lverb|1.07. Completely re-written in 1.08a, with spectacular speed +% 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.| +% \begin{macrocode} +\def\xintFloat {\romannumeral0\xintfloat }% +\def\xintfloat #1{\XINT_float_chkopt #1\Z }% +\def\XINT_float_chkopt #1% +{% + \ifx [#1\expandafter\XINT_float_opt + \else\expandafter\XINT_float_noopt + \fi #1% +}% +\def\XINT_float_noopt #1\Z +{% + \expandafter\XINT_float_a\expandafter\XINTdigits + \romannumeral0\XINT_infrac {#1}\XINT_float_Q +}% +\def\XINT_float_opt [\Z #1]#2% +{% + \expandafter\XINT_float_a\expandafter + {\the\numexpr #1\expandafter}% + \romannumeral0\XINT_infrac {#2}\XINT_float_Q +}% +\def\XINT_float_a #1#2#3% #1=P, #2=n, #3=A, #4=B +{% + \XINT_float_fork #3\Z {#1}{#2}% #1 = precision, #2=n +}% +\def\XINT_float_fork #1% +{% + \xint_UDzerominusfork + #1-\XINT_float_zero + 0#1\XINT_float_J + 0-{\XINT_float_K #1}% + \krof +}% +\def\XINT_float_zero #1\Z #2#3#4#5{ 0.e0}% +\def\XINT_float_J {\expandafter\xint_minus_thenstop\romannumeral0\XINT_float_K }% +\def\XINT_float_K #1\Z #2% #1=A, #2=P, #3=n, #4=B +{% + \expandafter\XINT_float_L\expandafter + {\the\numexpr\xintLength{#1}\expandafter}\expandafter + {\the\numexpr #2+\xint_c_ii}{#1}{#2}% +}% +\def\XINT_float_L #1#2% +{% + \ifnum #1>#2 + \expandafter\XINT_float_Ma + \else + \expandafter\XINT_float_Mc + \fi {#1}{#2}% +}% +\def\XINT_float_Ma #1#2#3% +{% + \expandafter\XINT_float_Mb\expandafter + {\the\numexpr #1-#2\expandafter\expandafter\expandafter}% + \expandafter\expandafter\expandafter + {\expandafter\xint_firstoftwo + \romannumeral0\XINT_split_fromleft_loop {#2}{}#3\W\W\W\W\W\W\W\W\Z + }{#2}% +}% +\def\XINT_float_Mb #1#2#3#4#5#6% #2=A', #3=P+2, #4=P, #5=n, #6=B +{% + \expandafter\XINT_float_N\expandafter + {\the\numexpr\xintLength{#6}\expandafter}\expandafter + {\the\numexpr #3\expandafter}\expandafter + {\the\numexpr #1+#5}% + {#6}{#3}{#2}{#4}% +}% long de B, P+2, n', B, |A'|=P+2, A', P +\def\XINT_float_Mc #1#2#3#4#5#6% +{% + \expandafter\XINT_float_N\expandafter + {\romannumeral0\xintlength{#6}}{#2}{#5}{#6}{#1}{#3}{#4}% +}% long de B, P+2, n, B, |A|, A, P +\def\XINT_float_N #1#2% +{% + \ifnum #1>#2 + \expandafter\XINT_float_O + \else + \expandafter\XINT_float_P + \fi {#1}{#2}% +}% +\def\XINT_float_O #1#2#3#4% +{% + \expandafter\XINT_float_P\expandafter + {\the\numexpr #2\expandafter}\expandafter + {\the\numexpr #2\expandafter}\expandafter + {\the\numexpr #3-#1+#2\expandafter\expandafter\expandafter}% + \expandafter\expandafter\expandafter + {\expandafter\xint_firstoftwo + \romannumeral0\XINT_split_fromleft_loop {#2}{}#4\W\W\W\W\W\W\W\W\Z + }% +}% |B|,P+2,n,B,|A|,A,P +\def\XINT_float_P #1#2#3#4#5#6#7#8% +{% + \expandafter #8\expandafter {\the\numexpr #1-#5+#2-\xint_c_i}% + {#6}{#4}{#7}{#3}% +}% |B|-|A|+P+1,A,B,P,n +\def\XINT_float_Q #1% +{% + \ifnum #1<\xint_c_ + \expandafter\XINT_float_Ri + \else + \expandafter\XINT_float_Rii + \fi {#1}% +}% +\def\XINT_float_Ri #1#2#3% +{% + \expandafter\XINT_float_Sa + \romannumeral0\xintiiquo {#2}% + {\XINT_dsx_addzerosnofuss {-#1}{#3}}\Z {#1}% +}% +\def\XINT_float_Rii #1#2#3% +{% + \expandafter\XINT_float_Sa + \romannumeral0\xintiiquo + {\XINT_dsx_addzerosnofuss {#1}{#2}}{#3}\Z {#1}% +}% +\def\XINT_float_Sa #1% +{% + \if #19% + \xint_afterfi {\XINT_float_Sb\XINT_float_Wb }% + \else + \xint_afterfi {\XINT_float_Sb\XINT_float_Wa }% + \fi #1% +}% +\def\XINT_float_Sb #1#2\Z #3#4% +{% + \expandafter\XINT_float_T\expandafter + {\the\numexpr #4+\xint_c_i\expandafter}% + \romannumeral-`0\XINT_lenrord_loop 0{}#2\Z\W\W\W\W\W\W\W\Z #1{#3}{#4}% +}% +\def\XINT_float_T #1#2#3% +{% + \ifnum #2>#1 + \xint_afterfi{\XINT_float_U\XINT_float_Xb}% + \else + \xint_afterfi{\XINT_float_U\XINT_float_Xa #3}% + \fi +}% +\def\XINT_float_U #1#2% +{% + \ifnum #2<\xint_c_v + \expandafter\XINT_float_Va + \else + \expandafter\XINT_float_Vb + \fi #1% +}% +\def\XINT_float_Va #1#2\Z #3% +{% + \expandafter#1% + \romannumeral0\expandafter\XINT_float_Wa + \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 \Z +}% +\def\XINT_float_Vb #1#2\Z #3% +{% + \expandafter #1% + \romannumeral0\expandafter #3% + \romannumeral0\XINT_addm_A 0{}1000\W\X\Y\Z #2000\W\X\Y\Z \Z +}% +\def\XINT_float_Wa #1{ #1.}% +\def\XINT_float_Wb #1#2% + {\if #11\xint_afterfi{ 10.}\else\xint_afterfi{ #1.#2}\fi }% +\def\XINT_float_Xa #1\Z #2#3#4% +{% + \expandafter\XINT_float_Y\expandafter + {\the\numexpr #3+#4-#2}{#1}% +}% +\def\XINT_float_Xb #1\Z #2#3#4% +{% + \expandafter\XINT_float_Y\expandafter + {\the\numexpr #3+#4+\xint_c_i-#2}{#1}% +}% +\def\XINT_float_Y #1#2{ #2e#1}% +% \end{macrocode} +% \subsection{\csh{XINTinFloat}} +% \lverb|1.07. Completely rewritten in 1.08a for immensely greater efficiency +% when the power of ten is big: previous version had some very serious +% bottlenecks arising from the creation of long strings of zeros, which made +% things such as 2^999999 completely impossible, but now even 2^999999999 with +% 24 significant digits is no problem! Again (slightly) improved in 1.08b. +% +% I decide in 1.09a not to use anymore \romannumeral`-0 mais \romannumeral0 also +% in the float routines, for consistency of style. +% +% Here again some inner macros used the \xintiquo with extra \xintnum overhead +% in 1.09a, 1.09f fixed that to use \xintiiquo for example. +% +% 1.09i added a stupid bug to \XINT_infloat_zero when it changed 0[0] to a silly +% 0/1[0], breaking in particular \xintFloatAdd when one of the argument is zero +% :((( +% +% 1.09j fixes this. Besides, for notational coherence \XINT_inFloat and +% \XINT_infloat have been renamed respectively \XINTinFloat and \XINTinfloat in +% release 1.09j.| +% \begin{macrocode} +\def\XINTinFloat {\romannumeral0\XINTinfloat }% +\def\XINTinfloat [#1]#2% +{% + \expandafter\XINT_infloat_a\expandafter + {\the\numexpr #1\expandafter}% + \romannumeral0\XINT_infrac {#2}\XINT_infloat_Q +}% +\def\XINT_infloat_a #1#2#3% #1=P, #2=n, #3=A, #4=B +{% + \XINT_infloat_fork #3\Z {#1}{#2}% #1 = precision, #2=n +}% +\def\XINT_infloat_fork #1% +{% + \xint_UDzerominusfork + #1-\XINT_infloat_zero + 0#1\XINT_infloat_J + 0-{\XINT_float_K #1}% + \krof +}% +\def\XINT_infloat_zero #1\Z #2#3#4#5{ 0[0]}% +% the 0[0] was stupidly changed to 0/1[0] in 1.09i, with the result that the +% Float addition would crash when an operand was zero +\def\XINT_infloat_J {\expandafter-\romannumeral0\XINT_float_K }% +\def\XINT_infloat_Q #1% +{% + \ifnum #1<\xint_c_ + \expandafter\XINT_infloat_Ri + \else + \expandafter\XINT_infloat_Rii + \fi {#1}% +}% +\def\XINT_infloat_Ri #1#2#3% +{% + \expandafter\XINT_infloat_S\expandafter + {\romannumeral0\xintiiquo {#2}% + {\XINT_dsx_addzerosnofuss {-#1}{#3}}}{#1}% +}% +\def\XINT_infloat_Rii #1#2#3% +{% + \expandafter\XINT_infloat_S\expandafter + {\romannumeral0\xintiiquo + {\XINT_dsx_addzerosnofuss {#1}{#2}}{#3}}{#1}% +}% +\def\XINT_infloat_S #1#2#3% +{% + \expandafter\XINT_infloat_T\expandafter + {\the\numexpr #3+\xint_c_i\expandafter}% + \romannumeral-`0\XINT_lenrord_loop 0{}#1\Z\W\W\W\W\W\W\W\Z + {#2}% +}% +\def\XINT_infloat_T #1#2#3% +{% + \ifnum #2>#1 + \xint_afterfi{\XINT_infloat_U\XINT_infloat_Wb}% + \else + \xint_afterfi{\XINT_infloat_U\XINT_infloat_Wa #3}% + \fi +}% +\def\XINT_infloat_U #1#2% +{% + \ifnum #2<\xint_c_v + \expandafter\XINT_infloat_Va + \else + \expandafter\XINT_infloat_Vb + \fi #1% +}% +\def\XINT_infloat_Va #1#2\Z +{% + \expandafter#1% + \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 \Z +}% +\def\XINT_infloat_Vb #1#2\Z +{% + \expandafter #1% + \romannumeral0\XINT_addm_A 0{}1000\W\X\Y\Z #2000\W\X\Y\Z \Z +}% +\def\XINT_infloat_Wa #1\Z #2#3% +{% + \expandafter\XINT_infloat_X\expandafter + {\the\numexpr #3+\xint_c_i-#2}{#1}% +}% +\def\XINT_infloat_Wb #1\Z #2#3% +{% + \expandafter\XINT_infloat_X\expandafter + {\the\numexpr #3+\xint_c_ii-#2}{#1}% +}% +\def\XINT_infloat_X #1#2{ #2[#1]}% +% \end{macrocode} +% \subsection{\csh{xintAdd}} +% \begin{macrocode} +\def\xintAdd {\romannumeral0\xintadd }% +\def\xintadd #1% +{% + \expandafter\xint_fadd\expandafter {\romannumeral0\XINT_infrac {#1}}% +}% +\def\xint_fadd #1#2{\expandafter\XINT_fadd_A\romannumeral0\XINT_infrac{#2}#1}% +\def\XINT_fadd_A #1#2#3#4% +{% + \ifnum #4 > #1 + \xint_afterfi {\XINT_fadd_B {#1}}% + \else + \xint_afterfi {\XINT_fadd_B {#4}}% + \fi + {#1}{#4}{#2}{#3}% +}% +\def\XINT_fadd_B #1#2#3#4#5#6#7% +{% + \expandafter\XINT_fadd_C\expandafter + {\romannumeral0\xintiimul {#7}{#5}}% + {\romannumeral0\xintiiadd + {\romannumeral0\xintiimul {\xintDSH {\the\numexpr -#3+#1\relax}{#6}}{#5}}% + {\romannumeral0\xintiimul {#7}{\xintDSH {\the\numexpr -#2+#1\relax}{#4}}}% + }% + {#1}% +}% +\def\XINT_fadd_C #1#2#3% +{% + \expandafter\XINT_fadd_D\expandafter {#2}{#3}{#1}% +}% +\def\XINT_fadd_D #1#2{\XINT_outfrac {#2}{#1}}% +% \end{macrocode} +% \subsection{\csh{xintSub}} +% \begin{macrocode} +\def\xintSub {\romannumeral0\xintsub }% +\def\xintsub #1% +{% + \expandafter\xint_fsub\expandafter {\romannumeral0\XINT_infrac {#1}}% +}% +\def\xint_fsub #1#2% + {\expandafter\XINT_fsub_A\romannumeral0\XINT_infrac {#2}#1}% +\def\XINT_fsub_A #1#2#3#4% +{% + \ifnum #4 > #1 + \xint_afterfi {\XINT_fsub_B {#1}}% + \else + \xint_afterfi {\XINT_fsub_B {#4}}% + \fi + {#1}{#4}{#2}{#3}% +}% +\def\XINT_fsub_B #1#2#3#4#5#6#7% +{% + \expandafter\XINT_fsub_C\expandafter + {\romannumeral0\xintiimul {#7}{#5}}% + {\romannumeral0\xintiisub + {\romannumeral0\xintiimul {\xintDSH {\the\numexpr -#3+#1\relax}{#6}}{#5}}% + {\romannumeral0\xintiimul {#7}{\xintDSH {\the\numexpr -#2+#1\relax}{#4}}}% + }% + {#1}% +}% +\def\XINT_fsub_C #1#2#3% +{% + \expandafter\XINT_fsub_D\expandafter {#2}{#3}{#1}% +}% +\def\XINT_fsub_D #1#2{\XINT_outfrac {#2}{#1}}% +% \end{macrocode} +% \subsection{\csh{xintSum}} +% \begin{macrocode} +\def\xintSum {\romannumeral0\xintsum }% +\def\xintsum #1{\xintsumexpr #1\relax }% +\def\xintSumExpr {\romannumeral0\xintsumexpr }% +\def\xintsumexpr {\expandafter\XINT_fsumexpr\romannumeral-`0}% +\def\XINT_fsumexpr {\XINT_fsum_loop_a {0/1[0]}}% +\def\XINT_fsum_loop_a #1#2% +{% + \expandafter\XINT_fsum_loop_b \romannumeral-`0#2\Z {#1}% +}% +\def\XINT_fsum_loop_b #1% +{% + \xint_gob_til_relax #1\XINT_fsum_finished\relax + \XINT_fsum_loop_c #1% +}% +\def\XINT_fsum_loop_c #1\Z #2% +{% + \expandafter\XINT_fsum_loop_a\expandafter{\romannumeral0\xintadd {#2}{#1}}% +}% +\def\XINT_fsum_finished #1\Z #2{ #2}% +% \end{macrocode} +% \subsection{\csh{xintMul}} +% \begin{macrocode} +\def\xintMul {\romannumeral0\xintmul }% +\def\xintmul #1% +{% + \expandafter\xint_fmul\expandafter {\romannumeral0\XINT_infrac {#1}}% +}% +\def\xint_fmul #1#2% + {\expandafter\XINT_fmul_A\romannumeral0\XINT_infrac {#2}#1}% +\def\XINT_fmul_A #1#2#3#4#5#6% +{% + \expandafter\XINT_fmul_B + \expandafter{\the\numexpr #1+#4\expandafter}% + \expandafter{\romannumeral0\xintiimul {#6}{#3}}% + {\romannumeral0\xintiimul {#5}{#2}}% +}% +\def\XINT_fmul_B #1#2#3% +{% + \expandafter \XINT_fmul_C \expandafter{#3}{#1}{#2}% +}% +\def\XINT_fmul_C #1#2{\XINT_outfrac {#2}{#1}}% +% \end{macrocode} +% \subsection{\csh{xintSqr}} +% \begin{macrocode} +\def\xintSqr {\romannumeral0\xintsqr }% +\def\xintsqr #1% +{% + \expandafter\xint_fsqr\expandafter{\romannumeral0\XINT_infrac {#1}}% +}% +\def\xint_fsqr #1{\XINT_fmul_A #1#1}% +% \end{macrocode} +% \subsection{\csh{xintPow}} +% \lverb|& +% Modified in 1.06 to give the exponent to a \numexpr. +% +% With 1.07 and for use within the \xintexpr parser, we must allow +% fractions (which are integers in disguise) as input to the exponent, so we +% must have a variant which uses \xintNum and not only \numexpr +% for normalizing the input. Hence the \xintfPow here. +% +% 1.08b: well actually I +% think that with xintfrac.sty loaded the exponent should always be allowed to +% be a fraction giving an integer. So I do as for \xintFac, and remove here the +% duplicated. Then \xintexpr can use the \xintPow as defined here.| +% \begin{macrocode} +\def\xintPow {\romannumeral0\xintpow }% +\def\xintpow #1% +{% + \expandafter\xint_fpow\expandafter {\romannumeral0\XINT_infrac {#1}}% +}% +\def\xint_fpow #1#2% +{% + \expandafter\XINT_fpow_fork\the\numexpr \xintNum{#2}\relax\Z #1% +}% +\def\XINT_fpow_fork #1#2\Z +{% + \xint_UDzerominusfork + #1-\XINT_fpow_zero + 0#1\XINT_fpow_neg + 0-{\XINT_fpow_pos #1}% + \krof + {#2}% +}% +\def\XINT_fpow_zero #1#2#3#4{ 1/1[0]}% +\def\XINT_fpow_pos #1#2#3#4#5% +{% + \expandafter\XINT_fpow_pos_A\expandafter + {\the\numexpr #1#2*#3\expandafter}\expandafter + {\romannumeral0\xintiipow {#5}{#1#2}}% + {\romannumeral0\xintiipow {#4}{#1#2}}% +}% +\def\XINT_fpow_neg #1#2#3#4% +{% + \expandafter\XINT_fpow_pos_A\expandafter + {\the\numexpr -#1*#2\expandafter}\expandafter + {\romannumeral0\xintiipow {#3}{#1}}% + {\romannumeral0\xintiipow {#4}{#1}}% +}% +\def\XINT_fpow_pos_A #1#2#3% +{% + \expandafter\XINT_fpow_pos_B\expandafter {#3}{#1}{#2}% +}% +\def\XINT_fpow_pos_B #1#2{\XINT_outfrac {#2}{#1}}% +% \end{macrocode} +% \subsection{\csh{xintFac}} +% \lverb|1.07: to be used by the \xintexpr scanner which needs to be able to +% apply \xintFac +% to a fraction which is an integer in disguise; so we use \xintNum and not only +% \numexpr. Je modifie cela dans 1.08b, au lieu d'avoir un \xintfFac +% spécialement pour \xintexpr, tout simplement j'étends \xintFac comme les +% autres macros, pour qu'elle utilise \xintNum. | +% \begin{macrocode} +\def\xintFac {\romannumeral0\xintfac }% +\def\xintfac #1% +{% + \expandafter\XINT_fac_fork\expandafter{\the\numexpr \xintNum{#1}}% +}% +% \end{macrocode} +% \subsection{\csh{xintPrd}} +% \begin{macrocode} +\def\xintPrd {\romannumeral0\xintprd }% +\def\xintprd #1{\xintprdexpr #1\relax }% +\def\xintPrdExpr {\romannumeral0\xintprdexpr }% +\def\xintprdexpr {\expandafter\XINT_fprdexpr \romannumeral-`0}% +\def\XINT_fprdexpr {\XINT_fprod_loop_a {1/1[0]}}% +\def\XINT_fprod_loop_a #1#2% +{% + \expandafter\XINT_fprod_loop_b \romannumeral-`0#2\Z {#1}% +}% +\def\XINT_fprod_loop_b #1% +{% + \xint_gob_til_relax #1\XINT_fprod_finished\relax + \XINT_fprod_loop_c #1% +}% +\def\XINT_fprod_loop_c #1\Z #2% +{% + \expandafter\XINT_fprod_loop_a\expandafter{\romannumeral0\xintmul {#1}{#2}}% +}% +\def\XINT_fprod_finished #1\Z #2{ #2}% +% \end{macrocode} +% \subsection{\csh{xintDiv}} +% \begin{macrocode} +\def\xintDiv {\romannumeral0\xintdiv }% +\def\xintdiv #1% +{% + \expandafter\xint_fdiv\expandafter {\romannumeral0\XINT_infrac {#1}}% +}% +\def\xint_fdiv #1#2% + {\expandafter\XINT_fdiv_A\romannumeral0\XINT_infrac {#2}#1}% +\def\XINT_fdiv_A #1#2#3#4#5#6% +{% + \expandafter\XINT_fdiv_B + \expandafter{\the\numexpr #4-#1\expandafter}% + \expandafter{\romannumeral0\xintiimul {#2}{#6}}% + {\romannumeral0\xintiimul {#3}{#5}}% +}% +\def\XINT_fdiv_B #1#2#3% +{% + \expandafter\XINT_fdiv_C + \expandafter{#3}{#1}{#2}% +}% +\def\XINT_fdiv_C #1#2{\XINT_outfrac {#2}{#1}}% +% \end{macrocode} +% \subsection{\csh{xintIsOne}} +% \lverb|& +% New with 1.09a. Could be more efficient. For fractions with big powers of +% tens, it is better to use \xintCmp{f}{1}. Restyled in 1.09i.| +% \begin{macrocode} +\def\xintIsOne {\romannumeral0\xintisone }% +\def\xintisone #1{\expandafter\XINT_fracisone + \romannumeral0\xintrawwithzeros{#1}\Z }% +\def\XINT_fracisone #1/#2\Z + {\if0\XINT_Cmp {#1}{#2}\xint_afterfi{ 1}\else\xint_afterfi{ 0}\fi}% +% \end{macrocode} +% \subsection{\csh{xintGeq}} +% \lverb|& +% Rewritten completely in 1.08a to be less dumb when comparing fractions having +% big powers of tens.| +% \begin{macrocode} +\def\xintGeq {\romannumeral0\xintgeq }% +\def\xintgeq #1% +{% + \expandafter\xint_fgeq\expandafter {\romannumeral0\xintabs {#1}}% +}% +\def\xint_fgeq #1#2% +{% + \expandafter\XINT_fgeq_A \romannumeral0\xintabs {#2}#1% +}% +\def\XINT_fgeq_A #1% +{% + \xint_gob_til_zero #1\XINT_fgeq_Zii 0% + \XINT_fgeq_B #1% +}% +\def\XINT_fgeq_Zii 0\XINT_fgeq_B #1[#2]#3[#4]{ 1}% +\def\XINT_fgeq_B #1/#2[#3]#4#5/#6[#7]% +{% + \xint_gob_til_zero #4\XINT_fgeq_Zi 0% + \expandafter\XINT_fgeq_C\expandafter + {\the\numexpr #7-#3\expandafter}\expandafter + {\romannumeral0\xintiimul {#4#5}{#2}}% + {\romannumeral0\xintiimul {#6}{#1}}% +}% +\def\XINT_fgeq_Zi 0#1#2#3#4#5#6#7{ 0}% +\def\XINT_fgeq_C #1#2#3% +{% + \expandafter\XINT_fgeq_D\expandafter + {#3}{#1}{#2}% +}% +\def\XINT_fgeq_D #1#2#3% +{% + \expandafter\XINT_cntSgnFork\romannumeral-`0\expandafter\XINT_cntSgn + \the\numexpr #2+\xintLength{#3}-\xintLength{#1}\relax\Z + { 0}{\XINT_fgeq_E #2\Z {#3}{#1}}{ 1}% +}% +\def\XINT_fgeq_E #1% +{% + \xint_UDsignfork + #1\XINT_fgeq_Fd + -{\XINT_fgeq_Fn #1}% + \krof +}% +\def\XINT_fgeq_Fd #1\Z #2#3% +{% + \expandafter\XINT_fgeq_Fe\expandafter + {\romannumeral0\XINT_dsx_addzerosnofuss {#1}{#3}}{#2}% +}% +\def\XINT_fgeq_Fe #1#2{\XINT_geq_pre {#2}{#1}}% +\def\XINT_fgeq_Fn #1\Z #2#3% +{% + \expandafter\XINT_geq_pre\expandafter + {\romannumeral0\XINT_dsx_addzerosnofuss {#1}{#2}}{#3}% +}% +% \end{macrocode} +% \subsection{\csh{xintMax}} +% \lverb|& +% Rewritten completely in 1.08a.| +% \begin{macrocode} +\def\xintMax {\romannumeral0\xintmax }% +\def\xintmax #1% +{% + \expandafter\xint_fmax\expandafter {\romannumeral0\xintraw {#1}}% +}% +\def\xint_fmax #1#2% +{% + \expandafter\XINT_fmax_A\romannumeral0\xintraw {#2}#1% +}% +\def\XINT_fmax_A #1#2/#3[#4]#5#6/#7[#8]% +{% + \xint_UDsignsfork + #1#5\XINT_fmax_minusminus + -#5\XINT_fmax_firstneg + #1-\XINT_fmax_secondneg + --\XINT_fmax_nonneg_a + \krof + #1#5{#2/#3[#4]}{#6/#7[#8]}% +}% +\def\XINT_fmax_minusminus --% + {\expandafter\xint_minus_thenstop\romannumeral0\XINT_fmin_nonneg_b }% +\def\XINT_fmax_firstneg #1-#2#3{ #1#2}% +\def\XINT_fmax_secondneg -#1#2#3{ #1#3}% +\def\XINT_fmax_nonneg_a #1#2#3#4% +{% + \XINT_fmax_nonneg_b {#1#3}{#2#4}% +}% +\def\XINT_fmax_nonneg_b #1#2% +{% + \if0\romannumeral0\XINT_fgeq_A #1#2% + \xint_afterfi{ #1}% + \else \xint_afterfi{ #2}% + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintMaxof}} +% \begin{macrocode} +\def\xintMaxof {\romannumeral0\xintmaxof }% +\def\xintmaxof #1{\expandafter\XINT_maxof_a\romannumeral-`0#1\relax }% +\def\XINT_maxof_a #1{\expandafter\XINT_maxof_b\romannumeral0\xintraw{#1}\Z }% +\def\XINT_maxof_b #1\Z #2% + {\expandafter\XINT_maxof_c\romannumeral-`0#2\Z {#1}\Z}% +\def\XINT_maxof_c #1% + {\xint_gob_til_relax #1\XINT_maxof_e\relax\XINT_maxof_d #1}% +\def\XINT_maxof_d #1\Z + {\expandafter\XINT_maxof_b\romannumeral0\xintmax {#1}}% +\def\XINT_maxof_e #1\Z #2\Z { #2}% +% \end{macrocode} +% \subsection{\csh{xintMin}} +% \lverb|& +% Rewritten completely in 1.08a.| +% \begin{macrocode} +\def\xintMin {\romannumeral0\xintmin }% +\def\xintmin #1% +{% + \expandafter\xint_fmin\expandafter {\romannumeral0\xintraw {#1}}% +}% +\def\xint_fmin #1#2% +{% + \expandafter\XINT_fmin_A\romannumeral0\xintraw {#2}#1% +}% +\def\XINT_fmin_A #1#2/#3[#4]#5#6/#7[#8]% +{% + \xint_UDsignsfork + #1#5\XINT_fmin_minusminus + -#5\XINT_fmin_firstneg + #1-\XINT_fmin_secondneg + --\XINT_fmin_nonneg_a + \krof + #1#5{#2/#3[#4]}{#6/#7[#8]}% +}% +\def\XINT_fmin_minusminus --% + {\expandafter\xint_minus_thenstop\romannumeral0\XINT_fmax_nonneg_b }% +\def\XINT_fmin_firstneg #1-#2#3{ -#3}% +\def\XINT_fmin_secondneg -#1#2#3{ -#2}% +\def\XINT_fmin_nonneg_a #1#2#3#4% +{% + \XINT_fmin_nonneg_b {#1#3}{#2#4}% +}% +\def\XINT_fmin_nonneg_b #1#2% +{% + \if0\romannumeral0\XINT_fgeq_A #1#2% + \xint_afterfi{ #2}% + \else \xint_afterfi{ #1}% + \fi +}% +% \end{macrocode} +% \subsection{\csh{xintMinof}} +% \begin{macrocode} +\def\xintMinof {\romannumeral0\xintminof }% +\def\xintminof #1{\expandafter\XINT_minof_a\romannumeral-`0#1\relax }% +\def\XINT_minof_a #1{\expandafter\XINT_minof_b\romannumeral0\xintraw{#1}\Z }% +\def\XINT_minof_b #1\Z #2% + {\expandafter\XINT_minof_c\romannumeral-`0#2\Z {#1}\Z}% +\def\XINT_minof_c #1% + {\xint_gob_til_relax #1\XINT_minof_e\relax\XINT_minof_d #1}% +\def\XINT_minof_d #1\Z + {\expandafter\XINT_minof_b\romannumeral0\xintmin {#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. Incredibly, it seems that 1.08b introduced a bug in +% delimited arguments making the macro just non-functional when one of the input +% was zero! I +% did not detect this until working on release 1.09a, somehow I had not tested +% that +% \xintCmp just did NOT work! I must have done some last minute change... | +% \begin{macrocode} +\def\xintCmp {\romannumeral0\xintcmp }% +\def\xintcmp #1% +{% + \expandafter\xint_fcmp\expandafter {\romannumeral0\xintraw {#1}}% +}% +\def\xint_fcmp #1#2% +{% + \expandafter\XINT_fcmp_A\romannumeral0\xintraw {#2}#1% +}% +\def\XINT_fcmp_A #1#2/#3[#4]#5#6/#7[#8]% +{% + \xint_UDsignsfork + #1#5\XINT_fcmp_minusminus + -#5\XINT_fcmp_firstneg + #1-\XINT_fcmp_secondneg + --\XINT_fcmp_nonneg_a + \krof + #1#5{#2/#3[#4]}{#6/#7[#8]}% +}% +\def\XINT_fcmp_minusminus --#1#2{\XINT_fcmp_B #2#1}% +\def\XINT_fcmp_firstneg #1-#2#3{ -1}% +\def\XINT_fcmp_secondneg -#1#2#3{ 1}% +\def\XINT_fcmp_nonneg_a #1#2% +{% + \xint_UDzerosfork + #1#2\XINT_fcmp_zerozero + 0#2\XINT_fcmp_firstzero + #10\XINT_fcmp_secondzero + 00\XINT_fcmp_pos + \krof + #1#2% +}% +\def\XINT_fcmp_zerozero #1#2#3#4{ 0}% 1.08b had some [ and ] here!!! +\def\XINT_fcmp_firstzero #1#2#3#4{ -1}% incredibly I never saw that until +\def\XINT_fcmp_secondzero #1#2#3#4{ 1}% preparing 1.09a. +\def\XINT_fcmp_pos #1#2#3#4% +{% + \XINT_fcmp_B #1#3#2#4% +}% +\def\XINT_fcmp_B #1/#2[#3]#4/#5[#6]% +{% + \expandafter\XINT_fcmp_C\expandafter + {\the\numexpr #6-#3\expandafter}\expandafter + {\romannumeral0\xintiimul {#4}{#2}}% + {\romannumeral0\xintiimul {#5}{#1}}% +}% +\def\XINT_fcmp_C #1#2#3% +{% + \expandafter\XINT_fcmp_D\expandafter + {#3}{#1}{#2}% +}% +\def\XINT_fcmp_D #1#2#3% +{% + \expandafter\XINT_cntSgnFork\romannumeral-`0\expandafter\XINT_cntSgn + \the\numexpr #2+\xintLength{#3}-\xintLength{#1}\relax\Z + { -1}{\XINT_fcmp_E #2\Z {#3}{#1}}{ 1}% +}% +\def\XINT_fcmp_E #1% +{% + \xint_UDsignfork + #1\XINT_fcmp_Fd + -{\XINT_fcmp_Fn #1}% + \krof +}% +\def\XINT_fcmp_Fd #1\Z #2#3% +{% + \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_Fn #1\Z #2#3% +{% + \expandafter\XINT_cmp_pre\expandafter + {\romannumeral0\XINT_dsx_addzerosnofuss {#1}{#2}}{#3}% +}% +% \end{macrocode} +% \subsection{\csh{xintAbs}} +% \lverb|Simplified in 1.09i. (original macro was 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 was 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 was written before \xintRaw)| +% \begin{macrocode} +\def\xintSgn {\romannumeral0\xintsgn }% +\def\xintsgn #1{\expandafter\XINT_sgn\romannumeral0\xintraw {#1}\Z }% +% \end{macrocode} +% \subsection{\csh{xintFloatAdd}, \csh{XINTinFloatAdd}} +% \lverb|1.07; 1.09ka improves a bit the efficieny of the coding of +% \XINT_FL_Add_d.| +% \begin{macrocode} +\def\xintFloatAdd {\romannumeral0\xintfloatadd }% +\def\xintfloatadd #1{\XINT_fladd_chkopt \xintfloat #1\Z }% +\def\XINTinFloatAdd {\romannumeral0\XINTinfloatadd }% +\def\XINTinfloatadd #1{\XINT_fladd_chkopt \XINTinfloat #1\Z }% +\def\XINT_fladd_chkopt #1#2% +{% + \ifx [#2\expandafter\XINT_fladd_opt + \else\expandafter\XINT_fladd_noopt + \fi #1#2% +}% +\def\XINT_fladd_noopt #1#2\Z #3% +{% + #1[\XINTdigits]{\XINT_FL_Add {\XINTdigits+\xint_c_ii}{#2}{#3}}% +}% +\def\XINT_fladd_opt #1[\Z #2]#3#4% +{% + #1[#2]{\XINT_FL_Add {#2+\xint_c_ii}{#3}{#4}}% +}% +\def\XINT_FL_Add #1#2% +{% + \expandafter\XINT_FL_Add_a\expandafter{\the\numexpr #1\expandafter}% + \expandafter{\romannumeral0\XINTinfloat [#1]{#2}}% +}% +\def\XINT_FL_Add_a #1#2#3% +{% + \expandafter\XINT_FL_Add_b\romannumeral0\XINTinfloat [#1]{#3}#2{#1}% +}% +\def\XINT_FL_Add_b #1% +{% + \xint_gob_til_zero #1\XINT_FL_Add_zero 0\XINT_FL_Add_c #1% +}% +\def\XINT_FL_Add_c #1[#2]#3% +{% + \xint_gob_til_zero #3\XINT_FL_Add_zerobis 0\XINT_FL_Add_d #1[#2]#3% +}% +\def\XINT_FL_Add_d #1[#2]#3[#4]#5% +{% + \ifnum \numexpr #2-#4-#5>\xint_c_i + \expandafter \xint_secondofthree_thenstop + \else + \ifnum \numexpr #4-#2-#5>\xint_c_i + \expandafter\expandafter\expandafter\xint_thirdofthree_thenstop + \fi + \fi + \xintadd {#1[#2]}{#3[#4]}% +}% +\def\XINT_FL_Add_zero 0\XINT_FL_Add_c 0[0]#1[#2]#3{#1[#2]}% +\def\XINT_FL_Add_zerobis 0\XINT_FL_Add_d #1[#2]0[0]#3{#1[#2]}% +% \end{macrocode} +% \subsection{\csh{xintFloatSub}, \csh{XINTinFloatSub}} +% \lverb|1.07| +% \begin{macrocode} +\def\xintFloatSub {\romannumeral0\xintfloatsub }% +\def\xintfloatsub #1{\XINT_flsub_chkopt \xintfloat #1\Z }% +\def\XINTinFloatSub {\romannumeral0\XINTinfloatsub }% +\def\XINTinfloatsub #1{\XINT_flsub_chkopt \XINTinfloat #1\Z }% +\def\XINT_flsub_chkopt #1#2% +{% + \ifx [#2\expandafter\XINT_flsub_opt + \else\expandafter\XINT_flsub_noopt + \fi #1#2% +}% +\def\XINT_flsub_noopt #1#2\Z #3% +{% + #1[\XINTdigits]{\XINT_FL_Add {\XINTdigits+\xint_c_ii}{#2}{\xintOpp{#3}}}% +}% +\def\XINT_flsub_opt #1[\Z #2]#3#4% +{% + #1[#2]{\XINT_FL_Add {#2+\xint_c_ii}{#3}{\xintOpp{#4}}}% +}% +% \end{macrocode} +% \subsection{\csh{xintFloatMul}, \csh{XINTinFloatMul}} +% \lverb|1.07| +% \begin{macrocode} +\def\xintFloatMul {\romannumeral0\xintfloatmul}% +\def\xintfloatmul #1{\XINT_flmul_chkopt \xintfloat #1\Z }% +\def\XINTinFloatMul {\romannumeral0\XINTinfloatmul }% +\def\XINTinfloatmul #1{\XINT_flmul_chkopt \XINTinfloat #1\Z }% +\def\XINT_flmul_chkopt #1#2% +{% + \ifx [#2\expandafter\XINT_flmul_opt + \else\expandafter\XINT_flmul_noopt + \fi #1#2% +}% +\def\XINT_flmul_noopt #1#2\Z #3% +{% + #1[\XINTdigits]{\XINT_FL_Mul {\XINTdigits+\xint_c_ii}{#2}{#3}}% +}% +\def\XINT_flmul_opt #1[\Z #2]#3#4% +{% + #1[#2]{\XINT_FL_Mul {#2+\xint_c_ii}{#3}{#4}}% +}% +\def\XINT_FL_Mul #1#2% +{% + \expandafter\XINT_FL_Mul_a\expandafter{\the\numexpr #1\expandafter}% + \expandafter{\romannumeral0\XINTinfloat [#1]{#2}}% +}% +\def\XINT_FL_Mul_a #1#2#3% +{% + \expandafter\XINT_FL_Mul_b\romannumeral0\XINTinfloat [#1]{#3}#2% +}% +\def\XINT_FL_Mul_b #1[#2]#3[#4]{\xintE{\xintiiMul {#1}{#3}}{#2+#4}}% +% \end{macrocode} +% \subsection{\csh{xintFloatDiv}, \csh{XINTinFloatDiv}} +% \lverb|1.07| +% \begin{macrocode} +\def\xintFloatDiv {\romannumeral0\xintfloatdiv}% +\def\xintfloatdiv #1{\XINT_fldiv_chkopt \xintfloat #1\Z }% +\def\XINTinFloatDiv {\romannumeral0\XINTinfloatdiv }% +\def\XINTinfloatdiv #1{\XINT_fldiv_chkopt \XINTinfloat #1\Z }% +\def\XINT_fldiv_chkopt #1#2% +{% + \ifx [#2\expandafter\XINT_fldiv_opt + \else\expandafter\XINT_fldiv_noopt + \fi #1#2% +}% +\def\XINT_fldiv_noopt #1#2\Z #3% +{% + #1[\XINTdigits]{\XINT_FL_Div {\XINTdigits+\xint_c_ii}{#2}{#3}}% +}% +\def\XINT_fldiv_opt #1[\Z #2]#3#4% +{% + #1[#2]{\XINT_FL_Div {#2+\xint_c_ii}{#3}{#4}}% +}% +\def\XINT_FL_Div #1#2% +{% + \expandafter\XINT_FL_Div_a\expandafter{\the\numexpr #1\expandafter}% + \expandafter{\romannumeral0\XINTinfloat [#1]{#2}}% +}% +\def\XINT_FL_Div_a #1#2#3% +{% + \expandafter\XINT_FL_Div_b\romannumeral0\XINTinfloat [#1]{#3}#2% +}% +\def\XINT_FL_Div_b #1[#2]#3[#4]{\xintE{#3/#1}{#4-#2}}% +% \end{macrocode} +% \subsection{\csh{XINTinFloatSum}} +% \lverb|1.09a: quick write-up, for use by \xintfloatexpr, will need to be +% thought through again. Renamed (and slightly modified) in 1.09h. Should be +% extended for optional precision. Should be rewritten for optimization. | +% \begin{macrocode} +\def\XINTinFloatSum {\romannumeral0\XINTinfloatsum }% +\def\XINTinfloatsum #1{\expandafter\XINT_floatsum_a\romannumeral-`0#1\relax }% +\def\XINT_floatsum_a #1{\expandafter\XINT_floatsum_b + \romannumeral0\XINTinfloat[\XINTdigits]{#1}\Z }% +\def\XINT_floatsum_b #1\Z #2% + {\expandafter\XINT_floatsum_c\romannumeral-`0#2\Z {#1}\Z}% +\def\XINT_floatsum_c #1% + {\xint_gob_til_relax #1\XINT_floatsum_e\relax\XINT_floatsum_d #1}% +\def\XINT_floatsum_d #1\Z + {\expandafter\XINT_floatsum_b\romannumeral0\XINTinfloatadd {#1}}% +\def\XINT_floatsum_e #1\Z #2\Z { #2}% +% \end{macrocode} +% \subsection{\csh{XINTinFloatPrd}} +% \lverb|1.09a: quick write-up, for use by \xintfloatexpr, will need to be +% thought through again. Renamed (and slightly modified) in 1.09h. Should be +% extended for optional precision. Should be rewritten for optimization. | +% \begin{macrocode} +\def\XINTinFloatPrd {\romannumeral0\XINTinfloatprd }% +\def\XINTinfloatprd #1{\expandafter\XINT_floatprd_a\romannumeral-`0#1\relax }% +\def\XINT_floatprd_a #1{\expandafter\XINT_floatprd_b + \romannumeral0\XINTinfloat[\XINTdigits]{#1}\Z }% +\def\XINT_floatprd_b #1\Z #2% + {\expandafter\XINT_floatprd_c\romannumeral-`0#2\Z {#1}\Z}% +\def\XINT_floatprd_c #1% + {\xint_gob_til_relax #1\XINT_floatprd_e\relax\XINT_floatprd_d #1}% +\def\XINT_floatprd_d #1\Z + {\expandafter\XINT_floatprd_b\romannumeral0\XINTinfloatmul {#1}}% +\def\XINT_floatprd_e #1\Z #2\Z { #2}% +% \end{macrocode} +% \subsection{\csh{xintFloatPow}, \csh{XINTinFloatPow}} +% \lverb|1.07. Release 1.09j has re-organized the core loop, and +% \XINT_flpow_prd sub-routine has been removed.| +% \begin{macrocode} +\def\xintFloatPow {\romannumeral0\xintfloatpow}% +\def\xintfloatpow #1{\XINT_flpow_chkopt \xintfloat #1\Z }% +\def\XINTinFloatPow {\romannumeral0\XINTinfloatpow }% +\def\XINTinfloatpow #1{\XINT_flpow_chkopt \XINTinfloat #1\Z }% +\def\XINT_flpow_chkopt #1#2% +{% + \ifx [#2\expandafter\XINT_flpow_opt + \else\expandafter\XINT_flpow_noopt + \fi + #1#2% +}% +\def\XINT_flpow_noopt #1#2\Z #3% +{% + \expandafter\XINT_flpow_checkB_start\expandafter + {\the\numexpr #3\expandafter}\expandafter + {\the\numexpr \XINTdigits}{#2}{#1[\XINTdigits]}% +}% +\def\XINT_flpow_opt #1[\Z #2]#3#4% +{% + \expandafter\XINT_flpow_checkB_start\expandafter + {\the\numexpr #4\expandafter}\expandafter + {\the\numexpr #2}{#3}{#1[#2]}% +}% +\def\XINT_flpow_checkB_start #1{\XINT_flpow_checkB_a #1\Z }% +\def\XINT_flpow_checkB_a #1% +{% + \xint_UDzerominusfork + #1-\XINT_flpow_BisZero + 0#1{\XINT_flpow_checkB_b 1}% + 0-{\XINT_flpow_checkB_b 0#1}% + \krof +}% +\def\XINT_flpow_BisZero \Z #1#2#3{#3{1/1[0]}}% +\def\XINT_flpow_checkB_b #1#2\Z #3% +{% + \expandafter\XINT_flpow_checkB_c \expandafter + {\romannumeral0\xintlength{#2}}{#3}{#2}#1% +}% +\def\XINT_flpow_checkB_c #1#2% +{% + \expandafter\XINT_flpow_checkB_d \expandafter + {\the\numexpr \expandafter\xintLength\expandafter + {\the\numexpr #1*20/\xint_c_iii }+#1+#2+\xint_c_i }% +}% +\def\XINT_flpow_checkB_d #1#2#3#4% +{% + \expandafter \XINT_flpow_a + \romannumeral0\XINTinfloat [#1]{#4}{#1}{#2}#3% +}% +\def\XINT_flpow_a #1% +{% + \xint_UDzerominusfork + #1-\XINT_flpow_zero + 0#1{\XINT_flpow_b 1}% + 0-{\XINT_flpow_b 0#1}% + \krof +}% +\def\XINT_flpow_b #1#2[#3]#4#5% +{% + \XINT_flpow_loopI {#5}{#2[#3]}{\romannumeral0\XINTinfloatmul [#4]}% + {#1*\ifodd #5 1\else 0\fi}% +}% +\def\XINT_flpow_zero [#1]#2#3#4#5% +% xint is not equipped to signal infinity, the 2^31 will provoke +% deliberately a number too big and arithmetic overflow in \XINT_float_Xb +{% + \if #41\xint_afterfi {\xintError:DivisionByZero #5{1[2147483648]}}% + \else \xint_afterfi {#5{0[0]}}\fi +}% +\def\XINT_flpow_loopI #1% +{% + \ifnum #1=\xint_c_i\XINT_flpow_ItoIII\fi + \ifodd #1 + \expandafter\XINT_flpow_loopI_odd + \else + \expandafter\XINT_flpow_loopI_even + \fi + {#1}% +}% +\def\XINT_flpow_ItoIII\fi #1\fi #2#3#4#5% +{% + \fi\expandafter\XINT_flpow_III\the\numexpr #5\relax #3% +}% +\def\XINT_flpow_loopI_even #1#2#3% +{% + \expandafter\XINT_flpow_loopI\expandafter + {\the\numexpr #1/\xint_c_ii\expandafter}\expandafter + {#3{#2}{#2}}{#3}% +}% +\def\XINT_flpow_loopI_odd #1#2#3% +{% + \expandafter\XINT_flpow_loopII\expandafter + {\the\numexpr #1/\xint_c_ii-\xint_c_i\expandafter}\expandafter + {#3{#2}{#2}}{#3}{#2}% +}% +\def\XINT_flpow_loopII #1% +{% + \ifnum #1 = \xint_c_i\XINT_flpow_IItoIII\fi + \ifodd #1 + \expandafter\XINT_flpow_loopII_odd + \else + \expandafter\XINT_flpow_loopII_even + \fi + {#1}% +}% +\def\XINT_flpow_loopII_even #1#2#3% +{% + \expandafter\XINT_flpow_loopII\expandafter + {\the\numexpr #1/\xint_c_ii\expandafter}\expandafter + {#3{#2}{#2}}{#3}% +}% +\def\XINT_flpow_loopII_odd #1#2#3#4% +{% + \expandafter\XINT_flpow_loopII_odda\expandafter + {#3{#2}{#4}}{#1}{#2}{#3}% +}% +\def\XINT_flpow_loopII_odda #1#2#3#4% +{% + \expandafter\XINT_flpow_loopII\expandafter + {\the\numexpr #2/\xint_c_ii-\xint_c_i\expandafter}\expandafter + {#4{#3}{#3}}{#4}{#1}% +}% +\def\XINT_flpow_IItoIII\fi #1\fi #2#3#4#5#6% +{% + \fi\expandafter\XINT_flpow_III\the\numexpr #6\expandafter\relax + #4{#3}{#5}% +}% +\def\XINT_flpow_III #1#2[#3]#4% +{% + \expandafter\XINT_flpow_IIIend\expandafter + {\the\numexpr\if #41-\fi#3\expandafter}% + \xint_UDzerofork + #4{{#2}}% + 0{{1/#2}}% + \krof #1% +}% +\def\XINT_flpow_IIIend #1#2#3#4% +{% + \xint_UDzerofork + #3{#4{#2[#1]}}% + 0{#4{-#2[#1]}}% + \krof +}% +% \end{macrocode} +% \subsection{\csh{xintFloatPower}, \csh{XINTinFloatPower}} +% \lverb|1.07. The core loop has been re-organized in 1.09j for some slight +% efficiency gain. | +% \begin{macrocode} +\def\xintFloatPower {\romannumeral0\xintfloatpower}% +\def\xintfloatpower #1{\XINT_flpower_chkopt \xintfloat #1\Z }% +\def\XINTinFloatPower {\romannumeral0\XINTinfloatpower}% +\def\XINTinfloatpower #1{\XINT_flpower_chkopt \XINTinfloat #1\Z }% +\def\XINT_flpower_chkopt #1#2% +{% + \ifx [#2\expandafter\XINT_flpower_opt + \else\expandafter\XINT_flpower_noopt + \fi + #1#2% +}% +\def\XINT_flpower_noopt #1#2\Z #3% +{% + \expandafter\XINT_flpower_checkB_start\expandafter + {\the\numexpr \XINTdigits\expandafter}\expandafter + {\romannumeral0\xintnum{#3}}{#2}{#1[\XINTdigits]}% +}% +\def\XINT_flpower_opt #1[\Z #2]#3#4% +{% + \expandafter\XINT_flpower_checkB_start\expandafter + {\the\numexpr #2\expandafter}\expandafter + {\romannumeral0\xintnum{#4}}{#3}{#1[#2]}% +}% +\def\XINT_flpower_checkB_start #1#2{\XINT_flpower_checkB_a #2\Z {#1}}% +\def\XINT_flpower_checkB_a #1% +{% + \xint_UDzerominusfork + #1-\XINT_flpower_BisZero + 0#1{\XINT_flpower_checkB_b 1}% + 0-{\XINT_flpower_checkB_b 0#1}% + \krof +}% +\def\XINT_flpower_BisZero \Z #1#2#3{#3{1/1[0]}}% +\def\XINT_flpower_checkB_b #1#2\Z #3% +{% + \expandafter\XINT_flpower_checkB_c \expandafter + {\romannumeral0\xintlength{#2}}{#3}{#2}#1% +}% +\def\XINT_flpower_checkB_c #1#2% +{% + \expandafter\XINT_flpower_checkB_d \expandafter + {\the\numexpr \expandafter\xintLength\expandafter + {\the\numexpr #1*20/\xint_c_iii }+#1+#2+\xint_c_i }% +}% +\def\XINT_flpower_checkB_d #1#2#3#4% +{% + \expandafter \XINT_flpower_a + \romannumeral0\XINTinfloat [#1]{#4}{#1}{#2}#3% +}% +\def\XINT_flpower_a #1% +{% + \xint_UDzerominusfork + #1-\XINT_flpow_zero + 0#1{\XINT_flpower_b 1}% + 0-{\XINT_flpower_b 0#1}% + \krof +}% +\def\XINT_flpower_b #1#2[#3]#4#5% +{% + \XINT_flpower_loopI {#5}{#2[#3]}{\romannumeral0\XINTinfloatmul [#4]}% + {#1*\xintiiOdd {#5}}% +}% +\def\XINT_flpower_loopI #1% +{% + \if1\XINT_isOne {#1}\XINT_flpower_ItoIII\fi + \if1\xintiiOdd{#1}% + \expandafter\expandafter\expandafter\XINT_flpower_loopI_odd + \else + \expandafter\expandafter\expandafter\XINT_flpower_loopI_even + \fi + \expandafter {\romannumeral0\xinthalf{#1}}% +}% +\def\XINT_flpower_ItoIII\fi #1\fi\expandafter #2#3#4#5% +{% + \fi\expandafter\XINT_flpow_III \the\numexpr #5\relax #3% +}% +\def\XINT_flpower_loopI_even #1#2#3% +{% + \expandafter\XINT_flpower_toI\expandafter {#3{#2}{#2}}{#1}{#3}% +}% +\def\XINT_flpower_loopI_odd #1#2#3% +{% + \expandafter\XINT_flpower_toII\expandafter {#3{#2}{#2}}{#1}{#3}{#2}% +}% +\def\XINT_flpower_toI #1#2{\XINT_flpower_loopI {#2}{#1}}% +\def\XINT_flpower_toII #1#2{\XINT_flpower_loopII {#2}{#1}}% +\def\XINT_flpower_loopII #1% +{% + \if1\XINT_isOne {#1}\XINT_flpower_IItoIII\fi + \if1\xintiiOdd{#1}% + \expandafter\expandafter\expandafter\XINT_flpower_loopII_odd + \else + \expandafter\expandafter\expandafter\XINT_flpower_loopII_even + \fi + \expandafter {\romannumeral0\xinthalf{#1}}% +}% +\def\XINT_flpower_loopII_even #1#2#3% +{% + \expandafter\XINT_flpower_toII\expandafter + {#3{#2}{#2}}{#1}{#3}% +}% +\def\XINT_flpower_loopII_odd #1#2#3#4% +{% + \expandafter\XINT_flpower_loopII_odda\expandafter + {#3{#2}{#4}}{#2}{#3}{#1}% +}% +\def\XINT_flpower_loopII_odda #1#2#3#4% +{% + \expandafter\XINT_flpower_toII\expandafter + {#3{#2}{#2}}{#4}{#3}{#1}% +}% +\def\XINT_flpower_IItoIII\fi #1\fi\expandafter #2#3#4#5#6% +{% + \fi\expandafter\XINT_flpow_III\the\numexpr #6\expandafter\relax + #4{#3}{#5}% +}% +% \end{macrocode} +% \subsection{\csh{xintFloatSqrt}, \csh{XINTinFloatSqrt}} +% \lverb|1.08| +% \begin{macrocode} +\def\xintFloatSqrt {\romannumeral0\xintfloatsqrt }% +\def\xintfloatsqrt #1{\XINT_flsqrt_chkopt \xintfloat #1\Z }% +\def\XINTinFloatSqrt {\romannumeral0\XINTinfloatsqrt }% +\def\XINTinfloatsqrt #1{\XINT_flsqrt_chkopt \XINTinfloat #1\Z }% +\def\XINT_flsqrt_chkopt #1#2% +{% + \ifx [#2\expandafter\XINT_flsqrt_opt + \else\expandafter\XINT_flsqrt_noopt + \fi #1#2% +}% +\def\XINT_flsqrt_noopt #1#2\Z +{% + #1[\XINTdigits]{\XINT_FL_sqrt \XINTdigits {#2}}% +}% +\def\XINT_flsqrt_opt #1[\Z #2]#3% +{% + #1[#2]{\XINT_FL_sqrt {#2}{#3}}% +}% +\def\XINT_FL_sqrt #1% +{% + \ifnum\numexpr #1<\xint_c_xviii + \xint_afterfi {\XINT_FL_sqrt_a\xint_c_xviii}% + \else + \xint_afterfi {\XINT_FL_sqrt_a {#1+\xint_c_i}}% + \fi +}% +\def\XINT_FL_sqrt_a #1#2% +{% + \expandafter\XINT_FL_sqrt_checkifzeroorneg + \romannumeral0\XINTinfloat [#1]{#2}% +}% +\def\XINT_FL_sqrt_checkifzeroorneg #1% +{% + \xint_UDzerominusfork + #1-\XINT_FL_sqrt_iszero + 0#1\XINT_FL_sqrt_isneg + 0-{\XINT_FL_sqrt_b #1}% + \krof +}% +\def\XINT_FL_sqrt_iszero #1[#2]{0[0]}% +\def\XINT_FL_sqrt_isneg #1[#2]{\xintError:RootOfNegative 0[0]}% +\def\XINT_FL_sqrt_b #1[#2]% +{% + \ifodd #2 + \xint_afterfi{\XINT_FL_sqrt_c 01}% + \else + \xint_afterfi{\XINT_FL_sqrt_c {}0}% + \fi + {#1}{#2}% +}% +\def\XINT_FL_sqrt_c #1#2#3#4% +{% + \expandafter\XINT_flsqrt\expandafter {\the\numexpr #4-#2}{#3#1}% +}% +\def\XINT_flsqrt #1#2% +{% + \expandafter\XINT_sqrt_a + \expandafter{\romannumeral0\xintlength {#2}}\XINT_flsqrt_big_d {#2}{#1}% +}% +\def\XINT_flsqrt_big_d #1#2% +{% + \ifodd #2 + \expandafter\expandafter\expandafter\XINT_flsqrt_big_eB + \else + \expandafter\expandafter\expandafter\XINT_flsqrt_big_eA + \fi + \expandafter {\the\numexpr (#2-\xint_c_i)/\xint_c_ii }{#1}% +}% +\def\XINT_flsqrt_big_eA #1#2#3% +{% + \XINT_flsqrt_big_eA_a #3\Z {#2}{#1}{#3}% +}% +\def\XINT_flsqrt_big_eA_a #1#2#3#4#5#6#7#8#9\Z +{% + \XINT_flsqrt_big_eA_b {#1#2#3#4#5#6#7#8}% +}% +\def\XINT_flsqrt_big_eA_b #1#2% +{% + \expandafter\XINT_flsqrt_big_f + \romannumeral0\XINT_flsqrt_small_e {#2001}{#1}% +}% +\def\XINT_flsqrt_big_eB #1#2#3% +{% + \XINT_flsqrt_big_eB_a #3\Z {#2}{#1}{#3}% +}% +\def\XINT_flsqrt_big_eB_a #1#2#3#4#5#6#7#8#9% +{% + \XINT_flsqrt_big_eB_b {#1#2#3#4#5#6#7#8#9}% +}% +\def\XINT_flsqrt_big_eB_b #1#2\Z #3% +{% + \expandafter\XINT_flsqrt_big_f + \romannumeral0\XINT_flsqrt_small_e {#30001}{#1}% +}% +\def\XINT_flsqrt_small_e #1#2% +{% + \expandafter\XINT_flsqrt_small_f\expandafter + {\the\numexpr #1*#1-#2-\xint_c_i}{#1}% +}% +\def\XINT_flsqrt_small_f #1#2% +{% + \expandafter\XINT_flsqrt_small_g\expandafter + {\the\numexpr (#1+#2)/(2*#2)-\xint_c_i }{#1}{#2}% +}% +\def\XINT_flsqrt_small_g #1% +{% + \ifnum #1>\xint_c_ + \expandafter\XINT_flsqrt_small_h + \else + \expandafter\XINT_flsqrt_small_end + \fi + {#1}% +}% +\def\XINT_flsqrt_small_h #1#2#3% +{% + \expandafter\XINT_flsqrt_small_f\expandafter + {\the\numexpr #2-\xint_c_ii*#1*#3+#1*#1\expandafter}\expandafter + {\the\numexpr #3-#1}% +}% +\def\XINT_flsqrt_small_end #1#2#3% +{% + \expandafter\space\expandafter + {\the\numexpr \xint_c_i+#3*\xint_c_x^iv- + (#2*\xint_c_x^iv+#3)/(\xint_c_ii*#3)}% +}% +\def\XINT_flsqrt_big_f #1% +{% + \expandafter\XINT_flsqrt_big_fa\expandafter + {\romannumeral0\xintiisqr {#1}}{#1}% +}% +\def\XINT_flsqrt_big_fa #1#2#3#4% +{% + \expandafter\XINT_flsqrt_big_fb\expandafter + {\romannumeral0\XINT_dsx_addzerosnofuss + {\numexpr #3-\xint_c_viii\relax}{#2}}% + {\romannumeral0\xintiisub + {\XINT_dsx_addzerosnofuss + {\numexpr \xint_c_ii*(#3-\xint_c_viii)\relax}{#1}}{#4}}% + {#3}% +}% +\def\XINT_flsqrt_big_fb #1#2% +{% + \expandafter\XINT_flsqrt_big_g\expandafter {#2}{#1}% +}% +\def\XINT_flsqrt_big_g #1#2% +{% + \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}% +}% +\def\XINT_flsqrt_big_j #1% +{% + \if0\XINT_Sgn #1\Z + \expandafter \XINT_flsqrt_big_end_a + \else \expandafter \XINT_flsqrt_big_k + \fi {#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}}}% +}% +\def\XINT_flsqrt_big_l #1#2% +{% + \expandafter\XINT_flsqrt_big_g\expandafter + {#2}{#1}% +}% +\def\XINT_flsqrt_big_end_a #1#2#3#4#5% +{% + \expandafter\XINT_flsqrt_big_end_b\expandafter + {\the\numexpr -#4+#5/\xint_c_ii\expandafter}\expandafter + {\romannumeral0\xintiisub + {\XINT_dsx_addzerosnofuss {#4}{#3}}% + {\xintHalf{\xintiiQuo{\XINT_dsx_addzerosnofuss {#4}{#2}}{#3}}}}% +}% +\def\XINT_flsqrt_big_end_b #1#2{#2[#1]}% +% \end{macrocode} +% \subsection{\csh{XINTinFloatMaxof}} +% \lverb|1.09a, for use by \xintNewFloatExpr. Name changed in 1.09h| +% \begin{macrocode} +\def\XINTinFloatMaxof {\romannumeral0\XINTinfloatmaxof }% +\def\XINTinfloatmaxof #1{\expandafter\XINT_flmaxof_a\romannumeral-`0#1\relax }% +\def\XINT_flmaxof_a #1{\expandafter\XINT_flmaxof_b + \romannumeral0\XINTinfloat [\XINTdigits]{#1}\Z }% +\def\XINT_flmaxof_b #1\Z #2% + {\expandafter\XINT_flmaxof_c\romannumeral-`0#2\Z {#1}\Z}% +\def\XINT_flmaxof_c #1% + {\xint_gob_til_relax #1\XINT_flmaxof_e\relax\XINT_flmaxof_d #1}% +\def\XINT_flmaxof_d #1\Z + {\expandafter\XINT_flmaxof_b\romannumeral0\xintmax + {\XINTinFloat [\XINTdigits]{#1}}}% +\def\XINT_flmaxof_e #1\Z #2\Z { #2}% +% \end{macrocode} +% \subsection{\csh{XINTinFloatMinof}} +% \lverb|1.09a, for use by \xintNewFloatExpr. Name changed in 1.09h| +% \begin{macrocode} +\def\XINTinFloatMinof {\romannumeral0\XINTinfloatminof }% +\def\XINTinfloatminof #1{\expandafter\XINT_flminof_a\romannumeral-`0#1\relax }% +\def\XINT_flminof_a #1{\expandafter\XINT_flminof_b + \romannumeral0\XINTinfloat [\XINTdigits]{#1}\Z }% +\def\XINT_flminof_b #1\Z #2% + {\expandafter\XINT_flminof_c\romannumeral-`0#2\Z {#1}\Z}% +\def\XINT_flminof_c #1% + {\xint_gob_til_relax #1\XINT_flminof_e\relax\XINT_flminof_d #1}% +\def\XINT_flminof_d #1\Z + {\expandafter\XINT_flminof_b\romannumeral0\xintmin + {\XINTinFloat [\XINTdigits]{#1}}}% +\def\XINT_flminof_e #1\Z #2\Z { #2}% +% \end{macrocode} +% \subsection{\csh{xintRound:csv}} +% \lverb|1.09a. For use by \xinttheiexpr.| +% \begin{macrocode} +\def\xintRound:csv #1{\expandafter\XINT_round:_a\romannumeral-`0#1,,^}% +\def\XINT_round:_a {\XINT_round:_b {}}% +\def\XINT_round:_b #1#2,% + {\expandafter\XINT_round:_c\romannumeral-`0#2,{#1}}% +\def\XINT_round:_c #1{\if #1,\expandafter\XINT_:_f + \else\expandafter\XINT_round:_d\fi #1}% +\def\XINT_round:_d #1,% + {\expandafter\XINT_round:_e\romannumeral0\xintiround 0{#1},}% +\def\XINT_round:_e #1,#2{\XINT_round:_b {#2,#1}}% +% \end{macrocode} +% \subsection{\csh{xintFloat:csv}} +% \lverb|1.09a. For use by \xintthefloatexpr.| +% \begin{macrocode} +\def\xintFloat:csv #1{\expandafter\XINT_float:_a\romannumeral-`0#1,,^}% +\def\XINT_float:_a {\XINT_float:_b {}}% +\def\XINT_float:_b #1#2,% + {\expandafter\XINT_float:_c\romannumeral-`0#2,{#1}}% +\def\XINT_float:_c #1{\if #1,\expandafter\XINT_:_f + \else\expandafter\XINT_float:_d\fi #1}% +\def\XINT_float:_d #1,% + {\expandafter\XINT_float:_e\romannumeral0\xintfloat {#1},}% +\def\XINT_float:_e #1,#2{\XINT_float:_b {#2,#1}}% +% \end{macrocode} +% \subsection{\csh{xintSum:csv}} +% \lverb|1.09a. For use by \xintexpr.| +% \begin{macrocode} +\def\xintSum:csv #1{\expandafter\XINT_sum:_a\romannumeral-`0#1,,^}% +\def\XINT_sum:_a {\XINT_sum:_b {0/1[0]}}% +\def\XINT_sum:_b #1#2,{\expandafter\XINT_sum:_c\romannumeral-`0#2,{#1}}% +\def\XINT_sum:_c #1{\if #1,\expandafter\XINT_:_e + \else\expandafter\XINT_sum:_d\fi #1}% +\def\XINT_sum:_d #1,#2{\expandafter\XINT_sum:_b\expandafter + {\romannumeral0\xintadd {#2}{#1}}}% +% \end{macrocode} +% \subsection{\csh{xintPrd:csv}} +% \lverb|1.09a. For use by \xintexpr.| +% \begin{macrocode} +\def\xintPrd:csv #1{\expandafter\XINT_prd:_a\romannumeral-`0#1,,^}% +\def\XINT_prd:_a {\XINT_prd:_b {1/1[0]}}% +\def\XINT_prd:_b #1#2,{\expandafter\XINT_prd:_c\romannumeral-`0#2,{#1}}% +\def\XINT_prd:_c #1{\if #1,\expandafter\XINT_:_e + \else\expandafter\XINT_prd:_d\fi #1}% +\def\XINT_prd:_d #1,#2{\expandafter\XINT_prd:_b\expandafter + {\romannumeral0\xintmul {#2}{#1}}}% +% \end{macrocode} +% \subsection{\csh{xintMaxof:csv}} +% \lverb|1.09a. For use by \xintexpr. Even with only one +% argument, there does not seem to be really a motive for using \xintraw?| +% \begin{macrocode} +\def\xintMaxof:csv #1{\expandafter\XINT_maxof:_b\romannumeral-`0#1,,}% +\def\XINT_maxof:_b #1,#2,{\expandafter\XINT_maxof:_c\romannumeral-`0#2,{#1},}% +\def\XINT_maxof:_c #1{\if #1,\expandafter\XINT_of:_e + \else\expandafter\XINT_maxof:_d\fi #1}% +\def\XINT_maxof:_d #1,{\expandafter\XINT_maxof:_b\romannumeral0\xintmax {#1}}% +% \end{macrocode} +% \subsection{\csh{xintMinof:csv}} +% \lverb|1.09a. For use by \xintexpr.| +% \begin{macrocode} +\def\xintMinof:csv #1{\expandafter\XINT_minof:_b\romannumeral-`0#1,,}% +\def\XINT_minof:_b #1,#2,{\expandafter\XINT_minof:_c\romannumeral-`0#2,{#1},}% +\def\XINT_minof:_c #1{\if #1,\expandafter\XINT_of:_e + \else\expandafter\XINT_minof:_d\fi #1}% +\def\XINT_minof:_d #1,{\expandafter\XINT_minof:_b\romannumeral0\xintmin {#1}}% +% \end{macrocode} +% \subsection{\csh{XINTinFloatMinof:csv}} +% \lverb|1.09a. For use by \xintfloatexpr. Name changed in 1.09h| +% \begin{macrocode} +\def\XINTinFloatMinof:csv #1{\expandafter\XINT_flminof:_a\romannumeral-`0#1,,}% +\def\XINT_flminof:_a #1,{\expandafter\XINT_flminof:_b + \romannumeral0\XINTinfloat [\XINTdigits]{#1},}% +\def\XINT_flminof:_b #1,#2,% + {\expandafter\XINT_flminof:_c\romannumeral-`0#2,{#1},}% +\def\XINT_flminof:_c #1{\if #1,\expandafter\XINT_of:_e + \else\expandafter\XINT_flminof:_d\fi #1}% +\def\XINT_flminof:_d #1,% + {\expandafter\XINT_flminof:_b\romannumeral0\xintmin + {\XINTinFloat [\XINTdigits]{#1}}}% +% \end{macrocode} +% \subsection{\csh{XINTinFloatMaxof:csv}} +% \lverb|1.09a. For use by \xintfloatexpr. Name changed in 1.09h| +% \begin{macrocode} +\def\XINTinFloatMaxof:csv #1{\expandafter\XINT_flmaxof:_a\romannumeral-`0#1,,}% +\def\XINT_flmaxof:_a #1,{\expandafter\XINT_flmaxof:_b + \romannumeral0\XINTinfloat [\XINTdigits]{#1},}% +\def\XINT_flmaxof:_b #1,#2,% + {\expandafter\XINT_flmaxof:_c\romannumeral-`0#2,{#1},}% +\def\XINT_flmaxof:_c #1{\if #1,\expandafter\XINT_of:_e + \else\expandafter\XINT_flmaxof:_d\fi #1}% +\def\XINT_flmaxof:_d #1,% + {\expandafter\XINT_flmaxof:_b\romannumeral0\xintmax + {\XINTinFloat [\XINTdigits]{#1}}}% +% \end{macrocode} +% \subsection{\csh{XINTinFloatSum:csv}} +% \lverb|1.09a. For use by \xintfloatexpr. Renamed in 1.09h| +% \begin{macrocode} +\def\XINTinFloatSum:csv #1{\expandafter\XINT_floatsum:_a\romannumeral-`0#1,,^}% +\def\XINT_floatsum:_a {\XINT_floatsum:_b {0[0]}}% +\def\XINT_floatsum:_b #1#2,% + {\expandafter\XINT_floatsum:_c\romannumeral-`0#2,{#1}}% +\def\XINT_floatsum:_c #1{\if #1,\expandafter\XINT_:_e + \else\expandafter\XINT_floatsum:_d\fi #1}% +\def\XINT_floatsum:_d #1,#2{\expandafter\XINT_floatsum:_b\expandafter + {\romannumeral0\XINTinfloatadd {#2}{#1}}}% +% \end{macrocode} +% \subsection{\csh{XINTinFloatPrd:csv}} +% \lverb|1.09a. For use by \xintfloatexpr. Renamed in 1.09h| +% \begin{macrocode} +\def\XINTinFloatPred:csv #1{\expandafter\XINT_floatprd:_a\romannumeral-`0#1,,^}% +\def\XINT_floatprd:_a {\XINT_floatprd:_b {1[0]}}% +\def\XINT_floatprd:_b #1#2,% + {\expandafter\XINT_floatprd:_c\romannumeral-`0#2,{#1}}% +\def\XINT_floatprd:_c #1{\if #1,\expandafter\XINT_:_e + \else\expandafter\XINT_floatprd:_d\fi #1}% +\def\XINT_floatprd:_d #1,#2{\expandafter\XINT_floatprd:_b\expandafter + {\romannumeral0\XINTinfloatmul {#2}{#1}}}% +\XINT_restorecatcodes_endinput% +% \end{macrocode} +%\catcode`\<=0 \catcode`\>=11 \catcode`\*=11 \catcode`\/=11 +%\let</xintfrac>\relax +%\def<*xintseries>{\catcode`\<=12 \catcode`\>=12 \catcode`\*=12 \catcode`\/=12 } +%</xintfrac> +%<*xintseries> +% +% \StoreCodelineNo {xintfrac} +% +% \section{Package \xintseriesnameimp implementation} +% \label{sec:seriesimp} +% +% The commenting is currently (\docdate) very sparse. +% +% \localtableofcontents +% \subsection{Catcodes, \protect\eTeX{} and reload detection} +% +% The code for reload detection is copied from \textsc{Heiko +% Oberdiek}'s packages, and adapted here to check for previous +% loading of the \xintfracname package. +% +% The method for catcodes is slightly different, but still +% directly inspired by these packages. +% +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \def\space { }% + \let\z\endgroup + \expandafter\let\expandafter\x\csname ver@xintseries.sty\endcsname + \expandafter\let\expandafter\w\csname ver@xintfrac.sty\endcsname + \expandafter + \ifx\csname PackageInfo\endcsname\relax + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \else + \def\y#1#2{\PackageInfo{#1}{#2}}% + \fi + \expandafter + \ifx\csname numexpr\endcsname\relax + \y{xintseries}{\numexpr not available, aborting input}% + \aftergroup\endinput + \else + \ifx\x\relax % plain-TeX, first loading of xintseries.sty + \ifx\w\relax % but xintfrac.sty not yet loaded. + \y{xintseries}{now issuing \string\input\space xintfrac.sty}% + \def\z{\endgroup\input xintfrac.sty\relax}% + \fi + \else + \def\empty {}% + \ifx\x\empty % LaTeX, first loading, + % variable is initialized, but \ProvidesPackage not yet seen + \ifx\w\relax % xintfrac.sty not yet loaded. + \y{xintseries}{now issuing \string\RequirePackage{xintfrac}}% + \def\z{\endgroup\RequirePackage{xintfrac}}% + \fi + \else + \y{xintseries}{I was already loaded, aborting input}% + \aftergroup\endinput + \fi + \fi + \fi +\z% +% \end{macrocode} +% \subsection{Confirmation of \xintfracnameimp loading} +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \ifdefined\PackageInfo + \def\y#1#2{\PackageInfo{#1}{#2}}% + \else + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \fi + \def\empty {}% + \expandafter\let\expandafter\w\csname ver@xintfrac.sty\endcsname + \ifx\w\relax % Plain TeX, user gave a file name at the prompt + \y{xintseries}{Loading of package xintfrac failed, aborting input}% + \aftergroup\endinput + \fi + \ifx\w\empty % LaTeX, user gave a file name at the prompt + \y{xintseries}{Loading of package xintfrac failed, aborting input}% + \aftergroup\endinput + \fi +\endgroup% +% \end{macrocode} +% \subsection{Catcodes} +% \begin{macrocode} +\XINTsetupcatcodes% +% \end{macrocode} +% \subsection{Package identification} +% \begin{macrocode} +\XINT_providespackage +\ProvidesPackage{xintseries}% + [2014/02/05 v1.09ka Expandable partial sums with xint package (jfB)]% +% \end{macrocode} +% \subsection{\csh{xintSeries}} +% \lverb|& +% Modified in 1.06 to give the indices first to a \numexpr rather than expanding +% twice. I just use \the\numexpr and maintain the previous code after that. +% 1.08a adds the forgotten optimization following that previous change.| +% \begin{macrocode} +\def\xintSeries {\romannumeral0\xintseries }% +\def\xintseries #1#2% +{% + \expandafter\XINT_series\expandafter + {\the\numexpr #1\expandafter}\expandafter{\the\numexpr #2}% +}% +\def\XINT_series #1#2#3% +{% + \ifnum #2<#1 + \xint_afterfi { 0/1[0]}% + \else + \xint_afterfi {\XINT_series_loop {#1}{0}{#2}{#3}}% + \fi +}% +\def\XINT_series_loop #1#2#3#4% +{% + \ifnum #3>#1 \else \XINT_series_exit \fi + \expandafter\XINT_series_loop\expandafter + {\the\numexpr #1+1\expandafter }\expandafter + {\romannumeral0\xintadd {#2}{#4{#1}}}% + {#3}{#4}% +}% +\def\XINT_series_exit \fi #1#2#3#4#5#6#7#8% +{% + \fi\xint_gobble_ii #6% +}% +% \end{macrocode} +% \subsection{\csh{xintiSeries}} +% \lverb|& +% Modified in 1.06 to give the indices first to a \numexpr rather than expanding +% twice. I just use \the\numexpr and maintain the previous code after that. +% 1.08a adds the forgotten optimization following that previous change.| +% \begin{macrocode} +\def\xintiSeries {\romannumeral0\xintiseries }% +\def\xintiseries #1#2% +{% + \expandafter\XINT_iseries\expandafter + {\the\numexpr #1\expandafter}\expandafter{\the\numexpr #2}% +}% +\def\XINT_iseries #1#2#3% +{% + \ifnum #2<#1 + \xint_afterfi { 0}% + \else + \xint_afterfi {\XINT_iseries_loop {#1}{0}{#2}{#3}}% + \fi +}% +\def\XINT_iseries_loop #1#2#3#4% +{% + \ifnum #3>#1 \else \XINT_iseries_exit \fi + \expandafter\XINT_iseries_loop\expandafter + {\the\numexpr #1+1\expandafter }\expandafter + {\romannumeral0\xintiiadd {#2}{#4{#1}}}% + {#3}{#4}% +}% +\def\XINT_iseries_exit \fi #1#2#3#4#5#6#7#8% +{% + \fi\xint_gobble_ii #6% +}% +% \end{macrocode} +% \subsection{\csh{xintPowerSeries}} +% \lverb|& +% The 1.03 version was very lame and created a build-up of denominators. +% The Horner scheme for polynomial evaluation is used in 1.04, this +% cures the denominator problem and drastically improves the efficiency +% of the macro. +% Modified in 1.06 to give the indices first to a \numexpr rather than expanding +% twice. I just use \the\numexpr and maintain the previous code after that. +% 1.08a adds the forgotten optimization following that previous change.| +% \begin{macrocode} +\def\xintPowerSeries {\romannumeral0\xintpowerseries }% +\def\xintpowerseries #1#2% +{% + \expandafter\XINT_powseries\expandafter + {\the\numexpr #1\expandafter}\expandafter{\the\numexpr #2}% +}% +\def\XINT_powseries #1#2#3#4% +{% + \ifnum #2<#1 + \xint_afterfi { 0/1[0]}% + \else + \xint_afterfi + {\XINT_powseries_loop_i {#3{#2}}{#1}{#2}{#3}{#4}}% + \fi +}% +\def\XINT_powseries_loop_i #1#2#3#4#5% +{% + \ifnum #3>#2 \else\XINT_powseries_exit_i\fi + \expandafter\XINT_powseries_loop_ii\expandafter + {\the\numexpr #3-1\expandafter}\expandafter + {\romannumeral0\xintmul {#1}{#5}}{#2}{#4}{#5}% +}% +\def\XINT_powseries_loop_ii #1#2#3#4% +{% + \expandafter\XINT_powseries_loop_i\expandafter + {\romannumeral0\xintadd {#4{#1}}{#2}}{#3}{#1}{#4}% +}% +\def\XINT_powseries_exit_i\fi #1#2#3#4#5#6#7#8#9% +{% + \fi \XINT_powseries_exit_ii #6{#7}% +}% +\def\XINT_powseries_exit_ii #1#2#3#4#5#6% +{% + \xintmul{\xintPow {#5}{#6}}{#4}% +}% +% \end{macrocode} +% \subsection{\csh{xintPowerSeriesX}} +% \lverb|& +% Same as \xintPowerSeries except for the initial expansion of the x parameter. +% Modified in 1.06 to give the indices first to a \numexpr rather than expanding +% twice. I just use \the\numexpr and maintain the previous code after that. +% 1.08a adds the forgotten optimization following that previous change.| +% \begin{macrocode} +\def\xintPowerSeriesX {\romannumeral0\xintpowerseriesx }% +\def\xintpowerseriesx #1#2% +{% + \expandafter\XINT_powseriesx\expandafter + {\the\numexpr #1\expandafter}\expandafter{\the\numexpr #2}% +}% +\def\XINT_powseriesx #1#2#3#4% +{% + \ifnum #2<#1 + \xint_afterfi { 0/1[0]}% + \else + \xint_afterfi + {\expandafter\XINT_powseriesx_pre\expandafter + {\romannumeral-`0#4}{#1}{#2}{#3}% + }% + \fi +}% +\def\XINT_powseriesx_pre #1#2#3#4% +{% + \XINT_powseries_loop_i {#4{#3}}{#2}{#3}{#4}{#1}% +}% +% \end{macrocode} +% \subsection{\csh{xintRationalSeries}} +% \lverb|& +% This computes F(a)+...+F(b) on the basis of the value of F(a) and the +% ratios F(n)/F(n-1). As in \xintPowerSeries we use an iterative scheme which +% has the great advantage to avoid denominator build-up. This makes exact +% computations possible with exponential type series, which would be completely +% inaccessible to \xintSeries. +% #1=a, #2=b, #3=F(a), #4=ratio function +% Modified in 1.06 to give the indices first to a \numexpr rather than expanding +% twice. I just use \the\numexpr and maintain the previous code after that. +% 1.08a adds the forgotten optimization following that previous change.| +% \begin{macrocode} +\def\xintRationalSeries {\romannumeral0\xintratseries }% +\def\xintratseries #1#2% +{% + \expandafter\XINT_ratseries\expandafter + {\the\numexpr #1\expandafter}\expandafter{\the\numexpr #2}% +}% +\def\XINT_ratseries #1#2#3#4% +{% + \ifnum #2<#1 + \xint_afterfi { 0/1[0]}% + \else + \xint_afterfi + {\XINT_ratseries_loop {#2}{1}{#1}{#4}{#3}}% + \fi +}% +\def\XINT_ratseries_loop #1#2#3#4% +{% + \ifnum #1>#3 \else\XINT_ratseries_exit_i\fi + \expandafter\XINT_ratseries_loop\expandafter + {\the\numexpr #1-1\expandafter}\expandafter + {\romannumeral0\xintadd {1}{\xintMul {#2}{#4{#1}}}}{#3}{#4}% +}% +\def\XINT_ratseries_exit_i\fi #1#2#3#4#5#6#7#8% +{% + \fi \XINT_ratseries_exit_ii #6% +}% +\def\XINT_ratseries_exit_ii #1#2#3#4#5% +{% + \XINT_ratseries_exit_iii #5% +}% +\def\XINT_ratseries_exit_iii #1#2#3#4% +{% + \xintmul{#2}{#4}% +}% +% \end{macrocode} +% \subsection{\csh{xintRationalSeriesX}} +% \lverb|& +% a,b,initial,ratiofunction,x$\ +% This computes F(a,x)+...+F(b,x) on the basis of the value of F(a,x) and the +% ratios F(n,x)/F(n-1,x). The argument x is first expanded and it is the value +% resulting from this which is used then throughout. The initial term F(a,x) +% must be defined as one-parameter macro which will be given x. +% Modified in 1.06 to give the indices first to a \numexpr rather than expanding +% twice. I just use \the\numexpr and maintain the previous code after that. +% 1.08a adds the forgotten optimization following that previous change.| +% \begin{macrocode} +\def\xintRationalSeriesX {\romannumeral0\xintratseriesx }% +\def\xintratseriesx #1#2% +{% + \expandafter\XINT_ratseriesx\expandafter + {\the\numexpr #1\expandafter}\expandafter{\the\numexpr #2}% +}% +\def\XINT_ratseriesx #1#2#3#4#5% +{% + \ifnum #2<#1 + \xint_afterfi { 0/1[0]}% + \else + \xint_afterfi + {\expandafter\XINT_ratseriesx_pre\expandafter + {\romannumeral-`0#5}{#2}{#1}{#4}{#3}% + }% + \fi +}% +\def\XINT_ratseriesx_pre #1#2#3#4#5% +{% + \XINT_ratseries_loop {#2}{1}{#3}{#4{#1}}{#5{#1}}% +}% +% \end{macrocode} +% \subsection{\csh{xintFxPtPowerSeries}} +% \lverb|& +% I am not two happy with this piece of code. Will make it more economical +% another day. +% Modified in 1.06 to give the indices first to a \numexpr rather than expanding +% twice. I just use \the\numexpr and maintain the previous code after that. +% 1.08a: forgot last time some optimization from the change to \numexpr.| +% \begin{macrocode} +\def\xintFxPtPowerSeries {\romannumeral0\xintfxptpowerseries }% +\def\xintfxptpowerseries #1#2% +{% + \expandafter\XINT_fppowseries\expandafter + {\the\numexpr #1\expandafter}\expandafter{\the\numexpr #2}% +}% +\def\XINT_fppowseries #1#2#3#4#5% +{% + \ifnum #2<#1 + \xint_afterfi { 0}% + \else + \xint_afterfi + {\expandafter\XINT_fppowseries_loop_pre\expandafter + {\romannumeral0\xinttrunc {#5}{\xintPow {#4}{#1}}}% + {#1}{#4}{#2}{#3}{#5}% + }% + \fi +}% +\def\XINT_fppowseries_loop_pre #1#2#3#4#5#6% +{% + \ifnum #4>#2 \else\XINT_fppowseries_dont_i \fi + \expandafter\XINT_fppowseries_loop_i\expandafter + {\the\numexpr #2+\xint_c_i\expandafter}\expandafter + {\romannumeral0\xintitrunc {#6}{\xintMul {#5{#2}}{#1}}}% + {#1}{#3}{#4}{#5}{#6}% +}% +\def\XINT_fppowseries_dont_i \fi\expandafter\XINT_fppowseries_loop_i + {\fi \expandafter\XINT_fppowseries_dont_ii }% +\def\XINT_fppowseries_dont_ii #1#2#3#4#5#6#7{\xinttrunc {#7}{#2[-#7]}}% +\def\XINT_fppowseries_loop_i #1#2#3#4#5#6#7% +{% + \ifnum #5>#1 \else \XINT_fppowseries_exit_i \fi + \expandafter\XINT_fppowseries_loop_ii\expandafter + {\romannumeral0\xinttrunc {#7}{\xintMul {#3}{#4}}}% + {#1}{#4}{#2}{#5}{#6}{#7}% +}% +\def\XINT_fppowseries_loop_ii #1#2#3#4#5#6#7% +{% + \expandafter\XINT_fppowseries_loop_i\expandafter + {\the\numexpr #2+\xint_c_i\expandafter}\expandafter + {\romannumeral0\xintiiadd {#4}{\xintiTrunc {#7}{\xintMul {#6{#2}}{#1}}}}% + {#1}{#3}{#5}{#6}{#7}% +}% +\def\XINT_fppowseries_exit_i\fi\expandafter\XINT_fppowseries_loop_ii + {\fi \expandafter\XINT_fppowseries_exit_ii }% +\def\XINT_fppowseries_exit_ii #1#2#3#4#5#6#7% +{% + \xinttrunc {#7} + {\xintiiadd {#4}{\xintiTrunc {#7}{\xintMul {#6{#2}}{#1}}}[-#7]}% +}% +% \end{macrocode} +% \subsection{\csh{xintFxPtPowerSeriesX}} +% \lverb|& +% a,b,coeff,x,D$\ +% Modified in 1.06 to give the indices first to a \numexpr rather than expanding +% twice. I just use \the\numexpr and maintain the previous code after that. +% 1.08a adds the forgotten optimization following that previous change.| +% \begin{macrocode} +\def\xintFxPtPowerSeriesX {\romannumeral0\xintfxptpowerseriesx }% +\def\xintfxptpowerseriesx #1#2% +{% + \expandafter\XINT_fppowseriesx\expandafter + {\the\numexpr #1\expandafter}\expandafter{\the\numexpr #2}% +}% +\def\XINT_fppowseriesx #1#2#3#4#5% +{% + \ifnum #2<#1 + \xint_afterfi { 0}% + \else + \xint_afterfi + {\expandafter \XINT_fppowseriesx_pre \expandafter + {\romannumeral-`0#4}{#1}{#2}{#3}{#5}% + }% + \fi +}% +\def\XINT_fppowseriesx_pre #1#2#3#4#5% +{% + \expandafter\XINT_fppowseries_loop_pre\expandafter + {\romannumeral0\xinttrunc {#5}{\xintPow {#1}{#2}}}% + {#2}{#1}{#3}{#4}{#5}% +}% +% \end{macrocode} +% \subsection{\csh{xintFloatPowerSeries}} +% \lverb|1.08a. I still have to re-visit \xintFxPtPowerSeries; temporarily I +% just adapted the code to the case of floats.| +% \begin{macrocode} +\def\xintFloatPowerSeries {\romannumeral0\xintfloatpowerseries }% +\def\xintfloatpowerseries #1{\XINT_flpowseries_chkopt #1\Z }% +\def\XINT_flpowseries_chkopt #1% +{% + \ifx [#1\expandafter\XINT_flpowseries_opt + \else\expandafter\XINT_flpowseries_noopt + \fi + #1% +}% +\def\XINT_flpowseries_noopt #1\Z #2% +{% + \expandafter\XINT_flpowseries\expandafter + {\the\numexpr #1\expandafter}\expandafter + {\the\numexpr #2}\XINTdigits +}% +\def\XINT_flpowseries_opt [\Z #1]#2#3% +{% + \expandafter\XINT_flpowseries\expandafter + {\the\numexpr #2\expandafter}\expandafter + {\the\numexpr #3\expandafter}{\the\numexpr #1}% +}% +\def\XINT_flpowseries #1#2#3#4#5% +{% + \ifnum #2<#1 + \xint_afterfi { 0.e0}% + \else + \xint_afterfi + {\expandafter\XINT_flpowseries_loop_pre\expandafter + {\romannumeral0\XINTinfloatpow [#3]{#5}{#1}}% + {#1}{#5}{#2}{#4}{#3}% + }% + \fi +}% +\def\XINT_flpowseries_loop_pre #1#2#3#4#5#6% +{% + \ifnum #4>#2 \else\XINT_flpowseries_dont_i \fi + \expandafter\XINT_flpowseries_loop_i\expandafter + {\the\numexpr #2+\xint_c_i\expandafter}\expandafter + {\romannumeral0\XINTinfloatmul [#6]{#5{#2}}{#1}}% + {#1}{#3}{#4}{#5}{#6}% +}% +\def\XINT_flpowseries_dont_i \fi\expandafter\XINT_flpowseries_loop_i + {\fi \expandafter\XINT_flpowseries_dont_ii }% +\def\XINT_flpowseries_dont_ii #1#2#3#4#5#6#7{\xintfloat [#7]{#2}}% +\def\XINT_flpowseries_loop_i #1#2#3#4#5#6#7% +{% + \ifnum #5>#1 \else \XINT_flpowseries_exit_i \fi + \expandafter\XINT_flpowseries_loop_ii\expandafter + {\romannumeral0\XINTinfloatmul [#7]{#3}{#4}}% + {#1}{#4}{#2}{#5}{#6}{#7}% +}% +\def\XINT_flpowseries_loop_ii #1#2#3#4#5#6#7% +{% + \expandafter\XINT_flpowseries_loop_i\expandafter + {\the\numexpr #2+\xint_c_i\expandafter}\expandafter + {\romannumeral0\XINTinfloatadd [#7]{#4}% + {\XINTinfloatmul [#7]{#6{#2}}{#1}}}% + {#1}{#3}{#5}{#6}{#7}% +}% +\def\XINT_flpowseries_exit_i\fi\expandafter\XINT_flpowseries_loop_ii + {\fi \expandafter\XINT_flpowseries_exit_ii }% +\def\XINT_flpowseries_exit_ii #1#2#3#4#5#6#7% +{% + \xintfloatadd [#7]{#4}{\XINTinfloatmul [#7]{#6{#2}}{#1}}% +}% +% \end{macrocode} +% \subsection{\csh{xintFloatPowerSeriesX}} +% \lverb|1.08a| +% \begin{macrocode} +\def\xintFloatPowerSeriesX {\romannumeral0\xintfloatpowerseriesx }% +\def\xintfloatpowerseriesx #1{\XINT_flpowseriesx_chkopt #1\Z }% +\def\XINT_flpowseriesx_chkopt #1% +{% + \ifx [#1\expandafter\XINT_flpowseriesx_opt + \else\expandafter\XINT_flpowseriesx_noopt + \fi + #1% +}% +\def\XINT_flpowseriesx_noopt #1\Z #2% +{% + \expandafter\XINT_flpowseriesx\expandafter + {\the\numexpr #1\expandafter}\expandafter + {\the\numexpr #2}\XINTdigits +}% +\def\XINT_flpowseriesx_opt [\Z #1]#2#3% +{% + \expandafter\XINT_flpowseriesx\expandafter + {\the\numexpr #2\expandafter}\expandafter + {\the\numexpr #3\expandafter}{\the\numexpr #1}% +}% +\def\XINT_flpowseriesx #1#2#3#4#5% +{% + \ifnum #2<#1 + \xint_afterfi { 0.e0}% + \else + \xint_afterfi + {\expandafter \XINT_flpowseriesx_pre \expandafter + {\romannumeral-`0#5}{#1}{#2}{#4}{#3}% + }% + \fi +}% +\def\XINT_flpowseriesx_pre #1#2#3#4#5% +{% + \expandafter\XINT_flpowseries_loop_pre\expandafter + {\romannumeral0\XINTinfloatpow [#5]{#1}{#2}}% + {#2}{#1}{#3}{#4}{#5}% +}% +\XINT_restorecatcodes_endinput% +% \end{macrocode} +%\catcode`\<=0 \catcode`\>=11 \catcode`\*=11 \catcode`\/=11 +%\let</xintseries>\relax +%\def<*xintcfrac>{\catcode`\<=12 \catcode`\>=12 \catcode`\*=12 \catcode`\/=12 } +%</xintseries> +%<*xintcfrac> +% +% \StoreCodelineNo {xintseries} +% +% \section{Package \xintcfracnameimp implementation} +% \label{sec:cfracimp} +% +% The commenting is currently (\docdate) very sparse. +% +% \localtableofcontents +% \subsection{Catcodes, \protect\eTeX{} and reload detection} +% +% The code for reload detection is copied from \textsc{Heiko +% Oberdiek}'s packages, and adapted here to check for previous +% loading of the \xintfracname package. +% +% The method for catcodes is slightly different, but still +% directly inspired by these packages. +% +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \def\space { }% + \let\z\endgroup + \expandafter\let\expandafter\x\csname ver@xintcfrac.sty\endcsname + \expandafter\let\expandafter\w\csname ver@xintfrac.sty\endcsname + \expandafter + \ifx\csname PackageInfo\endcsname\relax + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \else + \def\y#1#2{\PackageInfo{#1}{#2}}% + \fi + \expandafter + \ifx\csname numexpr\endcsname\relax + \y{xintcfrac}{\numexpr not available, aborting input}% + \aftergroup\endinput + \else + \ifx\x\relax % plain-TeX, first loading of xintcfrac.sty + \ifx\w\relax % but xintfrac.sty not yet loaded. + \y{xintcfrac}{now issuing \string\input\space xintfrac.sty}% + \def\z{\endgroup\input xintfrac.sty\relax}% + \fi + \else + \def\empty {}% + \ifx\x\empty % LaTeX, first loading, + % variable is initialized, but \ProvidesPackage not yet seen + \ifx\w\relax % xintfrac.sty not yet loaded. + \y{xintcfrac}{now issuing \string\RequirePackage{xintfrac}}% + \def\z{\endgroup\RequirePackage{xintfrac}}% + \fi + \else + \y{xintcfrac}{I was already loaded, aborting input}% + \aftergroup\endinput + \fi + \fi + \fi +\z% +% \end{macrocode} +% \subsection{Confirmation of \xintfracnameimp loading} +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \ifdefined\PackageInfo + \def\y#1#2{\PackageInfo{#1}{#2}}% + \else + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \fi + \def\empty {}% + \expandafter\let\expandafter\w\csname ver@xintfrac.sty\endcsname + \ifx\w\relax % Plain TeX, user gave a file name at the prompt + \y{xintcfrac}{Loading of package xintfrac failed, aborting input}% + \aftergroup\endinput + \fi + \ifx\w\empty % LaTeX, user gave a file name at the prompt + \y{xintcfrac}{Loading of package xintfrac failed, aborting input}% + \aftergroup\endinput + \fi +\endgroup% +% \end{macrocode} +% \subsection{Catcodes} +% \begin{macrocode} +\XINTsetupcatcodes% +% \end{macrocode} +% \subsection{Package identification} +% \begin{macrocode} +\XINT_providespackage +\ProvidesPackage{xintcfrac}% + [2014/02/05 v1.09ka Expandable continued fractions with xint package (jfB)]% +% \end{macrocode} +% \subsection{\csh{xintCFrac}} +% \begin{macrocode} +\def\xintCFrac {\romannumeral0\xintcfrac }% +\def\xintcfrac #1% +{% + \XINT_cfrac_opt_a #1\Z +}% +\def\XINT_cfrac_opt_a #1% +{% + \ifx[#1\XINT_cfrac_opt_b\fi \XINT_cfrac_noopt #1% +}% +\def\XINT_cfrac_noopt #1\Z +{% + \expandafter\XINT_cfrac_A\romannumeral0\xintrawwithzeros {#1}\Z + \relax\relax +}% +\def\XINT_cfrac_opt_b\fi\XINT_cfrac_noopt [\Z #1]% +{% + \fi\csname XINT_cfrac_opt#1\endcsname +}% +\def\XINT_cfrac_optl #1% +{% + \expandafter\XINT_cfrac_A\romannumeral0\xintrawwithzeros {#1}\Z + \relax\hfill +}% +\def\XINT_cfrac_optc #1% +{% + \expandafter\XINT_cfrac_A\romannumeral0\xintrawwithzeros {#1}\Z + \relax\relax +}% +\def\XINT_cfrac_optr #1% +{% + \expandafter\XINT_cfrac_A\romannumeral0\xintrawwithzeros {#1}\Z + \hfill\relax +}% +\def\XINT_cfrac_A #1/#2\Z +{% + \expandafter\XINT_cfrac_B\romannumeral0\xintiidivision {#1}{#2}{#2}% +}% +\def\XINT_cfrac_B #1#2% +{% + \XINT_cfrac_C #2\Z {#1}% +}% +\def\XINT_cfrac_C #1% +{% + \xint_gob_til_zero #1\XINT_cfrac_integer 0\XINT_cfrac_D #1% +}% +\def\XINT_cfrac_integer 0\XINT_cfrac_D 0#1\Z #2#3#4#5{ #2}% +\def\XINT_cfrac_D #1\Z #2#3{\XINT_cfrac_loop_a {#1}{#3}{#1}{{#2}}}% +\def\XINT_cfrac_loop_a +{% + \expandafter\XINT_cfrac_loop_d\romannumeral0\XINT_div_prepare +}% +\def\XINT_cfrac_loop_d #1#2% +{% + \XINT_cfrac_loop_e #2.{#1}% +}% +\def\XINT_cfrac_loop_e #1% +{% + \xint_gob_til_zero #1\xint_cfrac_loop_exit0\XINT_cfrac_loop_f #1% +}% +\def\XINT_cfrac_loop_f #1.#2#3#4% +{% + \XINT_cfrac_loop_a {#1}{#3}{#1}{{#2}#4}% +}% +\def\xint_cfrac_loop_exit0\XINT_cfrac_loop_f #1.#2#3#4#5#6% + {\XINT_cfrac_T #5#6{#2}#4\Z }% +\def\XINT_cfrac_T #1#2#3#4% +{% + \xint_gob_til_Z #4\XINT_cfrac_end\Z\XINT_cfrac_T #1#2{#4+\cfrac{#11#2}{#3}}% +}% +\def\XINT_cfrac_end\Z\XINT_cfrac_T #1#2#3% +{% + \XINT_cfrac_end_b #3% +}% +\def\XINT_cfrac_end_b \Z+\cfrac#1#2{ #2}% +% \end{macrocode} +% \subsection{\csh{xintGCFrac}} +% \begin{macrocode} +\def\xintGCFrac {\romannumeral0\xintgcfrac }% +\def\xintgcfrac #1{\XINT_gcfrac_opt_a #1\Z }% +\def\XINT_gcfrac_opt_a #1% +{% + \ifx[#1\XINT_gcfrac_opt_b\fi \XINT_gcfrac_noopt #1% +}% +\def\XINT_gcfrac_noopt #1\Z +{% + \XINT_gcfrac #1+\W/\relax\relax +}% +\def\XINT_gcfrac_opt_b\fi\XINT_gcfrac_noopt [\Z #1]% +{% + \fi\csname XINT_gcfrac_opt#1\endcsname +}% +\def\XINT_gcfrac_optl #1% +{% + \XINT_gcfrac #1+\W/\relax\hfill +}% +\def\XINT_gcfrac_optc #1% +{% + \XINT_gcfrac #1+\W/\relax\relax +}% +\def\XINT_gcfrac_optr #1% +{% + \XINT_gcfrac #1+\W/\hfill\relax +}% +\def\XINT_gcfrac +{% + \expandafter\XINT_gcfrac_enter\romannumeral-`0% +}% +\def\XINT_gcfrac_enter {\XINT_gcfrac_loop {}}% +\def\XINT_gcfrac_loop #1#2+#3/% +{% + \xint_gob_til_W #3\XINT_gcfrac_endloop\W + \XINT_gcfrac_loop {{#3}{#2}#1}% +}% +\def\XINT_gcfrac_endloop\W\XINT_gcfrac_loop #1#2#3% +{% + \XINT_gcfrac_T #2#3#1\Z\Z +}% +\def\XINT_gcfrac_T #1#2#3#4{\XINT_gcfrac_U #1#2{\xintFrac{#4}}}% +\def\XINT_gcfrac_U #1#2#3#4#5% +{% + \xint_gob_til_Z #5\XINT_gcfrac_end\Z\XINT_gcfrac_U + #1#2{\xintFrac{#5}% + \ifcase\xintSgn{#4} + +\or+\else-\fi + \cfrac{#1\xintFrac{\xintAbs{#4}}#2}{#3}}% +}% +\def\XINT_gcfrac_end\Z\XINT_gcfrac_U #1#2#3% +{% + \XINT_gcfrac_end_b #3% +}% +\def\XINT_gcfrac_end_b #1\cfrac#2#3{ #3}% +% \end{macrocode} +% \subsection{\csh{xintGCtoGCx}} +% \begin{macrocode} +\def\xintGCtoGCx {\romannumeral0\xintgctogcx }% +\def\xintgctogcx #1#2#3% +{% + \expandafter\XINT_gctgcx_start\expandafter {\romannumeral-`0#3}{#1}{#2}% +}% +\def\XINT_gctgcx_start #1#2#3{\XINT_gctgcx_loop_a {}{#2}{#3}#1+\W/}% +\def\XINT_gctgcx_loop_a #1#2#3#4+#5/% +{% + \xint_gob_til_W #5\XINT_gctgcx_end\W + \XINT_gctgcx_loop_b {#1{#4}}{#2{#5}#3}{#2}{#3}% +}% +\def\XINT_gctgcx_loop_b #1#2% +{% + \XINT_gctgcx_loop_a {#1#2}% +}% +\def\XINT_gctgcx_end\W\XINT_gctgcx_loop_b #1#2#3#4{ #1}% +% \end{macrocode} +% \subsection{\csh{xintFtoCs}} +% \begin{macrocode} +\def\xintFtoCs {\romannumeral0\xintftocs }% +\def\xintftocs #1% +{% + \expandafter\XINT_ftc_A\romannumeral0\xintrawwithzeros {#1}\Z +}% +\def\XINT_ftc_A #1/#2\Z +{% + \expandafter\XINT_ftc_B\romannumeral0\xintiidivision {#1}{#2}{#2}% +}% +\def\XINT_ftc_B #1#2% +{% + \XINT_ftc_C #2.{#1}% +}% +\def\XINT_ftc_C #1% +{% + \xint_gob_til_zero #1\XINT_ftc_integer 0\XINT_ftc_D #1% +}% +\def\XINT_ftc_integer 0\XINT_ftc_D 0#1.#2#3{ #2}% +\def\XINT_ftc_D #1.#2#3{\XINT_ftc_loop_a {#1}{#3}{#1}{#2,}}% +\def\XINT_ftc_loop_a +{% + \expandafter\XINT_ftc_loop_d\romannumeral0\XINT_div_prepare +}% +\def\XINT_ftc_loop_d #1#2% +{% + \XINT_ftc_loop_e #2.{#1}% +}% +\def\XINT_ftc_loop_e #1% +{% + \xint_gob_til_zero #1\xint_ftc_loop_exit0\XINT_ftc_loop_f #1% +}% +\def\XINT_ftc_loop_f #1.#2#3#4% +{% + \XINT_ftc_loop_a {#1}{#3}{#1}{#4#2,}% +}% +\def\xint_ftc_loop_exit0\XINT_ftc_loop_f #1.#2#3#4{ #4#2}% +% \end{macrocode} +% \subsection{\csh{xintFtoCx}} +% \begin{macrocode} +\def\xintFtoCx {\romannumeral0\xintftocx }% +\def\xintftocx #1#2% +{% + \expandafter\XINT_ftcx_A\romannumeral0\xintrawwithzeros {#2}\Z {#1}% +}% +\def\XINT_ftcx_A #1/#2\Z +{% + \expandafter\XINT_ftcx_B\romannumeral0\xintiidivision {#1}{#2}{#2}% +}% +\def\XINT_ftcx_B #1#2% +{% + \XINT_ftcx_C #2.{#1}% +}% +\def\XINT_ftcx_C #1% +{% + \xint_gob_til_zero #1\XINT_ftcx_integer 0\XINT_ftcx_D #1% +}% +\def\XINT_ftcx_integer 0\XINT_ftcx_D 0#1.#2#3#4{ #2}% +\def\XINT_ftcx_D #1.#2#3#4{\XINT_ftcx_loop_a {#1}{#3}{#1}{#2#4}{#4}}% +\def\XINT_ftcx_loop_a +{% + \expandafter\XINT_ftcx_loop_d\romannumeral0\XINT_div_prepare +}% +\def\XINT_ftcx_loop_d #1#2% +{% + \XINT_ftcx_loop_e #2.{#1}% +}% +\def\XINT_ftcx_loop_e #1% +{% + \xint_gob_til_zero #1\xint_ftcx_loop_exit0\XINT_ftcx_loop_f #1% +}% +\def\XINT_ftcx_loop_f #1.#2#3#4#5% +{% + \XINT_ftcx_loop_a {#1}{#3}{#1}{#4{#2}#5}{#5}% +}% +\def\xint_ftcx_loop_exit0\XINT_ftcx_loop_f #1.#2#3#4#5{ #4{#2}}% +% \end{macrocode} +% \subsection{\csh{xintFtoGC}} +% \begin{macrocode} +\def\xintFtoGC {\romannumeral0\xintftogc }% +\def\xintftogc {\xintftocx {+1/}}% +% \end{macrocode} +% \subsection{\csh{xintFtoCC}} +% \begin{macrocode} +\def\xintFtoCC {\romannumeral0\xintftocc }% +\def\xintftocc #1% +{% + \expandafter\XINT_ftcc_A\expandafter {\romannumeral0\xintrawwithzeros {#1}}% +}% +\def\XINT_ftcc_A #1% +{% + \expandafter\XINT_ftcc_B + \romannumeral0\xintrawwithzeros {\xintAdd {1/2[0]}{#1[0]}}\Z {#1[0]}% +}% +\def\XINT_ftcc_B #1/#2\Z +{% + \expandafter\XINT_ftcc_C\expandafter {\romannumeral0\xintiiquo {#1}{#2}}% +}% +\def\XINT_ftcc_C #1#2% +{% + \expandafter\XINT_ftcc_D\romannumeral0\xintsub {#2}{#1}\Z {#1}% +}% +\def\XINT_ftcc_D #1% +{% + \xint_UDzerominusfork + #1-\XINT_ftcc_integer + 0#1\XINT_ftcc_En + 0-{\XINT_ftcc_Ep #1}% + \krof +}% +\def\XINT_ftcc_Ep #1\Z #2% +{% + \expandafter\XINT_ftcc_loop_a\expandafter + {\romannumeral0\xintdiv {1[0]}{#1}}{#2+1/}% +}% +\def\XINT_ftcc_En #1\Z #2% +{% + \expandafter\XINT_ftcc_loop_a\expandafter + {\romannumeral0\xintdiv {1[0]}{#1}}{#2+-1/}% +}% +\def\XINT_ftcc_integer #1\Z #2{ #2}% +\def\XINT_ftcc_loop_a #1% +{% + \expandafter\XINT_ftcc_loop_b + \romannumeral0\xintrawwithzeros {\xintAdd {1/2[0]}{#1}}\Z {#1}% +}% +\def\XINT_ftcc_loop_b #1/#2\Z +{% + \expandafter\XINT_ftcc_loop_c\expandafter + {\romannumeral0\xintiiquo {#1}{#2}}% +}% +\def\XINT_ftcc_loop_c #1#2% +{% + \expandafter\XINT_ftcc_loop_d + \romannumeral0\xintsub {#2}{#1[0]}\Z {#1}% +}% +\def\XINT_ftcc_loop_d #1% +{% + \xint_UDzerominusfork + #1-\XINT_ftcc_end + 0#1\XINT_ftcc_loop_N + 0-{\XINT_ftcc_loop_P #1}% + \krof +}% +\def\XINT_ftcc_end #1\Z #2#3{ #3#2}% +\def\XINT_ftcc_loop_P #1\Z #2#3% +{% + \expandafter\XINT_ftcc_loop_a\expandafter + {\romannumeral0\xintdiv {1[0]}{#1}}{#3#2+1/}% +}% +\def\XINT_ftcc_loop_N #1\Z #2#3% +{% + \expandafter\XINT_ftcc_loop_a\expandafter + {\romannumeral0\xintdiv {1[0]}{#1}}{#3#2+-1/}% +}% +% \end{macrocode} +% \subsection{\csh{xintFtoCv}} +% \begin{macrocode} +\def\xintFtoCv {\romannumeral0\xintftocv }% +\def\xintftocv #1% +{% + \xinticstocv {\xintFtoCs {#1}}% +}% +% \end{macrocode} +% \subsection{\csh{xintFtoCCv}} +% \begin{macrocode} +\def\xintFtoCCv {\romannumeral0\xintftoccv }% +\def\xintftoccv #1% +{% + \xintigctocv {\xintFtoCC {#1}}% +}% +% \end{macrocode} +% \subsection{\csh{xintCstoF}} +% \begin{macrocode} +\def\xintCstoF {\romannumeral0\xintcstof }% +\def\xintcstof #1% +{% + \expandafter\XINT_cstf_prep \romannumeral-`0#1,\W,% +}% +\def\XINT_cstf_prep +{% + \XINT_cstf_loop_a 1001% +}% +\def\XINT_cstf_loop_a #1#2#3#4#5,% +{% + \xint_gob_til_W #5\XINT_cstf_end\W + \expandafter\XINT_cstf_loop_b + \romannumeral0\xintrawwithzeros {#5}.{#1}{#2}{#3}{#4}% +}% +\def\XINT_cstf_loop_b #1/#2.#3#4#5#6% +{% + \expandafter\XINT_cstf_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}}}% +}% +\def\XINT_cstf_loop_c #1#2% +{% + \expandafter\XINT_cstf_loop_d\expandafter {\expandafter{#2}{#1}}% +}% +\def\XINT_cstf_loop_d #1#2% +{% + \expandafter\XINT_cstf_loop_e\expandafter {\expandafter{#2}#1}% +}% +\def\XINT_cstf_loop_e #1#2% +{% + \expandafter\XINT_cstf_loop_a\expandafter{#2}#1% +}% +\def\XINT_cstf_end #1.#2#3#4#5{\xintrawwithzeros {#2/#3}}% 1.09b removes [0] +% \end{macrocode} +% \subsection{\csh{xintiCstoF}} +% \begin{macrocode} +\def\xintiCstoF {\romannumeral0\xinticstof }% +\def\xinticstof #1% +{% + \expandafter\XINT_icstf_prep \romannumeral-`0#1,\W,% +}% +\def\XINT_icstf_prep +{% + \XINT_icstf_loop_a 1001% +}% +\def\XINT_icstf_loop_a #1#2#3#4#5,% +{% + \xint_gob_til_W #5\XINT_icstf_end\W + \expandafter + \XINT_icstf_loop_b \romannumeral-`0#5.{#1}{#2}{#3}{#4}% +}% +\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}}}% + {#2}{#3}% +}% +\def\XINT_icstf_loop_c #1#2% +{% + \expandafter\XINT_icstf_loop_a\expandafter {#2}{#1}% +}% +\def\XINT_icstf_end#1.#2#3#4#5{\xintrawwithzeros {#2/#3}}% 1.09b removes [0] +% \end{macrocode} +% \subsection{\csh{xintGCtoF}} +% \begin{macrocode} +\def\xintGCtoF {\romannumeral0\xintgctof }% +\def\xintgctof #1% +{% + \expandafter\XINT_gctf_prep \romannumeral-`0#1+\W/% +}% +\def\XINT_gctf_prep +{% + \XINT_gctf_loop_a 1001% +}% +\def\XINT_gctf_loop_a #1#2#3#4#5+% +{% + \expandafter\XINT_gctf_loop_b + \romannumeral0\xintrawwithzeros {#5}.{#1}{#2}{#3}{#4}% +}% +\def\XINT_gctf_loop_b #1/#2.#3#4#5#6% +{% + \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}}}% +}% +\def\XINT_gctf_loop_c #1#2% +{% + \expandafter\XINT_gctf_loop_d\expandafter {\expandafter{#2}{#1}}% +}% +\def\XINT_gctf_loop_d #1#2% +{% + \expandafter\XINT_gctf_loop_e\expandafter {\expandafter{#2}#1}% +}% +\def\XINT_gctf_loop_e #1#2% +{% + \expandafter\XINT_gctf_loop_f\expandafter {\expandafter{#2}#1}% +}% +\def\XINT_gctf_loop_f #1#2/% +{% + \xint_gob_til_W #2\XINT_gctf_end\W + \expandafter\XINT_gctf_loop_g + \romannumeral0\xintrawwithzeros {#2}.#1% +}% +\def\XINT_gctf_loop_g #1/#2.#3#4#5#6% +{% + \expandafter\XINT_gctf_loop_h\expandafter + {\romannumeral0\XINT_mul_fork #1\Z #6\Z }% + {\romannumeral0\XINT_mul_fork #1\Z #5\Z }% + {\romannumeral0\XINT_mul_fork #2\Z #4\Z }% + {\romannumeral0\XINT_mul_fork #2\Z #3\Z }% +}% +\def\XINT_gctf_loop_h #1#2% +{% + \expandafter\XINT_gctf_loop_i\expandafter {\expandafter{#2}{#1}}% +}% +\def\XINT_gctf_loop_i #1#2% +{% + \expandafter\XINT_gctf_loop_j\expandafter {\expandafter{#2}#1}% +}% +\def\XINT_gctf_loop_j #1#2% +{% + \expandafter\XINT_gctf_loop_a\expandafter {#2}#1% +}% +\def\XINT_gctf_end #1.#2#3#4#5{\xintrawwithzeros {#2/#3}}% 1.09b removes [0] +% \end{macrocode} +% \subsection{\csh{xintiGCtoF}} +% \begin{macrocode} +\def\xintiGCtoF {\romannumeral0\xintigctof }% +\def\xintigctof #1% +{% + \expandafter\XINT_igctf_prep \romannumeral-`0#1+\W/% +}% +\def\XINT_igctf_prep +{% + \XINT_igctf_loop_a 1001% +}% +\def\XINT_igctf_loop_a #1#2#3#4#5+% +{% + \expandafter\XINT_igctf_loop_b + \romannumeral-`0#5.{#1}{#2}{#3}{#4}% +}% +\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}}}% + {#2}{#3}% +}% +\def\XINT_igctf_loop_c #1#2% +{% + \expandafter\XINT_igctf_loop_f\expandafter {\expandafter{#2}{#1}}% +}% +\def\XINT_igctf_loop_f #1#2#3#4/% +{% + \xint_gob_til_W #4\XINT_igctf_end\W + \expandafter\XINT_igctf_loop_g + \romannumeral-`0#4.{#2}{#3}#1% +}% +\def\XINT_igctf_loop_g #1.#2#3% +{% + \expandafter\XINT_igctf_loop_h\expandafter + {\romannumeral0\XINT_mul_fork #1\Z #3\Z }% + {\romannumeral0\XINT_mul_fork #1\Z #2\Z }% +}% +\def\XINT_igctf_loop_h #1#2% +{% + \expandafter\XINT_igctf_loop_i\expandafter {#2}{#1}% +}% +\def\XINT_igctf_loop_i #1#2#3#4% +{% + \XINT_igctf_loop_a {#3}{#4}{#1}{#2}% +}% +\def\XINT_igctf_end #1.#2#3#4#5{\xintrawwithzeros {#4/#5}}% 1.09b removes [0] +% \end{macrocode} +% \subsection{\csh{xintCstoCv}} +% \begin{macrocode} +\def\xintCstoCv {\romannumeral0\xintcstocv }% +\def\xintcstocv #1% +{% + \expandafter\XINT_cstcv_prep \romannumeral-`0#1,\W,% +}% +\def\XINT_cstcv_prep +{% + \XINT_cstcv_loop_a {}1001% +}% +\def\XINT_cstcv_loop_a #1#2#3#4#5#6,% +{% + \xint_gob_til_W #6\XINT_cstcv_end\W + \expandafter\XINT_cstcv_loop_b + \romannumeral0\xintrawwithzeros {#6}.{#2}{#3}{#4}{#5}{#1}% +}% +\def\XINT_cstcv_loop_b #1/#2.#3#4#5#6% +{% + \expandafter\XINT_cstcv_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}}}% +}% +\def\XINT_cstcv_loop_c #1#2% +{% + \expandafter\XINT_cstcv_loop_d\expandafter {\expandafter{#2}{#1}}% +}% +\def\XINT_cstcv_loop_d #1#2% +{% + \expandafter\XINT_cstcv_loop_e\expandafter {\expandafter{#2}#1}% +}% +\def\XINT_cstcv_loop_e #1#2% +{% + \expandafter\XINT_cstcv_loop_f\expandafter{#2}#1% +}% +\def\XINT_cstcv_loop_f #1#2#3#4#5% +{% + \expandafter\XINT_cstcv_loop_g\expandafter + {\romannumeral0\xintrawwithzeros {#1/#2}}{#5}{#1}{#2}{#3}{#4}% +}% +\def\XINT_cstcv_loop_g #1#2{\XINT_cstcv_loop_a {#2{#1}}}% 1.09b removes [0] +\def\XINT_cstcv_end #1.#2#3#4#5#6{ #6}% +% \end{macrocode} +% \subsection{\csh{xintiCstoCv}} +% \begin{macrocode} +\def\xintiCstoCv {\romannumeral0\xinticstocv }% +\def\xinticstocv #1% +{% + \expandafter\XINT_icstcv_prep \romannumeral-`0#1,\W,% +}% +\def\XINT_icstcv_prep +{% + \XINT_icstcv_loop_a {}1001% +}% +\def\XINT_icstcv_loop_a #1#2#3#4#5#6,% +{% + \xint_gob_til_W #6\XINT_icstcv_end\W + \expandafter + \XINT_icstcv_loop_b \romannumeral-`0#6.{#2}{#3}{#4}{#5}{#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}}}% + {{#2}{#3}}% +}% +\def\XINT_icstcv_loop_c #1#2% +{% + \expandafter\XINT_icstcv_loop_d\expandafter {#2}{#1}% +}% +\def\XINT_icstcv_loop_d #1#2% +{% + \expandafter\XINT_icstcv_loop_e\expandafter + {\romannumeral0\xintrawwithzeros {#1/#2}}{{#1}{#2}}% +}% +\def\XINT_icstcv_loop_e #1#2#3#4{\XINT_icstcv_loop_a {#4{#1}}#2#3}% +\def\XINT_icstcv_end #1.#2#3#4#5#6{ #6}% 1.09b removes [0] +% \end{macrocode} +% \subsection{\csh{xintGCtoCv}} +% \begin{macrocode} +\def\xintGCtoCv {\romannumeral0\xintgctocv }% +\def\xintgctocv #1% +{% + \expandafter\XINT_gctcv_prep \romannumeral-`0#1+\W/% +}% +\def\XINT_gctcv_prep +{% + \XINT_gctcv_loop_a {}1001% +}% +\def\XINT_gctcv_loop_a #1#2#3#4#5#6+% +{% + \expandafter\XINT_gctcv_loop_b + \romannumeral0\xintrawwithzeros {#6}.{#2}{#3}{#4}{#5}{#1}% +}% +\def\XINT_gctcv_loop_b #1/#2.#3#4#5#6% +{% + \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}}}% +}% +\def\XINT_gctcv_loop_c #1#2% +{% + \expandafter\XINT_gctcv_loop_d\expandafter {\expandafter{#2}{#1}}% +}% +\def\XINT_gctcv_loop_d #1#2% +{% + \expandafter\XINT_gctcv_loop_e\expandafter {\expandafter{#2}{#1}}% +}% +\def\XINT_gctcv_loop_e #1#2% +{% + \expandafter\XINT_gctcv_loop_f\expandafter {#2}#1% +}% +\def\XINT_gctcv_loop_f #1#2% +{% + \expandafter\XINT_gctcv_loop_g\expandafter + {\romannumeral0\xintrawwithzeros {#1/#2}}{{#1}{#2}}% +}% +\def\XINT_gctcv_loop_g #1#2#3#4% +{% + \XINT_gctcv_loop_h {#4{#1}}{#2#3}% 1.09b removes [0] +}% +\def\XINT_gctcv_loop_h #1#2#3/% +{% + \xint_gob_til_W #3\XINT_gctcv_end\W + \expandafter\XINT_gctcv_loop_i + \romannumeral0\xintrawwithzeros {#3}.#2{#1}% +}% +\def\XINT_gctcv_loop_i #1/#2.#3#4#5#6% +{% + \expandafter\XINT_gctcv_loop_j\expandafter + {\romannumeral0\XINT_mul_fork #1\Z #6\Z }% + {\romannumeral0\XINT_mul_fork #1\Z #5\Z }% + {\romannumeral0\XINT_mul_fork #2\Z #4\Z }% + {\romannumeral0\XINT_mul_fork #2\Z #3\Z }% +}% +\def\XINT_gctcv_loop_j #1#2% +{% + \expandafter\XINT_gctcv_loop_k\expandafter {\expandafter{#2}{#1}}% +}% +\def\XINT_gctcv_loop_k #1#2% +{% + \expandafter\XINT_gctcv_loop_l\expandafter {\expandafter{#2}#1}% +}% +\def\XINT_gctcv_loop_l #1#2% +{% + \expandafter\XINT_gctcv_loop_m\expandafter {\expandafter{#2}#1}% +}% +\def\XINT_gctcv_loop_m #1#2{\XINT_gctcv_loop_a {#2}#1}% +\def\XINT_gctcv_end #1.#2#3#4#5#6{ #6}% +% \end{macrocode} +% \subsection{\csh{xintiGCtoCv}} +% \begin{macrocode} +\def\xintiGCtoCv {\romannumeral0\xintigctocv }% +\def\xintigctocv #1% +{% + \expandafter\XINT_igctcv_prep \romannumeral-`0#1+\W/% +}% +\def\XINT_igctcv_prep +{% + \XINT_igctcv_loop_a {}1001% +}% +\def\XINT_igctcv_loop_a #1#2#3#4#5#6+% +{% + \expandafter\XINT_igctcv_loop_b + \romannumeral-`0#6.{#2}{#3}{#4}{#5}{#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}}}% + {{#2}{#3}}% +}% +\def\XINT_igctcv_loop_c #1#2% +{% + \expandafter\XINT_igctcv_loop_f\expandafter {\expandafter{#2}{#1}}% +}% +\def\XINT_igctcv_loop_f #1#2#3#4/% +{% + \xint_gob_til_W #4\XINT_igctcv_end_a\W + \expandafter\XINT_igctcv_loop_g + \romannumeral-`0#4.#1#2{#3}% +}% +\def\XINT_igctcv_loop_g #1.#2#3#4#5% +{% + \expandafter\XINT_igctcv_loop_h\expandafter + {\romannumeral0\XINT_mul_fork #1\Z #5\Z }% + {\romannumeral0\XINT_mul_fork #1\Z #4\Z }% + {{#2}{#3}}% +}% +\def\XINT_igctcv_loop_h #1#2% +{% + \expandafter\XINT_igctcv_loop_i\expandafter {\expandafter{#2}{#1}}% +}% +\def\XINT_igctcv_loop_i #1#2{\XINT_igctcv_loop_k #2{#2#1}}% +\def\XINT_igctcv_loop_k #1#2% +{% + \expandafter\XINT_igctcv_loop_l\expandafter + {\romannumeral0\xintrawwithzeros {#1/#2}}% +}% +\def\XINT_igctcv_loop_l #1#2#3{\XINT_igctcv_loop_a {#3{#1}}#2}%1.09i removes [0] +\def\XINT_igctcv_end_a #1.#2#3#4#5% +{% + \expandafter\XINT_igctcv_end_b\expandafter + {\romannumeral0\xintrawwithzeros {#2/#3}}% +}% +\def\XINT_igctcv_end_b #1#2{ #2{#1}}% 1.09b removes [0] +% \end{macrocode} +% \subsection{\csh{xintCntoF}} +% \lverb|& +% Modified in 1.06 to give the N first to a \numexpr rather than expanding +% twice. I just use \the\numexpr and maintain the previous code after that.| +% \begin{macrocode} +\def\xintCntoF {\romannumeral0\xintcntof }% +\def\xintcntof #1% +{% + \expandafter\XINT_cntf\expandafter {\the\numexpr #1}% +}% +\def\XINT_cntf #1#2% +{% + \ifnum #1>\xint_c_ + \xint_afterfi {\expandafter\XINT_cntf_loop\expandafter + {\the\numexpr #1-1\expandafter}\expandafter + {\romannumeral-`0#2{#1}}{#2}}% + \else + \xint_afterfi + {\ifnum #1=\xint_c_ + \xint_afterfi {\expandafter\space \romannumeral-`0#2{0}}% + \else \xint_afterfi { 0/1[0]}% + \fi}% + \fi +}% +\def\XINT_cntf_loop #1#2#3% +{% + \ifnum #1>\xint_c_ \else \XINT_cntf_exit \fi + \expandafter\XINT_cntf_loop\expandafter + {\the\numexpr #1-1\expandafter }\expandafter + {\romannumeral0\xintadd {\xintDiv {1[0]}{#2}}{#3{#1}}}% + {#3}% +}% +\def\XINT_cntf_exit \fi + \expandafter\XINT_cntf_loop\expandafter + #1\expandafter #2#3% +{% + \fi\xint_gobble_ii #2% +}% +% \end{macrocode} +% \subsection{\csh{xintGCntoF}} +% \lverb|& +% Modified in 1.06 to give the N first to a \numexpr rather than expanding +% twice. I just use \the\numexpr and maintain the previous code after that.| +% \begin{macrocode} +\def\xintGCntoF {\romannumeral0\xintgcntof }% +\def\xintgcntof #1% +{% + \expandafter\XINT_gcntf\expandafter {\the\numexpr #1}% +}% +\def\XINT_gcntf #1#2#3% +{% + \ifnum #1>\xint_c_ + \xint_afterfi {\expandafter\XINT_gcntf_loop\expandafter + {\the\numexpr #1-1\expandafter}\expandafter + {\romannumeral-`0#2{#1}}{#2}{#3}}% + \else + \xint_afterfi + {\ifnum #1=\xint_c_ + \xint_afterfi {\expandafter\space\romannumeral-`0#2{0}}% + \else \xint_afterfi { 0/1[0]}% + \fi}% + \fi +}% +\def\XINT_gcntf_loop #1#2#3#4% +{% + \ifnum #1>\xint_c_ \else \XINT_gcntf_exit \fi + \expandafter\XINT_gcntf_loop\expandafter + {\the\numexpr #1-1\expandafter }\expandafter + {\romannumeral0\xintadd {\xintDiv {#4{#1}}{#2}}{#3{#1}}}% + {#3}{#4}% +}% +\def\XINT_gcntf_exit \fi + \expandafter\XINT_gcntf_loop\expandafter + #1\expandafter #2#3#4% +{% + \fi\xint_gobble_ii #2% +}% +% \end{macrocode} +% \subsection{\csh{xintCntoCs}} +% \lverb|& +% Modified in 1.06 to give the N first to a \numexpr rather than expanding +% twice. I just use \the\numexpr and maintain the previous code after that.| +% \begin{macrocode} +\def\xintCntoCs {\romannumeral0\xintcntocs }% +\def\xintcntocs #1% +{% + \expandafter\XINT_cntcs\expandafter {\the\numexpr #1}% +}% +\def\XINT_cntcs #1#2% +{% + \ifnum #1<0 + \xint_afterfi { }% 1.09i: a 0/1[0] was strangely here, removed + \else + \xint_afterfi {\expandafter\XINT_cntcs_loop\expandafter + {\the\numexpr #1-1\expandafter}\expandafter + {\expandafter{\romannumeral-`0#2{#1}}}{#2}}% + \fi +}% +\def\XINT_cntcs_loop #1#2#3% +{% + \ifnum #1>-1 \else \XINT_cntcs_exit \fi + \expandafter\XINT_cntcs_loop\expandafter + {\the\numexpr #1-1\expandafter }\expandafter + {\expandafter{\romannumeral-`0#3{#1}},#2}{#3}% +}% +\def\XINT_cntcs_exit \fi + \expandafter\XINT_cntcs_loop\expandafter + #1\expandafter #2#3% +{% + \fi\XINT_cntcs_exit_b #2% +}% +\def\XINT_cntcs_exit_b #1,{ }% +% \end{macrocode} +% \subsection{\csh{xintCntoGC}} +% \lverb|& +% Modified in 1.06 to give the N first to a \numexpr rather than expanding +% twice. I just use \the\numexpr and maintain the previous code after that.| +% \begin{macrocode} +\def\xintCntoGC {\romannumeral0\xintcntogc }% +\def\xintcntogc #1% +{% + \expandafter\XINT_cntgc\expandafter {\the\numexpr #1}% +}% +\def\XINT_cntgc #1#2% +{% + \ifnum #1<0 + \xint_afterfi { }% 1.09i there was as strange 0/1[0] here, removed + \else + \xint_afterfi {\expandafter\XINT_cntgc_loop\expandafter + {\the\numexpr #1-1\expandafter}\expandafter + {\expandafter{\romannumeral-`0#2{#1}}}{#2}}% + \fi +}% +\def\XINT_cntgc_loop #1#2#3% +{% + \ifnum #1>-1 \else \XINT_cntgc_exit \fi + \expandafter\XINT_cntgc_loop\expandafter + {\the\numexpr #1-1\expandafter }\expandafter + {\expandafter{\romannumeral-`0#3{#1}}+1/#2}{#3}% +}% +\def\XINT_cntgc_exit \fi + \expandafter\XINT_cntgc_loop\expandafter + #1\expandafter #2#3% +{% + \fi\XINT_cntgc_exit_b #2% +}% +\def\XINT_cntgc_exit_b #1+1/{ }% +% \end{macrocode} +% \subsection{\csh{xintGCntoGC}} +% \lverb|& +% Modified in 1.06 to give the N first to a \numexpr rather than expanding +% twice. I just use \the\numexpr and maintain the previous code after that.| +% \begin{macrocode} +\def\xintGCntoGC {\romannumeral0\xintgcntogc }% +\def\xintgcntogc #1% +{% + \expandafter\XINT_gcntgc\expandafter {\the\numexpr #1}% +}% +\def\XINT_gcntgc #1#2#3% +{% + \ifnum #1<0 + \xint_afterfi { }% 1.09i now returns nothing + \else + \xint_afterfi {\expandafter\XINT_gcntgc_loop\expandafter + {\the\numexpr #1-1\expandafter}\expandafter + {\expandafter{\romannumeral-`0#2{#1}}}{#2}{#3}}% + \fi +}% +\def\XINT_gcntgc_loop #1#2#3#4% +{% + \ifnum #1>-1 \else \XINT_gcntgc_exit \fi + \expandafter\XINT_gcntgc_loop_b\expandafter + {\expandafter{\romannumeral-`0#4{#1}}/#2}{#3{#1}}{#1}{#3}{#4}% +}% +\def\XINT_gcntgc_loop_b #1#2#3% +{% + \expandafter\XINT_gcntgc_loop\expandafter + {\the\numexpr #3-1\expandafter}\expandafter + {\expandafter{\romannumeral-`0#2}+#1}% +}% +\def\XINT_gcntgc_exit \fi + \expandafter\XINT_gcntgc_loop_b\expandafter #1#2#3#4#5% +{% + \fi\XINT_gcntgc_exit_b #1% +}% +\def\XINT_gcntgc_exit_b #1/{ }% +% \end{macrocode} +% \subsection{\csh{xintCstoGC}} +% \begin{macrocode} +\def\xintCstoGC {\romannumeral0\xintcstogc }% +\def\xintcstogc #1% +{% + \expandafter\XINT_cstc_prep \romannumeral-`0#1,\W,% +}% +\def\XINT_cstc_prep #1,{\XINT_cstc_loop_a {{#1}}}% +\def\XINT_cstc_loop_a #1#2,% +{% + \xint_gob_til_W #2\XINT_cstc_end\W + \XINT_cstc_loop_b {#1}{#2}% +}% +\def\XINT_cstc_loop_b #1#2{\XINT_cstc_loop_a {#1+1/{#2}}}% +\def\XINT_cstc_end\W\XINT_cstc_loop_b #1#2{ #1}% +% \end{macrocode} +% \subsection{\csh{xintGCtoGC}} +% \begin{macrocode} +\def\xintGCtoGC {\romannumeral0\xintgctogc }% +\def\xintgctogc #1% +{% + \expandafter\XINT_gctgc_start \romannumeral-`0#1+\W/% +}% +\def\XINT_gctgc_start {\XINT_gctgc_loop_a {}}% +\def\XINT_gctgc_loop_a #1#2+#3/% +{% + \xint_gob_til_W #3\XINT_gctgc_end\W + \expandafter\XINT_gctgc_loop_b\expandafter + {\romannumeral-`0#2}{#3}{#1}% +}% +\def\XINT_gctgc_loop_b #1#2% +{% + \expandafter\XINT_gctgc_loop_c\expandafter + {\romannumeral-`0#2}{#1}% +}% +\def\XINT_gctgc_loop_c #1#2#3% +{% + \XINT_gctgc_loop_a {#3{#2}+{#1}/}% +}% +\def\XINT_gctgc_end\W\expandafter\XINT_gctgc_loop_b +{% + \expandafter\XINT_gctgc_end_b +}% +\def\XINT_gctgc_end_b #1#2#3{ #3{#1}}% +\XINT_restorecatcodes_endinput% +% \end{macrocode} +%\catcode`\<=0 \catcode`\>=11 \catcode`\*=11 \catcode`\/=11 +%\let</xintcfrac>\relax +%\def<*xintexpr>{\catcode`\<=12 \catcode`\>=12 \catcode`\*=12 \catcode`\/=12 } +%</xintcfrac> +%<*xintexpr> +% +% \StoreCodelineNo {xintcfrac} +% +% \section{Package \xintexprnameimp implementation} +% \label{sec:exprimp} +% +% The first version was released in June 2013. I was greatly helped in this task +% of writing an expandable parser of infix operations by the comments provided +% in |l3fp-parse.dtx| (in its version as available in April-May 2013). One will +% recognize in particular the idea of the `until' macros; I have not looked into +% the actual |l3fp| code beyond the very useful comments provided in its +% documentation. +% +% A main worry was that my data has no a priori bound on its size; to keep the +% code reasonably efficient, I experimented with a technique of storing and +% retrieving data expandably as \emph{names} of control sequences. Intermediate +% computation results are stored as control sequences |\.=a/b[n]|. +% +% Another peculiarity is that the input is allowed to contain (but only where +% the scanner looks for a number or fraction) material within braces |{...}|. +% This will be expanded completely and must give an integer, decimal number or +% fraction (not in scientific notation). Conversely any explict fraction +% |A/B[n]| \emph{with the brackets} or macro expanding to such a thing +% \textbf{must} be enclosed within such braces: square brackets are not +% acceptable by the expression parser. +% +% These two things are a bit \emph{experimental} and perhaps I will opt for +% another approach at a later stage. To circumvent the potential hash-table +% impact of the |\.=a/b[n]| I have provided the macro creators |\xintNewExpr| +% and |\xintNewFloatExpr|. +% +% Roughly speaking, the parser mechanism is as follows: at any given time the +% last found ``operator'' has its associated |until| macro awaiting some news +% from the token flow; first |getnext| expands forward in the hope to construct +% some number, which may come from a parenthesized sub-expression, from some +% braced material, or from a digit by digit scan. After this number has been +% formed the next operator is looked for by the |getop| macro. Once |getop| has +% finished its job, |until| is presented with three tokens: the first one is the +% precedence level of the new found operator (which may be an end of expression +% marker), the second is the operator character token (earlier versions had here +% already some macro name, but in order to keep as much common code to expr and +% floatexpr common as possible, this was modied) of the new found operator, and +% the third one is the newly found number (which was encountered just before the +% new operator). +% +% The |until| macro of the earlier operator examines the precedence level of the +% new found one, and either executes the earlier operator (in the case of a +% binary operation, with the found number and a previously stored one) or it +% delays execution, giving the hand to the |until| macro of the operator having +% been found of higher precedence. +% +% A minus sign acting as prefix gets converted into a (unary) operator +% inheriting the precedence level of the previous operator. +% +% Once the end of the expression is found (it has to be marked by a |\relax|) +% the final result is output as four tokens: the first one a catcode 11 +% exclamation mark, the second one an error generating macro, the third one a +% printing macro and the fourth is |\.=a/b[n]|. The prefix |\xintthe| makes the +% output printable by killing the first two tokens. +% +% Version |1.08b| |[2013/06/14]| corrected a problem originating in the attempt +% to attribute a special rôle to braces: expansion could be stopped by space +% tokens, as various macros tried to expand without grabbing what came next. +% They now have a doubled |\romannumeral-`0|. +% +% Version |1.09a| |[2013/09/24]| has a better mechanism regarding |\xintthe|, +% more commenting and better organization of the code, and most importantly it +% implements functions, comparison operators, logic operators, conditionals. The +% code was reorganized and expansion proceeds a bit differently in order to have +% the |_getnext| and |_getop| codes entirely shared by |\xintexpr| and +% |\xintfloatexpr|. |\xintNewExpr| was rewritten in order to work with the +% standard macro parameter character |#|, to be catcode protected and to also +% allow comma separated expressions. +% +% Version |1.09c| |[2013/10/09]| added the |bool| and |togl| operators, +% |\xintboolexpr|, and |\xintNewNumExpr|, |\xintNewBoolExpr|. The code for +% |\xintNewExpr| is shared with |float|, |num|, and |bool|-expressions. Also the +% precedence level of the postfix operators |!|, |?| and |:| has been made lower +% than the one of functions. +% +% Version |1.09i| |[2013/12/18]| unpacks count and dimen registers and control +% squences, with tacit multiplication. It has also made small improvements. +% (speed gains in macro expansions in quite a few places.) +% +% Also, |1.09i| implements |\xintiiexpr|, |\xinttheiiexpr|. New function |frac|. +% And encapsulation in |\csname..\endcsname| is done with |.=| as first tokens, +% so unpacking with |\string| can be done in a completely escape char agnostic +% way. +% +% Version |1.09j| |[2014/01/09]| extends the tacit multiplication to the case of +% a sub |\xintexpr|-essions. Also, it now |\xint_protect|s the result of the +% |\xintexpr| full expansions, thus, an |\xintexpr| without |\xintthe| prefix +% can be used not only as the first item within an ``|\fdef|'' as previously but +% also now anywhere within an |\edef|. Five tokens are used to pack the +% computation result rather than the possibly hundreds or thousands of digits of +% an |\xintthe| unlocked result. I deliberately omit a second |\xint_protect| +% which, however would be necessary if some macro |\.=digits/digits[digits]| had +% acquired some expandable meaning elsewhere. But this seems not that probable, +% and adding the protection would mean impacting everything only to allow some +% crazy user which has loaded something else than xint to do an |\edef|... the +% |\xintexpr| computations are otherwise in no way affected if such control +% sequences have a meaning. +% +% Version |1.09k| |[2014/01/21]| does tacit multiplication also for an opening +% parenthesis encountered during the scanning of a number, or at a time when the +% parser expects an infix operator. +% +% And it adds to the syntax recognition of hexadecimal numbers starting with a +% |"|, and having possibly a fractional part (except in |\xintiiexpr|, +% naturally). +% +% \localtableofcontents +% \subsection{Catcodes, \protect\eTeX{} and reload detection} +% +% The code for reload detection is copied from \textsc{Heiko +% Oberdiek}'s packages, and adapted here to check for previous +% loading of the \xintfracname package. +% +% The method for catcodes is slightly different, but still +% directly inspired by these packages. +% +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \def\space { }% + \let\z\endgroup + \expandafter\let\expandafter\x\csname ver@xintexpr.sty\endcsname + \expandafter\let\expandafter\w\csname ver@xintfrac.sty\endcsname + \expandafter + \ifx\csname PackageInfo\endcsname\relax + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \else + \def\y#1#2{\PackageInfo{#1}{#2}}% + \fi + \expandafter + \ifx\csname numexpr\endcsname\relax + \y{xintexpr}{\numexpr not available, aborting input}% + \aftergroup\endinput + \else + \ifx\x\relax % plain-TeX, first loading of xintexpr.sty + \ifx\w\relax % but xintfrac.sty not yet loaded. + \y{xintexpr}{now issuing \string\input\space xintfrac.sty}% + \def\z{\endgroup\input xintfrac.sty\relax}% + \fi + \else + \def\empty {}% + \ifx\x\empty % LaTeX, first loading, + % variable is initialized, but \ProvidesPackage not yet seen + \ifx\w\relax % xintfrac.sty not yet loaded. + \y{xintexpr}{now issuing \string\RequirePackage{xintfrac}}% + \def\z{\endgroup\RequirePackage{xintfrac}}% + \fi + \else + \y{xintexpr}{I was already loaded, aborting input}% + \aftergroup\endinput + \fi + \fi + \fi +\z% +% \end{macrocode} +% \subsection{Confirmation of \xintfracnameimp loading} +% \begin{macrocode} +\begingroup\catcode61\catcode48\catcode32=10\relax% + \catcode13=5 % ^^M + \endlinechar=13 % + \catcode123=1 % { + \catcode125=2 % } + \catcode64=11 % @ + \catcode35=6 % # + \catcode44=12 % , + \catcode45=12 % - + \catcode46=12 % . + \catcode58=12 % : + \ifdefined\PackageInfo + \def\y#1#2{\PackageInfo{#1}{#2}}% + \else + \def\y#1#2{\immediate\write-1{Package #1 Info: #2.}}% + \fi + \def\empty {}% + \expandafter\let\expandafter\w\csname ver@xintfrac.sty\endcsname + \ifx\w\relax % Plain TeX, user gave a file name at the prompt + \y{xintexpr}{Loading of package xintfrac failed, aborting input}% + \aftergroup\endinput + \fi + \ifx\w\empty % LaTeX, user gave a file name at the prompt + \y{xintexpr}{Loading of package xintfrac failed, aborting input}% + \aftergroup\endinput + \fi +\endgroup% +% \end{macrocode} +% \subsection{Catcodes} +% \begin{macrocode} +\XINTsetupcatcodes% +% \end{macrocode} +% \subsection{Package identification} +% \begin{macrocode} +\XINT_providespackage +\ProvidesPackage{xintexpr}% + [2014/02/05 v1.09k Expandable expression parser (jfB)]% +% \end{macrocode} +% \subsection{Encapsulation in pseudo cs names, helper macros} +% \lverb|1.09i uses .= for encapsulation, thus allowing \escapechar to be +% anything (all previous releases were with ., so \escapechar 46 was forbidden). +% Besides, the \edef definition has \space already expanded, perhaps this will +% compensate a tiny bit the time penalty of `.=' viz `.' in unlocking... well +% not really, I guess. (for no special reason 1.09k uses some \expandafter's +% rather than \edef+\noexpand's for the definition of \XINT_expr_lock)| +% \begin{macrocode} +\def\xint_gob_til_! #1!{}% nota bene: this ! has catcode 11 +\expandafter\def\expandafter +\XINT_expr_lock\expandafter#\expandafter1\expandafter !\expandafter + {\expandafter\expandafter\space\csname .=#1\endcsname }% +\def\XINT_expr_unlock {\expandafter\XINT_expr_unlock_a\string }% +\def\XINT_expr_unlock_a #1.={}% +\def\XINT_expr_unexpectedtoken {\xintError:ignored }% +\def\XINT_newexpr_setprefix #1>{\noexpand\romannumeral-`0}% +\def\xint_UDxintrelaxfork #1\xint_relax #2#3\krof {#2}% +% \end{macrocode} +% \subsection{\csh{xintexpr}, \csh{xinttheexpr}, \csh{xintthe}, ...} +% \lverb|\xintthe is defined with a parameter, I guess I wanted to make sure no +% stray space tokens could cause a problem. +% +% With 1.09i, \xintiexpr replaces +% \xintnumexpr which is kept for compatibility but will be removed at some +% point. Should perhaps issue a warning, but well, people can also read the +% documentation. Also 1.09i removes \xinttheeval. +% +% 1.09i has re-organized the material here. +% +% 1.09j modifies the mechanism of \XINT_expr_usethe and +% \XINT_expr_print, etc... in order for \xintexpr-essions to be usable +% within \edef'initions. I hesitated quite a bit with adding +% \xint_protect in front of the \.=digits macros, which will in +% 99.99999$% of use cases supposed all have \relax meaning; and it is a +% bit of a pain, really, it is quite a pain to add these extra tokens +% only for \edef contexts and for situations which will never occur... +% well no damn'it let's *NOT* add this extra \xint_protect. Just one +% before the printing macro (which can not be \protected, else \xintthe +% could not work).| +% \begin{macrocode} +\def\xint_protect {\noexpand\xint_protect\noexpand }% 1.09j +\def\XINT_expr_done {!\XINT_expr_usethe\xint_protect\XINT_expr_print }% +\let\XINT_iiexpr_done \XINT_expr_done +\def\XINT_iexpr_done {!\XINT_expr_usethe\xint_protect\XINT_iexpr_print }% +\def\XINT_flexpr_done {!\XINT_expr_usethe\xint_protect\XINT_flexpr_print }% +\def\XINT_boolexpr_done {!\XINT_expr_usethe\xint_protect\XINT_boolexpr_print }% +\protected\def\XINT_expr_usethe #1#2#3% modified in 1.09j + {\xintError:missing_xintthe!\show#3missing xintthe (see log)!}% +\def\xintthe #1{\romannumeral-`0\expandafter\xint_gobble_iii\romannumeral-`0#1}% +\let\XINT_expr_print \XINT_expr_unlock +\def\XINT_iexpr_print #1{\xintRound:csv {\XINT_expr_unlock #1}}% +\def\XINT_flexpr_print #1{\xintFloat:csv {\XINT_expr_unlock #1}}% +\def\XINT_boolexpr_print #1{\xintIsTrue:csv{\XINT_expr_unlock #1}}% +\def\xintexpr {\romannumeral0\xinteval }% +\def\xintfloatexpr {\romannumeral0\xintfloateval }% +\def\xintiiexpr {\romannumeral0\xintiieval }% +\def\xinteval + {\expandafter\XINT_expr_until_end_a \romannumeral-`0\XINT_expr_getnext }% +\def\xintfloateval + {\expandafter\XINT_flexpr_until_end_a\romannumeral-`0\XINT_expr_getnext }% +\def\xintiieval + {\expandafter\XINT_iiexpr_until_end_a\romannumeral-`0\XINT_expr_getnext }% +\def\xinttheexpr + {\romannumeral-`0\expandafter\xint_gobble_iii\romannumeral0\xinteval }% +\def\xintthefloatexpr + {\romannumeral-`0\expandafter\xint_gobble_iii\romannumeral0\xintfloateval }% +\def\xinttheiiexpr + {\romannumeral-`0\expandafter\xint_gobble_iii\romannumeral0\xintiieval }% +\def\xintiexpr {\romannumeral0\expandafter\expandafter\expandafter + \XINT_iexpr_done \expandafter\xint_gobble_iv\romannumeral0\xinteval }% +\def\xinttheiexpr {\romannumeral-`0\expandafter\expandafter\expandafter + \XINT_iexpr_print\expandafter\xint_gobble_iv\romannumeral0\xinteval }% +\def\xintboolexpr {\romannumeral0\expandafter\expandafter\expandafter + \XINT_boolexpr_done \expandafter\xint_gobble_iv\romannumeral0\xinteval }% +\def\xinttheboolexpr {\romannumeral-`0\expandafter\expandafter\expandafter + \XINT_boolexpr_print\expandafter\xint_gobble_iv\romannumeral0\xinteval }% +\let\xintnumexpr \xintiexpr % deprecated +\let\xintthenumexpr\xinttheiexpr % deprecated +% \end{macrocode} +% \subsection{\csh{xintifboolexpr}, \csh{xintifboolfloatexpr}, csh{xintifbooliiexpr}} +% \lverb|1.09c. Does not work with comma separated expressions. I could +% make use \xintORof:csv (or AND, or XOR) to allow it, but don't know it the +% overhead is worth it. +% +% 1.09i adds \xintifbooliiexpr | +% \begin{macrocode} +\def\xintifboolexpr #1% + {\romannumeral0\xintifnotzero {\xinttheexpr #1\relax}}% +\def\xintifboolfloatexpr #1% + {\romannumeral0\xintifnotzero {\xintthefloatexpr #1\relax}}% +\def\xintifbooliiexpr #1% + {\romannumeral0\xintifnotzero {\xinttheiiexpr #1\relax}}% +% \end{macrocode} +% \subsection{\csh{XINT\_get\_next}: looking for a number} +% \lverb|June 14: 1.08b adds a second \romannumeral-`0 to \XINT_expr_getnext in +% an attempt to solve a problem with space tokens stopping the \romannumeral and +% thus preventing expansion of the following token. For example: 1+ \the\cnta +% caused a problem, as `\the' was not expanded. I did not define +% \XINT_expr_getnext as a macro with parameter (which would have cured +% preventively this), precisely to try to recognize brace pairs. The second +% \romannumeral-`0 is added for the same reason in other places. +% +% The get-next scans forward to find a number: after expansion of what comes +% next, an opening parenthesis signals a parenthesized sub-expression, a ! with +% catcode 11 signals there was there an \xintexpr.. \relax sub-expression (now +% evaluated), a minus is a prefix operator, a plus is silently ignored, a digit +% or decimal point signals to start gathering a number, braced material {...} is +% allowed and will be directly fed into a \csname..\endcsname for complete +% expansion which must delivers a (fractional) number, possibly ending in [n]; +% explicit square brackets must be enclosed into such braces. Once a number +% issues from the previous procedures, it is a locked into a +% \csname...\endcsname, and the flow then proceeds with \XINT_expr_getop which +% will scan for an infix or postfix operator following the number. +% +% A special r\^ole is played by underscores _ for use with \xintNewExpr +% to input macro parameters. +% +% Release 1.09a implements functions; the idea is that a letter (actually, +% anything not otherwise recognized!) triggers the function name gatherer, the +% comma is promoted to a binary operator of priority intermediate between +% parentheses and infix operators. The code had some other revisions in order +% for all the _getnext and _getop macros to now be shared by \xintexpr and +% \xintfloatexpr. +% +% 1.09i now allows direct insertion of \count's, \dimen's and \skip's which will +% be unpacked using \number. +% +% 1.09i speeds up a bit the recognition of a braced thing: the case of a single +% braced control sequence makes a third expansion mandatory, let's do it +% immediately and not wait. So macros got shuffled and modified a bit. +% +% \XINT_expr_unpackvariable does not insert a [0] for compatibility with +% \xintiiexpr. A [0] would have made a bit faster \xintexpr macros when dealing +% with an unpacked count control sequence, as without it the \xintnum will be +% used in the parsing by xintfrac macros when the number is used. But [0] is not +% accepted by most macros ultimately called by \xintiiexpr.| +% \begin{macrocode} +\def\XINT_expr_getnext +{% + \expandafter\XINT_expr_getnext_checkforbraced_a + \romannumeral-`0\romannumeral-`0% +}% +\def\XINT_expr_getnext_checkforbraced_a #1% was done later in <1.09i +{% + \expandafter\XINT_expr_getnext_checkforbraced_b\expandafter + {\romannumeral-`0#1}% +}% +\def\XINT_expr_getnext_checkforbraced_b #1% +{% + \XINT_expr_getnext_checkforbraced_c #1\xint_relax\Z {#1}% +}% +\def\XINT_expr_getnext_checkforbraced_c #1#2% +{% + \xint_UDxintrelaxfork + #1\XINT_expr_getnext_wasemptyorspace + #2\XINT_expr_getnext_gotonetoken_wehope + \xint_relax\XINT_expr_getnext_gotbracedstuff + \krof +}% doubly braced things are not acceptable, will cause errors. +\def\XINT_expr_getnext_wasemptyorspace #1{\XINT_expr_getnext }% +\def\XINT_expr_getnext_gotbracedstuff #1\xint_relax\Z #2% +{% + \expandafter\XINT_expr_getop\csname .=#2\endcsname +}% +\def\XINT_expr_getnext_gotonetoken_wehope\Z #1% +{% screens out sub-expressions and \count or \dimen registers/variables + \xint_gob_til_! #1\XINT_expr_subexpr !% recall this ! has catcode 11 + \ifcat\relax#1% \count or \numexpr etc... token or count, dimen, skip cs + \expandafter\XINT_expr_countdimenetc_fork + \else + \expandafter\expandafter\expandafter + \XINT_expr_getnext_onetoken_fork\expandafter\string + \fi + #1% +}% +\def\XINT_expr_subexpr !#1\fi !{\expandafter\XINT_expr_getop\xint_gobble_iii }% +\def\XINT_expr_countdimenetc_fork #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 + \XINT_expr_unpackvariable + \fi\fi\fi\fi\fi\fi + \expandafter\XINT_expr_getnext\number #1% +}% +\def\XINT_expr_unpackvariable\fi\fi\fi\fi\fi\fi\expandafter\XINT_expr_getnext + \number #1{\fi\fi\fi\fi\fi\fi + \expandafter\XINT_expr_getop\csname .=\number#1\endcsname }% +% \end{macrocode} +% \lverb|1.09a: In order to have this code shared by \xintexpr and +% \xintfloatexpr, I have moved to the until macros the responsability to choose +% expr or floatexpr, hence here, the opening parenthesis for example can not be +% triggered directly as it would not know in which context it works. Hence the +% \xint_c_xviii ({}. And also the mechanism of \xintNewExpr has been modified to +% allow use of #. +% +% 1.09i also has \xintiiexpr. | +% \begin{macrocode} +\begingroup +\lccode`*=`# +\lowercase{\endgroup +\def\XINT_expr_sixwayfork #1(-.+*#2#3\krof {#2}% +\def\XINT_expr_getnext_onetoken_fork #1% +{% The * is in truth catcode 12 #. For (hacking) use with \xintNewExpr. + \XINT_expr_sixwayfork + #1-.+*{\xint_c_xviii ({}}% back to until for oparen triggering + (#1.+*{-}% + (-#1+*{\XINT_expr_scandec_II .}% + (-.#1*{\XINT_expr_getnext }% + (-.+#1{\XINT_expr_scandec_II }% + (-.+*{\XINT_expr_scan_dec_or_func #1}% + \krof +}}% +% \end{macrocode} +% \subsection{\csh{XINT\_expr\_scan\_dec\_or\_func}: collecting an integer or +% decimal number or hexa-decimal number or function name} +% \lverb|\XINT_expr_scanfunc_b rewritten in 1.09i. And 1.09k adds hexadecimal +% numbers to the syntax, with " as prefix, and possibly a fractional part. +% Naturally to postfix with an E in scientific notation, one would need to +% surround the hexadecimal number in parentheses to avoid ambiguities; or +% rather, just use a lowercase e. By the way, if I allowed only lowercase e for +% scientific notation I could possibly fuse together the scanning in the dec and +% hexa cases; up to some loss of syntax control in the dec case.| +% \begin{macrocode} +\def\XINT_expr_scan_dec_or_func #1% this #1 has necessarily here catcode 12 +{% + \ifnum \xint_c_ix<1#1 + \expandafter\XINT_expr_scandec_I + \else + \if #1"\expandafter\expandafter\expandafter\XINT_expr_scanhex_I + \else % We assume we are dealing with a function name!! + \expandafter\expandafter\expandafter\XINT_expr_scanfunc + \fi + \fi #1% +}% +\def\XINT_expr_scanfunc +{% + \expandafter\XINT_expr_func\romannumeral-`0\XINT_expr_scanfunc_c +}% +\def\XINT_expr_scanfunc_c #1% +{% + \expandafter #1\romannumeral-`0\expandafter + \XINT_expr_scanfunc_a\romannumeral-`0\romannumeral-`0% +}% +\def\XINT_expr_scanfunc_a #1% please no braced things here! +{% + \ifcat #1\relax % missing opening parenthesis, probably + \expandafter\XINT_expr_scanfunc_panic + \else + \xint_afterfi{\expandafter\XINT_expr_scanfunc_b \string #1}% + \fi +}% +\def\xint_UDparenfork #1()#2#3\krof {#2}% +\def\XINT_expr_scanfunc_b #1% +{% + \xint_UDparenfork + #1){(}% and then \XINT_expr_func + (#1{(}% and then \XINT_expr_func (this is for bool/toggle names) + (){\XINT_expr_scanfunc_c #1}% + \krof +}% +\def\XINT_expr_scanfunc_panic {\xintError:bigtroubleahead(0\relax }% +\def\XINT_expr_func #1(% common to expr and flexpr and iiexpr +{% + \xint_c_xviii @{#1}% functions have the highest priority. +}% +% \end{macrocode} +% \lverb|Scanning for a number of fraction. Once gathered, lock it and do +% _getop. 1.09i modifies \XINT_expr_scanintpart_a (splits _aa) and also +% \XINT_expr_scanfracpart_a in +% order for the tacit multiplication of \count's and \dimen's to be compatible +% with escape-char=a digit. +% +% 1.09j further extends for recognition of an \xint..expr and then insertion +% of a * (which is done in \XINT_expr_getop_a).| +% \begin{macrocode} +\def\XINT_expr_scandec_I +{% + \expandafter\XINT_expr_getop\romannumeral-`0\expandafter + \XINT_expr_lock\romannumeral-`0\XINT_expr_scanintpart_b +}% +\def\XINT_expr_scandec_II +{% + \expandafter\XINT_expr_getop\romannumeral-`0\expandafter + \XINT_expr_lock\romannumeral-`0\XINT_expr_scanfracpart_b +}% +\def\XINT_expr_scanintpart_a #1% Please no braced material: 123{FORBIDDEN} +{% careful that ! has catcode letter here + \ifcat #1\relax\else + \ifx !#1\else + \expandafter\expandafter\expandafter + \xint_thirdofthree + \fi\fi + \xint_firstoftwo !% this stops the scan + {\expandafter\XINT_expr_scanintpart_aa\string }#1% +}% +\def\XINT_expr_scanintpart_aa #1% +{% + \ifnum \xint_c_ix<1#1 + \expandafter\XINT_expr_scanintpart_b + \else + \if .#1% + \expandafter\expandafter\expandafter + \XINT_expr_scandec_transition + \else % gather what we got so far, leave catcode 12 #1 in stream + \expandafter\expandafter\expandafter !% ! of catcode 11, space needed + \fi + \fi + #1% +}% +\def\XINT_expr_scanintpart_b #1% +{% + \expandafter #1\romannumeral-`0\expandafter + \XINT_expr_scanintpart_a\romannumeral-`0\romannumeral-`0% +}% +\def\XINT_expr_scandec_transition .% +{% + \expandafter.\romannumeral-`0\expandafter + \XINT_expr_scanfracpart_a\romannumeral-`0\romannumeral-`0% +}% +\def\XINT_expr_scanfracpart_a #1% +{% + \ifcat #1\relax\else + \ifx !#1\else + \expandafter\expandafter\expandafter + \xint_thirdofthree + \fi\fi + \xint_firstoftwo !% this stops the scan + {\expandafter\XINT_expr_scanfracpart_aa\string }#1% +}% +\def\XINT_expr_scanfracpart_aa #1% +{% + \ifnum \xint_c_ix<1#1 + \expandafter\XINT_expr_scanfracpart_b + \else + \expandafter !% + \fi + #1% +}% +\def\XINT_expr_scanfracpart_b #1% +{% + \expandafter #1\romannumeral-`0\expandafter + \XINT_expr_scanfracpart_a\romannumeral-`0\romannumeral-`0% +}% +% \end{macrocode} +% \lverb|1.09k [2014/01/21]: added scanning for an hexadecimal number, possibly +% with a "hexa-decimal" part, only with uppercase ABCDEF (xintbinhex.sty works +% with ABCDEF, as tex itself requires uppercase letters after ", thus at least I +% feel comfortable with not bothering allowing abcdef... which would be possible +% but would complicate things; although perhaps there could be some use for +% lowercase. If needed, can be implemented, but I will probably long be dead +% when an archivist droid will be the first around circa 2500 AD to read these +% lines). +% +% For compatibility with \xintiiexpr, the [] thing is incorporated only if there +% the parser encounters a . indicating a fractional part (this fractional part +% may be empty). Thus for (infinitesimally) faster further processing by +% \xintexpr, "ABC.+ etc... is better than "ABC+ etc... on the other hand the +% initial processing with a . followed by an empty fractional part adds its bit +% of overhead... The . is not allowed in \xintiiexpr, as it will provoke +% insertion of [0] which is incompatible with it.| +% \begin{macrocode} +\def\XINT_expr_scanhex_I #1% +{% + \expandafter\XINT_expr_getop\romannumeral-`0\expandafter + \XINT_expr_lock\expandafter\XINT_expr_inhex + \romannumeral-`0\XINT_expr_scanhexI_a +}% +\def\XINT_expr_inhex #1.#2#3;% expanded inside \csname..\endcsname +{% + \if#2I\xintHexToDec{#1}% + \else + \xintiiMul{\xintiiPow{625}{\xintLength{#3}}}{\xintHexToDec{#1#3}}% + [\the\numexpr-4*\xintLength{#3}]% + \fi +}% +\def\XINT_expr_scanhexI_a #1% +{% + \ifcat #1\relax\else + \ifx !#1\else + \expandafter\expandafter\expandafter + \xint_thirdofthree + \fi\fi + \xint_firstoftwo {.I;!}% + {\expandafter\XINT_expr_scanhexI_aa\string }#1% +}% +\def\XINT_expr_scanhexI_aa #1% +{% + \if\ifnum`#1>`/ + \ifnum`#1>`9 + \ifnum`#1>`@ + \ifnum`#1>`F + 0\else1\fi\else0\fi\else1\fi\else0\fi 1% + \expandafter\XINT_expr_scanhexI_b + \else + \if .#1% + \expandafter\xint_firstoftwo + \else % gather what we got so far, leave catcode 12 #1 in stream + \expandafter\xint_secondoftwo + \fi + {\expandafter\XINT_expr_scanhex_transition}% + {\xint_afterfi {.I;!}}% + \fi + #1% +}% +\def\XINT_expr_scanhexI_b #1% +{% + \expandafter #1\romannumeral-`0\expandafter + \XINT_expr_scanhexI_a\romannumeral-`0\romannumeral-`0% +}% +\def\XINT_expr_scanhex_transition .% +{% + \expandafter.\expandafter.\romannumeral-`0\expandafter + \XINT_expr_scanhexII_a\romannumeral-`0\romannumeral-`0% +}% +\def\XINT_expr_scanhexII_a #1% +{% + \ifcat #1\relax\else + \ifx !#1\else + \expandafter\expandafter\expandafter + \xint_thirdofthree + \fi\fi + \xint_firstoftwo {;!}% this stops the scan + {\expandafter\XINT_expr_scanhexII_aa\string }#1% +}% +\def\XINT_expr_scanhexII_aa #1% +{% + \if\ifnum`#1>`/ + \ifnum`#1>`9 + \ifnum`#1>`@ + \ifnum`#1>`F + 0\else1\fi\else0\fi\else1\fi\else0\fi 1% + \expandafter\XINT_expr_scanhexII_b + \else + \xint_afterfi {;!}% + \fi + #1% +}% +\def\XINT_expr_scanhexII_b #1% +{% + \expandafter #1\romannumeral-`0\expandafter + \XINT_expr_scanhexII_a\romannumeral-`0\romannumeral-`0% +}% +% \end{macrocode} +% \subsection{\csh{XINT\_expr\_getop}: looking for an operator} +% \lverb|June 14 (1.08b): I add here a second \romannumeral-`0, because +% \XINT_expr_getnext and others try to expand the next token +% but without grabbing it. +% +% This finds the next infix operator or closing parenthesis or postfix +% exclamation mark ! +% or expression end. It then leaves in the token flow +% <precedence> <operator> <locked number>. The <precedence> is generally +% a character command which thus stops expansion and gives back control to an +% \XINT_expr_until_<op> command; or it is the minus sign which will be +% converted by a suitable \XINT_expr_checkifprefix_<p> into an operator +% with a given inherited precedence. Earlier releases than 1.09c used tricks for +% the postfix !, ?, :, with <precedence> being in fact a macro to act +% immediately, and then re-activate \XINT_expr_getop. +% +% In versions earlier than 1.09a the <operator> was already made in to a control +% sequence; but now it is a left as a token and will be (generally) converted by +% the until macro which knows if it is in a \xintexpr or an \xintfloatexpr. (or +% an \xintiiexpr, since 1.09i) +% +% 1.09i allows \count's, \dimen's, \skip's with tacit multiplication. +% +% 1.09j extends the mechanism of tacit multiplication to the case of a sub +% xintexpression in its various variants. Careful that our ! has catcode 11 so +% \ifx! would be a disaster... +% +% 1.09k extends tacit multiplication to the case of an encountered opening +% parenthesis. +% +% | +% \begin{macrocode} +\def\XINT_expr_getop #1% this #1 is the current locked computed value +{% full expansion of next token, first swallowing a possible space + \expandafter\XINT_expr_getop_a\expandafter #1% + \romannumeral-`0\romannumeral-`0% +}% +\def\XINT_expr_getop_a #1#2% +{% if a control sequence is found, must be either \relax or register|variable + \ifcat #2\relax\expandafter\xint_firstoftwo + \else \expandafter\xint_secondoftwo + \fi + {\ifx #2\relax\expandafter\xint_firstofthree + \else\expandafter\xint_secondofthree % tacit multiplication + \fi }% + {\ifx !#2\expandafter\xint_secondofthree % tacit multiplication + \else % 1.09k adds tacit multiplication in front of ( + \if (#2\expandafter\expandafter\expandafter\xint_secondofthree + \else + \expandafter\expandafter\expandafter\xint_thirdofthree + \fi + \fi }% + {\XINT_expr_foundend #1}% + {\XINT_expr_foundop *#1#2}% + {\XINT_expr_foundop #2#1}% +}% +\def\XINT_expr_foundend {\xint_c_ \relax }% \relax is a place holder here. +\def\XINT_expr_foundop #1% then becomes <prec> <op> and is followed by <\.=f> +{% 1.09a: no control sequence \XINT_expr_op_#1, code common to expr/flexpr + \ifcsname XINT_expr_precedence_#1\endcsname + \expandafter\xint_afterfi\expandafter + {\csname XINT_expr_precedence_#1\endcsname #1}% + \else + \XINT_expr_unexpectedtoken + \expandafter\XINT_expr_getop + \fi +}% +% \end{macrocode} +% \subsection{Parentheses} +% \lverb|1.09a removes some doubling of \romannumeral-`\0 from 1.08b +% which served no useful purpose here (I think...). | +% \begin{macrocode} +\def\XINT_tmpa #1#2#3#4#5% +{% + \def#1##1% + {% + \xint_UDsignfork + ##1{\expandafter#1\romannumeral-`0#3}% + -{#2##1}% + \krof + }% + \def#2##1##2% + {% + \ifcase ##1\expandafter #4% + \or\xint_afterfi{% + \XINT_expr_extra_closing_paren + \expandafter #1\romannumeral-`0\XINT_expr_getop + }% + \else + \xint_afterfi{\expandafter#1\romannumeral-`0\csname XINT_#5_op_##2\endcsname }% + \fi + }% +}% +\xintFor #1 in {expr,flexpr,iiexpr} \do {% +\expandafter\XINT_tmpa + \csname XINT_#1_until_end_a\expandafter\endcsname + \csname XINT_#1_until_end_b\expandafter\endcsname + \csname XINT_#1_op_-vi\expandafter\endcsname + \csname XINT_#1_done\endcsname + {#1}% +}% +\def\XINT_expr_extra_closing_paren {\xintError:removed }% +\def\XINT_tmpa #1#2#3#4#5#6% +{% + \def #1{\expandafter #3\romannumeral-`0\XINT_expr_getnext }% + \let #2#1% + \def #3##1{\xint_UDsignfork + ##1{\expandafter #3\romannumeral-`0#5}% + -{#4##1}% + \krof }% + \def #4##1##2% + {% + \ifcase ##1\expandafter \XINT_expr_missing_cparen + \or \expandafter \XINT_expr_getop + \else \xint_afterfi + {\expandafter #3\romannumeral-`0\csname XINT_#6_op_##2\endcsname }% + \fi + }% +}% +\xintFor #1 in {expr,flexpr,iiexpr} \do {% +\expandafter\XINT_tmpa + \csname XINT_#1_op_(\expandafter\endcsname + \csname XINT_#1_oparen\expandafter\endcsname + \csname XINT_#1_until_)_a\expandafter\endcsname + \csname XINT_#1_until_)_b\expandafter\endcsname + \csname XINT_#1_op_-vi\endcsname + {#1}% +}% +\def\XINT_expr_missing_cparen {\xintError:inserted \xint_c_ \XINT_expr_done }% +\expandafter\let\csname XINT_expr_precedence_)\endcsname \xint_c_i +\expandafter\let\csname XINT_flexpr_precedence_)\endcsname \xint_c_i +\expandafter\let\csname XINT_iiexpr_precedence_)\endcsname \xint_c_i +\expandafter\let\csname XINT_expr_op_)\endcsname \XINT_expr_getop +\expandafter\let\csname XINT_flexpr_op_)\endcsname\XINT_expr_getop +\expandafter\let\csname XINT_iiexpr_op_)\endcsname\XINT_expr_getop +% \end{macrocode} +% \subsection{The \csh{XINT\_expr\_until\_<op>} macros for boolean operators, +% comparison operators, arithmetic operators, scientfic notation.} +% \lverb|Extended in 1.09a with comparison and boolean operators. +% 1.09i adds \xintiiexpr and incorporates optional part [\XINTdigits] for a tiny +% bit faster float operations now already equipped with their optional +% argument|. +% \begin{macrocode} +\def\XINT_tmpb #1#2#3#4#5#6%#7% +{% + \expandafter\XINT_tmpc + \csname XINT_#1_op_#3\expandafter\endcsname + \csname XINT_#1_until_#3_a\expandafter\endcsname + \csname XINT_#1_until_#3_b\expandafter\endcsname + \csname XINT_#1_op_-#5\expandafter\endcsname + \csname xint_c_#4\expandafter\endcsname + \csname #2#6\expandafter\endcsname + \csname XINT_expr_precedence_#3\endcsname {#1}%{#7}% +}% +\def\XINT_tmpc #1#2#3#4#5#6#7#8#9% +{% + \def #1##1% \XINT_expr_op_<op> + {% keep value, get next number and operator, then do until + \expandafter #2\expandafter ##1% + \romannumeral-`0\expandafter\XINT_expr_getnext + }% + \def #2##1##2% \XINT_expr_until_<op>_a + {\xint_UDsignfork + ##2{\expandafter #2\expandafter ##1\romannumeral-`0#4}% + -{#3##1##2}% + \krof }% + \def #3##1##2##3##4% \XINT_expr_until_<op>_b + {% either execute next operation now, or first do next (possibly unary) + \ifnum ##2>#5% + \xint_afterfi {\expandafter #2\expandafter ##1\romannumeral-`0% + \csname XINT_#8_op_##3\endcsname {##4}}% + \else + \xint_afterfi + {\expandafter ##2\expandafter ##3% + \csname .=#6#9{\XINT_expr_unlock ##1}{\XINT_expr_unlock ##4}\endcsname }% + \fi + }% + \let #7#5% +}% +\def\XINT_tmpa #1{\XINT_tmpb {expr}{xint}#1{}}% +\xintApplyInline {\XINT_tmpa }{% + {|{iii}{vi}{OR}}% + {&{iv}{vi}{AND}}% + {<{v}{vi}{Lt}}% + {>{v}{vi}{Gt}}% + {={v}{vi}{Eq}}% + {+{vi}{vi}{Add}}% + {-{vi}{vi}{Sub}}% + {*{vii}{vii}{Mul}}% + {/{vii}{vii}{Div}}% + {^{viii}{viii}{Pow}}% + {e{ix}{ix}{fE}}% + {E{ix}{ix}{fE}}% +}% +\def\XINT_tmpa #1{\XINT_tmpb {flexpr}{xint}#1{}}% +\xintApplyInline {\XINT_tmpa }{% + {|{iii}{vi}{OR}}% + {&{iv}{vi}{AND}}% + {<{v}{vi}{Lt}}% + {>{v}{vi}{Gt}}% + {={v}{vi}{Eq}}% +}% +\def\XINT_tmpa #1{\XINT_tmpb {flexpr}{XINTinFloat}#1{[\XINTdigits]}}% +\xintApplyInline {\XINT_tmpa }{% + {+{vi}{vi}{Add}}% + {-{vi}{vi}{Sub}}% + {*{vii}{vii}{Mul}}% + {/{vii}{vii}{Div}}% + {^{viii}{viii}{Power}}% + {e{ix}{ix}{fE}}% + {E{ix}{ix}{fE}}% +}% +\def\XINT_tmpa #1{\XINT_tmpb {iiexpr}{xint}#1{}}% +\xintApplyInline {\XINT_tmpa }{% + {|{iii}{vi}{OR}}% + {&{iv}{vi}{AND}}% + {<{v}{vi}{Lt}}% + {>{v}{vi}{Gt}}% + {={v}{vi}{Eq}}% + {+{vi}{vi}{iiAdd}}% + {-{vi}{vi}{iiSub}}% + {*{vii}{vii}{iiMul}}% + {/{vii}{vii}{iiQuo}}% + {^{viii}{viii}{iiPow}}% + {e{ix}{ix}{iE}}% + {E{ix}{ix}{iE}}% +}% +% \end{macrocode} +% \subsection{The comma as binary operator} +% \lverb|New with 1.09a.| +% \begin{macrocode} +\def\XINT_tmpa #1#2#3#4#5#6% +{% + \def #1##1% \XINT_expr_op_,_a + {% + \expandafter #2\expandafter ##1\romannumeral-`0\XINT_expr_getnext + }% + \def #2##1##2% \XINT_expr_until_,_a + {\xint_UDsignfork + ##2{\expandafter #2\expandafter ##1\romannumeral-`0#4}% + -{#3##1##2}% + \krof }% + \def #3##1##2##3##4% \XINT_expr_until_,_b + {% + \ifnum ##2>\xint_c_ii + \xint_afterfi {\expandafter #2\expandafter ##1\romannumeral-`0% + \csname XINT_#6_op_##3\endcsname {##4}}% + \else + \xint_afterfi + {\expandafter ##2\expandafter ##3% + \csname .=\XINT_expr_unlock ##1,\XINT_expr_unlock ##4\endcsname }% + \fi + }% + \let #5\xint_c_ii +}% +\xintFor #1 in {expr,flexpr,iiexpr} \do {% +\expandafter\XINT_tmpa + \csname XINT_#1_op_,\expandafter\endcsname + \csname XINT_#1_until_,_a\expandafter\endcsname + \csname XINT_#1_until_,_b\expandafter\endcsname + \csname XINT_#1_op_-vi\expandafter\endcsname + \csname XINT_expr_precedence_,\endcsname {#1}% +}% +% \end{macrocode} +% \subsection{\csh{XINT\_expr\_op\_-<level>}: minus as prefix inherits its +% precedence level} +% \lverb|1.09i: \xintiiexpr must use \xintiiOpp (or at least \xintiOpp, but that +% would be a waste; however impacts round and trunc as I allow them).| +% \begin{macrocode} +\def\XINT_tmpa #1#2#3% +{% + \expandafter\XINT_tmpb + \csname XINT_#1_op_-#3\expandafter\endcsname + \csname XINT_#1_until_-#3_a\expandafter\endcsname + \csname XINT_#1_until_-#3_b\expandafter\endcsname + \csname xint_c_#3\endcsname {#1}#2% +}% +\def\XINT_tmpb #1#2#3#4#5#6% +{% + \def #1% \XINT_expr_op_-<level> + {% get next number+operator then switch to _until macro + \expandafter #2\romannumeral-`0\XINT_expr_getnext + }% + \def #2##1% \XINT_expr_until_-<l>_a + {\xint_UDsignfork + ##1{\expandafter #2\romannumeral-`0#1}% + -{#3##1}% + \krof }% + \def #3##1##2##3% \XINT_expr_until_-<l>_b + {% _until tests precedence level with next op, executes now or postpones + \ifnum ##1>#4% + \xint_afterfi {\expandafter #2\romannumeral-`0% + \csname XINT_#5_op_##2\endcsname {##3}}% + \else + \xint_afterfi {\expandafter ##1\expandafter ##2% + \csname .=#6{\XINT_expr_unlock ##3}\endcsname }% + \fi + }% +}% +\xintApplyInline{\XINT_tmpa {expr}\xintOpp}{{vi}{vii}{viii}{ix}}% +\xintApplyInline{\XINT_tmpa {flexpr}\xintOpp}{{vi}{vii}{viii}{ix}}% +\xintApplyInline{\XINT_tmpa {iiexpr}\xintiiOpp}{{vi}{vii}{viii}{ix}}% +% \end{macrocode} +% \subsection{? as two-way conditional} +% \lverb|New with 1.09a. Modified in 1.09c to have less precedence than +% functions. Code is cleaner as it does not play tricks with _precedence. There +% is no associated until macro, because action is immediate once activated (only +% a previously scanned function can delay activation).| +% \begin{macrocode} +\let\XINT_expr_precedence_? \xint_c_x +\def \XINT_expr_op_? #1#2#3% +{% + \xintifZero{\XINT_expr_unlock #1}% + {\XINT_expr_getnext #3}% + {\XINT_expr_getnext #2}% +}% +\let\XINT_flexpr_op_?\XINT_expr_op_? +\let\XINT_iiexpr_op_?\XINT_expr_op_? +% \end{macrocode} +% \subsection{: as three-way conditional} +% \lverb|New with 1.09a. Modified in 1.09c to have less precedence than +% functions. | +% \begin{macrocode} +\let\XINT_expr_precedence_: \xint_c_x +\def \XINT_expr_op_: #1#2#3#4% +{% + \xintifSgn {\XINT_expr_unlock #1}% + {\XINT_expr_getnext #2}% + {\XINT_expr_getnext #3}% + {\XINT_expr_getnext #4}% +}% +\let\XINT_flexpr_op_:\XINT_expr_op_: +\let\XINT_iiexpr_op_:\XINT_expr_op_: +% \end{macrocode} +% \subsection{! as postfix factorial operator} +% \lverb|The factorial is currently the exact one, there is no float version. +% Starting with 1.09c, it has lower priority than functions, it is not executed +% immediately anymore. The code is cleaner and does not abuse _precedence, but +% does assign it a true level. There is no until macro, because the factorial +% acts on what precedes it.| +% \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_iiexpr_op_! #1{\expandafter\XINT_expr_getop + \csname .=\xintiFac{\XINT_expr_unlock #1}\endcsname }% +% \end{macrocode} +% \subsection{Functions} +% \lverb|New with 1.09a. Names of ..Float..:csv macros have been changed in +% 1.09h | +% \begin{macrocode} +\def\XINT_tmpa #1#2#3#4{% + \def #1##1% + {% + \ifcsname XINT_expr_onlitteral_##1\endcsname + \expandafter\XINT_expr_funcoflitteral + \else + \expandafter #2% + \fi {##1}% + }% + \def #2##1% + {% + \ifcsname XINT_#4_func_##1\endcsname + \xint_afterfi + {\expandafter\expandafter\csname XINT_#4_func_##1\endcsname}% + \else \csname xintError:unknown `##1\string'\endcsname + \xint_afterfi{\expandafter\XINT_expr_func_unknown}% + \fi + \romannumeral-`0#3% + }% +}% +\xintFor #1 in {expr,flexpr,iiexpr} \do {% + \expandafter\XINT_tmpa + \csname XINT_#1_op_@\expandafter\endcsname + \csname XINT_#1_op_@@\expandafter\endcsname + \csname XINT_#1_oparen\endcsname {#1}% +}% +\def\XINT_expr_funcoflitteral #1% +{% + \expandafter\expandafter\csname XINT_expr_onlitteral_#1\endcsname + \romannumeral-`0\XINT_expr_scanfunc +}% +\def\XINT_expr_onlitteral_bool #1#2#3{\expandafter\XINT_expr_getop + \csname .=\xintBool{#3}\endcsname }% +\def\XINT_expr_onlitteral_togl #1#2#3{\expandafter\XINT_expr_getop + \csname .=\xintToggle{#3}\endcsname }% +\def\XINT_expr_func_unknown #1#2#3% 1.09i removes [0], because \xintiiexpr + {\expandafter #1\expandafter #2\csname .=0\endcsname }% +\def\XINT_expr_func_reduce #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintIrr {\XINT_expr_unlock #3}\endcsname +}% +\let\XINT_flexpr_func_reduce\XINT_expr_func_reduce +% \XINT_iiexpr_func_reduce not defined +\def\XINT_expr_func_frac #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintTFrac {\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_flexpr_func_frac #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\XINTinFloatFrac [\XINTdigits]{\XINT_expr_unlock #3}\endcsname +}% +% \XINT_iiexpr_func_frac not defined +\def\XINT_expr_func_sqr #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintSqr {\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_flexpr_func_sqr #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\XINTinFloatMul [\XINTdigits]% + {\XINT_expr_unlock #3}{\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_iiexpr_func_sqr #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintiiSqr {\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_expr_func_abs #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintAbs {\XINT_expr_unlock #3}\endcsname +}% +\let\XINT_flexpr_func_abs\XINT_expr_func_abs +\def\XINT_iiexpr_func_abs #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintiiAbs {\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_expr_func_sgn #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintSgn {\XINT_expr_unlock #3}\endcsname +}% +\let\XINT_flexpr_func_sgn\XINT_expr_func_sgn +\def\XINT_iiexpr_func_sgn #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintiiSgn {\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_expr_func_floor #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintFloor {\XINT_expr_unlock #3}\endcsname +}% +\let\XINT_flexpr_func_floor\XINT_expr_func_floor +\let\XINT_iiexpr_func_floor\XINT_expr_func_floor +\def\XINT_expr_func_ceil #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintCeil {\XINT_expr_unlock #3}\endcsname +}% +\let\XINT_flexpr_func_ceil\XINT_expr_func_ceil +\let\XINT_iiexpr_func_ceil\XINT_expr_func_ceil +\def\XINT_expr_twoargs #1,#2,{{#1}{#2}}% +\def\XINT_expr_func_quo #1#2#3% +{% + \expandafter #1\expandafter #2\csname .=% + \expandafter\expandafter\expandafter\xintQuo + \expandafter\XINT_expr_twoargs + \romannumeral-`0\XINT_expr_unlock #3,\endcsname +}% +\let\XINT_flexpr_func_quo\XINT_expr_func_quo +\def\XINT_iiexpr_func_quo #1#2#3% +{% + \expandafter #1\expandafter #2\csname .=% + \expandafter\expandafter\expandafter\xintiiQuo + \expandafter\XINT_expr_twoargs + \romannumeral-`0\XINT_expr_unlock #3,\endcsname +}% +\def\XINT_expr_func_rem #1#2#3% +{% + \expandafter #1\expandafter #2\csname .=% + \expandafter\expandafter\expandafter\xintRem + \expandafter\XINT_expr_twoargs + \romannumeral-`0\XINT_expr_unlock #3,\endcsname +}% +\let\XINT_flexpr_func_rem\XINT_expr_func_rem +\def\XINT_iiexpr_func_rem #1#2#3% +{% + \expandafter #1\expandafter #2\csname .=% + \expandafter\expandafter\expandafter\xintiiRem + \expandafter\XINT_expr_twoargs + \romannumeral-`0\XINT_expr_unlock #3,\endcsname +}% +\def\XINT_expr_oneortwo #1#2#3,#4,#5.% +{% + \if\relax#5\relax\expandafter\xint_firstoftwo\else + \expandafter\xint_secondoftwo\fi + {#1{0}}{#2{\xintNum {#4}}}{#3}% +}% +\def\XINT_expr_func_round #1#2#3% +{% + \expandafter #1\expandafter #2\csname .=% + \expandafter\XINT_expr_oneortwo + \expandafter\xintiRound\expandafter\xintRound + \romannumeral-`0\XINT_expr_unlock #3,,.\endcsname +}% +\let\XINT_flexpr_func_round\XINT_expr_func_round +\def\XINT_iiexpr_oneortwo #1#2,#3,#4.% +{% + \if\relax#4\relax\expandafter\xint_firstoftwo\else + \expandafter\xint_secondoftwo\fi + {#1{0}}{#1{#3}}{#2}% +}% +\def\XINT_iiexpr_func_round #1#2#3% +{% + \expandafter #1\expandafter #2\csname .=% + \expandafter\XINT_iiexpr_oneortwo\expandafter\xintiRound + \romannumeral-`0\XINT_expr_unlock #3,,.\endcsname +}% +\def\XINT_expr_func_trunc #1#2#3% +{% + \expandafter #1\expandafter #2\csname .=% + \expandafter\XINT_expr_oneortwo + \expandafter\xintiTrunc\expandafter\xintTrunc + \romannumeral-`0\XINT_expr_unlock #3,,.\endcsname +}% +\let\XINT_flexpr_func_trunc\XINT_expr_func_trunc +\def\XINT_iiexpr_func_trunc #1#2#3% +{% + \expandafter #1\expandafter #2\csname .=% + \expandafter\XINT_iiexpr_oneortwo\expandafter\xintiTrunc + \romannumeral-`0\XINT_expr_unlock #3,,.\endcsname +}% +\def\XINT_expr_argandopt #1,#2,#3.% +{% + \if\relax#3\relax\expandafter\xint_firstoftwo\else + \expandafter\xint_secondoftwo\fi + {[\XINTdigits]}{[\xintNum {#2}]}{#1}% +}% +\def\XINT_expr_func_float #1#2#3% +{% + \expandafter #1\expandafter #2\csname .=% + \expandafter\XINTinFloat + \romannumeral-`0\expandafter\XINT_expr_argandopt + \romannumeral-`0\XINT_expr_unlock #3,,.\endcsname +}% +\let\XINT_flexpr_func_float\XINT_expr_func_float +% \XINT_iiexpr_func_float not defined +\def\XINT_expr_func_sqrt #1#2#3% +{% + \expandafter #1\expandafter #2\csname .=% + \expandafter\XINTinFloatSqrt + \romannumeral-`0\expandafter\XINT_expr_argandopt + \romannumeral-`0\XINT_expr_unlock #3,,.\endcsname +}% +\let\XINT_flexpr_func_sqrt\XINT_expr_func_sqrt +\def\XINT_iiexpr_func_sqrt #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintiSqrt {\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_expr_func_gcd #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintGCDof:csv{\XINT_expr_unlock #3}\endcsname +}% +\let\XINT_flexpr_func_gcd\XINT_expr_func_gcd +\let\XINT_iiexpr_func_gcd\XINT_expr_func_gcd +\def\XINT_expr_func_lcm #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintLCMof:csv{\XINT_expr_unlock #3}\endcsname +}% +\let\XINT_flexpr_func_lcm\XINT_expr_func_lcm +\let\XINT_iiexpr_func_lcm\XINT_expr_func_lcm +\def\XINT_expr_func_max #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintMaxof:csv{\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_iiexpr_func_max #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintiMaxof:csv{\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_flexpr_func_max #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\XINTinFloatMaxof:csv{\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_expr_func_min #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintMinof:csv{\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_iiexpr_func_min #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintiMinof:csv{\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_flexpr_func_min #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\XINTinFloatMinof:csv{\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_expr_func_sum #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintSum:csv{\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_flexpr_func_sum #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\XINTinFloatSum:csv{\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_iiexpr_func_sum #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintiiSum:csv{\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_expr_func_prd #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintPrd:csv{\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_flexpr_func_prd #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\XINTinFloatPrd:csv{\XINT_expr_unlock #3}\endcsname +}% +\def\XINT_iiexpr_func_prd #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintiiPrd:csv{\XINT_expr_unlock #3}\endcsname +}% +\let\XINT_expr_func_add\XINT_expr_func_sum +\let\XINT_expr_func_mul\XINT_expr_func_prd +\let\XINT_flexpr_func_add\XINT_flexpr_func_sum +\let\XINT_flexpr_func_mul\XINT_flexpr_func_prd +\let\XINT_iiexpr_func_add\XINT_iiexpr_func_sum +\let\XINT_iiexpr_func_mul\XINT_iiexpr_func_prd +\def\XINT_expr_func_? #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintIsNotZero {\XINT_expr_unlock #3}\endcsname +}% +\let\XINT_flexpr_func_? \XINT_expr_func_? +\let\XINT_iiexpr_func_? \XINT_expr_func_? +\def\XINT_expr_func_! #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintIsZero {\XINT_expr_unlock #3}\endcsname +}% +\let\XINT_flexpr_func_! \XINT_expr_func_! +\let\XINT_iiexpr_func_! \XINT_expr_func_! +\def\XINT_expr_func_not #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintIsZero {\XINT_expr_unlock #3}\endcsname +}% +\let\XINT_flexpr_func_not \XINT_expr_func_not +\let\XINT_iiexpr_func_not \XINT_expr_func_not +\def\XINT_expr_func_all #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintANDof:csv{\XINT_expr_unlock #3}\endcsname +}% +\let\XINT_flexpr_func_all\XINT_expr_func_all +\let\XINT_iiexpr_func_all\XINT_expr_func_all +\def\XINT_expr_func_any #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintORof:csv{\XINT_expr_unlock #3}\endcsname +}% +\let\XINT_flexpr_func_any\XINT_expr_func_any +\let\XINT_iiexpr_func_any\XINT_expr_func_any +\def\XINT_expr_func_xor #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\xintXORof:csv{\XINT_expr_unlock #3}\endcsname +}% +\let\XINT_flexpr_func_xor\XINT_expr_func_xor +\let\XINT_iiexpr_func_xor\XINT_expr_func_xor +\def\xintifNotZero:: #1,#2,#3,{\xintifNotZero{#1}{#2}{#3}}% +\def\XINT_expr_func_if #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\expandafter\xintifNotZero:: + \romannumeral-`0\XINT_expr_unlock #3,\endcsname +}% +\let\XINT_flexpr_func_if\XINT_expr_func_if +\let\XINT_iiexpr_func_if\XINT_expr_func_if +\def\xintifSgn:: #1,#2,#3,#4,{\xintifSgn{#1}{#2}{#3}{#4}}% +\def\XINT_expr_func_ifsgn #1#2#3% +{% + \expandafter #1\expandafter #2\csname + .=\expandafter\xintifSgn:: + \romannumeral-`0\XINT_expr_unlock #3,\endcsname +}% +\let\XINT_flexpr_func_ifsgn\XINT_expr_func_ifsgn +\let\XINT_iiexpr_func_ifsgn\XINT_expr_func_ifsgn +% \end{macrocode} +% \subsection{\csh{xintNewExpr}, \csh{xintNewFloatExpr}\dots} +% \lverb|& +% Rewritten in 1.09a. Now, the parameters of the formula are entered in the +% usual way by the user, with # not _. And _ is assigned to make macros +% not expand. This way, : is freed, as we now need it for the ternary operator. +% (on numeric data; if use with macro parameters, should be coded with the +% functionn ifsgn , rather) +% +% Code unified in 1.09c, and \xintNewNumExpr, \xintNewBoolExpr added. 1.09i +% renames \xintNewNumExpr to \xintNewIExpr, and defines \xintNewIIExpr.| +% \begin{macrocode} +\def\XINT_newexpr_print #1{\ifnum\xintNthElt{0}{#1}>1 + \expandafter\xint_firstoftwo + \else + \expandafter\xint_secondoftwo + \fi + {_xintListWithSep,{#1}}{\xint_firstofone#1}}% +\xintForpair #1#2 in {(fl,Float),(i,iRound0),(bool,IsTrue)}\do {% + \expandafter\def\csname XINT_new#1expr_print\endcsname + ##1{\ifnum\xintNthElt{0}{##1}>1 + \expandafter\xint_firstoftwo + \else + \expandafter\xint_secondoftwo + \fi + {_xintListWithSep,{\xintApply{_xint#2}{##1}}} + {_xint#2##1}}}% +\toks0 {}% +\xintFor #1 in {Bool,Toggle,Floor,Ceil,iRound,Round,iTrunc,Trunc,TFrac,% + Lt,Gt,Eq,AND,OR,IsNotZero,IsZero,ifNotZero,ifSgn,% + Irr,Num,Abs,Sgn,Opp,Quo,Rem,Add,Sub,Mul,Sqr,Div,Pow,Fac,fE,iSqrt,% + iiAdd,iiSub,iiMul,iiSqr,iiPow,iiQuo,iiRem,iiSgn,iiAbs,iiOpp,iE}\do + {\toks0 + \expandafter{\the\toks0\expandafter\def\csname xint#1\endcsname {_xint#1}}}% +\xintFor #1 in {,Sqrt,Add,Sub,Mul,Div,Power,fE,Frac}\do + {\toks0 + \expandafter{\the\toks0\expandafter\def\csname XINTinFloat#1\endcsname + {_XINTinFloat#1}}}% +\xintFor #1 in {GCDof,LCMof,Maxof,Minof,ANDof,ORof,XORof,Sum,Prd,% + iMaxof,iMinof,iiSum,iiPrd}\do + {\toks0 + \expandafter{\the\toks0\expandafter\def\csname xint#1:csv\endcsname + ####1{_xint#1{\xintCSVtoListNonStripped {####1}}}}}% +\xintFor #1 in {Maxof,Minof,Sum,Prd}\do + {\toks0 + \expandafter{\the\toks0\expandafter\def\csname XINTinFloat#1:csv\endcsname + ####1{_XINTinFloat#1{\xintCSVtoListNonStripped {####1}}}}}% +\expandafter\def\expandafter\XINT_expr_protect\expandafter{\the\toks0 + \def\XINTdigits {_XINTdigits}% + \def\XINT_expr_print ##1{\expandafter\XINT_newexpr_print\expandafter + {\romannumeral0\xintcsvtolistnonstripped{\XINT_expr_unlock ##1}}}% + \def\XINT_flexpr_print ##1{\expandafter\XINT_newflexpr_print\expandafter + {\romannumeral0\xintcsvtolistnonstripped{\XINT_expr_unlock ##1}}}% + \def\XINT_iexpr_print ##1{\expandafter\XINT_newiexpr_print\expandafter + {\romannumeral0\xintcsvtolistnonstripped{\XINT_expr_unlock ##1}}}% + \def\XINT_boolexpr_print ##1{\expandafter\XINT_newboolexpr_print\expandafter + {\romannumeral0\xintcsvtolistnonstripped{\XINT_expr_unlock ##1}}}% +}% +\toks0 {}% +\def\xintNewExpr {\xint_NewExpr\xinttheexpr }% +\def\xintNewFloatExpr {\xint_NewExpr\xintthefloatexpr }% +\def\xintNewIExpr {\xint_NewExpr\xinttheiexpr }% +\let\xintNewNumExpr\xintNewIExpr +\def\xintNewIIExpr {\xint_NewExpr\xinttheiiexpr }% +\def\xintNewBoolExpr {\xint_NewExpr\xinttheboolexpr }% +% \end{macrocode} +% \lverb|1.09i has added \escapechar 92, as \meaning is used in \XINT_NewExpr, +% and a non existent escape-char would be a problem with \scantokens. Also +% \catcode32 is set to 10 in \xintexprSafeCatcodes for being extra-safe.| +% \begin{macrocode} +\def\xint_NewExpr #1#2[#3]% +{% + \begingroup + \ifcase #3\relax + \toks0 {\xdef #2}% + \or \toks0 {\xdef #2##1}% + \or \toks0 {\xdef #2##1##2}% + \or \toks0 {\xdef #2##1##2##3}% + \or \toks0 {\xdef #2##1##2##3##4}% + \or \toks0 {\xdef #2##1##2##3##4##5}% + \or \toks0 {\xdef #2##1##2##3##4##5##6}% + \or \toks0 {\xdef #2##1##2##3##4##5##6##7}% + \or \toks0 {\xdef #2##1##2##3##4##5##6##7##8}% + \or \toks0 {\xdef #2##1##2##3##4##5##6##7##8##9}% + \fi + \xintexprSafeCatcodes + \escapechar92 + \XINT_NewExpr #1% +}% +\catcode`* 13 +\def\XINT_NewExpr #1#2% +{% + \def\XINT_tmpa ##1##2##3##4##5##6##7##8##9{#2}% + \XINT_expr_protect + \lccode`*=`_ \lowercase {\def*}{!noexpand!}% + \catcode`_ 13 \catcode`: 11 %\endlinechar -1 %not sure why I had that, \par? + \everyeof {\noexpand }% + \edef\XINT_tmpb ##1##2##3##4##5##6##7##8##9% + {\scantokens + \expandafter{\romannumeral-`0#1% + \XINT_tmpa {####1}{####2}{####3}% + {####4}{####5}{####6}% + {####7}{####8}{####9}% + \relax}}% + \lccode`*=`\$ \lowercase {\def*}{####}% + \catcode`\$ 13 \catcode`! 0 \catcode`_ 11 % + \the\toks0 + {\scantokens\expandafter{\expandafter + \XINT_newexpr_setprefix\meaning\XINT_tmpb}}% + \endgroup +}% +\let\xintexprRestoreCatcodes\empty +\def\xintexprSafeCatcodes +{% for end user. + \edef\xintexprRestoreCatcodes {% + \catcode34=\the\catcode34 % " + \catcode63=\the\catcode63 % ? + \catcode124=\the\catcode124 % | + \catcode38=\the\catcode38 % & + \catcode33=\the\catcode33 % ! + \catcode93=\the\catcode93 % ] + \catcode91=\the\catcode91 % [ + \catcode94=\the\catcode94 % ^ + \catcode95=\the\catcode95 % _ + \catcode47=\the\catcode47 % / + \catcode41=\the\catcode41 % ) + \catcode40=\the\catcode40 % ( + \catcode42=\the\catcode42 % * + \catcode43=\the\catcode43 % + + \catcode62=\the\catcode62 % > + \catcode60=\the\catcode60 % < + \catcode58=\the\catcode58 % : + \catcode46=\the\catcode46 % . + \catcode45=\the\catcode45 % - + \catcode44=\the\catcode44 % , + \catcode61=\the\catcode61 % = + \catcode32=\the\catcode32\relax % space + }% it's hard to know where to stop... + \catcode34=12 % " + \catcode63=12 % ? + \catcode124=12 % | + \catcode38=4 % & + \catcode33=12 % ! + \catcode93=12 % ] + \catcode91=12 % [ + \catcode94=7 % ^ + \catcode95=8 % _ + \catcode47=12 % / + \catcode41=12 % ) + \catcode40=12 % ( + \catcode42=12 % * + \catcode43=12 % + + \catcode62=12 % > + \catcode60=12 % < + \catcode58=12 % : + \catcode46=12 % . + \catcode45=12 % - + \catcode44=12 % , + \catcode61=12 % = + \catcode32=10 % space +}% +\let\XINT_tmpa\relax \let\XINT_tmpb\relax \let\XINT_tmpc\relax +\XINT_restorecatcodes_endinput% +% \end{macrocode} +% \DeleteShortVerb{\|} +% \MakePercentComment +%</xintexpr> +%<*dtx> +\StoreCodelineNo {xintexpr} + +\def\mymacro #1{\mymacroaux #1} +\def\mymacroaux #1#2{\strut \texttt{#1:}& \digitstt{ #2.}\tabularnewline } +\indent +\begin{tabular}[t]{r@{}r} +\xintApplyInline\mymacro\storedlinecounts +\end{tabular} +\def\mymacroaux #1#2{#2}% +% +\parbox[t]{10cm}{Total number of code lines: + \digitstt{\xintiiSum{\xintApply\mymacro\storedlinecounts}}. Each + package starts + with circa \digitstt{80} lines dealing with catcodes, package identification + and reloading management, also for Plain \TeX\strut. Version + \texttt{\xintversion} of \texttt{\xintdate}.\par} + + +\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 + Lower-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 + Digits \0\1\2\3\4\5\6\7\8\9 + Exclamation \! Double quote \" Hash (number) \# + Dollar \$ Percent \% Ampersand \& + Acute accent \' Left paren \( Right paren \) + Asterisk \* Plus \+ Comma \, + Minus \- Point \. Solidus \/ + Colon \: Semicolon \; Less than \< + Equals \= Greater than \> Question mark \? + Commercial at \@ Left bracket \[ Backslash \\ + Right bracket \] Circumflex \^ Underscore \_ + Grave accent \` Left brace \{ Vertical bar \| + Right brace \} Tilde \~} +\CheckSum {21378} +\makeatletter\check@checksum\makeatother +\Finale +%% End of file xint.dtx diff --git a/Master/texmf-dist/doc/generic/xint/xint.pdf b/Master/texmf-dist/doc/generic/xint/xint.pdf Binary files differindex aaa1dc0b610..4b2f17f993c 100644 --- a/Master/texmf-dist/doc/generic/xint/xint.pdf +++ b/Master/texmf-dist/doc/generic/xint/xint.pdf |