diff options
author | Karl Berry <karl@freefriends.org> | 2022-05-19 20:11:06 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2022-05-19 20:11:06 +0000 |
commit | b48cdc7688e6483099499c0e3ec927b258e0f569 (patch) | |
tree | 9114384a0594ecf94a373504dd393617954608a2 /Master/texmf-dist/source/generic/xint | |
parent | b9769098c5fcee8329d370e153f3b332f137850b (diff) |
xint (19may22)
git-svn-id: svn://tug.org/texlive/trunk@63338 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/generic/xint')
-rw-r--r-- | Master/texmf-dist/source/generic/xint/xint.dtx | 3854 |
1 files changed, 2278 insertions, 1576 deletions
diff --git a/Master/texmf-dist/source/generic/xint/xint.dtx b/Master/texmf-dist/source/generic/xint/xint.dtx index a1ad014bc22..213000e7521 100644 --- a/Master/texmf-dist/source/generic/xint/xint.dtx +++ b/Master/texmf-dist/source/generic/xint/xint.dtx @@ -3,28 +3,28 @@ % Extract all files via "etex xint.dtx" and do "make help" % or follow instructions from extracted README.md. %<*dtx> -\def\xintdtxtimestamp {Time-stamp: <13-07-2021 at 21:50:14 CEST>} +\def\xintdtxtimestamp {Time-stamp: <18-05-2022 at 20:55:23 CEST>} %</dtx> %<*drv> %% --------------------------------------------------------------- -\def\xintdocdate {2021/07/13} -\def\xintbndldate{2021/07/13} -\def\xintbndlversion {1.4j} +\def\xintdocdate {2022/05/18} +\def\xintbndldate{2022/05/18} +\def\xintbndlversion {1.4k} %</drv> %<readme>% README %<changes>% CHANGE LOG -%<readme|changes>% xint 1.4j -%<readme|changes>% 2021/07/13 +%<readme|changes>% xint 1.4k +%<readme|changes>% 2022/05/18 %<readme|changes> -%<readme|changes> Source: xint.dtx 1.4j 2021/07/13 (doc 2021/07/13) +%<readme|changes> Source: xint.dtx 1.4k 2022/05/18 (doc 2022/05/18) %<readme|changes> Author: Jean-Francois Burnol %<readme|changes> Info: Expandable operations on big integers, decimals, fractions %<readme|changes> License: LPPL 1.3c %<readme|changes> %<*!readme&!changes&!dohtmlsh&!makefile> %% --------------------------------------------------------------- -%% The xint bundle 1.4j 2021/07/13 -%% Copyright (C) 2013-2021 by Jean-Francois Burnol +%% The xint bundle 1.4k 2022/05/18 +%% Copyright (C) 2013-2022 by Jean-Francois Burnol %<xintkernel>%% xintkernel: Paraphernalia for the xint packages %<xinttools>%% xinttools: Expandable and non-expandable utilities %<xintcore>%% xintcore: Expandable arithmetic on big integers @@ -128,7 +128,7 @@ is a functionality of all major TeX engines since TeXLive 2019. License ======= -Copyright (C) 2013-2021 by Jean-Francois Burnol +Copyright (C) 2013-2022 by Jean-Francois Burnol This Work may be distributed and/or modified under the conditions of the LaTeX Project Public License version 1.3c. @@ -152,6 +152,69 @@ See `xint.pdf` for contact information. %</readme>-------------------------------------------------------- %<*changes>------------------------------------------------------- +`1.4k (2022/05/18)` +---- + +### Breaking changes + + - **xintfrac**: the longstanding (but documented as undecided and + unstable) way of `\xintFloat` to output the zero value was `0.e0` and + it has now been modified into `0.0e0`. Customizable via + `\xintFloatZero`. + + - **xintfrac**/**xintexpr**: the behaviour of `\xintPFloat` (hence of + `\xintfloateval`) has again changed: when the output is an integer + (not using scientific notation) it does not get postfixed by `.0`. + This applies in particular for the zero value, now printed `0`. + Similarly, in the case of scientific notation with a single-digit + (trimmed) mantissa, no `.0` is used. + + Customizable via + `\xintPFloatIntSuffix`, `\xintPFloatLengthOneSuffix`, and + `\xintPFloatZero`. + + Also, `\xintPFloat` trims trailing zeros from the + full significand only if there are at least `4` of them, see + `\xintPFloatMinTrimmed`. + + - **xintfrac**/**xintexpr**: definition of `\xintFracToSci` migrated + from the former to the latter. + + - **xintexpr**: `\xintexpr{Safe,Restore}Catcodes` pairs now behave like + a "last in first out" stack. Check the `pdf` documentation for + details. + +### Bug fixes + + - **xintexpr**: the `\xintexpr{Safe,Restore}Catcodes` were documented + at user level, but also used by the package `\xintdefvar` or + `\xintdeffunc`. This could result in some bad interaction due to the + somewhat strange (but documented) behaviour of nested + `\xintexpr{Safe,Restore}Catcodes` (which has now been modified). + + - **xintexpr**: ever since `1.4`, `\xintdefufunc` (but not + `\xintdeffunc`) forgot to reset the catcodes to their status prior to + the sanitization done by the macro at the start of its execution. + +### New features + + - **xintfrac**: `\xintPFloatZero`, `\xintPFloatIntSuffix`, + `\xintPFloatLengthOneSuffix`, `\xintPFloatNoSciEmax`, + `\xintPFloatNoSciEmin` and `\xintPFloatMinTrimmed` customize the + output of `\xintPFloat`, hence also of `\xintfloateval` (and of + `\xinteval` when scientific notation was used in the expression). + Also added `\xintFloatZero`. + + - **xintfrac**: `\xintFloatToDecimal`. + + - **xintexpr**: `\xintFracToDecimal`, an alternative to + `\xintFracToSci` for the configuration of `\xintexprPrintOne`. + + - **xintexpr**: long awaited syntax `\xintieval[D]{...}` and + `\xintfloateval[Q]{...}` now implemented. The legacy syntax with + `\xintieval{[D]...}` and `\xintfloateval{[Q]...}` is kept for + backwards compatibility. + `1.4j (2021/07/13)` ---- @@ -2724,16 +2787,21 @@ cleanall: clean #! /bin/sh # <s>README.html and</s> CHANGES.html from <s>README.md and </s>CHANGES.md # tested with pandoc 1.13.1 +# updated 2022 for usage with pandoc 2.18 and its strange CSS obsessed by mobile devices # pandoc -o README.html -s --toc -V highlighting-css=' body{margin-left : 10%; margin-right : 15%; margin-top: 4ex; font-size: 12pt;} # pre {white-space: pre-wrap; } # code {white-space: pre-wrap; } # .mono {font-family: monospace;}' README.md -pandoc -o CHANGES.html -s --toc -V highlighting-css=' body{margin-left : 10%; margin-right : 15%; margin-top: 4ex; font-size: 12pt;} +pandoc -o CHANGES.html -s --toc -V highlighting-css=' body{margin: 0; margin-left : 10%; margin-right : 15%; margin-top: 4ex; font-size: 20px; font-family: serif; max-width: 100%; padding: 0; } pre {white-space: pre-wrap;} code {white-space: pre-wrap;} - #TOC {float: right; position: relative; top: 100px; margin-bottom: 100px;}' CHANGES.md + a:link { color: blue; } + a:visited { color: green; } + a:hover { text-decoration: underline; color: hotpink } + a:active { color: brown; } + #TOC {float: right; position: relative; top: 100px; margin-bottom: 100px; margin-left: 20px;}' CHANGES.md %</dohtmlsh>------------------------------------------------------ %<*drv>----------------------------------------------------------- @@ -2993,17 +3061,64 @@ pandoc -o CHANGES.html -s --toc -V highlighting-css=' body{margin-left : 10%; \usepackage[autolanguage,np]{numprint} \AtBeginDocument{\npthousandsep{,\hskip .5pt plus .1pt minus .1pt}} -\usepackage[dvipsnames]{xcolor} -\definecolor{joli}{RGB}{225,95,0} -\definecolor{JOLI}{RGB}{225,95,0} -\definecolor{BLUE}{RGB}{0,0,255} -\definecolor{niceone}{RGB}{38,128,192} -\definecolor{sedate}{RGB}{193,132,1} -\definecolor{saddlebrown}{rgb}{.545,.27,.075} -\definecolor{jfbrown}{RGB}{165,100,10}% - - - +\usepackage[dvipsnames,svgnames]{xcolor} +\definecolor{xintnamecolor}{RGB}{228,57,0} +\colorlet{XINTNAMECOLOR}{xintnamecolor} +\colorlet{xintnameimpcolor}{blue} +\colorlet{XINTNAMEIMPCOLOR}{xintnameimpcolor} +\definecolor{xintmanualurlcolor}{RGB}{38,128,192} +\colorlet{xintmanuallinkcolor}{blue} + + + + +% Colors for \verb and everbatim/everbatim* environments +% former legacy colors used in xint.pdf up to xint 1.4j (2021/07/13) +% (I should retrieve since when) +% \colorlet{verbcolor}{jfbrown} +% \colorlet{verbsoftwrapiconcolor}{blue} +% \colorlet{everbatimfgcolor}{Brown} +% \colorlet{everbatimbgcolor}{yellow!5} +% \colorlet{everbatimxfgcolor}{OrangeRed} + +% https://contrast-ratio.com/#rgb%28165%2C100%2C10%29-on-white +% says the contrast ratio on white is 4.74 and I do see the contrast +% is less strong than +% for the DarkBlue/Beige and Maroon/White combinations seen below +% \colorlet{verbcolor}{jfbrown} +% I will simply use also Maroon +\colorlet{verbcolor}{Maroon} +\colorlet{verbimpcolor}{Purple} +\colorlet{digitsttcolor}{Maroon} + +\colorlet{verbsoftwrapiconcolor}{DarkBlue} +\colorlet{everbatimfgcolor}{DarkBlue} +% +% According to +% https://contrast-ratio.com/#rgb%2811%2C35%2C139%29-on-rgb%28245%2C244%2C220%29 +% the DarkBlue on Beige +% gives a contrast-ratio of 11.58 which confirmed my intuition it is not bad +% "Passes AAA level for any size text and AA for user interface components and graphical objects" +% +% memo: with Apple ColorPicker it seems one needs to select "sRVB" (I guess +% "sRGB" in English) for values matching xcolor RGB input or the above html +% page rgb(R,G,B) input, also this did not work +% 100%, most probably due to the window transparency by default on my mac? +\colorlet{everbatimbgcolor}{Beige} + +% https://contrast-ratio.com/#rgb%28128%2C31%2C19%29-on-white +% gives 9.89 contrast ratio which is a bit less but still AAA +\colorlet{everbatimxfgcolor}{Maroon} + + +% colors for margin notes +\colorlet{marginnotecolor}{PineGreen} +\colorlet{marginwarningcolor}{Red} + +% colors for toc +\colorlet{tocsectioncolor}{cyan} +\colorlet{tocsectionimpcolor}{RoyalPurple} +\colorlet{tocbundlesectioncolor}{xintnamecolor} \usepackage{eso-pic}% après xcolor sinon Option clash for package xcolor. @@ -3042,8 +3157,8 @@ pandoc -o CHANGES.html -s --toc -V highlighting-css=' body{margin-left : 10%; linktoc=all,% breaklinks=true,% colorlinks=true,% -urlcolor=niceone,% -linkcolor=blue,% +urlcolor=xintmanualurlcolor,% +linkcolor=xintmanuallinkcolor,% pdfauthor={Jean-Fran\c cois Burnol},% pdftitle={The xintexpr and allied packages},% pdfsubject={Arithmetic with TeX},% @@ -3068,95 +3183,8 @@ pdfpagemode=UseNone,% -\DeclareFontFamily{T1}{newtxttb}{\hyphenchar\font\m@ne} - -\DeclareFontShape{T1}{newtxttb}{m}{n}{ - <-> s*[\newtxtt@scale]newtxttbq -}{} -\DeclareFontShape{T1}{newtxttb}{b}{n}{ - <-> s*[\newtxtt@scale]newtxbttbq -}{} -\DeclareFontShape{T1}{newtxttb}{bx}{n}{ - <-> ssub * newtxttb/b/n -}{} -\DeclareFontShape{T1}{newtxttb}{m}{sl}{ - <-> s*[\newtxtt@scale]newtxttslbq -}{} -\DeclareFontShape{T1}{newtxttb}{m}{it}{ - <-> ssub * newtxttb/m/sl -}{} - -% Ajouté le 9 mars 2016 - -\DeclareFontShape{T1}{newtxttb}{m}{sc}{%cap & small cap - <-> s*[\newtxtt@scale]newtxttscbq -}{} -\DeclareFontShape{T1}{newtxttb}{b}{sc}{%bold cap & small cap - <-> s*[\newtxtt@scale]newtxbttscbq -}{} -\DeclareFontShape{T1}{newtxttb}{b}{sl}{%bold slanted - <-> s*[\newtxtt@scale]newtxbttslbq -}{} -\DeclareFontShape{T1}{newtxttb}{b}{it}{%bold italic - <-> ssub * newtxttb/b/sl% -}{} -\DeclareFontShape{T1}{newtxttb}{bx}{sc}{%bold extended cap & small cap - <-> ssub * newtxttb/b/sc% -}{} -\DeclareFontShape{T1}{newtxttb}{bx}{sl}{%bold extended slanted - <-> ssub * newtxttb/b/sl% -}{} -\DeclareFontShape{T1}{newtxttb}{bx}{it}{%bold extended italic - <-> ssub * newtxttb/b/sl% -}{} - -% Ajouté le 9 mars 2016 -\DeclareEncodingSubset{TS1}{newtxttb}{0} -\DeclareFontFamily{TS1}{newtxttb}{\hyphenchar\font\m@ne} - -\DeclareFontShape{TS1}{newtxttb}{m}{n}{%medium - <-> s*[\newtxtt@scale]tcxtt% -}{} -\DeclareFontShape{TS1}{newtxttb}{m}{sc}{%cap & small cap - <->ssub * newtxttb/m/n% -}{} -\DeclareFontShape{TS1}{newtxttb}{m}{sl}{%slanted - <-> s*[\newtxtt@scale]tcxttsl% -}{} -\DeclareFontShape{TS1}{newtxttb}{m}{it}{%italic - <->ssub * newtxttb/m/sl% -}{} -\DeclareFontShape{TS1}{newtxttb}{b}{n}{%bold - <-> s*[\newtxtt@scale]tcxbtt% -}{} -\DeclareFontShape{TS1}{newtxttb}{b}{sc}{%bold cap & small cap - <->ssub * newtxttb/b/n% -}{} -\DeclareFontShape{TS1}{newtxttb}{b}{sl}{%bold slanted - <-> s*[\newtxtt@scale]tcxbttsl% -}{} -\DeclareFontShape{TS1}{newtxttb}{b}{it}{%bold italic - <->ssub * newtxttb/b/sl% -}{} -\DeclareFontShape{TS1}{newtxttb}{bx}{n}{%bold extended - <->ssub * newtxttb/b/n% -}{} -\DeclareFontShape{TS1}{newtxttb}{bx}{sc}{ %bold extended cap & small cap - <->ssub * newtxttb/b/sc% -}{} -\DeclareFontShape{TS1}{newtxttb}{bx}{sl}{%bold extended slanted - <->ssub * newtxttb/b/sl% -}{} -\DeclareFontShape{TS1}{newtxttb}{bx}{it}{%bold extended italic - <->ssub * newtxttb/b/it% -}{} - - \makeatother -% This is with a slashed 0 like the original txtt. -\newcommand\ttbfamily {\fontfamily{newtxttb}\selectfont } - \ifnum\dosourcexint=1 \else \renewcommand\familydefault\ttdefault @@ -3178,8 +3206,7 @@ pdfpagemode=UseNone,% \ifnum\dosourcexint=0 \inmanualmaintoctrue \fi -\def\sectioncouleur{{cyan}} - +\def\sectioncouleur{{tocsectioncolor}} \def\MARGEPAGENO {1.5em}% changera pour la partie implémentation @@ -3262,13 +3289,9 @@ pdfpagemode=UseNone,% % ===================== -\def\digitstt #1{\begingroup\color[named]{OrangeRed}#1\endgroup} +\def\digitstt #1{\begingroup\color{digitsttcolor}#1\endgroup} \let\dtt\digitstt -% \ctexttt is a remnant of 1.09n manual, don't have time to get rid of it now. -\newcommand\ctexttt [1]{\begingroup\color[named]{DarkOrchid}%\bfseries - #1\endgroup} - % \fexpan 22 octobre 2013 \newcommand\fexpan {\hyperref[ssec:expansions]{\textit{f}-expan}} % Septembre 2015 @@ -3299,7 +3322,7 @@ pdfpagemode=UseNone,% \def\@MyMarginNote [#1]#2{\@bsphack \vadjust{\vskip-\dp\strutbox \hbox{\smash{\hbox to 0pt - {\color[named]{PineGreen}\normalfont\small + {\color{marginnotecolor}\normalfont\small \hsize 1.6cm\rightskip.5cm minus.5cm \hss\vtop{#2}\ $\to$#1\ }}}% \vskip\dp\strutbox @@ -3307,7 +3330,7 @@ pdfpagemode=UseNone,% \def\MyMarginNoteWithBrace #1#2{\@bsphack \vadjust{\vskip-\dp\strutbox \hbox{\smash{\hbox to 0pt - {\color[named]{PineGreen}%\normalfont\small + {\color{marginnotecolor}%\normalfont\small \hss #1\ $\bigg\{$#2}}}% \vskip\dp\strutbox }\strut\@esphack} @@ -3318,18 +3341,18 @@ pdfpagemode=UseNone,% {\kern\dimexpr\FrameSep+\FrameRule\relax\ }} \def\etype #1{\@bsphack \vadjust{\vskip-\dp\strutbox - \hbox{\smash{\hbox to 0pt {\hss\color[named]{PineGreen}% + \hbox{\smash{\hbox to 0pt {\hss\color{marginnotecolor}% \itshape \xintListWithSep{\,}{#1}\ $\star$\quad }}}% \vskip\dp\strutbox }\strut\@esphack} \def\xtype #1{\@bsphack \vadjust{\vskip-\dp\strutbox - \hbox{\smash{\hbox to 0pt {\hss\color[named]{PineGreen}% + \hbox{\smash{\hbox to 0pt {\hss\color{marginnotecolor}% \itshape \xintListWithSep{\,}{#1}\ \ding{73}\quad }}}% \vskip\dp\strutbox }\strut\@esphack} \def\ntype #1{\@bsphack \vadjust{\vskip-\dp\strutbox - \hbox{\smash{\hbox to 0pt {\hss\color[named]{PineGreen}% + \hbox{\smash{\hbox to 0pt {\hss\color{marginnotecolor}% \itshape \xintListWithSep{\,}{#1}\quad }}}% \vskip\dp\strutbox }\strut\@esphack} % @@ -3348,7 +3371,7 @@ pdfpagemode=UseNone,% % \def\NewWith #1{\@bsphack \vadjust{\vskip-\dp\strutbox - \hbox{\smash{\hbox to 0pt {\hss\color[named]{PineGreen}% + \hbox{\smash{\hbox to 0pt {\hss\color{marginnotecolor}% \normalfont\small\bfseries \hsize 1.5cm\rightskip.5cm minus.5cm \vtop{\noindent New with #1}\ }}}% @@ -3356,7 +3379,7 @@ pdfpagemode=UseNone,% % \def\CHANGED #1{\@bsphack \vadjust{\vskip-\dp\strutbox - \hbox{\smash{\hbox to 0pt {\hss\color[named]{Red}% + \hbox{\smash{\hbox to 0pt {\hss\color{marginwarningcolor}% \normalfont\small\bfseries \hsize 1.5cm\rightskip.5cm minus.5cm \vtop{\noindent Changed at #1!}\ }}}% @@ -3364,7 +3387,7 @@ pdfpagemode=UseNone,% \def\DNU#1{\@bsphack \vadjust{\vskip-\dp\strutbox - \hbox{\smash{\hbox to 0pt {\hss\color[named]{Red}% + \hbox{\smash{\hbox to 0pt {\hss\color{marginwarningcolor}% \normalfont\small\bfseries \hsize 1.5cm\rightskip.5cm minus.5cm \vtop{\noindent Do not use! #1}\ }}}% @@ -3372,7 +3395,7 @@ pdfpagemode=UseNone,% \def\UNSTABLE#1{\@bsphack \vadjust{\vskip-\dp\strutbox - \hbox{\smash{\hbox to 0pt {\hss\color[named]{Red}% + \hbox{\smash{\hbox to 0pt {\hss\color{marginwarningcolor}% \normalfont\small\bfseries \hsize 1.5cm\rightskip.5cm minus.5cm \vtop{\noindent Unstable! #1}\ }}}% @@ -3380,7 +3403,7 @@ pdfpagemode=UseNone,% \def\unstable#1{\@bsphack \vadjust{\vskip-\dp\strutbox - \hbox{\smash{\hbox to 0pt {\hss\color[named]{Red}% + \hbox{\smash{\hbox to 0pt {\hss\color{marginwarningcolor}% \normalfont\small\bfseries \hsize 1.5cm\rightskip.5cm minus.5cm \vtop{\noindent unstable? #1}\ }}}% @@ -3388,7 +3411,7 @@ pdfpagemode=UseNone,% \def\DEPRECATED #1{\@bsphack \vadjust{\vskip-\dp\strutbox - \hbox{\smash{\hbox to 0pt {\hss\color[named]{PineGreen}% + \hbox{\smash{\hbox to 0pt {\hss\color{marginnotecolor}% \normalfont\small\bfseries \hsize 2cm\rightskip.5cm minus.5cm \vtop{\noindent Deprecated! (#1)}\ }}}% @@ -3396,7 +3419,7 @@ pdfpagemode=UseNone,% % \def\CHANGEDf #1{\@bsphack \vadjust{\vskip-\dp\strutbox - \hbox{\smash{\hbox to 0pt {\hss\color[named]{Red}% + \hbox{\smash{\hbox to 0pt {\hss\color{marginwarningcolor}% \normalfont\small\bfseries \hsize 1.5cm\rightskip.5cm minus.5cm \vtop{\noindent Changed at #1!}\ @@ -3405,7 +3428,7 @@ pdfpagemode=UseNone,% % \def\NewWithf #1{\@bsphack \vadjust{\vskip-\dp\strutbox - \hbox{\smash{\hbox to 0pt {\hss\color[named]{PineGreen}% + \hbox{\smash{\hbox to 0pt {\hss\color{marginnotecolor}% \normalfont\small\bfseries \hsize 1.5cm\rightskip.5cm minus.5cm \vtop{\noindent New with #1}\ @@ -3476,29 +3499,6 @@ pdfpagemode=UseNone,% -% \MacroFont and \MicroFont -% ========================= - -\def\restoreMicroFont {\def\MicroFont {\ttbfamily\makestarlowast -% \ifinlefted\else\ifineverb\else\color[named]{verbatim}\fi\fi -% \ifinlefted\else\color[named]{saddlebrown}\fi -% \ifinlefted\else\color[named]{sedate}\fi - \ifinlefted\else\color[named]{jfbrown}\fi -}} -\restoreMicroFont - -% Notice that \macrocode uses \macro@font which stores the \MacroFont meaning -% in force at \begin{document}. But doc.sty's verbatim uses current \MacroFont -% not the meaning at \begin{document}. Comprenne qui pourra... - -\def\restoreMacroFont {\def\MacroFont {\ttbfamily -% \ifinlefted\else\ifineverb\else\color[named]{Blue}\fi\fi -% \ifinlefted\else\color[named]{Blue}\fi -% \ifinlefted\else\color[named]{sedate}\fi - \ifinlefted\else\color[named]{Brown}\fi -}} -\restoreMacroFont - % \verb % ===== @@ -3528,6 +3528,14 @@ pdfpagemode=UseNone,% % with delimited argument. Here is what I do now, this is compatible % with short verbs. +\def\verbcolorcmd{\color{verbcolor}} +\def\verbsoftwrapiconcolorcmd{\color{verbsoftwrapiconcolor}} + +\def\restoreMicroFont {\def\MicroFont {\ttfamily\makestarlowast + \ifinlefted\else\verbcolorcmd\fi +}} +\restoreMicroFont + \def\verb {% \relax \ifmmode\else\leavevmode\null\fi @@ -3535,7 +3543,7 @@ pdfpagemode=UseNone,% \let\do\@makeother \dospecials \@ifstar{\@sverb}% \verb* is used in the index (obsolete: no indices at 1.3e), % leave it using ambient font - {\MicroFont % used to change font (ttbfamily=slashed 0), color, + {\MicroFont % used to change font (\ttfamily), color, % will make * active via \makestarlowast \catcode 32 10 \endlinechar 32 % allows to fetch across line breaks \frenchspacing % done globally in document @@ -3570,24 +3578,22 @@ pdfpagemode=UseNone,% #1\expandafter\@@jfverb_b\fi } -% \SoftWrapIcon box for line-breaking using discretionaries -% ========================================================= \DeclareFontFamily{U}{MdSymbolC}{} \DeclareFontShape {U}{MdSymbolC}{m}{n}{<-> MdSymbolC-Regular}{} - \newbox\SoftWrapIcon -\colorlet {softwrapicon}{blue} -% Emacs/AUCTeX uses very strange comment-like highlighting for \usefont{U}... \def\SetSoftWrapIcon{% \setbox\SoftWrapIcon\hb@xt@\z@ - {\hb@xt@\fontdimen2\font - {\hss{\color{softwrapicon}\usefont{U}{MdSymbolC}{m}{n}\char"97}\hss}% + {\kern.5ex%\hb@xt@\z@%\fontdimen2\font + %{ + \smash{\lower3pt\hbox{% + \verbsoftwrapiconcolorcmd\usefont{U}{MdSymbolC}{m}{n}\char 151 + }}%\hss}% \hss}% } -\AtBeginDocument {\SetSoftWrapIcon }% ttzfamily déjà fait +\AtBeginDocument {\SetSoftWrapIcon }% ok car ttzfamily déjà fait \catcode`_ 8 \makeatother @@ -3595,6 +3601,14 @@ pdfpagemode=UseNone,% % everbatim environment % ===================== +\def\restoreMacroFont {\def\MacroFont {\ttfamily + \ifinlefted\else\color{everbatimfgcolor}\fi +}} +\restoreMacroFont +% Notice that \macrocode uses \macro@font which stores the \MacroFont meaning +% in force at \begin{document}. But doc.sty's verbatim uses current \MacroFont +% not the meaning at \begin{document}. Comprenne qui pourra... + % October 13-14, 2014 % Verbatim with an \everypar hook, mainly to have background color, followed by % execution of the contents (not limited by a group-scope) @@ -3602,44 +3616,10 @@ pdfpagemode=UseNone,% \makeatletter \catcode`_ 11 -% Je modifie Mardi 18 février 2020 \MacroFont -% pour essayer couleur de foreground, -% je supprime donc le \ifineverb de \MacroFont. -% \newif\ifineverb -\def\everbatimtop {\MacroFont \small} -\let\everbatimbottom\relax -\let\everbatimhook\relax - -\def\everbatim {\s@everbatim\@everbatim } -\@namedef{everbatim*}{\s@everbatim\expandafter\@everbatimx\expandafter - {\the\newlinechar}} - -\def\everbatimeverypar{\strut - {\color{yellow!5}\vrule\@width\linewidth }% - \kern-\linewidth - \kern\everbatimindent } -\def\everbatimindent {\z@} -% voir plus loin atbegindocument - -\def\endeverbatim {\if@newlist \leavevmode\fi\endtrivlist } - -\@namedef{endeverbatim*}{\endeverbatim\aftergroup\everbatimundoparskip} -\def\everbatimundoparskip{\vbox{}\kern-\baselineskip\kern-\parskip} -% Note 24 juin 2021 -% -% Si everbatim[*] suit immédiatement un premier everbatim* dont l'exécution -% n'a fait que des définitions de macros sans créer de paragraphe (ou un -% environnment de liste comme center) le \kern-\parskip émis après le rendu -% verbatim (et qui vient de \everbatimundoparskip) ne sera pas compensé. -% Plus précisément le everbatim* (ou everbatim) qui vient en -% deuxième utilise \trivlist mais en ayant mis les paramètres d'espacements -% verticaux à zéro. Donc il y aura chevauchement. -% -% Pour régler ce problème, on peut : -% - soit fusionner les deux everbatim*, -% - soit si cela est embêtant, par exemple si le second environnment est -% un everbatim, pas un everbatim*, ajouter \kern-\parskip entre les deux. +\def\everbatim {\s@everbatim\@everbatim} +\@namedef{everbatim*}{\s@everbatim\@everbatimx} +% Note: one can not use everbatim inside itself or everbatim* inside itself \def\s@everbatim {% % \ineverbtrue \everbatimtop % put there size changes @@ -3669,6 +3649,13 @@ pdfpagemode=UseNone,% }% \obeylines \@vobeyspaces } +\def\everbatimtop {\MacroFont \small}% +\let\everbatimhook\empty +\def\everbatimeverypar{\strut + {\color{everbatimbgcolor}\vrule\@width\linewidth }% + \kern-\linewidth + \kern\everbatimindent } +\def\everbatimindent {\z@}% voir plus loin atbegindocument \begingroup \lccode`X 13 @@ -3682,38 +3669,79 @@ pdfpagemode=UseNone,% |lowercase[|endgroup% both freezes catcodes and converts X to active ^^M |def|@everbatim #1X#2\end{everbatim}% [#2|end[everbatim]|everbatimbottom ] -|def|@everbatimx #1#2X#3\end{everbatimY}]% - {#3\end{everbatim*}% - \everbatimbottom +|def|@everbatimx #1X#2\end{everbatimY}]% + {#2\end{everbatim*}% +% No group here: this allows executed code to make macro +% definitions which may reused in later uses of everbatim. +% refactored 2022/01/11, rather than passing \newlinechar value +% as was done formerly via everbatim* (see above) and fetching it here as #1 +% it is thus assumed executed contents do not terminate a scope + \edef\everbatimrestorenewlinechar{\newlinechar\the\newlinechar\relax}% \newlinechar 13 +% refactored 2022/01/11 to fix a \parskip issue +% attention, \parskip thus set to zero for execution of contents +% reason: avoid extra space if everbatim* is in an \item of a list +% between verbatim and output of execution, if it starts a paragraph +% a \vskip-\parskip approach (cf former \everbatimundoparskip) +% would be no good in case contents create a display + \edef\everbatimrestoreparskip{\parskip\the\parskip\relax}% + \parskip\z@skip +% execution of the contents (expected to be LaTeX code...) \everbatimxprehook - \scantokens {#3}% - \newlinechar #1\relax + \scantokens {#2}% + \everbatimrestorenewlinechar + \everbatimrestoreparskip \everbatimxposthook +% input after \end{everbatim*} on same line in source is allowed }% - -% L'espace venant du endofline final mis par \scantokens sera inhibé si #3 se +% L'espace venant du endofline final mis par \scantokens sera inhibé si #2 se % termine par un % ou un \x, etc... -\def\everbatimxprehook {\colorlet{everbsavedcolor}{.}\color[named]{OrangeRed}} -\def\everbatimxposthook {\color{everbsavedcolor}} +\let\everbatimbottom\empty + +\def\endeverbatim{\if@newlist \leavevmode\fi\endtrivlist} +\@namedef{endeverbatim*}{\endeverbatim} + +% There is an issue with how to inhibit the \parskip if execution +% of contents generate a paragraph. Because the design is aimed at +% keeping output close to verbatim input. +% Even in a document with zero \parskip overall, the \parskip will possibly +% be reset to some annoying high value e.g. if we are in an \item of a list +% environment. +% In this documentation, many usage of everbatim* are indeed inside such +% \item's. The former (2020) approach was to do: +% \@namedef{endeverbatim*}{\endeverbatim\aftergroup\everbatimundoparskip} +% \def\everbatimundoparskip{\vbox{}\kern-\baselineskip\kern-\parskip\leavevmode} +% but it had its problems if executed contents start a display, with +% not enough vertical whitespace then +% Also if source had two everbatim* environments one after the other, +% the first one not producing any ouput, this caused overlap. +% The new approach (Feb 2022) is much simpler and avoids these problems. + + +% These definitions are provisory and get overwritten below in order +% to avoid color stack overflow problems with latex + dvipdfmx, and xelatex +\def\everbatimxprehook {\colorlet{everbsavedcolor}{.}% + \color{everbatimxfgcolor}}% +\def\everbatimxposthook{\color{everbsavedcolor}} +% actual definitions: +{\sbox0{\color{everbatimxfgcolor}\xdef\@tempa{\current@color}}} \ifpdf - \def\everbatimxprehook - {\pdfcolorstack\@pdfcolorstack push{0 1 0.5 0 k 0 1 0.5 0 K}\relax} - \def\everbatimxposthook - {\pdfcolorstack\@pdfcolorstack pop\relax} + \edef\everbatimxprehook + {\pdfcolorstack\noexpand\@pdfcolorstack push{\@tempa}\relax} + \def\everbatimxposthook{\pdfcolorstack\@pdfcolorstack pop\relax} \else % Le 24 juin 2021 je vérifie que ceci est encore nécessaire avex xelatex % (sinon color leak de OrangeRed à partir de la page 97 dans la doc) % et aussi pour dvipdfmx (sinon color stack overflow au moment de la page 98 % lors du passage par dvipdfmx) \ifxetex - \def\everbatimxprehook {\special{color push cmyk 0 1 0.5 0}} - \def\everbatimxposthook {\special{color pop}} + \edef\everbatimxprehook{\special{color push \@tempa}} + \def\everbatimxposthook{\special{color pop}} \else \ifnum\Withdvipdfmx=1 - \def\everbatimxprehook {\special{pdf:bcolor OrangeRed}} - \def\everbatimxposthook {\special{pdf:ecolor}} + \edef\everbatimxprehook{\special{color push \@tempa}} + \def\everbatimxposthook{\special{color pop}} \fi\fi\fi @@ -3877,20 +3905,20 @@ pdfpagemode=UseNone,% \expandafter\def\csname #1name\endcsname {\texorpdfstring {\hyperref[sec:#2]% - {\relax{\color{joli}\MakeNameUp{#1}}}}% + {\relax{\color{xintnamecolor}\MakeNameUp{#1}}}}% {#1}% \xspace }% \expandafter\def\csname #1nameimp\endcsname {\texorpdfstring {\hyperref[sec:#2imp]% - {\relax{\color{blue}\MakeNameUp{#1}}}}% + {\relax{\color{xintnameimpcolor}\MakeNameUp{#1}}}}% {#1}% \xspace }% }% \def\DOCxintfrontpage {\texorpdfstring - {\hyperref[frontpage]{\relax{\color{joli}TOC}}}% + {\hyperref[frontpage]{\relax{\color{xintnamecolor}TOC}}}% {TOC}% \xspace }% @@ -3943,7 +3971,7 @@ pdfpagemode=UseNone,% The \xintnameimp packages source code\par \gdef\DOCxintfrontpage {\texorpdfstring - {\hyperref[frontpage]{\relax{\color{blue}TOC}}}% + {\hyperref[frontpage]{\relax{\color{xintnameimpcolor}TOC}}}% {TOC}% \xspace }% \else @@ -3967,19 +3995,19 @@ pdfpagemode=UseNone,% \def\DOCxintexprintro {\texorpdfstring - {\hyperref[part:1]{\relax{\color{joli}\MakeNameUp{Start here}}}}% + {\hyperref[part:1]{\relax{\color{xintnamecolor}\MakeNameUp{Start here}}}}% {Start here}% \xspace }% \def\DOCxintexprmacros {\texorpdfstring - {\hyperref[sec:oldxintexpr]{\relax{\color{joli}\MakeNameUp{xintexpr}}}}% + {\hyperref[sec:oldxintexpr]{\relax{\color{xintnamecolor}\MakeNameUp{xintexpr}}}}% {xintexpr}% \xspace }% \def\DOCexamples {\texorpdfstring - {\hyperref[sec:examples]{\relax{\color{joli}\MakeNameUp{Examples}}}}% + {\hyperref[sec:examples]{\relax{\color{xintnamecolor}\MakeNameUp{Examples}}}}% {Examples}% \xspace }% @@ -4254,7 +4282,7 @@ pdfpagemode=UseNone,% \etocsetnexttocdepth{section} \localtableofcontents -\section {Usage} +\section {Introduction and changes} \begin{itemize} \item To use with |etex|, |pdftex|, ..., i.e.\@ with \TeX{} engines activating @@ -4346,38 +4374,28 @@ which got randomly shuffled to new places (at least I did delete large sections, which was a hard decision to take, almost breaking the palimpsest quality of the document). Reports welcome.% % -\footnote{Thanks to Jürgen Gilg for keeping the author motivated and - helping proof-read the 1.4 documentation.} +\footnote{Thanks to Jürgen Gilg for keeping the author motivated and helping + proof-read the 1.4 documentation. Sadly, Jürgen passed away unexpectedly in + 2022. His enthusiasm, kindness, and friendship will be profundly missed.} -\subsection{Improved support for logarithm, exponential, sine, etc...\@ at - the \texttt{1.4e} release of \texttt{2021/05/05}} - -They are now supported up to \dtt{62} digits and achieve «correct rounding»% -% -\footnote{This means that the produced value is the rounding to |Digits| - significant digits of the theoretical exact mathematical value. The - rounding mode is currently not customizable and is «rounding to nearest, - ties go to infinity of same sign».} -% -at least -in \dtt{99\%} of cases% -% -\footnote{It is even better than that, but depends a bit on how |Digits| is - located relative to some thresholds governing Taylor series - or other approximation means.} -% -for |Digits| being at least \dtt{9}. +\subsection{Breaking changes since the \texttt{1.4} release} -For Digits up to \dtt{8}, a special more approximate implementation is used, -and the functions achieve the correct rounding (particularly at |Digits| -equal to \dtt{8} or \dtt{7}) less often, but are significantly faster -(especially logarithm, exponential, powers) than working with \dtt{9} digits -or more. The achieved precision is largely enough for plots. - -See \xintlogname and \xinttrigname for some additional information. +\subsubsection{Breaking changes at the \texttt{1.4k} release} +\begin{enumerate}[noitemsep] + \item Changed behaviour for nested + \csbxint{exprSafeCatcodes}/\csbxint{exprRestoreCatcodes}. + \item The output format of \csbxint{floateval}, which by default is produced + by \csbxint{PFloat}, has changed once more (!): integers (without + scientific exponent) get now printed without a trailing "\dtt{.0}". + Furthermore trailing zeros in the significand are removed only if there are + at least \dtt{4} of them. This changed behaviour is reversible + via customizing macros. + \item \csbxint{Float} now outputs the zero value as + "\dtt{\xintFloat{0}}". Customizable via \csbxint{FloatZero}. +\end{enumerate} -\subsection{Breaking changes at the \texttt{1.4g} release} +\subsubsection{Breaking changes at the \texttt{1.4g} release} \begin{enumerate}[noitemsep] \item Power operators |**| and |^| are now parsed @@ -4394,7 +4412,7 @@ $$5^{4^{3^2}} = 5^{262144}\approx \xintTeXfromSci{\xintfloateval{5^4^3^2}}$$ respectively. \end{enumerate} -\subsection{Breaking changes at the \texttt{1.4f} release} +\subsubsection{Breaking changes at the \texttt{1.4f} release} \begin{enumerate}[noitemsep] \item \csbxint{ieval}|{[-D]...}|\IMPORTANT{} @@ -4414,7 +4432,7 @@ $$5^{4^{3^2}} = 5^{262144}\approx \xintTeXfromSci{\xintfloateval{5^4^3^2}}$$ of |Digits| and \dtt{64} digits. \end{enumerate} -\subsection{Breaking changes at the \texttt{1.4e} release} +\subsubsection{Breaking changes at the \texttt{1.4e} release} In principle, I try for breaking changes regarding output to happen only at major releases. But it is not as if I had a gigantic user base, and sometimes @@ -4429,13 +4447,16 @@ support is needed... \begin{itemize} \item \csbxint{floateval} output macro \csbxint{PFloat} has been modified. In - particular mantissas are trimmed of trailing zeros. Integers are printed - with a zero after the decimal mark. + particular mantissas are trimmed of trailing zeros. + {\setbox8\hbox{Integers are printed with a zero after the decimal mark.}% + \rule[0.5ex]{\wd8}{1pt}\kern-\wd8\box8}\CHANGED{1.4k again} \item \csbxint{eval} output macro \csbxint{FracToSci} has been modified, regarding the handling of numbers involving a decimal exponent; rather than - printing out an integer mantissa, it now uses the same conventions as - \csbxint{PFloat} (of course without pre-rounding to the |Digits| precision). - The \csa{xintFracToSciE} was removed because \csbxint{PFloatE} is used. + printing out an integer mantissa, it uses scientific notation, + i.e.\@ more specifically it uses the same conventions as + \csbxint{PFloat}, but of course without pre-rounding to the |Digits| precision. + The \csa{xintFracToSciE} macro was removed because \csbxint{PFloatE} + is used in its place. Notice though that fractions are still not automatically reduced to lowest terms even on output. I hesitated about this, but when for example the @@ -4443,7 +4464,7 @@ support is needed... it would be a very costly operation to apply \csbxint{Irr} or \csbxint{PIrr} to it. \item \csbxint{ieval} was modified to use on output - \csbxint{DecToString} and not anymore \csbxint{FracToSci}. + \csbxint{DecToString}, not \csbxint{FracToSci}. This means than in case of usage of the |[D]| optional argument with a negative |D| (i.e.\@ rounding the output to a multiple of a positive power @@ -4483,7 +4504,50 @@ support is needed... For bugfixes and possibly more details check |CHANGES.html|: \centeredline{|texdoc --list xint|} + + \begin{itemize} +\item The most important has been the improved support for logarithm, exponential, +sine, etc...\@ added at the \texttt{1.4e} release of \texttt{2021/05/05}: + +They\NewWith{1.4e !!} are now supported up to \dtt{62} digits and achieve «correct rounding»% +% +\footnote{This means that the produced value is the rounding to |Digits| + significant digits of the theoretical exact mathematical value. The + rounding mode is currently not customizable and is «rounding to nearest, + ties go to infinity of same sign».} +% +at least +in \dtt{99\%} of cases% +% +\footnote{It is even better than that, but depends a bit on how |Digits| is + located relative to some thresholds governing Taylor series + or other approximation means.} +% +for |Digits| being at least \dtt{9}. + +For Digits up to \dtt{8}, a special more approximate implementation is used, +and the functions achieve the correct rounding (particularly at |Digits| +equal to \dtt{8} or \dtt{7}) less often, but are significantly faster +(especially logarithm, exponential, powers) than working with \dtt{9} digits +or more. The achieved precision is largely enough for plots. + +See \xintlogname and \xinttrigname for some additional information. + +\item The long awaited\NewWith{1.4k} syntax \csbxint{ieval}|[D]{...}| and + \csbxint{floateval}|[Q]{...}| has been implemented. The legacy + \csbxint{ieval}|{[D]...}| and \csbxint{floateval}|{[Q]...}| syntax is kept + for backwards compatibility. + +\item \csbxint{FloatToDecimal}, \csbxint{FracToDecimal}.\NewWith{1.4k} + +\item \csbxint{PFloat}\NewWith{1.4k} is customizable via \csbxint{PFloatZero}, + \csbxint{PFloatIntSuffix}, \csbxint{PFloatLengthOneSuffix}, + \csbxint{PFloatNoSciEmax}, \csbxint{PFloatNoSciEmin} and + \csbxint{PFloatMinTrimmed}. + +\item \csbxint{FloatZero}.\NewWith{1.4k} + \item The concept of simultaneous assignments is extended:\NewWith{1.4i} in case of more variables than values the extraneous variables do not cause an error message but are simply set to the |nil| value; in case of more values @@ -4497,9 +4561,6 @@ For bugfixes and possibly more details check |CHANGES.html|: \item \csbxint{TeXfromSci}\NewWith{1.4g} - \item The most important feature is at |1.4e| the extended range and accuracy - of the scientific functions, up to \dtt{62} digits.%\NewWith{1.4e} - \item The constraints for the replacement macro to be used for \csbxint{exprPrintOne} have been much simplified. See the documentation of \csbxint{FracToSci} which is the package default. @@ -4590,7 +4651,7 @@ author a few decades to finish absorbing Python/NumPy. \end{itemize} \end{framed} -\subsection{Known bugs/features (last updated at \texttt{1.4i})} +\subsection{Known bugs/features (last updated at \texttt{1.4j})} \begin{description} \item[if(100>0,(100,125),(100,128)) breaks my code:] @@ -4668,6 +4729,14 @@ author a few decades to finish absorbing Python/NumPy. only at |1.4h|. The non-nested case |seq((i)?{i}{abort}+10, i=-2, -1, 0, 1)| works and the «must be last in expression if nested» limitation is currently considered a feature. + +\item[{seq([i,i\string^2], i=1..10) crashes with Ooops, looks like we are missing a + ]. Aborting!}] +% + The cause is that the square brackets do not hide the comma from |seq()| + parsing. This will probably remain ``wont-fix''. Work-arounds: either use + an extra pair of parentheses |seq(([i,i^2]), ...)| or hide the inner + comma within braces |seq([i{,}i^2], ...)|. \end{description} The list stops here, but there are certainly other pending bugs in my bug-log, @@ -4734,405 +4803,48 @@ The rendering here uses extra decoration. \localtableofcontents -\subsection{Oples and nutples: terminology for the \text{1.4} \xintname generation}\label{oples} - -\emph{Skip this on first reading, else you will never start using the - package.} \fbox{SKIP THIS!} (understood?) - -In this section I will describe a mathematical terminology which models -how the parser handles the input syntax with numbers, commas, and brackets, -and how it maps internally to \TeX\ specific concept, particularly braces and -macro arguments. - -\etocsetnexttocdepth{subsubsection} -\localtableofcontents - -\subsubsection{Base terminology} - -We start with a set $\mathcal{A}$ of \emph{atoms}, which represent numeric -data. In \TeX{} syntax such \emph{atoms} are always braced, more precisely, -currently they look like -% -\centeredline{\dtt{\{raw format within \TeX{} braces\}}} -% -The \TeX{} braces are not set-theoretical braces here, they are simply used -for \TeX nical reasons (one could imagine using rather some terminator token, -but ultimately support macros for built-in and user defined functions rely on -\TeX\ macros with undelimited parameters, at least so far). - -Our category $\mathcal{C}$ of «oples» is the smallest collection of -\emph{totally ordered finite sets} verifying these properties: -\begin{enumerate} -\item The empty set \dtt{$\emptyset$} is an \emph{ople}, i.e.\@ it belongs to - $\mathcal{C}$. -\item Each singleton set \dtt{$\{O\}$} whose element \dtt{$O$} is either an - \emph{atom} $a\in\mathcal{A}$ or an \emph{ople} qualifies as an \emph{ople}. -\item $\mathcal{C}$ is stable by concatenation. -\end{enumerate} - -Notes: -\begin{itemize} -\item -We refer to the empty set \dtt{$\emptyset$} via the variable \emph{nil}.% -% -\footnote{There is -actually a built-in variable with this name. At |1.4|, |\xintexpr\relax| is -legal and also generates the \emph{nil}.} - -\item It is convenient to accept the empty set as being also an - \emph{atom}. If this is done, then we may refer to the original - \emph{atoms} (elements of $\mathcal{A}$) as \emph{non empty numerical data}. - -\item -Concatenation is represented in the syntax by the -comma. Thus repeated commas are like only one and |nil| is a neutral element. - -\item A singleton \emph{ople} \dtt{$\{a\}$} whose single element is a - (non-empty) \emph{atom} is called a \emph{number}.% -% - \footnote{This has to be taken in a general sense, for example with - \ctanpackage{polexpr}, polynomials are represented by such «numbers».} -% - -\item -The operation of constructing \dtt{$\{O\}$} from the \emph{ople} \dtt{$O$} is -called \emph{bracing} (set theory, \TeX), or \emph{bracketing} (\xintexprname -input syntax, Python |lists|), or \emph{packing} (as a reverse to Python's -unpacking of sequence type objects). In the expression input syntax it -corresponds to enclosing \dtt{$O$} within square brackets: \dtt{$[O]$}. - -\item A braced \emph{ople} is called a \emph{nutple}. Among them \dtt{\{nil\}} - (aka $\{\emptyset\}$) is a bit special. It is called the \emph{none-ple}.% -% - \footnote{Prior to version |1.4j| of this documentation it was called the - \emph{not-ple}.} -% -It is not \dtt{nil}.% -% -\footnote{There is (experimental) a pre-defined «\dtt{None}» variable which - stands for the \emph{none-ple}. It can also be input as |[]|.} -\end{itemize} - -Each \emph{ople} has a \emph{length} which is its cardinality as set. The -singleton |oples| are called \emph{one-ples}. There are thus two types of -\emph{one-ples}: -\begin{itemize} -\item \emph{numbers} \dtt{$\{a\}$}, $a \in \mathcal{A}$, -\item \emph{nutples} \dtt{$\{O\}$}, $O \in \mathcal{C}$. -\end{itemize} - -If we consider the empty set |nil| on the same footing as |atoms|, the two -types have only one common object which is the \emph{none-ple}. As a rule -arithmetic operations will either break or silently convert the \emph{none-ple} -to the zero value: -\begin{everbatim*} -\xinteval{3+[], 5^[], 10*[]} -\end{everbatim*}. -But attention that \csbxint{iieval} in contrast to \csbxint{eval} is broken by -such inputs. - -\subsubsection{Items (and sub-items) versus elements} +\subsection{The three parsers} -In order to illustrate these concepts, let us consider how one should -interpret notation such as |3,5,7,9| when it arises in an -\csbxint{expr}|ession|: -\begin{description} -\item[tempting vocabulary:] Each of |3|, |5|, |7|, and |9| is an \emph{item}, or - \emph{element} of the (comma separated) \emph{list}. In other terms we have - here a list with 4 items. -\item[rigorous vocabulary:] each one of |3|, |5|, |7|, |9| stands for an - \emph{ople} (of the \emph{one-ple} type) and |3,5,7,9| stands for their \emph{concatenation}. +\xintexprname provides three numerical expression parsers corresponding to +these three respective tasks: +\begin{description}[noitemsep] +\item[\csh{xinteval}:] exact evaluations with fractions, decimal fixed point numbers, numbers + in scientific notation, with no size limitation, +\item[\csh{xintiieval}:] evaluations allowing only integers with no size limitation, +\item[\csh{xintfloateval}:] evaluations with floating points numbers according to the prevailing + precision (see \csbxint{Digits*}), \end{description} -It is important to understand that in an \csbxint{expr}|ession|, there is no -difference between |3,5,7| and |3,,,,5,,,,,,,,,7|. So the view of the comma -as separator is misleading. In other terms, the comma is NOT a separator but -the (associative) operator of concatenation of totally ordered sets, and the -number |3| for example represents a (singleton) set. - -If we want to refer to |3| or |5| or |7| or |9| as «the items of the -(open) list |3,5,7,9|» (and probably this documentation already has such -utterances, due to legacy reasons from the pre-|1.4| internal model), we -\emph{must} realize that this clashes with using the word \emph{item} as -synonymous to \emph{element} in the set-theoretical sense. - -To repeat, any ople \dtt{$O$} is a finite totally ordered set: if not the empty -set, it has \emph{elements} \dtt{$a_1$}, \dots, \dtt{$a_k$}, and the above means that -its \emph{items} are the singleton oples (aka one-ples) \dtt{$I_1=\{a_1\}$}, -\dots, \dtt{$I_k=\{a_k\}$}. Each \dtt{$a_j$} may be an |atom|, then -\dtt{$I_j$} is a |number|, or \dtt{$a_j$} is an |ople| (possibly the empty set), then -\dtt{$I_j$} is a |nutple| whose depth is one more than the one of the ople -\dtt{$a_j$}. - -Thus we can refer to «items» but must then understand they are not «elements»: -«items» are «singleton sub-sets». The cardinality (aka length) of an ople is -also the number of its -items. It would be tempting to use the terminology «sub-item» to keep in mind they are «sub-sets» -but this would again create confusion: a |nutple| has only one item which is -itself; and we need some terminology to refer to the individual numbers in the -|nutple| given in input as |[1,2,3]| for example. It is natural to refer to -|1|, |2|, |3| as «sub-items» of |[1,2,3]| as the latter may be an «item» (it -is in particular an «item» of itself, the unique one at that). - -We distinguish the |oples| of length zero (there is only one, the empty set) -or at least two as those which can never be an «item». Those of length one, -the |one-ples|, are exactly those which can be «items». Among them some may -have «sub-items», they are the |nutples| with the exception of the |none-ple|. -And the others do not have «sub-items», they are the |numbers| and the |none-ple| (whose input syntax is -either |[]| or the variable |None|).% -% -\footnote{% -A note on the \csbxint{verbosetrue} regime: for a variable defined to be -|3,5,7,9|, it will say that its value is |{3}{5}{7}{9}|, because it does not -keep the external set-theoretical braces. The braces here are only \TeX{} -braces, and |{3}| is an |atom|. The |number| would be |{{3}}| with the -external braces being set-theoretical and also used internally as \TeX{} -braces. From the four numbers |{{3}}|, ..., |{{9}}| concatenation gives -|{{3}{5}{7}{9}}|, which is the |ople| |3,5,7,9|. But the log view drops -deliberately the external braces. If the variable is defined to be the -|nutple| |[3,5,7,9]|, then the log view will be |{{3}{5}{7}{9}}| (up to -details on how exactly the numeric quantities are coded) and the actual -internal \TeX{} entity will be |{{{3}{5}{7}{9}}}|, where the two external -layers of braces are both set-theoretical and \TeX nical braces.} - - -\subsubsection{Oples as trees} - -We say that the empty set |nil| and \emph{atoms} are \emph{leaves}. - -We associate with any \emph{ople} a tree. The root is the ople. In the case of -the |nil| ople, there is nothing else than the root, which we then consider -also a \emph{leaf}. Else the children at top level are the successive -\emph{elements} (not «items»!) of the ople.% -% -\footnote{\label{fn:alttree}% - We could also consider a tree for which the children of the root node would - be its items and recursively; in that case the leaves would be |numbers| and - possibly the |None|. The tree of the |nil| would be the empty tree, the tree - of |None| would have a single node and no edges. Such a tree would match - the input syntax (of course applying the rule that iterated commas are like - only one). The tree which is described in this section matches more - directly the internal syntax, hence is more useful to the author, who is - also the sole reader who extracts some benefit from reading this - documentation once in a while.} -% -Among the elements some are \emph{atoms} giving \emph{leaves} of the tree, -others are \emph{nutples} which in turn have children. In the special case of -the \emph{none-ple} we consider it has a child, which is the empty set and this -is why we consider the empty set |nil| to be also a potential \emph{leaf}. We -then proceed recursively. We thus obtain from the root \emph{ople} a tree -whose vertices are either \emph{oples} or \emph{leaves}. Only the empty set -|nil| is both a \emph{leaf} and an \emph{ople}. - -Considering the empty set |nil| as an \emph{atom} fits with the \xintexprname -internal implementation based on \TeX: |nil| is an empty pair of braces |{}|, -whereas an \emph{atom} is a braced representation of a numeric value using -digits and other characters. We construct \emph{oples} by putting one after -the other such constituents and bracing them, and then repeating the process -recursively. - -It has also an impact on the definition of the \emph{depth} (a.k.a as -\emph{maximal dimension}) of an \emph{ople}. For example the \emph{ople} -$\{\emptyset A_1A_2\}$ with three elements, among them the empty set and two -atoms is said to have depth $1$, or to have maximal dimension $1$. And -$\{\{\emptyset\}A_1A_2\}$ is of depth $2$ because it has a leaf (the empty -set) which is a child of a child of the \emph{ople}. NumPy \emph{ndarrays} -have a more restricted structure for example -$\{\{A_{00}A_{01}\}\{A_{10}A_{11}\}\}$ is a $2$-dimensional array, where all -leaves are at the same depth. When slicing empties the array from its atoms, -NumPy keeps the shape information but prints the array as $[]$. This will not -be the case with \xintexprname, which has no other way to indicate the shape -than display it. -\begin{everbatim*} -\xinteval{[[],[]]} -\end{everbatim*} -\begin{everbatim*} -\xinteval{[[0,1],[10,11]][:,2:]} -\end{everbatim*} - -\subsubsection{Ople slicing and indexing} -\label{sssec:opleslicing} - -«Set-theoretical» slicing of an \emph{ople} means replacing it with one of its -subsets. This applies also if it is a \emph{number}. Then it can be sliced -only to itself or to the empty set (indeed it has only one element, which is -an atom). Similarly the \emph{none-ple} can only be sliced to give itself or -the empty set. And more generally a \emph{nutple} is a singleton so also can -only be set-sliced to either the empty set or itself. - -\xintexprname extends «Python-like» slicing to act on \emph{oples}: -\begin{itemize}[nosep] -\item if they are not \emph{nutples} set-theoretical slicing applies, -\item if they are \emph{nutples} (only case having a one-to-one - correspondence in Python) then the slicing happens \emph{within brackets}: - i.e.\@ the \emph{nutple} is unpacked then the set-theoretical slicing is - applied, then the result is \emph{repacked} to produce a new \emph{nutple}. -\end{itemize} -With these conventions the \emph{none-ple} for example is invariant under -slicing: unpacking it gives the empty set, which has only the empty set as -subset and repacking gives back the \emph{none-ple}. Slicing a general -\emph{nutple} returns a \emph{nutple} but now of course in general distinct -from the first one. - -The input syntax for Python slicing is to postfix a variable or a -parenthesized ople with |[a:b]|. See \autoref{ssec:lists} for more. There -are never any out-of-range errors when slicing or indexing. All operations -are licit and resolved by the |nil|, a.k.a. empty set. - -«Set-theoretical» item indexing of an \emph{ople} means reducing it to a -subset which is a singleton. It is thus a special case of set-theoretical -slicing (which is the general process of selecting a subset as replacement of -a set). - -\xintexprname extends «Python-like» indexing to act on \emph{oples}: -\begin{itemize}[nosep] -\item if they are not \emph{nutples} set-theoretical item indexing applies, -\item if they are \emph{nutples} (only case having a one-to-one - correspondence in Python) then the meaning becomes \emph{extracting}: i.e.\@ - the \emph{nutple} is unpacked then the set-theoretical indexing is applied, - but the result is \emph{not repacked}. -\end{itemize} -For example when applied to the \emph{none-ple} we always obtain -the |nil|. Whereas as we saw slicing the \emph{none-ple} always gives back the -\emph{none-ple}. Indexing is denoted in the syntax by postfixing by |[N]|. Thus -for \emph{nutples} (which are analogous to Python objects), there is genuine -difference between the |[N]| extractor and the |[N:N+1]| slicer. But for -\emph{oples} which are either |nil|, a \emph{number}, or of length at least 2, -there is no difference. - -\subsubsection{Nested slicing of oples} - -Nested slicing is a concept from NumPy, which is extended by \xintexprname to -trees of varying depths. We have a chain of slicers and extractors. I will -describe only the case of slicers and letting them act on a |nutple|. The -first slicer gives back a new |nutple|. The second slicer will be applied to -each of one of its remaining elements. However some of them may be -\emph{atoms} or the empty set. In the NumPy context all leaves are at the -same depth thus this can happen only when we have reached beyond the last -dimension (axis). This is not permitted by NumPy and generates an error. -\xintexprname does not generate an error. But any attempt to slice an -\emph{atom} or the empty set (as element of its container) removes it. Recall -we call them \emph{leaves}. We can not slice leaves. We can only slice -non-leaf elements: such items are necessarily |nutples|. The procedure then -applies recursively. - -If we handle an extractor rather than a slicer, the procedure is similar: we -can not extract out of an \emph{atom} or the empty set. They are thus -removed. Else we have a |nutple|. It is thus unpacked and replaced by the -selected element. This element may be an atom or the empty set and any further -slicer or extractor will remove them, or it is a |nutple| and the procedure -applies with the next slicer/extractor. - -\xintexprname allows to apply such a |[a:b,c:d,N,e:f,...]| chain of -slicing/extracting also to an \emph{ople}, which is not a \emph{nutple}. We -simply apply the first step as has been described previously and successive -steps will only get applied to either \emph{nutples} or \emph{leaves}, the -latter getting silently removed by any attempted operation. - -\subsubsection{Function arguments versus variables} -\label{sssec:funcargs} - -In a function declaration with \csbxint{deffunc}, the call signature is parsed -as a comma separated list, so here it is not true that repeated commas are -like only one: repeated commas are not allowed and will break the function -declaration. - -When \xintexprname parses a function call, it first constructs the ople which -is delimited by the opening and closing parentheses, then it applies the -function body, after having mapped the successive items (not the elements) of -the parsed ople to the variables appearing in the function call -signature. Hence the arguments in the call signature stand for |one-ples| -(i.e.\@ either |numbers| or |nutples|). - -Let me explain why we can not define a function |foo(A,B)| of two oples: the -function call will evaluate as an ople what is enclosed within the -parentheses. It is then impossible in general to split this uniquely into two -oples |A| and |B|, except if for example we know a priori the length of |A|. -We could imagine defining a declarative interface for a |foo(A,B)| with |A| -preset to have \dtt{37} items or at least a pre-defined number of items but -this is extraneous layer for a functionality no-one will use. - -The alternative would be to consider that declaring |foo(A,B)| means |A| will -pick-up always the first item and |B| all the remaining ones, and thus will be -an ople; here, there are some \TeX nical implementation reasons which have -dissuaded the author to do this. +and two secondary ones which act like the exact evaluator then round the +output to a given number of fractional digits, or convert them to +|False| or |True| according to whether they vanish or do not vanish. -In its place, a special syntax |foo(A,*B)| for the declaration of the function -is available. It means that |B| stands for the |nutple| which -receives as items all arguments in the function call beyond the first one -already assigned to |A|. - -More generally, the last positional argument in a function declaration can -have the form |*|\meta{argname}. This then means that \meta{argname} -represents a |nutple| which will receive as items all arguments in the -function call remaining after the earlier positional arguments have been -assigned. The declared function body is free to again use the syntax -|*|\meta{argname} which will unpack it and thus produce the ople concatenating -all such optional arguments. - -With \csbxint{defvar} one can define a variable with value an |ople| of -arbitrary cardinality. Such a variable can be used in a function call, it -will then occupy the place of as many arguments as its cardinality (which is -its number of elements, hence of its associated items). For example if -function |foo| was declared as a function of 5 arguments |f(a,b,c,d,e)| it is -legitimate to use it as |f(A,B)| if |A| is an ople-valued variable of length -three and |B| of length two. The actual arguments |a,b,c,d,e| will be made to -match the three items of |A| and the two items of |B|. - -\subsubsection{Final words on leaves} - -In case things were too clear, let's try to add a bit of confusion with an -extra word on \emph{leaves}. When we discuss informally (particularly to -compare with NumPy) an input such as -\begin{everbatim} -[[1, 2], [3, 4]] -\end{everbatim} -we may well refer to |1|, |2|, |3|, and |4| as being «the leaves of the 2d -array». But obviously we have here numbers and previously we explained that a -number is not a \emph{leaf}, its \emph{atom} is. Well, the point here is that -we must make a difference between the input form as above and the actual -constructed \emph{ople} the parser will obtain out of it. In the input we do -have numbers. The comma is a \emph{concatenator}, it is not a separator for -enumeration! The \emph{ople} which corresponds to it has a \TeX{} -representation like this: -\begin{everbatim} -{{{1}{2}}{{3}{4}}} -\end{everbatim} -where we don't have the \emph{numbers} anymore (which would look like |{{1}}|, -|{{2}}|, ...) but numeric \emph{atoms} |{1}|, |{2}|, |{3}|, |{4}| where the -braces are \TeX{} braces and \textbf{not} set-theoretical braces (the other -braces are both). Hence we should see the above as the |ople| -$\{\{A_{00}A_{01}\}\{A_{10}A_{11}\}\}$ with atoms $A_{00}=\{1\}$, ..., being the -\emph{leaves} of the tree associated to (or which is) the \emph{ople}. - -Numbers may be called the \emph{leaves} of the \textbf{input}, but once -parsed, the input becomes an \emph{ople} which is -(morally) a tree whose leaves are \emph{atoms} (and the empty set). -This discussion can also be revisited with footnote -%%\footref{fn:alttree} -\ref{fn:alttree} in mind. - -\subsubsection{Farewell, thanks for your visit!} - -I hope this is clear to everyone. If not, maybe time to say this section is -not needed to understand almost all of the manual, but I needed to -write it to be able to maintain in future my own software. - -\subsection{The three parsers} - -\xintexprname provides three numerical expression parsers and two subsidiary -ones. They are designed to be compatible with expansion only context. All -computations ultimately rely on (and reduce to) usage of the |\numexpr| -primitive from \eTeX{}% -% -\footnote{It can handle only integers, and they must be at most -$2^{31}-1={}$\dtt{\the\numexpr"7FFFFFFF\relax}. Thus some work has to be done -to handle arbitrarily big integers or arbitrary float precision.}. -% -These \eTeX{} extensions date -back to 1999 and are by default incorporated into the |pdftex| -etc...\@ executables from major modern \TeX{} installations for more than -fifteen years now. +\begin{framed} + Please note the following: + \begin{itemize}[noitemsep] + \item Although \csbxint{eval} manipulates arbitrarily long integers or + fractions it also accepts scientific notation on input, as well as + all the mathematical functions (evaluated using the prevailing + digits precision), and (depending on customization) can thus produce + also scientific notation on output. + \item So far, individual operations and the printing routine of + \csbxint{eval} do not automatically reduce fractions to their lowest + terms. + \end{itemize} +\end{framed} +% They are designed to be compatible with expansion only context. All +% computations ultimately rely on (and reduce to) usage of the |\numexpr| +% primitive from \eTeX{}% +% % +% \footnote{It can handle only integers, and they must be at most +% $2^{31}-1={}$\dtt{\the\numexpr"7FFFFFFF\relax}. Thus some work has to be done +% to handle arbitrarily big integers or arbitrary float precision.}. +% % +% These \eTeX{} extensions date +% back to 1999 and are by default incorporated into the |pdftex| +% etc...\@ executables from major modern \TeX{} installations for more than +% fifteen years now. +The interface is: \begin{itemize} \item \csbxint{eval}\marg{expression} handles integers, decimal numbers, numbers in scientific notation and fractions. The algebraic computations are @@ -5142,43 +4854,66 @@ fifteen years now. \xinteval{add(x/(x+1), x = 1000..1014)}\par \end{everbatim*} In this example, the fraction obtained by addition is already -irreducible, but this is not always the case: -\begin{snugframed} - By default, basic operations on fractions do not automatically reduce to - smallest terms the output: |A/B| multiplied by |C/D| - returns |AC/BD|, and |A/B| added to |C/D| uses |lcm(B, D)| as denominator. -\end{snugframed} +irreducible, but this is not always the case, as pointed above + Arbitrarily long numbers are allowed in the input. The space character (contrarily to the situation inside |\numexpr|) and also the underscore character (as allowed in Python too) can serve to separate groups of digits for better readability. But the package currently provides no macros to let the output be formatted with such separators. - -Formatting of numeric output is apart from some minimal facilities such as -\csbxint{TeXfromSci}\NewWith{1.4g}, -\csbxint{TeXFrac}, \csbxint{DecToString}, \csbxint{PRaw}, \csbxint{FracToSci} or \csbxint{PFloat} left -to user macros or third-party packages% \begin{everbatim*} \xinteval{123_456_789_012^5} \end{everbatim*} -\item \csbxint{iieval}\marg{expression} does exact computations \emph{on (big) - integers only.} It is (of course) slightly faster than \csbxint{eval} for - equivalent operations. The forward slash \oper{/} does the \emph{rounded} - integer division to match behaviour of |\numexpr|. The \oper{//} operator - does floored division as in \csbxint{eval}. The \oper{/:} is the associated +\item \csbxint{ieval}\oarg{D}\marg{expression} is the same parser as + \csbxint{eval}, i.e. accepts the same inputs and does all computations + exactly in the same manner, but it then rounds its final result to the + nearest integer, or, in case there is an optional argument |[D]|, to: + \begin{itemize} + \item if |D>0|: the nearest fixed point number with |D| digits after the + decimal mark, + \item if |D=0|: the nearest integer (as for \csbxint{ieval} with no optional argument), + \item if |D<0|: the rounded quotient by |10^(-D)|.\CHANGED{1.4f} + \end{itemize} + + Prior to |1.4k| the optional argument \oarg{D} had to be located + \emph{within} the braces at the start of the expression. At long last, this + is not required anymore.\NewWith{1.4k} The legacy syntax is and will keep + being allowed. + +\item \csbxint{iieval}\marg{expression} executes computations \emph{on (big) + integers only.} It is (only slightly) faster than \csbxint{eval} for + the same expression. + + Attention: the forward slash \oper{/} does the \emph{rounded} integer + division to match behaviour of |\numexpr|. The \oper{//} operator does + floored division as in \csbxint{eval}. The \oper{/:} is the associated modulo operator (we could easily let the catcode 12 |%| - character be an alias, but using such an unusual percent character would be - a bit cumbersome in a \TeX{} workflow, if only for matters of + character be an alias, but using such an unusual percent character + would be a bit cumbersome in a \TeX{} workflow, if only for matters of syntax highlighting in \TeX-aware text editors). \begin{everbatim*} \xintiieval{add((i/:7)?{omit}{i^5}, i=1000..1020)}% only add fifth powers of multiples of 7 \end{everbatim*} -\item \csbxint{floateval}\marg{expression} does floating point computations - with a given precision \dtt{P}, as specified via a prior assignment - |\xintDigits:=P\relax |. The \oper{/} will compute the correct rounding of - the exact fraction. Again \oper{//} is floored division and \oper{/:} its +\item \csbxint{floateval}\oarg{Q}\marg{expression} does floating point + computations with a given precision |P|, as specified via a prior + assignment |\xintDigits:=P\relax | (the value |P| can be recovered + via \csbxint{theDigits}). + + Its optional argument |[Q]|, if present, means to do a \emph{final} float + rounding to a mantissa of |Q| digits (this thus makes sense only if + |Q<P|). + + A negative |Q| is allowed and means to round to |P+Q| digits only. + + Prior to |1.4k| the optional argument \oarg{Q} had to be located + \emph{within} the braces at the start of the expression. At long + last, this is not required anymore.\NewWith{1.4k} The legacy syntax is + and will keep being allowed. + + The infix operator \oper{/} will compute the correct rounding of the exact + fraction. The operator \oper{//} is floored division and \oper{/:} is its associated modulo (see also \func{divmod}). \begin{everbatim*} \begingroup @@ -5187,66 +4922,49 @@ to user macros or third-party packages% \endgroup \end{everbatim*} - The default is with \dtt{P=16} digits. The four basic - operations and the square root realize \emph{correct + The four basic operations and the square root achieve \emph{correct rounding.}\footnote{when the inputs are already floating point numbers with at most |P|-digits mantissas.} - It can be used with an optional argument |[Q]| which means to do a final - float rounding to mantissas of |Q| digits (this makes - sense only if |Q<P|). ATTENTION: the optional argument |[Q]| is to be - located \emph{within} the braces at the start of the expression. - - When |Q| is negative it means to round to |P+Q| digits only. - - On output, \csbxint{floateval} uses \csbxint{PFloat} for each number. This - can be modified (cf.\@ \csbxint{floatexprPrintOne}). + On output, \csbxint{floateval} uses \csbxint{PFloat} for each numeric + leaf. This can be modified (cf.\@ \csbxint{floatexprPrintOne}). \end{itemize} -The user can define variables and functions. Definition of functions is either -per parser (\csbxint{deffunc}, \csbxint{deffloatfunc}, ...), but there are -some restrictions, or generic (\csbxint{NewFunction}) but the latter is only -syntactic sugar for function-like disguise of a \TeX{} macro having not done -any pre-parsing. - -Two derived parsers: -\begin{itemize} -\item \csbxint{ieval}\marg{expression} does all computations like \csbxint{eval} - but rounds the result to the nearest integer. If there is an optional - argument |[D]|, the rounding is to: - \begin{itemize} - \item if |D>0|: the nearest fixed point number with |D| digits after the - decimal mark, - \item if |D=0|: the nearest integer, - \item if |D<0|: the rounded quotient by |10^(-D)|.\CHANGED{1.4f} - \end{itemize} - ATTENTION: the optional argument - |[D]| is to be located \emph{within} the braces at the start of the expression. -\item \csbxint{theboolexpr}\meta{expression}|\relax| does all computations like \csbxint{eval} - then converts all (non-empty) leaves% -% -\footnote{Currently, empty leaves are output using \csbxint{exprEmptyItem}, - i.e.\@ default to \dtt{\xintexprEmptyItem}. This may change.} -% -to |True| or |False| - (cf.\@ \csbxint{boolexprPrintOne}). There is no |\xintbooleval|. -\end{itemize} +% The user can define variables and functions. Definition of functions is either +% per parser (\csbxint{deffunc}, \csbxint{deffloatfunc}, ...), but there are +% some restrictions, or generic (\csbxint{NewFunction}) but the latter is only +% syntactic sugar for function-like disguise of a \TeX{} macro having not done +% any pre-parsing. -These macros are wrappers for a more core syntax: +There is a core syntax: \begin{itemize}[nosep] \item \csbxint{expr}\meta{expression}|\relax|, + \item \csbxint{iexpr}\meta{expression}|\relax|, \item \csbxint{iiexpr}\meta{expression}|\relax|, \item \csbxint{floatexpr}\meta{expression}|\relax|, - \item \csbxint{iexpr}\meta{expression}|\relax|, \item \csbxint{boolexpr}\meta{expression}|\relax|. \end{itemize} -This core syntax can be used directly in typesetting flow.\NewWith{1.4} In an -|\edef| they expand to some braced nested data (all computations having been -done) prefixed with some |\protected| «typesetter» macros. When using -\csbxint{eval} (in contrast to \csbxint{expr}), the protection of the -«typesetter» is by-passed and its action gives (expandably) -explicit digits and other characters such as those of scientific notation or -brackets.% +\csbxint{boolexpr}\meta{expression}|\relax| does all computations like +\csbxint{expr} then converts all (non-empty) leaves% +% +\footnote{Currently, empty leaves are output using \csbxint{exprEmptyItem}, + i.e.\@ default to \dtt{\xintexprEmptyItem}. This may change.} +% +to |True| or |False| (cf.\@ \csbxint{boolexprPrintOne}). There is no +|\xintbooleval|. + +Formerly this legacy syntax needed to be prefixed by |\xintthe| to appear in +the typesetting token flow. It may now be omitted.\NewWith{1.4} + +In an |\edef| these constructs expand to some braced nested data, all +computations having been completely done, which is prefixed with some +|\protected| «typesetter» macros. + +In an |\edef|, \csbxint{eval} (in contrast to \csbxint{expr}), or +\csbxint{floateval} (in contrast to \csbxint{floatexpr}) expand the +«typesetting macros» and the final complete expansion consists of +explicit digits and other characters such as those of scientific +notation or square brackets.% % \footnote{\csbxint{eval} and \csbxint{expr} both expand completely in exactly two steps. And \csbxint{expr} expands fully under \fexpan sion (of the @@ -5254,95 +4972,170 @@ brackets.% expand to nothing, then naturally \fexpan sion propagates to tokens following up in the input stream.} -It is possible to use the core syntax\NewWith{1.4} +In \LaTeX\ it is possible to use the core syntax\NewWith{1.4} \csbxint{expr}\meta{expression}|\relax| also in so-called moving arguments, -because when written out to a file the final expansion result uses only -standard catcodes and thus will get retokenized and the typesetter macro -(which being |\protected| is there intact in external file) will expand -as expected. +because when written out to a file the final expansion outcome uses only +standard catcodes and thus will get retokenized and expand as expected if +it has been written to an external file which is then reloaded. -One needs \csbxint{eval} et al.\@ only if one really wants the final digits (and -other characters), for example in a context where \TeX{} expects a number or a -dimension. +One needs \csbxint{eval} et al.\@ only if one really wants the final digits +(and other characters), for example in a context where \TeX{} expects a number +or a dimension. As alternative to \csbxint{eval}\marg{expression}, an equivalent is \csbxint{the}\csbxint{expr}\meta{expression}|\relax|. Similarly \csbxint{the} can prefix all other core parsers. And one can also use \csbxint{theexpr} as shortcut for \csbxint{the}\csbxint{expr}. -Throughout this documentation I will most of the time refer to \csbxint{eval} -and \csbxint{expr}. But beware that doing exact computations with fractions -leads very quickly to very big results (and furthermore one needs to use -explicitly the |reduce()| function to convert the fractions into smallest -terms). Thus most probably what you want is \csbxint{floateval} and -\csbxint{floatexpr}. - -\subsection{Expansion} +Doing exact computations with fractions leads very quickly to very big results +(and furthermore one needs to use explicitly the |reduce()| function to +convert the fractions into smallest terms). Thus most probably what you want +is \csbxint{floateval} and \csbxint{floatexpr}. -As mentioned already, the parsers are compatible with expansion-only -context. -Also, they expand the expression piece by piece: the normal mode of operation -of the parsers is to unveil the parsed material token by token. Unveiling is -a process combining space swallowing, brace removal (one level generally), and -\fexpan sion. +\subsection{Customization of the output from the three parsers} +\label{xintexprEmptyItem} +\label{xintexprPrintOne} +\label{xintiexprPrintOne} +\label{xintiiexprPrintOne} +\label{xintfloatexprPrintOne} +\label{xintboolexprPrintOne} -For example a closing parenthesis after some function arguments does not have -to be immediately visible, it and the arguments themselves may arise from -\fexpan sion (applied before grabbing each successive token). Even the ending -|\relax| may arise from expansion. Even though the \csbxint{eval} user -interface means that the package has at some point the entire expression in -its hands, it immediately re-inserts it into token stream with an additional -postfixed |\relax| and from this point on has lost any ways (a simple-minded -delimited macro won't do because the expression is allowed to contain -sub-\csbxint{expr}essions, even nested) to manipulate formally again the whole -thing; it can only re-discover it one token at a time. +The package provides only minimal facilities for formatting the numeric +output. A possibly not up-to-date list is (the first two use math +mode mark-up): \csbxint{TeXfromSci}, \csbxint{TeXFrac}, \csbxint{DecToString}, +\csbxint{PRaw}, \csbxint{FracToSci}, \csbxint{FracToDecimal}, +\csbxint{PFloat} and +\csbxint{FloatToDecimal}. More advanced formatting is left for the user to +provide by own macros or possibly using third-party packages. -This general behaviour (which allows much more freedom in assembling -expressions than is usually the case with familiar programming languages such -as Python, although admittedly that freedom will prove useful only to -power-\TeX users and possibly does not have that many significant use cases) -has significative exceptions. These exceptions are mostly related to -«pseudo»-functions. A «pseudo»-function will grab some of its arguments via -delimited macros. For example |subs(expr1,x=expr2)| needs to see the comma, -equal sign and closing parenthesis. But it has mechanisms to allow |expr1| and -|expr2| to possess their own commas and parentheses. - -Inner semi-colons on the other hand currently always can originate from expansion. -Defining functions or variables requires a visible semi-colon acting as -delimiter of the expression, but inner semi-colons do not need to be -hidden within braces or macros\NewWith{1.4}. +It is indeed possible to configure the parsers to use custom macros for output. +Here are the default package definitions: +\begin{everbatim} +\def\xintexprEmptyItem{[]} +\def\xintexprPrintOne{\xintFracToSci} +\def\xintiexprPrintOne{\xintDecToString} +\def\xintiiexprPrintOne #1{#1} +\def\xintfloatexprPrintOne{\xintPFloat} +\def\xintboolexprPrintOne#1{\xintiiifNotZero{#1}{True}{False}} +\end{everbatim} +The typesetter for \csa{xintiiexpr} simply prints ``as is'', but this +may change in future, if some internal format is used requiring a +conversion step. Users can copy the above (\LaTeX\ users may want to +use |\renewcommand|) and modify the chosen macros. -The expansion stops only when the ending |\relax| has been found -(it is then removed from the token stream). +Regarding the current behaviour of \csbxint{floateval}, here is the +default configuration of \csbxint{PFloat}: +\begin{everbatim} +\def\xintPFloatE{e} +\def\xintPFloatZero{0} +\def\xintPFloatIntSuffix{} +\def\xintPFloatLengthOneSuffix{} +\def\xintPFloatNoSciEmax{5} +\def\xintPFloatNoSciEmin{-4} +\def\xintPFloatMinTrimmed{4} +\end{everbatim} +With the custom +\begin{everbatim} +\def\xintfloatexprPrintOne{\xintFloatToDecimal} +\end{everbatim} +the \csbxint{floateval} output wil use decimal fixed point notation, +i.e.\@ no scientific exponents, and as many zeros as are needed (but no +more, as trailing zeros will be removed from the significant digits). +Here is an example with the +default configuration and then when using \csbxint{FloatToDecimal}: +\begingroup % DÉBUT DU GROUPE POUR DES EXEMPLES +\begin{everbatim*} +\xintfloateval{exp(-32.456)/2000}\newline +\def\xintfloatexprPrintOne{\xintFloatToDecimal}% +\xintfloateval{exp(-32.456)/2000}\par +\end{everbatim*} -For catcode related matters see \csbxint{exprSafeCatcodes}. +Similarly, with +\begin{everbatim} +\def\xintexprPrintOne{\xintFracToDecimal} +\end{everbatim} +the \csbxint{eval} output will use decimal fixed point notation (for the +numerators; the denominators are simply post-fixed with a |/| +delimiter). See \csbxint{FracToDecimal}, which like \csbxint{FracToSci} +however is not really a user level macro, it is restricted on its input +format, it understands only what is needed for the internal structure +currently used by \csbxint{eval}. Here is with the same input as above: +\begin{everbatim*} +\xinteval{exp(-32.456)/2000}\newline +\def\xintexprPrintOne{\xintFracToDecimal}% +\xinteval{exp(-32.456)/2000}\par +\end{everbatim*} +Notice that the |/2000| denominator remains ``as is'' in the +output in both cases, in conformity with the documented behaviour of +\csbxint{FracToSci} in the first example and of \csbxint{FracToDecimal} +for the second example. This has not changed since |1.4| (the handling +of the numerator part has changed at |1.4e| and again slightly at +|1.4k|, the zero value being now always printed as \dtt{0} and not +\dtt{0} or \dtt{0.0} depending on the input) but is to be considered +unstable and undecided so far. + +A more costly typesetter could be for example: +\begin{everbatim} +\def\xintexprPrintOne#1{\xintDecToStringREZ{\xintIrr{#1}}} +\end{everbatim} +Then the fraction (inclusive of its power of ten part) will be reduced +to lowest terms (see \csbxint{Irr}), next the trailing zeros will be +moved as an exponent (positive or negative) to the numerator, and +finally this numerator with a power of ten part will be printed in +decimal fixed point notation, with as few zeros as are needed. With the +use case above: +\begin{everbatim*} +\def\xintexprPrintOne#1{\xintDecToStringREZ{\xintIrr{#1}}} +\xinteval{exp(-32.456)/2000}\par +\end{everbatim*} +This trailing |/2| is somewhat of a pain, but as documented and +mentioned already \csbxint{DecToStringREZ} currently has not been +educated to identify its presence and handle it. Slightly faster (see +\csbxint{PIrr}) is +\begin{everbatim} +\def\xintexprPrintOne#1{\xintDecToStringREZ{\xintPIrr{#1}}} +\end{everbatim} +which with the used example produces the same output. -A word of warning on the bracketed optional argument of respectively -\csbxint{floatexpr} and \csbxint{iexpr}. When defining macros which will hand -over some argument to one of these two parsers, the argument may potentially -start with a left square bracket |[| (e.g. argument could be |[1, 2, 3]|) and -this will break the parser. The fix is to use in the macro definition -|\xintfloatexpr\empty|. This extra |\empty| token will prevent the parser -thinking there is an optional argument and it will then disappear during -expansion. +\endgroup % FIN DU GROUPE POUR LES EXEMPLES + +\medskip +Nested structures (for full internal details, see \autoref{oples}) +are rendered by default using left and right brackets, +commas and spaces in a non-customizable way, except via +\csa{xintexprEmptyItem}. For full customizability, use +\csbxint{thealign}, which is described in the next section. + +% The \csbxint{PFloatE} is now allowed to a be macro with an argument delimited +% by a dot, this argument will be the exponent.\NewWith{1.4e} The output must be produced +% \fexpan dably and again be delimited by a dot. The default does not grab the +% exponent and simply inserts the letter |e|. + +\paragraph{\TeX hackers note:} +Attention! The macros used in place of \csbxint{FracToSci} and +\csbxint{PFloat} must currently understand the raw \xintfracname format +|A/B[N]|, with the |/B| and |[N]| parts being optional. These requirements +may change at any release. + +Currently the interface for the macro used by +\csbxint{floatexprPrintOne} % changed at |1.4e|.\CHANGED{1.4e} +must be the same as +\csbxint{PFloat}. %, i.e. the target precision is |[P]| not a +%braced argument. +But it will always be employed with the |[P|] present hence does not +have to consider it to be optional. + +The replacement macros must be compatible with expansion-only context, but do not +have to be \fexpan dable. -\begin{footnotesize} - If comparing to other languages able to handle floating point numbers or big - integers, such as Python, one should take into account that what the \xintname - packages manipulate are streams of ascii bytes, one per digit. At no time - (due to expandability) is it possible to store intermediate results in an - arithmetic CPU register; each elementary operation via |\the\numexpr| will - output digit tokens (hence as many bytes), not things such as handles to - memory locations where some numbers are stored as memory words. The process - can never put aside things but can only possibly permute them with upcoming - tokens, to use them later, or, via combinations of |\expanded| and - |\unexpanded| or some other more antiquated means grab some tokens and shift - the expansion to some distant locations to later come back. The process is a - never-ending one-dimensional one...\par -\end{footnotesize} +% % pour mémoire +% \footnote{The constraints on any replacement to \csbxint{FracToSci} are much +% simplified at |1.4e|. Previously it had to be able to accept also input in +% fixed point notation, and in scientific notation with a catcode 12 |e|.} +% % -\subsection{\csh{xintthealign} and its customization} +\subsubsection{\csh{xintthealign} for multiple items outputs} \label{xintthealign} With \csbxint{thealign} one can get nested data use a \TeX{} alignment in the @@ -5419,63 +5212,6 @@ l.c.m.=\xintthealign\xintiiexpr ndmap(lcm, 1..12; 1..10)\relax \] \end{everbatim*} -\subsection{Customization of typesetting of individual items} -\label{xintexprEmptyItem} -\label{xintexprPrintOne} -\label{xintiexprPrintOne} -\label{xintiiexprPrintOne} -\label{xintfloatexprPrintOne} -\label{xintboolexprPrintOne} - -The way individual items are formatted (whether or not using -\csa{xintthealign}) is also customizable. Here are the default package -definitions: -%\kern-2pt -% the \kern is to fix some extra white line from first line being a bit overfull -\begin{everbatim} -\def\xintexprEmptyItem{[]} -\let\xintexprPrintOne\xintFracToSci -\let\xintiexprPrintOne\xintDecToString -\def\xintiiexprPrintOne #1{#1} -\let\xintfloatexprPrintOne\xintPFloat -\def\xintPFloatE{e} -\def\xintboolexprPrintOne#1{\xintiiifNotZero{#1}{True}{False}} -\end{everbatim} -Attention! The above macros convert from \xintexprname internal numeric data -format to «printed» output; they are thus susceptible to require adjustments -if the internal data format changes, which may happen at each release. Of course -the default for |\xintexprPrintOne| etc...\@ will be adjusted accordingly, but -user custom definitions may break. - -The interface for \csbxint{floatexprPrintOne} was changed.\CHANGED{1.4e} -It must now be the same as \csbxint{PFloat}, i.e. the target precision is |[P]| not a -braced argument. It will always be used with this |[P|] present so does not -have to consider it to be optional. It still must be expandable. - -The \csbxint{PFloatE} is now allowed to a be macro with an argument delimited -by a dot, this argument will be the exponent.\NewWith{1.4e} The output must be produced -\fexpan dably and again be delimited by a dot. The default does not grab the -exponent and simply inserts the letter |e|. - -Currently, this means that the macros used in place of \csbxint{FracToSci} and -\csbxint{PFloat} should understand the raw \xintfracname format |A/B[N]|, with -the |/B| and |[N]| parts being optional.% -% -\footnote{The constraints on any replacement to \csbxint{FracToSci} are much - simplified at |1.4e|. Previously it had to be able to accept also input in - fixed point notation, and in scientific notation with a catcode 12 |e|.} -% -The typesetter for -\csa{xintiiexpr} simply prints ``as is'', but this may change in future. - -The used macros must be compatible with expansion-only context, but do not -have to be \fexpan dable. - -Note: when not using \csbxint{thealign}, output of nested structures uses left -and right brackets, and commas and spaces in a non-customizable way, except -via \csa{xintexprEmptyItem}. Use the \csa{xintthealign} interface for full -customizability. - \subsection{Built-in operators and their precedences} @@ -6013,10 +5749,10 @@ Miscellaneous notes: % labelwidth=-\fontdimen2\font, labelsep=\fontdimen2\font, labelindent=0pt, % listparindent=\leftmarginiii] - \funcdesc[]{random} returns a random float |x| verifying |0 <= x < 1|. It obeys - the prevailing precision as set by \csbxint{Digits}: i.e.\@ with |P| being the - precision the random float multiplied by |10^P| is an integer, uniformly - distributed in the |0..10^P-1| range. + \funcdesc[]{random} returns a random float |x| verifying |0 <= x < 1|. It + obeys the prevailing precision as set by \csbxint{Digits}: i.e.\@ with |P| + being the precision the random float multiplied by |10^P| is an integer, + uniformly distributed in the |0..10^P-1| range. This description implies that if |x| turns out to be |<0.1| then its (normalized) mantissa has |P-1| digits and a trailing zero, if |x<0.01| @@ -8243,6 +7979,454 @@ some example here... % obtained via the expansion of the package macros during the \TeX{} % run.% +\subsection{Oples and nutples: the \texttt{1.4} terminology} +\label{oples} + +\emph{Skip this on first reading, else you will never start using the + package.} \fbox{SKIP THIS!} (understood?) + +In this section I will describe a mathematical terminology which models +how the parser handles the input syntax with numbers, commas, and brackets, +and how it maps internally to \TeX\ specific concept, particularly braces and +macro arguments. + +\etocsetnexttocdepth{subsubsection} +\localtableofcontents + +\subsubsection{Base terminology} + +We start with a set $\mathcal{A}$ of \emph{atoms}, which represent numeric +data. In \TeX{} syntax such \emph{atoms} are always braced, more precisely, +currently they look like +% +\centeredline{\dtt{\{raw format within \TeX{} braces\}}} +% +The \TeX{} braces are not set-theoretical braces here, they are simply used +for \TeX nical reasons (one could imagine using rather some terminator token, +but ultimately support macros for built-in and user defined functions rely on +\TeX\ macros with undelimited parameters, at least so far). + +Our category $\mathcal{C}$ of «oples» is the smallest collection of +\emph{totally ordered finite sets} verifying these properties: +\begin{enumerate} +\item The empty set \dtt{$\emptyset$} is an \emph{ople}, i.e.\@ it belongs to + $\mathcal{C}$. +\item Each singleton set \dtt{$\{O\}$} whose element \dtt{$O$} is either an + \emph{atom} $a\in\mathcal{A}$ or an \emph{ople} qualifies as an \emph{ople}. +\item $\mathcal{C}$ is stable by concatenation. +\end{enumerate} + +Notes: +\begin{itemize} +\item +We refer to the empty set \dtt{$\emptyset$} via the variable \emph{nil}.% +% +\footnote{There is +actually a built-in variable with this name. At |1.4|, |\xintexpr\relax| is +legal and also generates the \emph{nil}.} + +\item It is convenient to accept the empty set as being also an + \emph{atom}. If this is done, then we may refer to the original + \emph{atoms} (elements of $\mathcal{A}$) as \emph{non empty numerical data}. + +\item +Concatenation is represented in the syntax by the +comma. Thus repeated commas are like only one and |nil| is a neutral element. + +\item A singleton \emph{ople} \dtt{$\{a\}$} whose single element is a + (non-empty) \emph{atom} is called a \emph{number}.% +% + \footnote{This has to be taken in a general sense, for example with + \ctanpackage{polexpr}, polynomials are represented by such «numbers».} +% + +\item +The operation of constructing \dtt{$\{O\}$} from the \emph{ople} \dtt{$O$} is +called \emph{bracing} (set theory, \TeX), or \emph{bracketing} (\xintexprname +input syntax, Python |lists|), or \emph{packing} (as a reverse to Python's +unpacking of sequence type objects). In the expression input syntax it +corresponds to enclosing \dtt{$O$} within square brackets: \dtt{$[O]$}. + +\item A braced \emph{ople} is called a \emph{nutple}. Among them \dtt{\{nil\}} + (aka $\{\emptyset\}$) is a bit special. It is called the \emph{none-ple}.% +% + \footnote{Prior to version |1.4j| of this documentation it was called the + \emph{not-ple}.} +% +It is not \dtt{nil}.% +% +\footnote{There is (experimental) a pre-defined «\dtt{None}» variable which + stands for the \emph{none-ple}. It can also be input as |[]|.} +\end{itemize} + +Each \emph{ople} has a \emph{length} which is its cardinality as set. The +singleton |oples| are called \emph{one-ples}. There are thus two types of +\emph{one-ples}: +\begin{itemize} +\item \emph{numbers} \dtt{$\{a\}$}, $a \in \mathcal{A}$, +\item \emph{nutples} \dtt{$\{O\}$}, $O \in \mathcal{C}$. +\end{itemize} + +If we consider the empty set |nil| on the same footing as |atoms|, the two +types have only one common object which is the \emph{none-ple}. As a rule +arithmetic operations will either break or silently convert the \emph{none-ple} +to the zero value: +\begin{everbatim*} +\xinteval{3+[], 5^[], 10*[]} +\end{everbatim*}. +But attention that \csbxint{iieval} in contrast to \csbxint{eval} is broken by +such inputs. + +\subsubsection{Items (and sub-items) versus elements} + +In order to illustrate these concepts, let us consider how one should +interpret notation such as |3,5,7,9| when it arises in an +\csbxint{expr}|ession|: +\begin{description} +\item[tempting vocabulary:] Each of |3|, |5|, |7|, and |9| is an \emph{item}, or + \emph{element} of the (comma separated) \emph{list}. In other terms we have + here a list with 4 items. +\item[rigorous vocabulary:] each one of |3|, |5|, |7|, |9| stands for an + \emph{ople} (of the \emph{one-ple} type) and |3,5,7,9| stands for their \emph{concatenation}. +\end{description} +It is important to understand that in an \csbxint{expr}|ession|, there is no +difference between |3,5,7| and |3,,,,5,,,,,,,,,7|. So the view of the comma +as separator is misleading. In other terms, the comma is NOT a separator but +the (associative) operator of concatenation of totally ordered sets, and the +number |3| for example represents a (singleton) set. + +If we want to refer to |3| or |5| or |7| or |9| as «the items of the +(open) list |3,5,7,9|» (and probably this documentation already has such +utterances, due to legacy reasons from the pre-|1.4| internal model), we +\emph{must} realize that this clashes with using the word \emph{item} as +synonymous to \emph{element} in the set-theoretical sense. + +To repeat, any ople \dtt{$O$} is a finite totally ordered set: if not the empty +set, it has \emph{elements} \dtt{$a_1$}, \dots, \dtt{$a_k$}, and the above means that +its \emph{items} are the singleton oples (aka one-ples) \dtt{$I_1=\{a_1\}$}, +\dots, \dtt{$I_k=\{a_k\}$}. Each \dtt{$a_j$} may be an |atom|, then +\dtt{$I_j$} is a |number|, or \dtt{$a_j$} is an |ople| (possibly the empty set), then +\dtt{$I_j$} is a |nutple| whose depth is one more than the one of the ople +\dtt{$a_j$}. + +Thus we can refer to «items» but must then understand they are not «elements»: +«items» are «singleton sub-sets». The cardinality (aka length) of an ople is +also the number of its +items. It would be tempting to use the terminology «sub-item» to keep in mind they are «sub-sets» +but this would again create confusion: a |nutple| has only one item which is +itself; and we need some terminology to refer to the individual numbers in the +|nutple| given in input as |[1,2,3]| for example. It is natural to refer to +|1|, |2|, |3| as «sub-items» of |[1,2,3]| as the latter may be an «item» (it +is in particular an «item» of itself, the unique one at that). + +We distinguish the |oples| of length zero (there is only one, the empty set) +or at least two as those which can never be an «item». Those of length one, +the |one-ples|, are exactly those which can be «items». Among them some may +have «sub-items», they are the |nutples| with the exception of the |none-ple|. +And the others do not have «sub-items», they are the |numbers| and the |none-ple| (whose input syntax is +either |[]| or the variable |None|).% +% +\footnote{% +A note on the \csbxint{verbosetrue} regime: for a variable defined to be +|3,5,7,9|, it will say that its value is |{3}{5}{7}{9}|, because it does not +keep the external set-theoretical braces. The braces here are only \TeX{} +braces, and |{3}| is an |atom|. The |number| would be |{{3}}| with the +external braces being set-theoretical and also used internally as \TeX{} +braces. From the four numbers |{{3}}|, ..., |{{9}}| concatenation gives +|{{3}{5}{7}{9}}|, which is the |ople| |3,5,7,9|. But the log view drops +deliberately the external braces. If the variable is defined to be the +|nutple| |[3,5,7,9]|, then the log view will be |{{3}{5}{7}{9}}| (up to +details on how exactly the numeric quantities are coded) and the actual +internal \TeX{} entity will be |{{{3}{5}{7}{9}}}|, where the two external +layers of braces are both set-theoretical and \TeX nical braces.} + + +\subsubsection{Oples as trees} + +We say that the empty set |nil| and \emph{atoms} are \emph{leaves}. + +We associate with any \emph{ople} a tree. The root is the ople. In the case of +the |nil| ople, there is nothing else than the root, which we then consider +also a \emph{leaf}. Else the children at top level are the successive +\emph{elements} (not «items»!) of the ople.% +% +\footnote{\label{fn:alttree}% + We could also consider a tree for which the children of the root node would + be its items and recursively; in that case the leaves would be |numbers| and + possibly the |None|. The tree of the |nil| would be the empty tree, the tree + of |None| would have a single node and no edges. Such a tree would match + the input syntax (of course applying the rule that iterated commas are like + only one). The tree which is described in this section matches more + directly the internal syntax, hence is more useful to the author, who is + also the sole reader who extracts some benefit from reading this + documentation once in a while.} +% +Among the elements some are \emph{atoms} giving \emph{leaves} of the tree, +others are \emph{nutples} which in turn have children. In the special case of +the \emph{none-ple} we consider it has a child, which is the empty set and this +is why we consider the empty set |nil| to be also a potential \emph{leaf}. We +then proceed recursively. We thus obtain from the root \emph{ople} a tree +whose vertices are either \emph{oples} or \emph{leaves}. Only the empty set +|nil| is both a \emph{leaf} and an \emph{ople}. + +Considering the empty set |nil| as an \emph{atom} fits with the \xintexprname +internal implementation based on \TeX: |nil| is an empty pair of braces |{}|, +whereas an \emph{atom} is a braced representation of a numeric value using +digits and other characters. We construct \emph{oples} by putting one after +the other such constituents and bracing them, and then repeating the process +recursively. + +It has also an impact on the definition of the \emph{depth} (a.k.a as +\emph{maximal dimension}) of an \emph{ople}. For example the \emph{ople} +$\{\emptyset A_1A_2\}$ with three elements, among them the empty set and two +atoms is said to have depth $1$, or to have maximal dimension $1$. And +$\{\{\emptyset\}A_1A_2\}$ is of depth $2$ because it has a leaf (the empty +set) which is a child of a child of the \emph{ople}. NumPy \emph{ndarrays} +have a more restricted structure for example +$\{\{A_{00}A_{01}\}\{A_{10}A_{11}\}\}$ is a $2$-dimensional array, where all +leaves are at the same depth. When slicing empties the array from its atoms, +NumPy keeps the shape information but prints the array as $[]$. This will not +be the case with \xintexprname, which has no other way to indicate the shape +than display it. +\begin{everbatim*} +\xinteval{[[],[]]} +\end{everbatim*} +\begin{everbatim*} +\xinteval{[[0,1],[10,11]][:,2:]} +\end{everbatim*} + +\subsubsection{Ople slicing and indexing} +\label{sssec:opleslicing} + +«Set-theoretical» slicing of an \emph{ople} means replacing it with one of its +subsets. This applies also if it is a \emph{number}. Then it can be sliced +only to itself or to the empty set (indeed it has only one element, which is +an atom). Similarly the \emph{none-ple} can only be sliced to give itself or +the empty set. And more generally a \emph{nutple} is a singleton so also can +only be set-sliced to either the empty set or itself. + +\xintexprname extends «Python-like» slicing to act on \emph{oples}: +\begin{itemize}[nosep] +\item if they are not \emph{nutples} set-theoretical slicing applies, +\item if they are \emph{nutples} (only case having a one-to-one + correspondence in Python) then the slicing happens \emph{within brackets}: + i.e.\@ the \emph{nutple} is unpacked then the set-theoretical slicing is + applied, then the result is \emph{repacked} to produce a new \emph{nutple}. +\end{itemize} +With these conventions the \emph{none-ple} for example is invariant under +slicing: unpacking it gives the empty set, which has only the empty set as +subset and repacking gives back the \emph{none-ple}. Slicing a general +\emph{nutple} returns a \emph{nutple} but now of course in general distinct +from the first one. + +The input syntax for Python slicing is to postfix a variable or a +parenthesized ople with |[a:b]|. See \autoref{ssec:lists} for more. There +are never any out-of-range errors when slicing or indexing. All operations +are licit and resolved by the |nil|, a.k.a. empty set. + +«Set-theoretical» item indexing of an \emph{ople} means reducing it to a +subset which is a singleton. It is thus a special case of set-theoretical +slicing (which is the general process of selecting a subset as replacement of +a set). + +\xintexprname extends «Python-like» indexing to act on \emph{oples}: +\begin{itemize}[nosep] +\item if they are not \emph{nutples} set-theoretical item indexing applies, +\item if they are \emph{nutples} (only case having a one-to-one + correspondence in Python) then the meaning becomes \emph{extracting}: i.e.\@ + the \emph{nutple} is unpacked then the set-theoretical indexing is applied, + but the result is \emph{not repacked}. +\end{itemize} +For example when applied to the \emph{none-ple} we always obtain +the |nil|. Whereas as we saw slicing the \emph{none-ple} always gives back the +\emph{none-ple}. Indexing is denoted in the syntax by postfixing by |[N]|. Thus +for \emph{nutples} (which are analogous to Python objects), there is genuine +difference between the |[N]| extractor and the |[N:N+1]| slicer. But for +\emph{oples} which are either |nil|, a \emph{number}, or of length at least 2, +there is no difference. + +\subsubsection{Nested slicing of oples} + +Nested slicing is a concept from NumPy, which is extended by \xintexprname to +trees of varying depths. We have a chain of slicers and extractors. I will +describe only the case of slicers and letting them act on a |nutple|. The +first slicer gives back a new |nutple|. The second slicer will be applied to +each of one of its remaining elements. However some of them may be +\emph{atoms} or the empty set. In the NumPy context all leaves are at the +same depth thus this can happen only when we have reached beyond the last +dimension (axis). This is not permitted by NumPy and generates an error. +\xintexprname does not generate an error. But any attempt to slice an +\emph{atom} or the empty set (as element of its container) removes it. Recall +we call them \emph{leaves}. We can not slice leaves. We can only slice +non-leaf elements: such items are necessarily |nutples|. The procedure then +applies recursively. + +If we handle an extractor rather than a slicer, the procedure is similar: we +can not extract out of an \emph{atom} or the empty set. They are thus +removed. Else we have a |nutple|. It is thus unpacked and replaced by the +selected element. This element may be an atom or the empty set and any further +slicer or extractor will remove them, or it is a |nutple| and the procedure +applies with the next slicer/extractor. + +\xintexprname allows to apply such a |[a:b,c:d,N,e:f,...]| chain of +slicing/extracting also to an \emph{ople}, which is not a \emph{nutple}. We +simply apply the first step as has been described previously and successive +steps will only get applied to either \emph{nutples} or \emph{leaves}, the +latter getting silently removed by any attempted operation. + +\subsubsection{Function arguments versus variables} +\label{sssec:funcargs} + +In a function declaration with \csbxint{deffunc}, the call signature is parsed +as a comma separated list, so here it is not true that repeated commas are +like only one: repeated commas are not allowed and will break the function +declaration. + +When \xintexprname parses a function call, it first constructs the ople which +is delimited by the opening and closing parentheses, then it applies the +function body, after having mapped the successive items (not the elements) of +the parsed ople to the variables appearing in the function call +signature. Hence the arguments in the call signature stand for |one-ples| +(i.e.\@ either |numbers| or |nutples|). + +Let me explain why we can not define a function |foo(A,B)| of two oples: the +function call will evaluate as an ople what is enclosed within the +parentheses. It is then impossible in general to split this uniquely into two +oples |A| and |B|, except if for example we know a priori the length of |A|. +We could imagine defining a declarative interface for a |foo(A,B)| with |A| +preset to have \dtt{37} items or at least a pre-defined number of items but +this is extraneous layer for a functionality no-one will use. + +The alternative would be to consider that declaring |foo(A,B)| means |A| will +pick-up always the first item and |B| all the remaining ones, and thus will be +an ople; here, there are some \TeX nical implementation reasons which have +dissuaded the author to do this. + +In its place, a special syntax |foo(A,*B)| for the declaration of the function +is available. It means that |B| stands for the |nutple| which +receives as items all arguments in the function call beyond the first one +already assigned to |A|. + +More generally, the last positional argument in a function declaration can +have the form |*|\meta{argname}. This then means that \meta{argname} +represents a |nutple| which will receive as items all arguments in the +function call remaining after the earlier positional arguments have been +assigned. The declared function body is free to again use the syntax +|*|\meta{argname} which will unpack it and thus produce the ople concatenating +all such optional arguments. + +With \csbxint{defvar} one can define a variable with value an |ople| of +arbitrary cardinality. Such a variable can be used in a function call, it +will then occupy the place of as many arguments as its cardinality (which is +its number of elements, hence of its associated items). For example if +function |foo| was declared as a function of 5 arguments |f(a,b,c,d,e)| it is +legitimate to use it as |f(A,B)| if |A| is an ople-valued variable of length +three and |B| of length two. The actual arguments |a,b,c,d,e| will be made to +match the three items of |A| and the two items of |B|. + +\subsubsection{Final words on leaves} + +In case things were too clear, let's try to add a bit of confusion with an +extra word on \emph{leaves}. When we discuss informally (particularly to +compare with NumPy) an input such as +\begin{everbatim} +[[1, 2], [3, 4]] +\end{everbatim} +we may well refer to |1|, |2|, |3|, and |4| as being «the leaves of the 2d +array». But obviously we have here numbers and previously we explained that a +number is not a \emph{leaf}, its \emph{atom} is. Well, the point here is that +we must make a difference between the input form as above and the actual +constructed \emph{ople} the parser will obtain out of it. In the input we do +have numbers. The comma is a \emph{concatenator}, it is not a separator for +enumeration! The \emph{ople} which corresponds to it has a \TeX{} +representation like this: +\begin{everbatim} +{{{1}{2}}{{3}{4}}} +\end{everbatim} +where we don't have the \emph{numbers} anymore (which would look like |{{1}}|, +|{{2}}|, ...) but numeric \emph{atoms} |{1}|, |{2}|, |{3}|, |{4}| where the +braces are \TeX{} braces and \textbf{not} set-theoretical braces (the other +braces are both). Hence we should see the above as the |ople| +$\{\{A_{00}A_{01}\}\{A_{10}A_{11}\}\}$ with atoms $A_{00}=\{1\}$, ..., being the +\emph{leaves} of the tree associated to (or which is) the \emph{ople}. + +Numbers may be called the \emph{leaves} of the \textbf{input}, but once +parsed, the input becomes an \emph{ople} which is +(morally) a tree whose leaves are \emph{atoms} (and the empty set). +This discussion can also be revisited with footnote +%%\footref{fn:alttree} +\ref{fn:alttree} in mind. + +\subsubsection{Farewell, thanks for your visit!} + +I hope this is clear to everyone. If not, maybe time to say this section is +not needed to understand almost all of the manual, but I needed to +write it to be able to maintain in future my own software. + +\subsection{Expansion (for geeks only)} + +As mentioned already, the parsers are compatible with expansion-only +context. + +Also, they expand the expression piece by piece: the normal mode of operation +of the parsers is to unveil the parsed material token by token. Unveiling is +a process combining space swallowing, brace removal (one level generally), and +\fexpan sion. + +For example a closing parenthesis after some function arguments does not have +to be immediately visible, it and the arguments themselves may arise from +\fexpan sion (applied before grabbing each successive token). Even the ending +|\relax| may arise from expansion. Even though the \csbxint{eval} user +interface means that the package has at some point the entire expression in +its hands, it immediately re-inserts it into token stream with an additional +postfixed |\relax| and from this point on has lost any ways (a simple-minded +delimited macro won't do because the expression is allowed to contain +sub-\csbxint{expr}essions, even nested) to manipulate formally again the whole +thing; it can only re-discover it one token at a time. + +This general behaviour (which allows much more freedom in assembling +expressions than is usually the case with familiar programming languages such +as Python, although admittedly that freedom will prove useful only to +power-\TeX users and possibly does not have that many significant use cases) +has significative exceptions. These exceptions are mostly related to +«pseudo»-functions. A «pseudo»-function will grab some of its arguments via +delimited macros. For example |subs(expr1,x=expr2)| needs to see the comma, +equal sign and closing parenthesis. But it has mechanisms to allow |expr1| and +|expr2| to possess their own commas and parentheses. + +Inner semi-colons on the other hand currently always can originate from expansion. +Defining functions or variables requires a visible semi-colon acting as +delimiter of the expression, but inner semi-colons do not need to be +hidden within braces or macros\NewWith{1.4}. + +The expansion stops only when the ending |\relax| has been found +(it is then removed from the token stream). + +For catcode related matters see \csbxint{exprSafeCatcodes}. + +A word of warning on the bracketed optional argument of respectively +\csbxint{floatexpr} and \csbxint{iexpr}. When defining macros which will hand +over some argument to one of these two parsers, the argument may potentially +start with a left square bracket |[| (e.g. argument could be |[1, 2, 3]|) and +this will break the parser. The fix is to use in the macro definition +|\xintfloatexpr\empty|. This extra |\empty| token will prevent the parser +from thinking there is an optional argument and it will then disappear during +expansion. + +\begin{footnotesize} + If comparing to other languages able to handle floating point numbers or big + integers, such as Python, one should take into account that what the \xintname + packages manipulate are streams of ascii bytes, one per digit. At no time + (due to expandability) is it possible to store intermediate results in an + arithmetic CPU register; each elementary operation via |\the\numexpr| will + output digit tokens (hence as many bytes), not things such as handles to + memory locations where some numbers are stored as memory words. The process + can never put aside things but can only possibly permute them with upcoming + tokens, to use them later, or, via combinations of |\expanded| and + |\unexpanded| or some other more antiquated means grab some tokens and shift + the expansion to some distant locations to later come back. The process is a + never-ending one-dimensional one...\par +\end{footnotesize} \clearpage \etocdepthtag.toc {part1B} @@ -8279,6 +8463,10 @@ At \dtt{8} digits a special, faster, mode is used, which is less accurate. But f under friendly pressure of Jürgen \textsc{Gilg} and Thomas \textsc{Söll}, let them both be thanked here. +Jürgen passed away in 2022. I will miss our friendship which was born and grew +from numerous and regular exchanges on topics not limited to this package or +even the \TeX\ world. Let's now continue to «take care and keep motivated» ! + \subsection{\csh{xintreloadxinttrig}}\label{xintreloadxinttrig} The library is loaded automatically by \xintexprname at start-up. @@ -8717,7 +8905,7 @@ anecdotical evidence showing it is good. \markboth{\makebox[0pt]{\xintRunningHeader}}{\makebox[0pt]{\xintRunningHeader}} \etocdepthtag.toc {macros} -\addtocontents{toc}{\gdef\string\sectioncouleur{{joli}}} +\addtocontents{toc}{\gdef\string\sectioncouleur{{tocbundlesectioncolor}}} \addtocontents{toc}{\gdef\string\SKIPSECTIONINTERSPACE{\kern\smallskipamount}} \renewcommand{\etocaftertochook}{\addvspace{\bigskipamount}} @@ -9328,18 +9516,14 @@ be expressed as such a fraction even if the inputs are both integers and the mathematical result is an integer. The |B=1| is not removed.% % \footnote{refer to the documentation of \csbxint{PRaw} for an alternative.} -\item macros with |Float| in their names produce on output scientific -format with |P=|\nobreak\csbxint{theDigits} digits, a lowercase |e| and an -exponent |N|. The first digit is not zero, it is preceded by an optional minus -sign and is followed by a dot and |P-1| digits. Trailing zeroes are not -trimmed. There is one exceptional case: -\begin{itemize}[nosep] -\item if the value is mathematically zero, it is output as |0.e0|, - i.e.\@ zeros after the decimal mark are removed and the exponent is always |0|. -\end{itemize} -Future versions of the package may modify this. -\end{itemize} +\item macros from \xintfracname having |Float| in their names deliver a number + in the scientific notation as described in the documentation of + \csbxint{Float}. + The exceptions are \csbxint{PFloat} and its variant \csbxint{PFloatb} which + do some customizable pretty printing of the result. The former is also used + by default by \csbxint{floateval}. +\end{itemize} \subsection{Count registers and variables}\label{sec:useofcount} @@ -10811,7 +10995,7 @@ 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|. |\xintDSx|\x\n\etype{\numx f} for |x| negative is exactly as -|\xintDSH|\x\n, \emph{i.e.\@} multiplication by $10^{-|x|}$. For |x| zero or +|\xintDSH|\x\n, \emph{i.e.\@} multiplication by $10^{-\text{|x|}}$. For |x| zero or positive it returns the two numbers |{Q}{R}| described above, each one within braces. So |Q| is |\xintDSH|\x\n, and |R| is |\xintDSHr|\x\n, but computed simultaneously. @@ -10994,9 +11178,10 @@ satisfy |d>0| and |M^2-d=N| with \xintiiSub{\xintiiSqr\A}\B=\A\string^2-\B \end{everbatim*} -A rational approximation to $\sqrt{|N|}$ is $|M|-\frac{|d|}{|2M|}$ which is a -majorant and the error is at most |1/2M| (if |N| is a perfect square |k^2| -this gives |k+1/(2k+2)|, not |k|.) +A rational approximation to $\sqrt{\text{|N|}}$ is +$\text{|M|}-\frac{\text{|d|}}{\text{|2M|}}$ which is a majorant and the error +is at most |1/2M| (if |N| is a perfect square |k^2| this gives |k+1/(2k+2)|, +not |k|.) Package \xintfracname has \csbxint{FloatSqrt} for square roots of floating point numbers. @@ -11530,7 +11715,7 @@ to proceed is via a redefinition of \csbxint{floatexprPrintOne} and/or \csbxint{exprPrintOne}. \begin{everbatim*} \[\def\xintfloatexprPrintOne[#1]#2{\xintTeXfromSci{\xintPFloat[#1]{#2}}} - \xintfloateval{[10] 2^100, 3^100, 13^100}\] + \xintfloateval[10]{2^100, 3^100, 13^100}\] \end{everbatim*} \par\vskip-\belowdisplayskip \begin{everbatim*} @@ -11777,70 +11962,35 @@ from removing the |[N]| part if |N=0| and removing the |B| if |B=1|. \xintPRaw {123e10/321e10}, \xintPRaw {123e9/321e10}, \xintPRaw {\xintIrr{861/123}} \end{everbatim*} -\subsection{\csh{xintFracToSci}}\label{xintFracToSci} - - -\csa{xintFracToSci}\NewWith{1.4} is for usage by \csbxint{eval} for formatting -the output of numbers: the output routine of \csbxint{eval} uses -\csbxint{exprPrintOne} whose current default definition is: -\begin{everbatim} -\let\xintexprPrintOne\xintFracToSci -\end{everbatim} -Any replacement should obey the following blueprint: -\begin{itemize}[noitemsep] -\item to\xtype{} be expandable, but not necessarily \fexpan dable, -\item to accept on input |A|, |A/B|, |A[N]|, or |A/B[N]|, i.e. the ``raw'' - \xintfracname format, but with optional |/B| and |[N]| parts, - which can be called the ``relaxed raw format''. -\end{itemize} -These constraints\CHANGED{1.4e} are much simplified at |1.4e| (and \csa{xintFracToSci} has -been internally simplified to only have to obey the reduced constraints, which -is a breaking change). - -At |1.4e| the handling\CHANGED{1.4e} by this macro of input with a scientific -exponent part has changed. Rather than producing an integer mantissa it now -does as \csbxint{PFloat} (apart from the float-rounding of course) in -particular it trims out trailing zeros. - -Attention, \csa{xintFracToSci} does not behave as the other public macros from -\xintfracname: -\begin{itemize}[noitemsep] -\item it is expandable, but not \fexpan dable, so it can't appear as argument - to other \xintfracname macros without an explicit |\expanded{...}| wrapper - (as they only \fexpan d their arguments). -\item it expects input already (after \fexpan sion) in ``relaxed raw'' - \xintfracname format.\IMPORTANT{} -\end{itemize} - -\noindent\csa{xintFracToSciE} has been removed at |1.4e|, see \csbxint{PFloatE}. - \subsection{\csh{xintDecToStringREZ}}\label{xintDecToStringREZ} -\csa{xintDecToStringREZ}\etype{\Ff} uses fixed point notation -for the output. The argument is first parsed in the same way as for any other -\xintfracname macros,\NewWith{1.4e} which means that it is first transformed into an -internal format having a numerator |A|, a denominator |B| and a power of ten -exponent |N|. The following recipe applies: +\csa{xintDecToStringREZ}\etype{\Ff} uses fixed point (decimal) notation +for the output. The |REZ| means that it trims (REmoves) trailing Zeros. The name +is a bit strange, because\NewWith{1.4e} it its not limited to +\emph{decimal numbers} but accepts the same kind of inputs as most other +\xintfracname macros. The parsing of this input transforms it first +into an internal format having a numerator |A|, a denominator |B| and a +power of ten exponent |N|, standing for the fraction |A/B| times +\dtt{10} to the power |N|. Then the following recipe applies: \begin{itemize}[noitemsep] \item the zero value is printed as \dtt{\xintDecToStringREZ{0}} (no decimal point). \item trailing zeros of |A| and |B| are removed and |N| is adjusted, \item if the new |B| is not \dtt{1}, it will appear in the output as |/B|, -\item fixed point notation is used for |AeN|: +\item fixed point decimal notation is used for |AeN|: \begin{itemize}[noitemsep] \item if |N| is non-negative, the output is an integer with |N| trailing - zeros, + zeros (and no decimal mark) \item if |N| is negative a decimal point is used, and if |AeN| is less than - one in absolute value, output will start with \dtt{0.} (with a decimal point). + one in absolute value, output will start with \dtt{0.} (i.e. a decimal mark). \end{itemize} \end{itemize} -Please note the following: +The following should be noted: \begin{enumerate}[noitemsep] \item the fraction |AeN/B| or even |A/B| is not pre-reduced into lowest terms, \item the macro does not check if |B| contains only powers of \dtt{2} and \dtt{5}, so |1/2| is printed as \dtt{\xintDecToString{1/2}}, not as \dtt{0.5}. \end{enumerate} -The definitive behaviour remains to be decided regarding these two points. - +The definitive behaviour remains to be decided regarding these last two points. \begin{everbatim*} \xintDecToStringREZ{0}, \xintDecToStringREZ{1/2}, \xintDecToStringREZ{0.5000}\newline \xintDecToStringREZ{1.23456789e5}, \xintDecToStringREZ {1.23456789e-3}\newline @@ -11850,15 +12000,22 @@ The definitive behaviour remains to be decided regarding these two points. \xintDecToStringREZ{70/14} % is not reduced to lowest terms \end{everbatim*} +See \csbxint{FloatToDecimal} for a variant which first rounds the input +to some given number of significant digits. + \subsection{\csh{xintDecToString}}\label{xintDecToString} -\csa{xintDecToString}\etype{\Ff} uses fixed point notation for the output. It -was introduced at |1.3| as experimental backport from a -\href{http://ctan.org/pkg/polexpr}{polexpr} macro, and its behaviour remains -somewhat undecided in particular regarding whether it should identify inputs -which correspond to decimal numbers, \emph{after reduction to lowest terms}. +\csa{xintDecToString}\etype{\Ff} uses fixed point notation for the output. +Is behaviour remains +somewhat undecided in so far as whether it should identify inputs +which correspond to decimal numbers (i.e. fractions with only powers of +two and five in their denominator, once reduced to lowest terms). + +As with \csbxint{DecToStringREZ}, the name is a bit strange as inputs are in no +way limited to decimal numbers but are of the most general type accepted by +the \xintfracname macros. -It follows the same rules as \csbxint{DecToStringREZ} except that it does not +It is the same macro as \csbxint{DecToStringREZ} except that it does not remove trailing zeros, in fact \csbxint{DecToStringREZ}|{f}| is defined as \csbxint{DecToString}|{|\csbxint{REZ}|{f}}|. @@ -11872,13 +12029,16 @@ remove trailing zeros, in fact \csbxint{DecToStringREZ}|{f}| is defined as \end{everbatim*} Since |1.4e|\CHANGED{1.4e}, \csbxint{DecToString} is the default for -\csbxint{iexprPrintOne}, which governs the \csbxint{ieval} output format (in -this use case there is never a |/B| fractional part). +\csbxint{iexprPrintOne}, which governs the \csbxint{ieval} output format: in +this use case there is never a |/B| fractional part and the output is always +either an integer (if \csbxint{ieval} was used without optional argument) or a +decimal string \begin{everbatim} -\let\xintiexprPrintOne\xintDecToString +\def\xintiexprPrintOne{\xintDecToString} \end{everbatim} -Any replacement of \csbxint{iexprPrintOne} should obey the following blueprint: +Any replacement of \csbxint{DecToString} as the expansion of +\csbxint{iexprPrintOne} should obey the following blueprint: \begin{itemize}[noitemsep] \item to\xtype{} be expandable, but not necessarily \fexpan dable, \item to accept on input |A| or |A[N]|. @@ -12717,7 +12877,9 @@ expression will be fed to |\numexpr|. It is a shortcut for doing See also the \xintexprname-added variant \csbxint{SetDigits*}. \end{framed} -\subsection{\csh{xintFloat}}\label{xintFloat} +\subsection{\csh{xintFloat}} +\label{xintFloat} +\label{xintFloatZero} The macro |\xintFloat [P]{f}|\etype{{\upshape[\numx]}\Ff} has an optional @@ -12729,8 +12891,13 @@ prefixed by a minus sign and is followed by a dot and |P-1| digits, then a lower case |e| and an exponent |N|. The trailing zeroes are not trimmed. \begin{framed} - There is currently one exceptional case: the zero value, which gets output - as \dtt{\xintFloat{0}}. It is yet to be decided what the final policy will be. + There is one exception to the general description: the zero value, which + gets output as \dtt{\xintFloat{0}}.\CHANGEDf{1.4k} This was changed at + |1.4k|, until then it was using \dtt{0.e0} as output. Customize via + \csh{xintFloatZero} whose default definition is: +\begin{everbatim} +\def\xintFloatZero{0.0e0} +\end{everbatim} \end{framed} Starting with |1.2k|, when the input is a fraction |AeN/BeM| @@ -12776,81 +12943,282 @@ transitive in the number of kept digits. +\subsection{\csh{xintFloatToDecimal}} +\label{xintFloatToDecimal} + +|\xintFloatToDecimal [P]{f}|\etype{{\upshape[\numx]}\Ff} does float rounding +on input like \csbxint{Float} then outputs the number using decimal notation, +i.e. with as many zeros as are needed (and no more) and no scientific +exponent.\NewWith{1.4k} + +In other terms it behaves (and is essentially defined) as: +\begin{everbatim} +\xintDecToStringREZ{\xintFloat[optional P]{<input>}} +\end{everbatim} +Examples: +\begin{everbatim*} +\xintFloatToDecimal{6.02e23}\newline +\xintFloatToDecimal{6.02000000000000e23}\newline +\xintFloatToDecimal[20]{1/7e10}\newline +\xintFloatToDecimal[30]{1/7e10} +\end{everbatim*} + +See \csbxint{DecToString}. + \subsection{\csh{xintPFloat}} \label{xintPFloat} -\label{xintPFloatE} |\xintPFloat [P]{f}|\etype{{\upshape[\numx]}\Ff} is like \csbxint{Float} but ``pretty-prints'' the output. -This macro was added at |1.1| as a (very primitive) "prettifying printer" for -floating point number, and was basically influenced by Maple. +This macro was initially added at |1.1| as a (very primitive) "prettifying +printer" for floating point number, and was then somewhat influenced by Maple, +for example the zero value was printed as "\dtt{0.}". Then at |1.4e| there was +breaking change and the rules became somewhat similar to observed Python +behaviour: mantissas trimmed of trailing zeros (whether or not scientific +notation was used in the output) and integers printed with a trailing +"\dtt{.0}", in particular the zero value was printed as "\dtt{0.0}". -The old rules were: -\begin{enumerate}[nosep] -\item The input is float-rounded to either |Digits| or the optional argument, -\item zero is printed as \dtt{0.}, -\item \dtt{x.yz...eN} is printed ``as is'' if the exponent |N| is at least - \dtt{6} or at most \dtt{-6}, -\item else fixed point decimal notation is used, -\item and there is no trimming of trailing zeroes. -\end{enumerate} +|1.4k|\CHANGED{1.4k} brings some breaking changes, which are reversible +via customizing macros: +\begin{itemize} +\item Integers (when scientific notation is dropped) without a "\dtt{.0}" + suffix. +\item Same for the zero value, now "\dtt{\xintPFloat{0}}". +\item Significands are trimmed of trailing zeros only if that removes at least + \dtt{4} zeros. The rationale is that automatic removal of trailing zeros + (which was influenced at |1.4e| from practice with Python in interactive + mode) proves annoying visually with aligned values in tables, as this + creates voids, so we want to do this only when really the + presence of trailing zeros is not some kind of numerical fluke. +\end{itemize} +These changes impact the \csbxint{floateval} output as +\csbxint{floatexprPrintOne} defaults to using \csbxint{PFloat}. -At |1.4e|, there is breaking change\CHANGED{1.4e}. The new rules are: +The default rules are thus now: \begin{enumerate}[nolistsep] -\item The input is float-rounded to either |Digits| or the optional argument, -\item zero is printed as \dtt{0.0}, -\item \dtt{x.yz...eN} is printed in decimal fixed point if |-4<=N<=+5| - else it is printed in scientific notation, -\item Trailing zeros of the mantissa are trimmed always, -\item In case of decimal fixed point output format, and the value is an integer, there - is a trailing |.0|, -\item In case of scientific notation with a one-digit trimmed mantissa - there is an added |.0| too. +\item The input is float-rounded to either |Digits| or the optional argument. +\item zero is printed as \dtt{\xintPFloat{0}}.\CHANGED{1.4k} +\item \dtt{x.yz...eN} is printed in decimal fixed point if + $-4\leq\text{|N|}\leq+5$ else it is printed in scientific notation. +\item Trailing zeros of the mantissa are trimmed if, and only if there are at least \dtt{4} + of them.\CHANGED{1.4k} +\item In case of fixed point output format, and the value is an integer, the + integer is printed with no decimal mark.\CHANGED{1.4k} +\item In case of scientific notation output format, and the mantissa has only + one digit, no decimal mark is used. \end{enumerate} +Please note that ``trailing zeros'' refers to the ``trailing zeros of the full width +significand after float-rounding'', and not only to trailing zeros used in the input. + +% The old rules were: +% \begin{enumerate}[nosep] +% \item The input is float-rounded to either |Digits| or the optional argument, +% \item zero is printed as \dtt{0.}, +% \item \dtt{x.yz...eN} is printed ``as is'' if the exponent |N| is at least +% \dtt{6} or at most \dtt{-6}, +% \item else fixed point decimal notation is used, +% \item and there is no trimming of trailing zeroes. +% \end{enumerate} -The |1.4e| changes will affect all usages of \csbxint{floateval} as the latter -applies per default (cf.\@ \csbxint{floatexprPrintOne}) \csbxint{PFloat} to -each numerical leaf of the computed expression. +% At |1.4e|, there is breaking change\CHANGED{1.4e}. The new rules are: -\csa{xintPFloatE}\NewWith{1.4b} was added to allow customizing the -symbol used on output for separating the significand from the exponent, if -output uses scientific notation. The separator defaults to |e|, according to -this definition: +\begingroup\color{everbatimxfgcolor} +\begin{multicols}2 +\def\test #1{\item #1${}\to{}$\xintPFloat{#1}}% +\string\xintDigits\ at \xinttheDigits +\begin{itemize}[nosep,font=\normalcolor] +\test {0} +\test {1.2340000e-7}\test {1.2340000e-6}\test {1.2340000e-5}\test {1.2340000e-4} +\test {1.2340000e-3}\test {1.2340000e-2}\test {1.2340000e-1} +\test {1.2340000e0}\test {1.2340000e1}\test {1.2340000e2}\test {1.2340000e3} +\test {1.2340000e4}\test {1.2340000e5}\test {1.2340000e6}\test {1.2340000e7} +\test {1e-7/7}\test {1e-6/7}\test {1e-5/7}\test {1e-4/7} +\test {1e-3/7}\test {1e-2/7}\test {1e-1/7} +\test {1e0/7}\test {1e1/7}\test {1e2/7}\test {1e3/7} +\test {1e4/7}\test {1e5/7}\test {1e6/7}\test {1e7/7} +\end{itemize} +\end{multicols} +\endgroup + +\subsubsection{Customizing macros of \csh{xintPFloat}} +\label{xintPFloatE} +\label{xintPFloatZero} +\label{xintPFloatIntSuffix} +\label{xintPFloatLengthOneSuffix} +\label{xintPFloatNoSciEmin} +\label{xintPFloatNoSciEmax} +\label{xintPFloatMinTrimmed} + +A number of macros allow to customize the behaviour of \csbxint{PFloat}: +\begin{itemize} +\item \csa{xintPFloatE}\NewWith{1.4b} allows to modify the separator of the + scientific notation. Here is its default: +% + \footnote{For \TeX perts: it is allowed to define + \csa{xintPFloatE} as a macro which grabs the exponent as an argument + delimited by a dot, and produces \fexpan dably an output also delimited by + a dot (it will removed via further internal processing).\NewWith{1.4e}} +% \begin{everbatim} \def\xintPFloatE{e} \end{everbatim} -It is now possible\NewWith{1.4e} to let it grab the exponent as an argument (delimited by a -dot) and format it (output must be delimited by a dot, which will be removed -later on). +\item \csa{xintPFloatZero}\NewWith{1.4k} says how to print the zero value. + The default: +\begin{everbatim} +\def\xintPFloatZero{0} +\end{everbatim} + +\item \csa{xintPFloatIntSuffix}\NewWith{1.4k} is postfixed to integer values + (when scientific notation is not used). Its default at |1.4k| is to add + nothing. It replaces the formerly hard-coded "\dtt{.0}" from |1.4e| (prior + to that trailing zeros from the full significand of |P| or + \csbxint{theDigits} digits were not trimmed). +\begin{everbatim} +\def\xintPFloatIntSuffix{} +\end{everbatim} + +\item \csa{xintPFloatLengthOneSuffix}\NewWith{1.4k} is postfixed to trimmed + mantissas having only one digit, when scientific notation is used. Its + default at |1.4k| is to add nothing. It replaces formerly hard-coded + "\dtt{.0}". +\begin{everbatim} +\def\xintPFloatLengthOneSuffix{} +\end{everbatim} + +\item \csa{xintPFloatNoSciEmax}\NewWith{1.4k} is the maximal scientific exponent + which will trigger use of decimal fixed point notation and + \csa{xintPFloatNoSciEmin} is the minimal one. Their defaults at |1.4k| are the + same as the formerly hard-coded behaviour from |1.4e|: +\begin{everbatim} +\def\xintPFloatNoSciEmax{5} +\def\xintPFloatNoSciEmin{-4} +\end{everbatim} + For example (with the package default width of \dtt{16} digits for mantissas + of floating point numbers): \begin{everbatim*} -\begin{multicols}2 -\def\test #1{#1${}\to{}$\xintPFloat{#1}}\string\xintDigits\ at \xinttheDigits -\begin{itemize}[nosep] -\item \test {0} -\item \test {1.2340000e-7} -\item \test {1.2340000e-6} -\item \test {1.2340000e-5} -\item \test {1.2340000e-4} -\item \test {1.2340000e-3} -\item \test {1.2340000e-2} -\item \test {1.2340000e-1} -\end{itemize} -Change of scientific separator to |E|.\def\xintPFloatE{E}% -\begin{itemize}[nosep] -\item \test {1.2340000e0} -\item \test {1.2340000e1} -\item \test {1.2340000e2} -\item \test {1.2340000e3} -\item \test {1.2340000e4} -\item \test {1.2340000e5} -\item \test {1.2340000e6} -\item \test {1.2340000e7} -\end{itemize} -\end{multicols} +\begingroup +\def\xintPFloatNoSciEmin{-20} +\xintPFloat{1e-19/7}\newline +\xintPFloat{1e-20/7}\par +\def\xintPFloatNoSciEmax{19} +\xintPFloat{1e20/7}\newline +\xintPFloat{1e21/7}\par +\endgroup \end{everbatim*} +\item \csa{xintPFloatMinTrimmed}\NewWith{1.4k} is the minimal number +of trailing zeros which have to be present to activate actual trimming. +The default definition is: +\begin{everbatim} +\def\xintPFloatMinTrimmed{4} +\end{everbatim} +Defining it to expand to \dtt{-1} or \dtt{0} will enable the trimming of +trailing zeros always, and setting it to a high value will prevent it +altogther. + +\end{itemize} + +To mimick approximately the Python behaviour in interactive sessions, +one can use the following configuration: +\begin{everbatim} +\def\xintPFloatZero{0.0}% +\def\xintPFloatIntSuffix{.0}% +\def\xintPFloatLengthOneSuffix{.0}% +\def\xintPFloatNoSciEmax{15}% +\def\xintPFloatNoSciEmin{-4}% +\def\xintPFloatMinTrimmed{-1}% +\end{everbatim} +\begingroup\color{everbatimxfgcolor} +\def\xintPFloatZero{0.0}% +\def\xintPFloatIntSuffix{.0}% +\def\xintPFloatLengthOneSuffix{.0}% +\def\xintPFloatNoSciEmax{15}% +\def\xintPFloatNoSciEmin{-4}% +\def\xintPFloatMinTrimmed{-1}% +\def\test#1{#1${}\to{}$\xintPFloat{#1}\newline}% +\test{0.} +\test{1234.} +\test{6e100} +\test{1234567812345678.12345678} +\test{12345678123456781.2345678} +\test{12345678.12340} +\test{12345678.123400} +\test{0.1234567812345678} +\test{0.00012345678123456785} +\test{0.000012345678123456785}\par +\endgroup +% +The above using the default \csbxint{Digits} setting of \dtt{16} digits. +This can not naturally match exactly CPython which uses internally radix +|2| not |10|, and has (by default) mantissas with \dtt{53=1+52} bits. + +Same, but playing with \ctanpackage{xintsession} in its |&fp| mode: +\begin{everbatim} +>>> &fp +fp mode (16 digits) +>>> \\def\xintPFloatZero{0.0} +(executing \\def\xintPFloatZero {0.0} in background) +) +Runaway argument? +def\xintPFloatZero {0.0}\message { +}\xs_fetch_aa \endinput +! File ended while scanning use of \\. +<inserted text> + \par +<*> xintsession^^M + +? S +OK, entering \scrollmode... + +*\xintsession + + You are back to the xintexpr interactive session! + (current mode: fp (Digits=16), with Digits=16) + + ">>> " means central computing is waiting for input + "... " means that multi-line input continues. Use `;' to terminate it. + + Say `&bye' at any time to terminate the session and the TeX run. +>>> \def\xintPFloatZero{0.0} +(executing \def \xintPFloatZero {0.0} in background) + +>>> \def\xintPFloatIntSuffix{.0}\def\xintPFloatLengthOneSuffix{.0} + +(executing \def \xintPFloatIntSuffix {.0}\def \xintPFloatLengthOneSuffix {.0} i +n background) + +>>> \def\xintPFloatNoSciEmax{15}\def\xintPFloatNoSciEmin{-4} + +(executing \def \xintPFloatNoSciEmax {15}\def \xintPFloatNoSciEmin {-4} in back +ground) + +>>> \def\xintPFloatMinTrimmed{-1} +(executing \def \xintPFloatMinTrimmed {-1} in background) + +>>> 0., 1234., 6e100; +@_1 0.0, 1234.0, 6.0e100 +>>> 1234567812345678.12345678; +@_2 1234567812345678.0 +>>> 12345678123456781.2345678; +@_3 1.234567812345678e16 +>>> 12345678.12340; +@_4 12345678.1234 +>>> 12345678.123400; +@_5 12345678.1234 +>>> 0.1234567812345678; +@_6 0.1234567812345678 +>>> 0.00012345678123456785; +@_7 0.0001234567812345679 +>>> 0.000012345678123456785; +@_8 1.234567812345679e-5 +>>> &bye +\end{everbatim} +This is with version |0.4alpha (2021-11-01)| of +\ctanpackage{xintsession}. Probably some ``magic'' shortcuts will be +added in future to its interface for this kind of tasks, in place of +the |\def|. % \subsection{\csh{xintFloatE}}\label{xintFloatE} % %! {\small New with |1.097|.} @@ -13035,7 +13403,7 @@ handled exactly. And as said above its absolute value may exceed the \TeX\ bound \subsection{\csh{xintFloatSqrt}}\label{xintFloatSqrt} \csa{xintFloatSqrt}|[P]{f}|\etype{{\upshape[\numx]}\Ff} computes a floating -point approximation of $\sqrt{|f|}$, either using the optional precision |P| or +point approximation of $\sqrt{\text{|f|}}$, either using the optional precision |P| or the value of |\xinttheDigits|. More precisely since |1.2f| the macro achieves so-called \emph{correct @@ -13838,7 +14206,7 @@ needs a general calculus of special functions. This is why the package \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 +$\sum_{\text{|n=A|}}^{\text{|n=B|}}$|\coeff{n}|${}\cdot \text{|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 macro, @@ -13942,7 +14310,7 @@ an expanding only context, doing |\edef\g{\f}| is no option, then \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 +$\sum_{\text{|n=A|}}^{\text{|n=B|}}$|\coeff{n}|${}\cdot \text{|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 @@ -14011,7 +14379,7 @@ of \csa{xintPowerSeries}, the nineteenth partial sum, and to then give 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| +alternating we may even replace |N| with $\sqrt{\text{|N|}}$ to get the number |k| of digits possibly of dubious significance. \subsection{\csh{xintFxPtPowerSeriesX}}\label{xintFxPtPowerSeriesX} @@ -14033,7 +14401,7 @@ Let us illustrate this on the numerical exploration of the identity % 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 +terms of their respective series. We will assume $\text{|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. @@ -14094,7 +14462,7 @@ release. \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|}}$ +$\sum_{\text{|n=A|}}^{\text{|n=B|}}$|\coeff{n}|${}\cdot \text{|f|}^{\,\text{|n|}}$ with a floating point precision given by the optional parameter |P| or by the current setting of |\xintDigits|.\etype{\Ff\Ff} @@ -16926,61 +17294,65 @@ before a problematic (but reasonable) character catcode, or even to use \subsubsection{\csh{xintexprSafeCatcodes}} \label{xintexprSafeCatcodes} -For an even more radical way, there is \csbxint{exprSafeCatcodes} which sets -the catcodes of many characters to safe values. This is a non-expandable step -as it changes catcodes. +Some problems with active characters can be resolved on the fly by prefixing +them by |\string| but some aspects of the parsing done by \csbxint{expr} +involves delimited macros which need the comma, equality sign and closing +parenthesis to have their standard catcodes. + +So \csbxint{exprSafeCatcodes} is provided as a utility to set in one go +catcodes of many characters to \csbxint{expr}-safely compatible values. This +is a non-expandable step as it changes catcodes. % This is used % internally by \csbxint{NewExpr} (restoring the catcodes on exit), hence it % does not have to be protected against active characters when used at % top-level. -\csbxint{defvar}, \csbxint{deffunc}, et al., execute it before fetching their -semi-colon delimited arguments, so they can be used (also in the document -body) for example with Babel+French (which makes the semi-colon active in the -(\LaTeX) document body). This applies also to \csbxint{NewExpr}. +\csbxint{defvar}, \csbxint{deffunc}, et al., use it, and then they restore +catcodes to the prior state via \csbxint{exprRestoreCatcodes}. % As \csbxint{NewExpr} and \csbxint{deffunc} and variants use internally some % |\scantokens|, they will (reasonably) succeed in sanitizing catcodes in the % expressions, even if all is from the replacement text of some macro whose % definition was done under some special catcode regime. -But, if used in the body of macro definitions problems may arise from the -catcode regime at that location. This applies in particular to the -semi-colon as used by \csbxint{deffunc}, \csbxint{defvar} and variants as -delimiter. Thus make sure the semi-colon has its normal catcode when issueing -\csbxint{deffunc} inside some macro definition. +% \csbxint{deffunc} is more lenient than \csbxint{defvar} regarding catcodes of +% characters in expression bodies as it does some |\scantokens| which will reset +% compatible catcodes. -\csbxint{deffunc} is more lenient than \csbxint{defvar} regarding catcodes of -characters in expression bodies as it does some |\scantokens| which will reset -compatible catcodes. And also, characters inside the -expression may usually be prefixed with |\string|; but some aspects of the parsing -use delimited macros which need the comma, equality sign and closing -parenthesis to have standard catcodes. +% Even if used in a context where catcodes are already set, \csbxint{deffunc}, +% \csbxint{defvar} and variants ignore completely the colon in |:=| so it can +% have any (reasonable) catcode. Moreover it is optional. -Even if used in a context where catcodes are already set, \csbxint{deffunc}, -\csbxint{defvar} and variants ignore completely the colon in |:=| so it can -have any (reasonable) catcode. Moreover it is optional. - -The semi-colon in the syntax of \csbxint{Digits} is no real problem either -(cf. \csbxint{Digits} documentation). - -\begin{framed} - It is important to ALWAYS shortly let \csbxint{exprSafeCatcodes} be followed - by \csbxint{exprRestoreCatcodes}.\IMPORTANTf{} If one uses twice - \csbxint{exprSafeCatcodes} then the next \csbxint{exprRestoreCatcodes} will - restore the ancient catcode regime at time of the first one. -\end{framed} +% The semi-colon in the syntax of \csbxint{Digits} is no real problem either +% (cf. \csbxint{Digits} documentation). \subsubsection{\csh{xintexprRestoreCatcodes}} \label{xintexprRestoreCatcodes} -Restores the catcodes to the earlier state. More precisely, -\csbxint{exprSafeCatcodes} sets a toggle (with local scope). If the toggle is -set already it does not restore the current catcodes. The next -\csa{xintexprRestoreCatcodes} unsets the toggle. -So, in case of nesting, the -catcodes are restored to what they were when the \emph{first} un-paired -\csbxint{exprSafeCatcodes} got executed. +Restores the catcodes to the state prevailing at the time of the last executed +\csbxint{exprSafeCatcodes} (if located at the same \LaTeX\ environment or +\TeX\ grouping level). + +Prior to |1.4k|, in a situation like the following: +\begin{everbatim} +\xintexprSafeCatcodes +....stuff possibly changing catcodes +\xintexprSafeCatcodes +....stuff possibly changing catcodes +\xintexprSafeCatcodes +....stuff possibly changing catcodes +\xintexprRestoreCatcodes +\end{everbatim} +On exit, the catcodes recovered their status as prior to the \emph{first} +\csbxint{exprSafeCatcodes}. Since |1.4k|, they are set to what they were +prior to the \emph{last} \csbxint{exprSafeCatcodes}, i.e. the mechanism is now +similar to a ``last in, first out'' stack. + +Note that no global assignments are made so the behaviour can be modified +by usage of \TeX\ groups or \LaTeX\ environments: e.g. if an +\csbxint{exprSafeCatcodes} is issued inside a \LaTeX\ environment it does not +have to be paired by \csbxint{exprRestoreCatcodes} explicitly, the catcode +scope is limited by the environment. \bigskip @@ -16988,30 +17360,26 @@ 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 - escape-char agnostic. It should work with any \csa{escapechar} setting - including -1.} - -The characters |+|, |-|, |*|, |/|, |^|, |!|, |&|, \verb+|+, |?|, |:|, |<|, |>|, -|=|, |(|, |)|, |"|, |[|, |]|, |;|, the dot and the comma should not be active if -in the expression, as everything is expanded along the way. If one of them is -active, it should be prefixed with |\string|. +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, ..., except that they +% should not be \emph{active}, as for example are |!?;:| with |babel-french|.% +% % +% \footnote{Furthermore, although \csbxint{expr} uses \csa{string}, it is +% escape-char agnostic. It should work with any \csa{escapechar} setting +% including -1.} +but the characters +% |+|, |-|, |*|, |/|, |^|, |!|, |&|, \verb+|+, |?|, |:|, |<|, |>|, +%|=|, |(|, |)|, |"|, |[|, |]|, |;|, +in the expression should not be «active» (except on purpose) as everything is +expanded along the way, and |\xintexpr| will choke on typesetting related +commands. One can use |\string| to prefix a problematic character. -The exclamation mark |!| should have its standard catcode: with catcode letter -it is used internally and hence will confuse the parsers if it comes from the -expression. Digits, slash, square brackets, minus sign, in the output from an |\xinttheexpr| are all of catcode 12. For |\xintthefloatexpr| the `e' in the output has its standard catcode ``letter''. -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. @@ -17258,37 +17626,41 @@ arguments having at most |P| significant places already. \label{xinteval}\label{xintieval}\label{xintiieval}\label{xintfloateval} \csbxint{eval}\etype{x} is an \fexpan dable macro which is basically defined -like this (DON'T BELIEVE THIS; it has been entirely revamped at |1.4|): +like this (this is obsolete since |1.4|): \begin{everbatim} -\def\xinteval#1{\romannumeral-`0\xinttheexpr#1\relax}% OLD DEFINITION < 1.4 +\def\xinteval#1{\romannumeral-`0\xinttheexpr#1\relax}% THIS IS OLD DEFINITION \end{everbatim} -thus expands in two steps (its exact definition differs from the one given -above in order to achieve a slight optimization). +thus expands in two steps. \begin{everbatim*} \xinteval{add(x^2, x = 100..110), add(x^3, x = 100..110)} \end{everbatim*} -\csbxint{ieval}\etype{x} is similarly related to \csbxint{theiexpr}. Its optional -argument must be located inside the braces: +\csbxint{ieval}\etype{x} is similarly related to \csbxint{theiexpr}. Its +optional argument may be located in the expected location for \LaTeX\ users +since |1.4k|, but was long constrained to be inside the braces. \begin{everbatim*} -\xintieval{[7] 355/113} +\xintieval[7]{355/113} = \xintieval{[7]355/113} \end{everbatim*} +If one defines a macro which will do something such as |\xintieval{#1}| it is +recommended to code it as |\xintieval{\empty#1}| in case the |#1| will start +with some |[|, which will end up confusing |\xintieval|. + \csbxint{iieval}\etype{x} is similarly related to \csbxint{theiiexpr}. \begin{everbatim*} \xintiieval{add(x^2, x = 100..110), add(x^3, x = 100..110)} \end{everbatim*} -\csbxint{floateval}\etype{x} is similarly related to \csbxint{thefloatexpr}. Its optional -argument must be located inside the braces: +\csbxint{floateval}\etype{x} is similarly related to +\csbxint{thefloatexpr}. The same remarks as for |\xintieval| apply. \begin{everbatim*} -\xintfloateval{[7] 355/113} +\xintfloateval [7]{355/113} = \xintfloateval{[7] 355/113} \end{everbatim*} -When negative it tells how many digits to remove from the prevailing precision -(\csbxint{theDigits}): +When negative, the optional argument tells how many digits to remove from the +prevailing precision (\csbxint{theDigits}): \begin{everbatim*} -\xintfloateval{[-2] 355/113} has \xinttheDigits\ minus 2 digits. +\xintfloateval[-2]{355/113}=\xintfloateval{[-2]355/113} has \xinttheDigits\ minus 2 digits. \end{everbatim*} These macros are useful when one uses some extra wrapper doing some parsing of @@ -17327,6 +17699,111 @@ from \csbxint{expr} and \csbxint{floatexpr} can not be used directly in \end{everbatim*} +\subsection{\csh{xintFracToSci}}\label{xintFracToSci} + +% je ne dois pas mettre \Ff car la macro n'utilise pas \XINT_infrac + +\csa{xintFracToSci}\NewWith{1.4} is for usage by \csbxint{eval} for +formatting the output of numbers. It is not meant for direct use at +user level as it currently expects input formatted in the so-called +``relaxed raw format'' from \xintfracname, i.e. |A/B[N]|, with |/B| and +|[N]| being optional parts, and |A|, |B|, |N| being integers, |B| always +positive if present, and |A| having at most one leading minus sign (and +no sign if it is zero, and no leading zeros). + +Here is what it does:\CHANGED{1.4e} +\begin{itemize}[noitemsep,nosep] +\item with input respectively: |A|, |A/B|, |A[N]|, |A/B[N]| +\item it produces this output: |A|, |A/B| (if |B| is not |1|), |A| if + |N=0|, |A/B| if |N=0| (no |B| if |1|), and if + |N| is not zero, the output will be |AeN| written in scientific notation + exactly like it would by \csbxint{PFloat} but without of course prior + rounding to a given number of digits; in particular trailing zeros in the + significand will be removed. Then this value in scientific notation + (or decimal fixed point notation if the scientific exponent is in the + range deciding so by \csbxint{PFloat}) will be attached to a trailing + denominator part |/B| (if not equal to |1|). +\end{itemize} +Please note: +\begin{itemize} +\item there is no reduction of the fraction |A/B| to lowest terms, +\item trailing zeros in |B| are not moved and incorporated +into the final scientific exponent, +\item no attempt is made to check is |B| is only products of |2|'s and + |5|'s and thus could be integrated into some pure decimal notation for + the numerator or at least its significand. +\end{itemize} +This has not changed since |1.4| but is to be considered +\emph{unstable}. Actually even the description above was until |1.4k| +only to be found in the commented source code... So everything is +susceptible to change at some later release. + +Changes\CHANGED{1.4k} of \csbxint{PFloat} at |1.4k| have an impact here. +In particular the zero value will give \dtt{0} whether the input was +some |0|, |0e-5|, |0/3|, |0.00|, etc\dots, whereas at |1.4e| it would +have been +\dtt{0.0} for cases triggering some \csbxint{PFloat} subroutine. See +\csbxint{PFloatZero} for reenacting the |1.4e| behaviour. + +\medskip + +The output routine of \csbxint{eval} uses +\csbxint{exprPrintOne} whose current default definition is: +\begin{everbatim} +\def\xintexprPrintOne{\xintFracToSci} +\end{everbatim} +Any replacement should obey the following blueprint: +\begin{itemize}[noitemsep] +\item to\xtype{} be expandable, but not necessarily \fexpan dable, +\item to accept on input |A|, |A/B|, |A[N]|, or |A/B[N]|, i.e. the + ``relaxed raw'' + \xintfracname format. +\end{itemize} +% These constraints\CHANGED{1.4e} are much simplified at |1.4e| (and +% \csa{xintFracToSci} has been internally simplified to only have to obey +% the reduced constraints, which is a breaking change). + +% At |1.4e| the handling\CHANGED{1.4e} by this macro of input with a scientific +% exponent part has changed. Rather than producing an integer mantissa it now +% does as \csbxint{PFloat}, apart of course from its initial step of +% float-rounding. It trims out trailing zeros of the input always. + +Attention, \csa{xintFracToSci} does not behave as do the public macros from +\xintfracname: +\begin{itemize}[noitemsep] +\item it is expandable, but not \fexpan dable, so it can't appear as argument + to \xintfracname macros without an explicit |\expanded{...}| wrapper + (as they only \fexpan d their arguments). +\item it expects input which after \fexpan sion will be in ``relaxed raw'' + \xintfracname format.\IMPORTANT{} +\end{itemize} + +%\noindent\csa{xintFracToSciE} has been removed at |1.4e|, see \csbxint{PFloatE}. + +\subsection{\csh{xintFracToDecimal}} +\label{xintFracToDecimal} + +% je ne dois pas mettre \Ff car la macro n'utilise pas \XINT_infrac +% mais je pourrais utiliser \xtype +It is a variant of \csbxint{FracToSci}\NewWith{1.4k} +which differs from it in so far as it outputs a numerator using decimal +notation, i.e. with as many zeros as are needed (and no more) and no +scientific exponent. The denominator goes through ``as is'' except if +it is |1|, then it is omitted. + +In other terms its behaviour is currently intermediate between +\csbxint{DecToString} and \csbxint{DecToStringREZ}, as it does not +remove trailing zeros of the denominator. + +It is not meant to be used directly as it shares the same limitations +of \csbxint{FracToSci} for user level usage, but solely as a way to +customize \csbxint{exprPrintOne}: +\begin{everbatim} +\def\xintexprPrintOne{\xintFracToDecimal} +\end{everbatim} +Consider its behaviour as \emph{unstable} and \emph{barely documented}. + + \subsection{The \csh{xintthecoords} macro} \label{xintthecoords} @@ -19157,7 +19634,7 @@ currently this is implemented by using either |\xintifForFirst| or \etocsettocdepth{subsubsection}% 2015/09/15 \etocdepthtag.toc {implementation} -\addtocontents{toc}{\gdef\string\sectioncouleur{[named]{RoyalPurple}}} +\addtocontents{toc}{\gdef\string\sectioncouleur{{tocsectionimpcolor}}} \def\storedlinecounts {} \def\StoreCodelineNo #1{\edef\storedlinecounts{% @@ -19182,7 +19659,8 @@ currently this is implemented by using either |\xintifForFirst| or \makestarlowast \xmacro@code } -\def\macro@font {\ttbfamily }% slashed 0 +% finally 2022/05/17 removes slashed 0 dedicated ttbfamily usage +\def\macro@font {\ttfamily }% % \lverb % ====== @@ -19253,7 +19731,7 @@ currently this is implemented by using either |\xintifForFirst| or % there is a group to handle restore \def\MicroFont {%\ttzfamily - \color[named]{Purple}\makestarlowast } + \color{verbimpcolor}\makestarlowast } % privatecodecomments % =================== @@ -19278,6 +19756,16 @@ currently this is implemented by using either |\xintifForFirst| or \hangindent\parindent } +% \added +% ====== + +% new 2022/05/16 +\newcommand\added[2][]{% + \par\smallskip\noindent + \textbf{Added at #2\space(\xintreleasedate{#2})\if\relax\detokenize{#1}\relax + \else\space[on #1]\fi.}% +} + % \xintreleasedate % ================ @@ -19674,7 +20162,7 @@ math shift catcode. \fi \XINT_providespackage \ProvidesPackage {xintkernel}% - [2021/07/13 v1.4j Paraphernalia for the xint packages (JFB)]% + [2022/05/18 v1.4k Paraphernalia for the xint packages (JFB)]% % \end{macrocode} % \subsection{Constants} % \begin{macrocode} @@ -20634,7 +21122,7 @@ mode) and will go ahead hoping repair\endcsname % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xinttools}% - [2021/07/13 v1.4j Expandable and non-expandable utilities (JFB)]% + [2022/05/18 v1.4k Expandable and non-expandable utilities (JFB)]% % \end{macrocode} % \lverb|\XINT_toks is used in macros such as \xintFor. It is not used % elsewhere in the xint bundle.| @@ -22995,7 +23483,7 @@ mode) and will go ahead hoping repair\endcsname % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintcore}% - [2021/07/13 v1.4j Expandable arithmetic on big integers (JFB)]% + [2022/05/18 v1.4k Expandable arithmetic on big integers (JFB)]% % \end{macrocode} % \subsection{(WIP!) Error conditions and exceptions} % \lverb|As per the Mike Cowlishaw/IBM's General Decimal Arithmetic Specification @@ -26349,7 +26837,7 @@ mode) and will go ahead hoping repair\endcsname % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xint}% - [2021/07/13 v1.4j Expandable operations on big integers (JFB)]% + [2022/05/18 v1.4k Expandable operations on big integers (JFB)]% % \end{macrocode} % \subsection{More token management} % \begin{macrocode} @@ -28928,7 +29416,7 @@ mode) and will go ahead hoping repair\endcsname % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintbinhex}% - [2021/07/13 v1.4j Expandable binary and hexadecimal conversions (JFB)]% + [2022/05/18 v1.4k Expandable binary and hexadecimal conversions (JFB)]% % \end{macrocode} % \subsection{Constants, etc...} % \lverb|1.2n switches to \csname-governed expansion at various places.| @@ -29600,7 +30088,7 @@ mode) and will go ahead hoping repair\endcsname % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintgcd}% - [2021/07/13 v1.4j Euclide algorithm with xint package (JFB)]% + [2022/05/18 v1.4k Euclide algorithm with xint package (JFB)]% % \end{macrocode} % \subsection{\csh{xintBezout}} % \lverb|& @@ -30134,7 +30622,7 @@ mode) and will go ahead hoping repair\endcsname %\let<*xintfrac>\gardesinactifs %</xintgcd>^^A---------------------------------------------------- %<*xintfrac>^^A--------------------------------------------------- -%^^A -*- coding: utf-8; mode: doctex; fill-column: 78; sentence-end-double-space: t; -*- +%^^A -*- coding: utf-8; mode: doctex; fill-column: 72; sentence-end-double-space: t; -*- % \clearpage\csname xintfracnameUp\endcsname % \section{Package \xintfracnameimp implementation} % \RaisedLabel{sec:fracimp} @@ -30200,7 +30688,7 @@ mode) and will go ahead hoping repair\endcsname % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintfrac}% - [2021/07/13 v1.4j Expandable operations on fractions (JFB)]% + [2022/05/18 v1.4k Expandable operations on fractions (JFB)]% % \end{macrocode} % \subsection{\csh{XINT_cntSgnFork}} % \lverb|1.09i. Used internally, #1 must expand to \m@ne, \z@, or \@ne or @@ -30229,8 +30717,6 @@ mode) and will go ahead hoping repair\endcsname {% \expandafter#1% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \the\numexpr \XINT_abs##1+% \XINT_len_fork ##2##3\xint:\xint:\xint:\xint:\xint:\xint:\xint:\xint:\xint: @@ -30240,7 +30726,13 @@ mode) and will go ahead hoping repair\endcsname }}\XINT_flen{ }% % \end{macrocode} % \subsection{\csh{XINT_outfrac}} +% \changed{1.06b} % \lverb|& +% 1.06b 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). +% % Months later (2014/10/22): perhaps I should document what this macro does % before I forget? from {e}{N}{D} it outputs N/D[e], checking in passing if % D=0 or if N=0. It also makes sure D is not < 0. I am not sure but I don't @@ -30278,17 +30770,22 @@ mode) and will go ahead hoping repair\endcsname }% % \end{macrocode} % \subsection{\csh{XINT_inFrac}}\label{src-XINT_infrac} +% \added{1.03} % \lverb|& % Parses fraction, scientific notation, etc... and produces {n}{A}{B} % corresponding to A/B times 10^n. No reduction to smallest terms. -% +% | +% \changed{1.07} +% \lverb|& % Extended in 1.07 to accept scientific notation on input. With lowercase % e only. The \xintexpr parser does accept uppercase E also. Ah, by the way, % perhaps I should at least say what this macro does? (belated addition % 2014/10/22...), before I forget! It prepares the fraction in the internal % format {exponent}{Numerator}{Denominator} where Denominator is at least 1. -% -% 2015/10/09: this venerable macro from the very early days (1.03, 2013/04/14) +% | +% \changed[2015/10/09]{1.2} +% \lverb|& +% This venerable macro from the very early days % has gotten a lifting for release 1.2. There were two kinds of issues: % % 1) use of \W, \Z, \T delimiters was very poor choice as this could clash with @@ -30339,7 +30836,9 @@ mode) and will go ahead hoping repair\endcsname % numerator and denominator will be parsed for the more general format % allowing decimal digits and scientific part and possibly multiple leading % signs. -% +% | +% \changed{1.2l} +% \lverb|& % 1.2l fixes frailty of \XINT_infrac (hence basically of all xintfrac macros) % respective to non terminated \numexpr input: \xintRaw{\the\numexpr1} for % example. The issue was that \numexpr sees the / and expands what's next. @@ -30380,8 +30879,7 @@ mode) and will go ahead hoping repair\endcsname }% % \end{macrocode} % \lverb|An empty [] is not allowed. (this was authorized in 1.2, removed in -% 1.2f). As nobody reads xint documentation, no one will have noticed the -% fleeting possibility.| +% 1.2f).| % \begin{macrocode} \def\XINT_infrac_res_ca #1[#2]\xint:/\XINT_W[\XINT_W\XINT_T {\expandafter{\the\numexpr #2}{#1}{1}}% @@ -30391,14 +30889,19 @@ mode) and will go ahead hoping repair\endcsname {\expandafter{\the\numexpr #3}{#2}{#1}}% % \end{macrocode} % \subsection{\csh{XINT_frac_gen}} -% \lverb|Extended in 1.07 to recognize and accept scientific notation both at +% \changed{1.07} +% \lverb|Extended at 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 -% -% Completely rewritten for 1.2 2015/10/10. The parsing handles inputs such as +% | +% \changed{1.2} +% \lverb|& +% Completely rewritten. The parsing handles inputs such as % \A.\Be\C/\D.\Ee\F where each of \A, \B, \D, and \E may need f-expansion and % \C and \F will end up in \numexpr. -% +% | +% \changed{1.2f} +% \lverb|& % 1.2f corrects an issue to allow \C and \F to be \count variable (or % expressions with \numexpr): 1.2 did a bad \numexpr0#1 which allowed only % explicit digits for expanded #1.| @@ -30467,16 +30970,12 @@ mode) and will go ahead hoping repair\endcsname {% \expandafter\XINT_frac_gen_F\the\numexpr #5-#2-% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \numexpr\XINT_length_loop #1\xint:\xint:\xint:\xint:\xint:\xint:\xint:\xint:\xint: \xint_c_viii\xint_c_vii\xint_c_vi\xint_c_v \xint_c_iv\xint_c_iii\xint_c_ii\xint_c_i\xint_c_\xint_bye % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \relax\expandafter~% \romannumeral0\expandafter\XINT_num_cleanup\the\numexpr\XINT_num_loop @@ -30518,8 +31017,9 @@ mode) and will go ahead hoping repair\endcsname % \lverb|This is the core macro for \xintREZ. To be used as % \romannumeral0\XINT_factortens{...}. Output is A.N. (formerly {A}{N}) where % A is the integer stripped from trailing zeroes and N is the number of -% removed zeroes. Only for positive strict integers! -% +% removed zeroes. Only for positive strict integers!| +% \changed{1.3a} +% \lverb|& % Completely rewritten at 1.3a to replace a double \xintReverseOrder by a % direct \numexpr governed expansion to the end and back, à la 1.2. I should % comment more... and perhaps improve again in future. @@ -30681,6 +31181,7 @@ mode) and will go ahead hoping repair\endcsname }% % \end{macrocode} % \subsection{\csh{xintRaw}} +% \added{1.07} % \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 @@ -30694,8 +31195,10 @@ mode) and will go ahead hoping repair\endcsname \def\XINT_raw #1#2#3{ #2/#3[#1]}% % \end{macrocode} % \subsection{\csh{xintiLogTen}} +% \added{1.3e} % \lverb|& -% New at 1.3e. The exponent a, such that 10^a<= abs(x) < 10^(a+1). +% The exponent a, such that 10^a<= abs(x) < 10^(a+1). No rounding done on x, +% handled as an exact fraction. % | % \begin{macrocode} \def\xintiLogTen {\the\numexpr\xintilogten}% @@ -30735,7 +31238,7 @@ mode) and will go ahead hoping repair\endcsname }% % \end{macrocode} % \subsection{\csh{xintPRaw}} -% \lverb|1.09b| +% \added{1.09b} % \begin{macrocode} \def\xintPRaw {\romannumeral0\xintpraw }% \def\xintpraw @@ -30774,94 +31277,6 @@ mode) and will go ahead hoping repair\endcsname \def\XINT_spraw_a\W\XINT_spraw_p #1[\W]{ #1}% \def\XINT_spraw_p #1[\W]{\xintpraw {#1}}% % \end{macrocode} -% \subsection{\csh{xintFracToSci}} -% \lverb|1.4, refactored and much simplified at 1.4e. -% -% It only needs to be x-expandable, and indeed the implementation here is only -% x-expandable. -% -% (2021/04/13) the user documentation was really deplorable, I have -% tried to improve it and in the process tried to remember what this macro was -% supposed to do, and improved comments here, also lamentable. -% -% At 1.4e-dev this became provisorily basically like defunct \xintSPRaw, but -% doing less parsing at it does not go to \xintPRaw with its \XINT_infrac -% induced overhead. Previous 1.4b \xintFracToSci was much complicated from -% having to allow fixed point notation on input and scientific notation with a -% catcode 12 "e". Refactoring of \xintiexpr has removed these constraints. -% Now: -% -%( Input: A, A/B, A[N], A/B[N] -%: Output: AeN/B with special cases: -%: 0 if input gives a zero value -%: /B is skipped in output if B=1 in input -%: eN is skipped in output if N=0 in input -%) -% -% 0[N] when N not zero is possible as input, but 0/B currently not I think, -% and -0 for example never arises as one is guaranteed that A is in strict -% integer format. -% -% (2021/05/05) Finally for 1.4e release I modify. This is breaking -% change for all \xinteval output in case of scientific notation: it will not -% be with an integer mantissa, but in regular scientific notation, using the -% same rules as \xintPFloat. -% -% Of course there will be no float rounding applied! Also, as [0] will always -% or almost always be present from an \xinteval, we want then to use integer -% not scientific notation. But expression contained decimal fixed point input, -% or uses scientific functions, then probably the N will not be zero and this -% will trigger usage of scientific notation in output. -% -% Implementing these changes sort of ruin our previous efforts to minimize -% grabbing the argument, but well. So the rules now are -% -%( Input: A, A/B, A[N], A/B[N] -%: Output: A, A/B, A if N=0, A/B if N=0 -%: If N is not zero, scientific notation like \xintPFloat,& -% i.e. behaviour like \xintfloateval apart from the rounding& -% to Digits. In particular trailing zeros are trimmed. -%: The zero gives 0, except in A[N] and A/B[N] cases, it may give& -% 0.0 -%) -% -% As a result of these last minute 1.4e changes, the \xintFracToSciE is -% removed. -% | -% -% \begin{macrocode} -\def\xintFracToSci #1{\expandafter\XINT_FracToSci\romannumeral`&&@#1/\W[\R}% -\def\XINT_FracToSci #1/#2#3[#4% -{% - \xint_gob_til_W #2\XINT_FracToSci_noslash\W - \xint_gob_til_R #4\XINT_FracToSci_slash_noN\R - \XINT_FracToSci_slash_N #1/#2#3[#4% -}% -\def\XINT_FracToSci_noslash#1\XINT_FracToSci_slash_N #2[#3% -{% - \xint_gob_til_R #3\XINT_FracToSci_noslash_noN\R - \XINT_FracToSci_noslash_N #2[#3% -}% -\def\XINT_FracToSci_noslash_noN\R\XINT_FracToSci_noslash_N #1/\W[\R{#1}% -\def\XINT_FracToSci_noslash_N #1[#2]/\W[\R% -{% - \ifnum#2=\xint_c_ #1\else - \romannumeral0\expandafter\XINT_pfloat_fork\romannumeral0\xintrez{#1[#2]}% - \fi -}% -\def\XINT_FracToSci_slash_noN\R\XINT_FracToSci_slash_N #1#2/#3/\W[\R% -{% - #1\xint_gob_til_zero#1\expandafter\iffalse\xint_gobble_ii0\iftrue - #2\if\XINT_isOne{#3}1\else/#3\fi\fi -}% -\def\XINT_FracToSci_slash_N #1#2/#3[#4]/\W[\R% -{% - \ifnum#4=\xint_c_ #1#2\else - \romannumeral0\expandafter\XINT_pfloat_fork\romannumeral0\xintrez{#1#2[#4]}% - \fi - \if\XINT_isOne{#3}1\else\if#10\else/#3\fi\fi -}% -% \end{macrocode} % \subsection{\csh{xintRawWithZeros}} % \lverb|& % This was called \xintRaw in versions earlier than 1.07| @@ -30890,7 +31305,8 @@ mode) and will go ahead hoping repair\endcsname \def\XINT_rawz_Bb #1#2{ #2/#1}% % \end{macrocode} % \subsection{\csh{xintDecToString}} -% \lverb|1.3. This is a backport from polexpr 0.4. It is definitely not in +% \added{1.3} +% \lverb|This is a backport from polexpr 0.4. It is definitely not in % final form, consider it to be an unstable macro.| % \begin{macrocode} \def\xintDecToString{\romannumeral0\xintdectostring}% @@ -30913,13 +31329,15 @@ mode) and will go ahead hoping repair\endcsname }% % \end{macrocode} % \subsection{\csh{xintDecToStringREZ}} -% \lverb|1.4e. And I took this opportunity to improve documentation in manual.| +% \added{1.4e} +% \lverb|And I took this opportunity to improve documentation in manual.| % \begin{macrocode} \def\xintDecToStringREZ{\romannumeral0\xintdectostringrez}% \def\xintdectostringrez#1{\expandafter\XINT_dectostr\romannumeral0\xintrez{#1}}% % \end{macrocode} % \subsection{\csh{xintFloor}, \csh{xintiFloor}} -% \lverb|1.09a, 1.1 for \xintiFloor/\xintFloor. Not efficient if big negative +% \added{1.09a} +% \lverb|1.1 for \xintiFloor/\xintFloor. Not efficient if big negative % decimal exponent. Also sub-efficient if big positive decimal exponent.| % \begin{macrocode} \def\xintFloor {\romannumeral0\xintfloor }% @@ -30931,7 +31349,7 @@ mode) and will go ahead hoping repair\endcsname \def\XINT_ifloor #1/#2.{\xintiiquo {#1}{#2}}% % \end{macrocode} % \subsection{\csh{xintCeil}, \csh{xintiCeil}} -% \lverb|1.09a| +% \added{1.09a} % \begin{macrocode} \def\xintCeil {\romannumeral0\xintceil }% \def\xintceil #1{\xintiiopp {\xintFloor {\xintOpp{#1}}}}% @@ -30969,8 +31387,6 @@ mode) and will go ahead hoping repair\endcsname \def\XINT_denom_fork #1% {% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \ifnum#1<\xint_c_ \expandafter\XINT_denom_B @@ -30983,10 +31399,10 @@ mode) and will go ahead hoping repair\endcsname \def\XINT_denom_B -#1.#2#3{\XINT_dsx_addzeros{#1}#3;}% % \end{macrocode} % \subsection{\csh{xintTeXFrac}} -% \lverb|1.03 (2013/04/14). Useless typesetting macro. -% -% Renamed (2021/05/24) from \xintFrac at 1.4g. Old name deprecated but -% still usable.| +% \added{1.03} +% \lverb|Useless typesetting macro.| +% \changed[2021/05/24]{1.4g} +% \lverb|Renamed from \xintFrac. Old name deprecated but still usable.| % \begin{macrocode} \ifdefined\documentclass \def\xintfracTeXDeprecation#1#2{% @@ -31030,8 +31446,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINT_fracfrac_E \fi\space\frac #1#2{\fi \space #1\cdot }% % \end{macrocode} % \subsection{\csh{xintTeXsignedFrac}} -% \lverb|& -% Renamed (2021/05/24) from \xintSignedFrac at 1.4g. Old name deprecated but +% \changed[2021/05/24]{1.4g} +% \lverb|Renamed from \xintSignedFrac. Old name deprecated but % still usable.| % \begin{macrocode} \def\xintSignedFrac {\xintfracTeXDeprecation\xintSignedFrac\xintTeXsignedFrac}% @@ -31061,7 +31477,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{xintTeXfromSci}} -% \lverb|1.4g. The main problem is how to name this and related macros. +% \added{1.4g} +% \lverb|The main problem is how to name this and related macros. % % I use \expanded here, as \xintFracToSci is not f-expandable. But why do I % bother with the external \expanded? @@ -31096,8 +31513,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \fi % \end{macrocode} % \subsection{\csh{xintTeXOver}} -% \lverb|& -% Renamed (2021/05/24) from \xintFwOver at 1.4g. Old name deprecated but +% \changed[2021/05/24]{1.4g} +% \lverb|Renamed from \xintFwOver. Old name deprecated but % still usable.| % \begin{macrocode} \def\xintFwOver {\xintfracTeXDeprecation\xintFwOver\xintTeXOver}% @@ -31127,8 +31544,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{xintTeXsignedOver}} -% \lverb|& -% Renamed (2021/05/24) from \xintSignedFwOver at 1.4g. Old name deprecated but +% \changed[2021/05/24]{1.4g} +% \lverb|Renamed from \xintSignedFwOver. Old name deprecated but % still usable.| % \begin{macrocode} \def\xintSignedFwOver {\xintfracTeXDeprecation\xintSignedFwOver\xintTeXsignedOver}% @@ -31197,9 +31614,11 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \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. -% +% \added{1.07} +% \lverb|The fraction is the first argument contrarily to \xintTrunc and +% \xintRound.| +% \changed{1.1} +% \lverb|& % 1.1 modifies and moves \xintiiE to xint.sty.| % \begin{macrocode} \def\xintE {\romannumeral0\xinte }% @@ -31214,7 +31633,12 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINT_e_end #1.#2#3{ #2/#3[#1]}% % \end{macrocode} % \subsection{\csh{xintIrr}, \csh{xintPIrr}} -% \lverb|\xintPIrr (partial Irr, which ignores the decimal part) added at 1.3.| +% \changed{1.04}\lverb|fixes a buggy \xintIrr {0}.| +% \changed{1.05}\lverb|modifies the initial parsing and post-processing to use \xintrawwithzeros +% and to more quickly deal with an input denominator equal to 1.| +% \changed{1.08}\lverb|this version does not remove a /1 denominator.| +% \changed{1.3} +% \lverb|added \xintPIrr (partial Irr, which ignores the decimal part).| % \begin{macrocode} \def\xintIrr {\romannumeral0\xintirr }% \def\xintPIrr{\romannumeral0\xintpirr }% @@ -31390,7 +31814,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{xintTFrac}} -% \lverb|1.09i, for frac in \xintexpr. And \xintFrac is already assigned. T for +% \added{1.09i} +% \lverb|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 @@ -31415,8 +31840,9 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % \subsection{\csh{xintTrunc}, \csh{xintiTrunc}} % \lverb|& % -% This of course has a long history. Only showing here some comments. -% +% This of course has a long history. Only showing here some comments.| +% \changed{1.2i} +% \lverb|& % 1.2i release notes: ever since its inception this macro was stupid for a % decimal input: it did not handle it separately from the general fraction % case A/B[N] with B>1, hence ended up doing divisions by powers of ten. But @@ -31428,9 +31854,10 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % is quite longer and making it f-expandable would not shorten it... I decided % for the time being to not complicate things here. % | +% \changed[2020/02/18]{1.4a} % \lverb|& % -% 1.4a (2020/02/18) adds handling of a negative first argument. +% Adds handling of a negative first argument. % % Zero input still gives single digit 0 output as I did not want to complicate % the code. But if quantization gives 0, the exponent [D] will be there. Well @@ -31492,8 +31919,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% \def\XINT_trunc_CE #1.#2{\XINT_trunc_E #2.{#1}}% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_trunc_sp_C -#1.#2#3{\XINT_trunc_sp_Ca #2.#1.}% \def\XINT_trunc_sp_Ca #1% @@ -31580,9 +32005,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{xintTTrunc}} -% \lverb|1.1. Modified in 1.2i, it does simply \xintiTrunc0 with no -% shortcut (the latter having been modified) -%| +% \added{1.1} % \begin{macrocode} \def\xintTTrunc {\romannumeral0\xintttrunc }% \def\xintttrunc {\xintitrunc\xint_c_}% @@ -31625,8 +32048,11 @@ on input line \noexpand\the\inputlineno.&&J}}#2% {\XINT_dsrr #1\xint_bye\xint_Bye3456789\xint_bye/\xint_c_x\relax.}% % \end{macrocode} % \subsection{\csh{xintXTrunc}} -% \lverb@1.09j [2014/01/06] This is completely expandable but not f-expandable. -% Rewritten for 1.2i (2016/12/04): +% \added[2014/01/06]{1.09j} +% \lverb@This is completely expandable but not f-expandable.@ +% \changed[2016/12/04]{1.2i} +% \lverb|& +% Rewritten: % % - no more use of \xintiloop from xinttools.sty % (replaced by \xintreplicate... from xintkernel.sty), @@ -31635,9 +32061,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % \csname...\endcsname % % - handles better the case of an input already a decimal number -% -% Need to transfer code comments into public dtx. -% @ +% | % \begin{macrocode} \def\xintXTrunc #1%#2% {% @@ -31667,8 +32091,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }%[ \def\XINT_xtrunc_zero #1#2]{0.\romannumeral\xintreplicate{#1}0}% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_xtrunc_d #1#2#3/#4[#5]% {% @@ -31694,8 +32116,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \fi\XINT_xtrunc_BisSmall {#2}% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_xtrunc_BisOne\XINT_xtrunc_BisSmall #1#2#3#4% {\XINT_xtrunc_sp_e {#2}{#4}{#3}}% @@ -31731,8 +32151,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% .\the\numexpr \xint_c_x^viii+#1!}% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_xtrunc_small_a #1.#2!#3% {% @@ -31742,8 +32160,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% #3\XINT_sepbyviii_Z_end 2345678\relax }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_xtrunc_prepare_b {\expandafter\XINT_xtrunc_prepare_c\romannumeral0\XINT_zeroes_forviii }% @@ -31775,13 +32191,9 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \X }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_xtrunc_prepare_g #1;{\XINT_xtrunc_e {#1}}% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_xtrunc_e #1#2% {% @@ -31792,24 +32204,18 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \fi #2\xint:{#1}% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_xtrunc_I -#1\xint:#2#3#4% {% \expandafter\XINT_xtrunc_I_a\romannumeral0#2{#4}{#2}{#1}{#3}% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_I_a #1#2#3#4#5% {% \expandafter\XINT_xtrunc_I_b\the\numexpr #4-#5\xint:#4\xint:{#5}{#2}{#3}{#1}% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_I_b #1% {% @@ -31819,8 +32225,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \krof #1% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_IA_c -#1\xint:#2\xint:#3#4#5#6% {% @@ -31830,8 +32234,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \the\numexpr (#1+\xint_c_ii^v)/\xint_c_ii^vi-\xint_c_i\xint:#1\xint:{#5}{#4}% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_IA_d #1% {% @@ -31841,8 +32243,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \krof #1% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_IAA_e -#1\xint:#2% {% @@ -31850,32 +32250,24 @@ on input line \noexpand\the\inputlineno.&&J}}#2% #1.#2\xint_gobble_i\xint_bye2345678\xint_bye..% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_IAB_e #1\xint:#2% {% 0.\romannumeral\XINT_rep#1\endcsname0#2% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_IA_xd #1\xint:#2\xint:% {% \expandafter\XINT_xtrunc_IA_xe\the\numexpr #2-\xint_c_ii^vi*#1\xint:#1\xint:% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_xtrunc_IA_xe #1\xint:#2\xint:#3#4% {% \XINT_xtrunc_loop {#2}{#4}{#3}{#1}% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_IB_c #1\xint:#2\xint:#3#4#5#6% {% @@ -31883,16 +32275,12 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \romannumeral0\XINT_split_xfork #1.#6\xint_bye2345678\xint_bye..{#3}% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_xtrunc_IB_d #1.#2.#3% {% \expandafter\XINT_xtrunc_IA_d\the\numexpr#3-\xintLength {#1}\xint:{#1}% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_xtrunc_II #1\xint:% {% @@ -31909,16 +32297,12 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \expandafter\XINT_xtrunc_II_c\the\numexpr #2-\xint_c_ii^vi*#1\xint:#1\xint:% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_xtrunc_II_c #1\xint:#2\xint:#3#4#5% {% #3.\XINT_xtrunc_loop {#2}{#4}{#5}{#1}% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_xtrunc_loop #1% {% @@ -31937,8 +32321,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \XINT_xtrunc_loop {#3}{#2}% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_xtrunc_transition \expandafter\XINT_xtrunc_loop_a\the\numexpr #1\xint:#2#3#4% @@ -31956,8 +32338,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \romannumeral\xintreplicate{#3-\xintLength{#1}}0#1% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_xtrunc_sp_e #1% {% @@ -31968,16 +32348,12 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \fi #1\xint:% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_sp_I -#1\xint:#2#3% {% \expandafter\XINT_xtrunc_sp_I_a\the\numexpr #1-#3\xint:#1\xint:{#3}{#2}% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_sp_I_a #1% {% @@ -31987,8 +32363,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \krof #1% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_sp_IA_b -#1\xint:#2\xint:#3#4% {% @@ -31996,8 +32370,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \the\numexpr#2-\xintLength{#4}\xint:{#4}\romannumeral\XINT_rep#1\endcsname0% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_sp_IA_c #1% {% @@ -32007,8 +32379,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \krof #1% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_sp_IAA -#1\xint:#2% {% @@ -32016,16 +32386,12 @@ on input line \noexpand\the\inputlineno.&&J}}#2% #1.#2\xint_gobble_i\xint_bye2345678\xint_bye..% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_sp_IAB #1\xint:#2% {% 0.\romannumeral\XINT_rep#1\endcsname0#2% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_sp_IB_b #1\xint:#2\xint:#3#4% {% @@ -32033,16 +32399,12 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \romannumeral0\XINT_split_xfork #1.#4\xint_bye2345678\xint_bye..{#3}% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_xtrunc_sp_IB_c #1.#2.#3% {% \expandafter\XINT_xtrunc_sp_IA_c\the\numexpr#3-\xintLength {#1}\xint:{#1}% }% % \end{macrocode} -% \lverb@& -% @ % \begin{macrocode} \def\XINT_xtrunc_sp_II #1\xint:#2#3% {% @@ -32050,6 +32412,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{xintAdd}} +% \changed{1.3} % \lverb|Big change at 1.3: a/b+c/d uses lcm(b,d) as denominator.| % \begin{macrocode} \def\xintAdd {\romannumeral0\xintadd }% @@ -32126,6 +32489,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }\XINT_fadd_G{ }% % \end{macrocode} % \subsection{\csh{xintSub}} +% \changed{1.3} % \lverb|Since 1.3 will use least common multiple of denominators.| % \begin{macrocode} \def\xintSub {\romannumeral0\xintsub }% @@ -32148,8 +32512,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % may be empty. % % Refactored slightly at 1.4. \XINT_Sum used in xintexpr code. -% -% % | % \begin{macrocode} \def\xintSum {\romannumeral0\xintsum }% @@ -32192,9 +32554,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINT_fmul_zero #1.#2{ 0/1[0]}% % \end{macrocode} % \subsection{\csh{xintSqr}} -% \lverb|1.1 modifs comme xintMul. -% -% | % \begin{macrocode} \def\xintSqr {\romannumeral0\xintsqr }% \def\xintsqr #1{\expandafter\XINT_fsqr\romannumeral0\xintraw {#1}}% @@ -32271,9 +32630,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\xintfac #1{\expandafter\XINT_fac_fork\the\numexpr\xintNum{#1}.[0]}% % \end{macrocode} % \subsection{\csh{xintBinomial}} -% \lverb|1.2f. Binomial coefficients. \xintiBinomial deprecated at 1.2o and -% removed at 1.3; -% \xintBinomial needed by xintexpr.sty.| +% \added{1.2f} % \begin{macrocode} \def\xintBinomial {\romannumeral0\xintbinomial}% \def\xintbinomial #1#2% @@ -32283,7 +32640,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{xintPFactorial}} -% \lverb|1.2f. Partial factorial. For needs of xintexpr.sty.| +% \added{1.2f} +% \lverb|Partial factorial. For needs of xintexpr.sty.| % \begin{macrocode} \def\xintipfactorial #1#2% {% @@ -32346,18 +32704,16 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINT_fdiv_C #1#2{\XINT_outfrac {#2}{#1}}% % \end{macrocode} % \subsection{\csh{xintDivFloor}} -% \lverb|1.1. Changed at 1.2p to not append /1[0] ending but rather output a +% \added{1.1} +% \lverb|Changed at 1.2p to not append /1[0] ending but rather output a % big integer in strict format, like \xintDivTrunc and \xintDivRound. -% -% -% % | % \begin{macrocode} \def\xintDivFloor {\romannumeral0\xintdivfloor }% \def\xintdivfloor #1#2{\xintifloor{\xintDiv {#1}{#2}}}% % \end{macrocode} % \subsection{\csh{xintDivTrunc}} -% \lverb|1.1. \xintttrunc rather than \xintitrunc0 in 1.1a| +% \added{1.1} % \begin{macrocode} \def\xintDivTrunc {\romannumeral0\xintdivtrunc }% \def\xintdivtrunc #1#2{\xintttrunc {\xintDiv {#1}{#2}}}% @@ -32369,11 +32725,13 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\xintdivround #1#2{\xintiround 0{\xintDiv {#1}{#2}}}% % \end{macrocode} % \subsection{\csh{xintModTrunc}} -% \lverb|1.1. \xintModTrunc {q1}{q2} computes q1 - q2*t(q1/q2) with t(q1/q2) +% \added{1.1} +% \lverb|\xintModTrunc {q1}{q2} computes q1 - q2*t(q1/q2) with t(q1/q2) % equal to the truncated division of two fractions q1 and q2. % -% Its former name, prior to 1.2p, was \xintMod. -% +% Its former name, prior to 1.2p, was \xintMod.| +% \changed{1.3} +% \lverb|& % At 1.3, uses least common multiple denominator, like \xintMod (next).| % \begin{macrocode} \def\xintModTrunc {\romannumeral0\xintmodtrunc }% @@ -32422,9 +32780,11 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINT_modtrunc_pos_a #1.#2#3#4{\xintiirem {#3}{#4}/#2[#1]}% % \end{macrocode} % \subsection{\csh{xintDivMod}} -% \lverb|1.2p. \xintDivMod{q1}{q2} outputs {floor(q1/q2)}{q1 - q2*floor(q1/q2)}. -% Attention that it relies on \xintiiE{x}{e} returning x if e < 0. -% +% \added{1.2p} +% \lverb|\xintDivMod{q1}{q2} outputs {floor(q1/q2)}{q1 - q2*floor(q1/q2)}. +% Attention that it relies on \xintiiE{x}{e} returning x if e < 0.| +% \changed{1.3} +% \lverb|& % Modified (like \xintAdd and \xintSub) at 1.3 to use a l.c.m for final % denominator of the "mod" part.| % \begin{macrocode} @@ -32474,11 +32834,14 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINT_divmod_bpos_finish #1#2#3{{#1}{#2#3}}% % \end{macrocode} % \subsection{\csh{xintMod}} -% \lverb|1.2p. \xintMod{q1}{q2} computes q1 - q2*floor(q1/q2). Attention that +% \added{1.2p} +% \lverb|\xintMod{q1}{q2} computes q1 - q2*floor(q1/q2). Attention that % it relies on \xintiiE{x}{e} returning x if e < 0. % % Prior to 1.2p, that macro had the meaning now attributed to \xintModTrunc. -% +% | +% \changed{1.3} +% \lverb|& % Modified (like \xintAdd and \xintSub) at 1.3 to use a l.c.m for final % denominator.| % \begin{macrocode} @@ -32541,7 +32904,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINT_mod_bpos_a #1.#2#3#4{\xintiirem {#3}{#4}/#2[#1]}% % \end{macrocode} % \subsection{\csh{xintIsOne}} -% \lverb|New with 1.09a. Could be more efficient. For fractions with big +% \added{1.09a} +% \lverb|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 }% @@ -32595,8 +32959,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \krof }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_fgeq_Fd #1\Z #2#3% {% @@ -32802,8 +33164,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \krof }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_fcmp_Fd #1\Z #2#3% {% @@ -33218,8 +33578,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % | % % \subsection{\csh{xintDigits}, \csh{xintSetDigits}} +% \changed{1.3} % \lverb|& -% % 1.3f allows \xintDigits= in place of \xintDigits:= syntax. % It defines \xintDigits*[:]= which reloads xinttrig.sty. Perhaps this should % be default, well. @@ -33249,7 +33609,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % -% \subsection{\csh{xintFloat}} +% \subsection{\csh{xintFloat}, \csh{xintFloatZero}} % \lverb|& % 1.2f and 1.2g brought some refactoring which resulted in faster treatment of % decimal inputs. 1.2i dropped use of some old routines dating back to pre 1.2 @@ -33299,6 +33659,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % the macro used internally by the float macros for parsing their inputs, we % simply make now \xintFloat a wrapper of \XINTinFloat.| % \begin{macrocode} +\def\xintFloatZero{0.0e0}% 1.4k breaking change. Replaces hard-coded 0.e0 \def\xintFloat {\romannumeral0\xintfloat }% \def\xintfloat #1{\XINT_float_chkopt #1\xint:}% \def\XINT_float_chkopt #1% @@ -33329,7 +33690,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% 0-\XINT_float_pos \krof #1% }%[ -\def\XINT_float_zero #1]#2.{ 0.e0}% +\def\XINT_float_zero #1]#2.{\expanded{ \xintFloatZero}}% \def\XINT_float_neg-{\expandafter-\romannumeral0\XINT_float_pos}% \def\XINT_float_pos #1#2[#3]#4.% {% @@ -33337,7 +33698,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% \def\XINT_float_pos_done #1.#2;{ #2e#1}% % \end{macrocode} -% \subsection{\csh{XINTinFloat}, \csh{XINTinFloatS}, \csh{XINTiLogTen}} +% \subsection{\csh{XINTinFloat}, \csh{XINTinFloatS}} % \lverb|& % This routine is like \xintFloat but produces an output of the shape A[N] % which is then parsed faster as input to other float macros. @@ -33368,8 +33729,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % Since 1.2k, \XINTinFloat always correctly rounds its argument, even if it % is a fraction with very big numerator and denominator. See the discussion of % \xintFloat. -% -% 1.3e adds \XINTFloatiLogTen. % | % \begin{macrocode} \def\XINTinFloat {\romannumeral0\XINTinfloat }% @@ -33383,8 +33742,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% {\if #1!\xint_dothis\XINT_infloat_clean_a\fi\xint_orthat{ }#1}% % \end{macrocode} % \lverb|Ici on ajoute les zeros pour faire exactement avec P chiffres. -% Car le #1 = P - L avec L la longueur de #2, (ou de abs(#2), ici le #2 peut -% avoir un signe) qui est < P| +% Car le #1 = P - L avec L la longueur de #2, (ou plutôt de abs(#2), +% car ici le #2 peut avoir un signe) et L < P| % \begin{macrocode} \def\XINT_infloat_clean_a !#1.#2[#3]% {% @@ -33403,23 +33762,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% {\if #1!\xint_dothis\XINT_infloatS_clean_a\fi\xint_orthat{ }#1}% \def\XINT_infloatS_clean_a !#1.{ }% % \end{macrocode} -% \lverb|1.3e ajoute \XINTFloatiLogTen. Le comportement pour un input nul est non -% encore finalisé. Il changera lorsque NaN, +Inf, -Inf existeront. -% | -% \begin{macrocode} -\def\XINTFloatiLogTen {\the\numexpr\XINTfloatilogten}% -\def\XINTfloatilogten [#1]#2% - {\expandafter\XINT_floatilogten\romannumeral0\XINT_infloat[#1]{#2}#1.}% -\def\XINTFloatiLogTendigits{\the\numexpr\XINTfloatilogten[\XINTdigits]}% -\def\XINT_floatilogten #1{% - \if #10\xint_dothis\XINT_floatilogten_z\fi - \if #1!\xint_dothis\XINT_floatilogten_a\fi - \xint_orthat\XINT_floatilogten_b #1% -}% -\def\XINT_floatilogten_z 0[0]#1.{-"7FFF8000\relax}% -\def\XINT_floatilogten_a !#1.#2[#3]#4.{#3-#1+#4-1\relax}% -\def\XINT_floatilogten_b #1[#2]#3.{#2+#3-1\relax}% -% \end{macrocode} % \lverb|début de la routine proprement dite, % l'argument optionnel est obligatoire.| % \begin{macrocode} @@ -33731,7 +34073,99 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% \def\XINT_infloat_ZZ #1.#2.{ 1#2[#1]}% % \end{macrocode} -% \subsection{\csh{xintPFloat}, \csh{xintPFloatE}} +% \subsection{\csh{XINTFloatiLogTen}} +% \added{1.3e} +% \lverb|Le comportement pour un input nul est non +% encore finalisé. Il changera lorsque NaN, +Inf, -Inf existeront. +% | +% \begin{macrocode} +\def\XINTFloatiLogTen {\the\numexpr\XINTfloatilogten}% +\def\XINTfloatilogten [#1]#2% + {\expandafter\XINT_floatilogten\romannumeral0\XINT_infloat[#1]{#2}#1.}% +\def\XINTFloatiLogTendigits{\the\numexpr\XINTfloatilogten[\XINTdigits]}% +\def\XINT_floatilogten #1{% + \if #10\xint_dothis\XINT_floatilogten_z\fi + \if #1!\xint_dothis\XINT_floatilogten_a\fi + \xint_orthat\XINT_floatilogten_b #1% +}% +\def\XINT_floatilogten_z 0[0]#1.{-"7FFF8000\relax}% +\def\XINT_floatilogten_a !#1.#2[#3]#4.{#3-#1+#4-1\relax}% +\def\XINT_floatilogten_b #1[#2]#3.{#2+#3-1\relax}% +% \end{macrocode} +% \subsection{\csh{xintFloatSciExp}} +% \added[2022/05/16]{1.4k} +% \lverb|Hesitation about whether keeping the general \romannumeral0 +% trigger which is documented as general rule.| +% \begin{macrocode} +\def\xintFloatSciExp {\the\numexpr\xintfloatsciexp }% +\def\xintpfloatsciexp #1{\XINT_floatsciexp_chkopt #1\xint:}% +\def\XINT_floatsciexp_chkopt #1% +{% + \ifx [#1\expandafter\XINT_floatsciexp_opt + \else\expandafter\XINT_floatsciexp_noopt + \fi #1% +}% +\def\XINT_floatsciexp_noopt #1\xint:% +{% + \expandafter\XINT_floatsciexp\romannumeral0\XINT_infloat[\XINTdigits]{#1}% + \XINTdigits.% +}% +\def\XINT_floatsciexp_opt [\xint:#1]#2% +{% + \expandafter\XINT_floatsciexp\romannumeral0\XINT_infloat[#1]{#2}#1.% +}% +\def\XINT_floatsciexp #1{% + \if #10\xint_dothis\XINT_floatsciexp_z\fi + \if #1!\xint_dothis\XINT_floatsciexp_a\fi + \xint_orthat\XINT_floatsciexp_b #1% +}% +\def\XINT_floatsciexp_z 0[0]#1.{0\relax}% +\def\XINT_floatsciexp_a !#1.#2[#3]#4.{#3-#1+#4-1\relax}% +\def\XINT_floatsciexp_b #1[#2]#3.{#2+#3-1\relax}% +% \end{macrocode} +% \subsection{\csh{xintFloatSignificand}} +% \added[2022/05/16]{1.4k} +% \lverb|Hesitation about whether returning abcd... or a.bcd... +% with a separator +% and slight hesitation about handling of zero.| +% \begin{macrocode} +\def\xintFloatSignificand {\romannumeral0\xintfloatsignificand}% +\def\xintfloatsignificand #1{\XINT_floatsgf_chkopt #1\xint:}% +\def\XINT_floatsgf_chkopt #1% +{% + \ifx [#1\expandafter\XINT_floatsgf_opt + \else\expandafter\XINT_floatsgf_noopt + \fi #1% +}% +\def\XINT_floatsgf_noopt #1\xint:% +{% + \expandafter\XINT_floatsgf_post + \romannumeral0\XINTinfloat[\XINTdigits]{#1}\XINTdigits.% +}% +\def\XINT_floatsgf_opt [\xint:#1]% +{% + \expandafter\XINT_floatsgf_opt_a\the\numexpr #1.% +}% +\def\XINT_floatsgf_opt_a #1.#2% +{% + \expandafter\XINT_floatsgf_post + \romannumeral0\XINTinfloat[#1]{#2}#1.% +}% +\def\XINT_floatsgf_post #1% +{% + \xint_UDzerominusfork + #1-\XINT_floatsgf_zero + 0#1\XINT_floatsgf_neg + 0-\XINT_floatsgf_pos + \krof #1% +}%[ +\def\XINT_floatsgf_zero #1]#2.{\XINT_dsx_addzeros{#2};}% +\def\XINT_floatsgf_neg-{\XINT_floatsgf_pos}% +\def\XINT_floatsgf_pos #1[#2]#3.{ #1}% +% \end{macrocode} +% \subsection{\csh{xintPFloat}} +% \added{1.1} +% \changed{1.4e} % \lverb|& % % xint has not yet incorporated a general formatter as it was @@ -33756,8 +34190,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % % 1.4b added \xintPFloatE to customize whether to use % e or E. -% -% +% | +% \lverb|& % 1.4e, with some hesitation, decided to make a breaking change and to modify % the behaviour. % @@ -33774,19 +34208,69 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % there is an added ".0" too %) % -% Further, \xintPFloatE can now grab the scientific exponent K which is -% presented to it as explicit tokens (digit tokens, at least one, and an -% optional minus sign) delimited by a dot. It is thus now possible to -% customize at will for example adding a + sign in case of positive scientific -% exponent. The macro must be f-expandable. +% Further, \xintPFloatE can now also be redefined as a macro with a parameter +% delimited by a full stop, with the full stop also in its ouput as +% terminator. It would then grab the scientific exponent K as explicit digit +% possibly prefixed by a minus sign. The macro must be f-expandable. % +% The macro \xintPFloat_wopt is only there for a micro gain as the package +% does +% +% \let\xintfloatexprPrintOne\xintPFloat_wopt +% +% as it knows it will +% be used always with a [P] argument in the xintexpr.sty context. +% | +% \changed[2022/05/18]{1.4k} +% \lverb|& +% Addition of customization via \xintPFloatZero, \xintPFloatLengthOneSuffix, +% \xintPFloatNoSciEmax, \xintPFloatNoSciEmin which replace formerly +% hard-coded behaviour. +% +% Breaking change to not add ".0" suffix to integers (when scientific +% notation dropped) or to one-digit mantissas. +% +% In my own practice I started being annoyed by the automatic trimming of +% zeros added at 1.4e. +% +% This change had been influenced by using Python in interactive mode +% which since 3.1 prints floats (in decimal conversion) choosing the +% shortest string. In particular it trims trailing zeros, and it drops +% the scientific notation in favor of decimal notation for something +% like -4<= K <= 15, with K the scientific exponent. +% +% At 1.4e I was still influenced by my experience with Maple and +% did for -4 <= K <= 5. Not very well thought anyhow (one may wish +% to use decimal notation when sending things to PostScript, so perhaps +% I should have kept with -5). +% +% But, the main problem is with trimming trailing zeros: although in +% interactive sessions, this has its logic, as soon as one does tables +% with numbers, dropping a trailing zero upsets alignments or creates +% visual holes compared to other lines and this is in the end very +% annoying. +% +% After much hesitation, I decided to slightly modifify only the former +% behaviour: trimming only if that removes at least 4 zeros. I had also +% experimented with another condition: trimmed mantissas should be at +% most 6 digits (for example) wide, else use no trimming. +% +% Threshold customizable via \xintPFloatMinTrimmed. % | % \begin{macrocode} +\def\xintPFloatE{e}% +\def\xintPFloatNoSciEmax{\xint_c_v}% 1e6 uses sci.not. +\def\xintPFloatNoSciEmin{-\xint_c_iv}% 1e-5 uses sci.not. +\def\xintPFloatIntSuffix{}% +\def\xintPFloatLengthOneSuffix{}% +\def\xintPFloatZero{0}% +\def\xintPFloatMinTrimmed{\xint_c_iv}% \def\xintPFloat {\romannumeral0\xintpfloat }% \def\xintpfloat #1{\XINT_pfloat_chkopt #1\xint:}% -\def\xintPFloat_wopt +\def\xintPFloat_wopt[#1]#2% {% - \romannumeral0\expandafter\XINT_pfloat\romannumeral0\XINTinfloatS + \romannumeral0\expandafter\XINT_pfloat + \romannumeral0\XINTinfloatS[#1]{#2}#1.% }% \def\XINT_pfloat_chkopt #1% {% @@ -33797,10 +34281,12 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINT_pfloat_noopt #1\xint:% {% \expandafter\XINT_pfloat\romannumeral0\XINTinfloatS[\XINTdigits]{#1}% + \XINTdigits.% }% -\def\XINT_pfloat_opt [\xint:#1]% +\def\XINT_pfloat_opt [\xint:#1]#2% {% - \expandafter\XINT_pfloat\romannumeral0\XINTinfloatS[#1]% + \expandafter\XINT_pfloat\romannumeral0\XINTinfloatS[#1]{#2}% + #1.% }% \def\XINT_pfloat#1]% {% @@ -33814,22 +34300,92 @@ on input line \noexpand\the\inputlineno.&&J}}#2% 0-\XINT_pfloat_pos \krof #1% }% -\def\XINT_pfloat_zero#1]{ 0.0}% +\def\XINT_pfloat_zero#1]#2.{\expanded{ \xintPFloatZero}}% \def\XINT_pfloat_neg-{\expandafter-\romannumeral0\XINT_pfloat_pos}% -\def\XINT_pfloat_pos#1/1[#2]% +\def\XINT_pfloat_pos#1/1[#2]#3.% +{% + \expandafter\XINT_pfloat_aa\the\numexpr\xintLength{#1}.% + #3.#2.#1.% +}% +% \end{macrocode} +%\lverb|Needed for \xintFracToSci, which uses old pre 1.4k interface.| +% \begin{macrocode} +\def\XINT_pfloat_keeptrimmed_fork#1% +{% + \xint_UDzerominusfork + #1-\XINT_pfloat_keeptrimmed_zero + 0#1\XINT_pfloat_keeptrimmed_neg + 0-\XINT_pfloat_keeptrimmed_pos + \krof #1% +}% +\def\XINT_pfloat_keeptrimmed_zero#1]{\expanded{ \xintPFloatZero}}% +\def\XINT_pfloat_keeptrimmed_neg-{\expandafter-\romannumeral0\XINT_pfloat_keeptrimmed_pos}% +\def\XINT_pfloat_keeptrimmed_pos#1/1[#2]% +{% + \expandafter\XINT_pfloat_a\the\numexpr\xintLength{#1}.#2.#1.% +}% +% \end{macrocode} +%\lverb|& +%( #1 est la longueur de la mantisse trimmée +%: #2 est Digits ou P +%: Si #2-#1 < MinTrimmed, on remet les trailing zeros +%) +%| +% \begin{macrocode} +\def\XINT_pfloat_aa #1.#2.% +{% + \unless\ifnum\xintPFloatMinTrimmed>\numexpr#2-#1\relax + \xint_dothis\XINT_pfloat_a\fi + \ifnum#2>#1 \xint_dothis{\XINT_pfloat_i #2.}\fi + \xint_orthat\XINT_pfloat_a #1.% +}% +% \end{macrocode} +%\lverb|& +%( #2 est la longueur de la mantisse trimmée +%: #1 est P mais peut être encore sous la forme \XINTdigits +%: #3 est l'exposant non normalisé +%: #4 est la mantisse +%) +%| +% \begin{macrocode} +\def\XINT_pfloat_i #1.#2.#3.#4.% {% - \expandafter\XINT_pfloat_a\the\numexpr\xintLength{#1}.% - #2.#1.% + \expandafter\XINT_pfloat_j + \the\numexpr#3+#2-#1\expandafter.% + \romannumeral0\XINT_dsx_addzerosnofuss{#1-#2}#4;.#1.% }% +% \end{macrocode} +%\lverb|& +%( #1 est le nouvel exposant non normalisé +%: #2 est la nouvelle mantisse à P chiffres +%: #3 est P (peut être sous forme \XINTdigits) +%) +%| +% \begin{macrocode} +\def\XINT_pfloat_j #1.#2.#3.{\XINT_pfloat_a#3.#1.#2.}% \def\XINT_pfloat_a #1.#2#3.% {% \expandafter\XINT_pfloat_b\the\numexpr#1+#2#3-\xint_c_i.% #2#1.% }% +% \end{macrocode} +% \lverb|& +%( #1 est l'exposant scientifique K +%: #2 est le signe ou premier chiffre de l'exposant N pour mantisse trimmée +%: Il est suivi par la longueur de la mantisse trimmée +%) +% On va vers \XINT_float_P lorsque l'on n'utilise pas la notation +% scientifique, mais qu'on a besoin de chiffres non nuls fractionnaires, +% et vers \XINT_float_Ps si on n'en a pas besoin. +% +% On va vers \XINT_pfloat_N lorsque l'on n'utilise pas la notation +% scientifique et que l'exposant scientifique était strictement négatif. +%| +% \begin{macrocode} \def\XINT_pfloat_b #1.#2% {% - \ifnum #1>\xint_c_v \xint_dothis\XINT_pfloat_sci\fi - \ifnum #1<-\xint_c_iv \xint_dothis\XINT_pfloat_sci\fi + \ifnum \xintPFloatNoSciEmax<#1 \xint_dothis\XINT_pfloat_sci\fi + \ifnum \xintPFloatNoSciEmin>#1 \xint_dothis\XINT_pfloat_sci\fi \ifnum #1<\xint_c_ \xint_dothis\XINT_pfloat_N\fi \if-#2\xint_dothis\XINT_pfloat_P\fi \xint_orthat\XINT_pfloat_Ps @@ -33837,10 +34393,11 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \lverb|& -% #1 is the scientific exponent, #2 is the length of trimmed mantissa. +% #1 is the scientific exponent, #2 is the length of the trimmed mantissa. +% (may be the \XINTdigits token) % % \xintPFloatE can be replaced by any f-expandable macro with a dot-delimited -% argument. +% argument which produces a dot-delimited output. % | % \begin{macrocode} \def\XINT_pfloat_sci #1.#2.% @@ -33853,56 +34410,103 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % \lverb|& % #1#2=\fi\XINT_pfloat_sci_a % -% 1-digit mantissa, hesitation between d.0eK or deK| +% 1-digit mantissa, hesitation between d.0eK or deK +% Finally at 1.4k, \xintPFloatLengthOneSuffix for customization. +% | +% \begin{macrocode} +\def\XINT_pfloat_sci_i #1#2#3.#4.{\expanded{#1 #4\xintPFloatLengthOneSuffix}#3}% +% \end{macrocode} +% \lverb|& +% #1=sci.exp. K, #2=mant. wd L, #3=mantissa +% +% For _N, #1 is at most -1, for _P, #1 is at least 0. For _P there +% will be fractional digits, and #1+1 digits before the mark. +% | % \begin{macrocode} -\edef\XINT_pfloat_sci_i #1#2#3.#4.{#1\space#4.0#3}% -\def\xintPFloatE{e}% \def\XINT_pfloat_N#1.#2.#3.% {% - \csname XINT_pfloat_N_\romannumeral-#1\endcsname #3% + \expandafter\XINT_pfloat_N_e\romannumeral\xintreplicate{-#1}{0}#3% }% -\def\XINT_pfloat_N_i { 0.}% -\def\XINT_pfloat_N_ii { 0.0}% -\def\XINT_pfloat_N_iii{ 0.00}% -\def\XINT_pfloat_N_iv { 0.000}% +\def\XINT_pfloat_N_e 0{ 0.}% +% \end{macrocode} +% \lverb|& +% Abusive usage of internal \XINT_split_fromleft_a. +% It means using x = -1 - #1 in \xintDecSplit from xint.sty. +% We benefit also with the way \xintDecSplit is built upon +% \XINT_split_fromleft with a final clean-up which here +% we can shortcut (non \xint_bye. not \xint_bye..). +% | +% \begin{macrocode} \def\XINT_pfloat_P #1.#2.#3.% {% - \csname XINT_pfloat_P_\romannumeral#1\endcsname #3% + \expandafter\XINT_split_fromleft_a + \the\numexpr\xint_c_vii-#1.#3\xint_bye2345678\xint_bye.% }% -\def\XINT_pfloat_P_ #1{ #1.}% -\def\XINT_pfloat_P_i #1#2{ #1#2.}% -\def\XINT_pfloat_P_ii #1#2#3{ #1#2#3.}% -\def\XINT_pfloat_P_iii#1#2#3#4{ #1#2#3#4.}% -\def\XINT_pfloat_P_iv #1#2#3#4#5{ #1#2#3#4#5.}% -\def\XINT_pfloat_P_v #1#2#3#4#5#6{ #1#2#3#4#5#6.}% +% \end{macrocode} +% \lverb|& +% Here we have an integer so we only need to postfix mantissa #3 +% with #1+1-#2 zeros (#1=sci exp., #2=mantissa width). Less cumbersome +% to do that with \expanded. +% | +% \begin{macrocode} \def\XINT_pfloat_Ps #1.#2.#3.% {% - \csname XINT_pfloat_Ps_\romannumeral#1\endcsname #300000.% + \expanded{ #3% + \romannumeral\xintreplicate{#1+\xint_c_i-#2}{0}\xintPFloatIntSuffix}% +}% +% \end{macrocode} +% \subsection{\csh{xintFloatToDecimal}} +% \added{1.4k} +% \begin{macrocode} +\def\xintFloatToDecimal {\romannumeral0\xintfloattodecimal }% +\def\xintfloattodecimal #1{\XINT_floattodec_chkopt #1\xint:}% +\def\XINT_floattodec_chkopt #1% +{% + \ifx [#1\expandafter\XINT_floattodec_opt + \else\expandafter\XINT_floattodec_noopt + \fi #1% +}% +\def\XINT_floattodec_noopt #1\xint:% +{% + \expandafter\XINT_floattodec\romannumeral0\XINTinfloatS[\XINTdigits]{#1}% +}% +\def\XINT_floattodec_opt [\xint:#1]% +{% + \expandafter\XINT_floattodec\romannumeral0\XINTinfloatS[#1]% +}% +% \end{macrocode} +% \lverb|Tentation to try to use direct access to lower entry points +% from \xintREZ, but it dates back from very early days and uses old \Z +% delimiters (same remarks for the code jumping from \xintFracToSci +% to \xintrez)| +% \begin{macrocode} +\def\XINT_floattodec#1]% +{% + \expandafter\XINT_dectostr\romannumeral0\xintrez{#1]}% }% -\def\XINT_pfloat_Ps_ #1#2.{ #1.0}% -\def\XINT_pfloat_Ps_i #1#2#3.{ #1#2.0}% -\def\XINT_pfloat_Ps_ii #1#2#3#4.{ #1#2#3.0}% -\def\XINT_pfloat_Ps_iii#1#2#3#4#5.{ #1#2#3#4.0}% -\def\XINT_pfloat_Ps_iv #1#2#3#4#5#6.{ #1#2#3#4#5.0}% -\def\XINT_pfloat_Ps_v #1#2#3#4#5#6#7.{ #1#2#3#4#5#6.0}% % \end{macrocode} +% % \subsection{\csh{XINTinFloatFrac}} -% \lverb|1.09i, for frac function in \xintfloatexpr. This version computes +% \added{1.09i} +% +% \lverb|For frac function 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. +% it again some day, certainly.| % +% \changed{1.1} +% \lverb|& % 1.1 removes optional argument for which there was anyhow no interface, for -% technical reasons having to do with \xintNewExpr. +% technical reasons having to do with \xintNewExpr.| % +% \changed{1.1a} +% \lverb|& % 1.1a renames the macro as \XINTinFloatFracdigits (from \XINTinFloatFrac) to % be synchronous with the \XINTinFloatSqrt and \XINTinFloat habits related to -% \xintNewExpr context and issues with macro names. -% -% Note to myself: I still have to rethink the whole thing about what is the best -% to do, the initial way of going through \xinttfrac was just a first -% implementation. +% \xintNewExpr context and issues with macro names.| % +% \changed{1.4e} +% \lverb|& % 1.4e renames it back to \XINTinFloatFrac because of all such similarly named % macros also using \XINTdigits forcedly. % | @@ -33960,8 +34564,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \xint_gob_til_zero #1\XINT_FL_add_zero 0\XINT_FL_add_b #1% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_FL_add_zero #1.#2{#2}%[[ \def\XINT_FL_add_b #1]#2.#3% @@ -33969,16 +34571,12 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \expandafter\XINT_FL_add_c\romannumeral0\XINTinfloat[#2]{#3}#2.#1]% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_FL_add_c #1% {% \xint_gob_til_zero #1\XINT_FL_add_zero 0\XINT_FL_add_d #1% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_FL_add_d #1[#2]#3.#4[#5]% {% @@ -33988,8 +34586,9 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{xintFloatSub}, \csh{XINTinFloatSub}} -% \lverb|First done 1.07. -% +% \added{1.07} +% \changed{1.2f} +% \lverb|& % Starting with 1.2f the arguments undergo an intial rounding to the target % precision P not P+2.| % @@ -34022,18 +34621,16 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{xintFloatMul}, \csh{XINTinFloatMul}} -% \lverb|1.07. -% +% \added{1.07} +% \changed{1.2d} +% \lverb|& % Starting with 1.2f the arguments are rounded to the target precision P not -% P+2. -% +% P+2.| +% \changed{1.2g} +% \lverb|& % 1.2g handles the inputs via \XINTinFloatS which will be more efficient when % the precision is large and the input is for example a small constant like 2. -% -% 1.2k does a micro improvement to the way the macro passes over control -% to its output routine (former version used a higher level \xintE causing -% some extra un-needed processing with two calls to \XINT_infrac where -% one was amply enough).| +% | % \begin{macrocode} \def\xintFloatMul {\romannumeral0\xintfloatmul}% \def\xintfloatmul #1{\XINT_flmul_chkopt \xintfloat #1\xint:}% @@ -34072,7 +34669,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINT_FL_mul_b #1[#2]#3[#4]{\xintiiMul{#3}{#1}/1[#4+#2]}% % \end{macrocode} % \subsection{\csh{xintFloatSqr}, \csh{XINTinFloatSqr}} -% \lverb|Added only at 1.4e, strangely \xintFloatSqr had never been defined so far. +% \added{1.4e} +% \lverb|Strangely \xintFloatSqr had never been defined so far. % % An \XINTinFloatSqr{#1} was defined in xintexpr.sty directly as % \XINTinFloatMul[\XINTdigits]{#1}{#1}, to support the sqr() function. The @@ -34111,6 +34709,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINTinFloatSqr_wopt[#1]#2{\XINTinFloatS[#1]{\expandafter\XINT_FL_sqr_a\romannumeral0\XINTinfloatS[#1]{#2}}}% % \end{macrocode} % \subsection{\csh{XINTinFloatInv}} +% \added{1.3e} % \lverb|Added belatedly at 1.3e, to support inv() function. We use Short % output, for rare inv(\xintexpr 1/3\relax) case. I need to think the whole % thing out at some later date.| @@ -34119,17 +34718,20 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINTinFloatInv_wopt[#1]#2{\XINTinFloatS[#1]{\xintInv{#2}}}% % \end{macrocode} % \subsection{\csh{xintFloatDiv}, \csh{XINTinFloatDiv}} -% \lverb|1.07. -% -% Starting with 1.2f the arguments are rounded to the target precision P not -% P+2. -% +% \added{1.07} +% \changed{1.2f} +% \lverb|Starting with 1.2f the arguments are rounded to the target precision P not +% P+2.| +% \changed{1.2g} +% \lverb|& % 1.2g handles the inputs via \XINTinFloatS which will be more efficient when % the precision is large and the input is for example a small constant like 2. % % The actual rounding of the quotient is handled via \xintfloat (or % \XINTinfloatS). -% +% | +% \changed{1.2k} +% \lverb|& % 1.2k does the same kind of improvement in \XINT_FL_div_b as for % multiplication: earlier code was unnecessarily high level. % | @@ -34187,13 +34789,13 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \expandafter\XINT_FL_div_b\romannumeral0\XINTinfloatS[#3]{#4}/#1e#2% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_FL_div_b #1[#2]{#1e#2}% % \end{macrocode} % \subsection{\csh{xintFloatPow}, \csh{XINTinFloatPow}} -% \lverb|1.07: initial version. 1.09j has re-organized the core loop. +% \added{1.07} +% +% \lverb|1.09j has re-organized the core loop. % % 2015/12/07. I have hesitated to map ^ in expressions to \xintFloatPow rather % than \xintFloatPower. But for 1.234567890123456 to the power 2145678912 with @@ -34201,11 +34803,13 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % gain. % % This routine requires the exponent x to be compatible with \numexpr parsing. +% | % +% \changed{1.2f} +% \lverb|& % 1.2f has rewritten the code for better efficiency. Also, now the argument A % for A^x is first rounded to P digits before switching to the increased % working precision (which depends upon x). -% % | % \begin{macrocode} \def\xintFloatPow {\romannumeral0\xintfloatpow}% @@ -34243,8 +34847,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% \def\XINT_flpow_BisZero .#1.#2#3{#3{1[0]}}% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flpow_checkB_b #1#2.#3.% {% @@ -34269,8 +34871,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \romannumeral0\XINTinfloat [#3]{#6}{#2}{#1}{#4}{#5}% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flpow_aa #1[#2]#3% {% @@ -34278,13 +34878,9 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \romannumeral\XINT_rep #3\endcsname0.#1.% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flpow_ab #1.#2.#3.{\XINT_flpow_a #3#2[#1]}% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flpow_a #1% {% @@ -34302,16 +34898,12 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flpow_b #1#2[#3]#4#5% {% \XINT_flpow_loopI #5.#3.#2.#4.{#1\ifodd #5 \xint_c_i\fi\fi}% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flpow_truncate #1.#2.#3.% {% @@ -34320,8 +34912,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% #3.#2\xint_bye2345678\xint_bye..#1.#3.% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flpow_truncate_a #1.#2.#3.{#3+\xintLength{#2}.#1.}% \def\XINT_flpow_loopI #1.% @@ -34335,16 +34925,12 @@ on input line \noexpand\the\inputlineno.&&J}}#2% #1.% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flpow_ItoIII\ifodd #1\fi #2.#3.#4.#5.#6% {% \expandafter\XINT_flpow_III\the\numexpr #6+\xint_c_.#3.#4.#5.% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flpow_loopI_even #1.#2.#3.%#4.% {% @@ -34393,8 +34979,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% #1.#2.% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flpow_IItoIII\ifodd #1\fi #2.#3.#4.#5.#6.#7.#8% {% @@ -34435,17 +35019,18 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \krof #1% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flpow_IIIend #1#2#3% {#3{\if#21\xint_afterfi{\expandafter-\romannumeral`&&@}\fi#1}}% % \end{macrocode} % \subsection{\csh{xintFloatPower}, \csh{XINTinFloatPower}} -% \lverb|1.07. The core loop has been re-organized in 1.09j for some slight +% \added{1.07} +% \lverb|The core loop has been re-organized in 1.09j for some slight % efficiency gain. The exponent B is given to \xintNum. The ^ in expressions % is mapped to this routine. -% +% | +% \changed{1.2f} +% \lverb|& % Same modifications as in \xintFloatPow for 1.2f. % % 1.2f \XINTinFloatPowerH (now moved to $xintlognameimp, and renamed). It @@ -34454,7 +35039,9 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % rounded to Digits before, not after the square root extraction, 1.2k kept 3 % guard digits for this last step. And the initial step was % changed to a rounding rather than truncating. -% +% | +% \changed{1.4e} +% \lverb|& % Until 1.4e this \XINTinFloatPowerH was the macro for a^b in expressions, % but of course it behaved strangely for b not an integer or an half-integer! % At 1.4e, the non-integer, non-half-integer exponents will be handled via @@ -34505,16 +35092,12 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \the\numexpr\xintLength{#2}+\xint_c_iii.#3.#2.{#1}% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flpower_checkB_c #1.#2.% {% \expandafter\XINT_flpower_checkB_d\the\numexpr#1+#2.#1.#2.% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flpower_checkB_d #1.#2.#3.#4.#5#6% {% @@ -34522,8 +35105,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \romannumeral0\XINTinfloat [#3]{#6}{#2}{#1}{#4}{#5}% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flpower_aa #1[#2]#3% {% @@ -34550,8 +35131,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \xint_dothis{\expandafter\XINT_flpower_loopI_odd}\fi \xint_orthat{\expandafter\XINT_flpower_loopI_even}% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \romannumeral0\XINT_half #1\xint_bye\xint_Bye345678\xint_bye @@ -34583,8 +35162,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \xint_dothis{\expandafter\XINT_flpower_loopII_odd}\fi \xint_orthat{\expandafter\XINT_flpower_loopII_even}% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \romannumeral0\XINT_half#1\xint_bye\xint_Bye345678\xint_bye *\xint_c_v+\xint_c_v)/\xint_c_x-\xint_c_i\relax.% @@ -34617,16 +35194,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{xintFloatFac}, \csh{XINTFloatFac}} -% \lverb|&1.2. -% -% Done at 1.2. -% -% At 1.3e \XINTinFloatFac uses \XINTinFloatS for output. -% -% 1.4e adds some overhead for individual evaluations in float context as it -% obeys the guard digits for the default target precision. It is a waste for -% individual evaluation of one factorial... -% | +% \added{1.2} % \begin{macrocode} \def\xintFloatFac {\romannumeral0\xintfloatfac}% \def\xintfloatfac #1{\XINT_flfac_chkopt \xintfloat #1\xint:}% @@ -34710,7 +35278,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % than the earlier 5=13-8. Whatever happens, the value computed in % \XINT_FL_fac_increaseP is at least 8. There will always be an extra block. % -% Note: with Digits:=32; Maple gives for 200!:$bgroup$obeylines$obeyspaces$ttbfamily +% Note: with Digits:=32; Maple gives for 200!:$bgroup$obeylines$obeyspaces$ttfamily % > factorial(200.); % $indent 375 % $indent 0.78865786736479050355236321393218 10 @@ -34911,12 +35479,14 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{xintFloatPFactorial}, \csh{XINTinFloatPFactorial}} -% \lverb|2015/11/29 for 1.2f. Partial factorial pfactorial(a,b)=(a+1)...b, -% only for non-negative integers with a<=b<10^8. -% -% 1.2h (2016/11/20) now avoids raising \xintError:OutOfRangePFac if the -% condition 0<=a<=b<10^8 is violated. Same as for \xintiiPFactorial. -% +% \added[2015/11/29]{1.2f} +% \lverb|Partial factorial pfactorial(a,b)=(a+1)...b, +% only for non-negative integers with a<=b<10^8.| +% \changed[2016/11/20]{1.2h} +% \lverb|Now avoids raising \xintError:OutOfRangePFac if the +% condition 0<=a<=b<10^8 is violated. Same as for \xintiiPFactorial.| +% \changed{1.4e} +% \lverb|& % 1.4e extends the precision in floating point context adding some overhead % but well.| % \begin{macrocode} @@ -35115,22 +35685,22 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{xintFloatBinomial}, \csh{XINTinFloatBinomial}} -% \lverb|1.2f. We compute binomial(x,y) as pfac(x-y,x)/y!, where the numerator +% \added[2015/12/01]{1.2f} +% \lverb|We compute binomial(x,y) as pfac(x-y,x)/y!, where the numerator % and denominator are computed with a relative error at most 4.10^{-P-2}, then % rounded (once I have a float truncation, I will use truncation rather) to % P+3 digits, and finally the quotient is correctly rounded to P digits. This % will guarantee that the exact value X differs from the computed one Y by at -% most 0.6 ulp(Y). (2015/12/01). -% -% 2016/11/19 for 1.2h. As for \xintiiBinomial, hard to understand why last +% most 0.6 ulp(Y).| +% \changed[2016/11/19]{1.2h} +% \lverb|As for \xintiiBinomial, hard to understand why last % year I coded this to raise an error if y<0 or y>x ! The question of the % Gamma function is for another occasion, here x and y must be (small) % integers. % % 1.4e: same remarks as for factorial and partial factorial about added % overhead due to extra guard digits. -% -%| +% | % \begin{macrocode} \def\xintFloatBinomial {\romannumeral0\xintfloatbinomial}% \def\xintfloatbinomial #1{\XINT_flbinom_chkopt \xintfloat #1\xint:}% @@ -35199,7 +35769,9 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{xintFloatSqrt}, \csh{XINTinFloatSqrt}} -% \lverb|First done for 1.08. +% \added{1.08} +% \changed{1.2f} +% \lverb|& % % The float version was developed at the same time as the integer one and even % a bit earlier. As a result the integer variant had some sub-optimal parts. @@ -35219,22 +35791,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % macros. % % Final note: with 1.2f the input is always first rounded to P significant -% places. -% -% 1.4e (2021/04/15) great hesitation about what to do regarding guard digits. -% This will spoil the guaranteed "correct-rounding" property for individual -% calculations... but is interesting for precision as soon as the square root -% is embedded into some larger calculation. Annoying. But there is \xintexpr -% which I can left configured to use strictly \xintDigits in contrast to -% \xintfloatexpr. Ah ok and there will always be sqrt(x,\xinttheDigits) syntax -% if one wants. And finally I keep sqrt() acting the same in expr and floatexpr. -% -% Attention that at 1.4e \XINTinFloatSqrt is defined to be used ONLY with -% optional argument. -% -% -% -% | +% places.| % \begin{macrocode} \def\xintFloatSqrt {\romannumeral0\xintfloatsqrt}% \def\xintfloatsqrt #1{\XINT_flsqrt_chkopt \xintfloat #1\xint:}% @@ -35275,8 +35832,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% {Square root of negative: -#1].}{}{ 0[0]}}% }% % \end{macrocode} -%\lverb|& -% | +% \begin{privatecodecomments} +% \end{privatecodecomments} % \begin{macrocode} \def\XINT_FL_sqrt_pos #1[#2]#3.% {% @@ -35285,8 +35842,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \xint_orthat {+\xint_c_ii.#2.{}}#100.#3.% }% % \end{macrocode} -% \lverb|& -% | +% \begin{privatecodecomments} +% \end{privatecodecomments} % \begin{macrocode} \def\XINT_flsqrt #1.#2.% {% @@ -35294,8 +35851,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \the\numexpr #2/\xint_c_ii-(#1-\xint_c_i)/\xint_c_ii.#1.% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flsqrt_a #1.#2.#3#4.#5.% {% @@ -35304,8 +35859,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \romannumeral0\XINT_sqrt_start #2.#4#3.#5.#2.#4#3.#5.#1.% }% % \end{macrocode} -% \lverb|& -% | +% % \begin{macrocode} \def\XINT_flsqrt_b #1.#2#3% {% @@ -35316,8 +35870,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% {\XINT_dbl#2\xint_bye2345678\xint_bye*\xint_c_ii\relax}}.% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flsqrt_c #1.#2.% {% @@ -35325,8 +35877,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \romannumeral0\XINT_split_fromleft#2.#1\xint_bye2345678\xint_bye..% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flsqrt_d #1.#2#3.% {% @@ -35335,13 +35885,9 @@ on input line \noexpand\the\inputlineno.&&J}}#2% #2#3.#1.% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flsqrt_finish #1#2.#3.#4.#5.#6.#7.#8{#8[#6]{#3#1[#7]}}% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flsqrt_f 5#1.% {\expandafter\XINT_flsqrt_g\romannumeral0\xintinum{#1}\relax.}% @@ -35350,16 +35896,12 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINT_flsqrt_h #1{\ifnum #1<\xint_c_iii\xint_dothis{\XINT_flsqrt_again}\fi \xint_orthat{\XINT_flsqrt_finish 5.}}% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flsqrt_again #1.#2.% {% \expandafter\XINT_flsqrt_again_a\the\numexpr #2+\xint_c_viii.% }% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_flsqrt_again_a #1.#2.#3.% {% @@ -35370,12 +35912,11 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{xintFloatE}, \csh{XINTinFloatE}} -% \lverb|1.07: The fraction is the first argument contrarily to \xintTrunc and -% \xintRound. -% -% 1.2k had to rewrite this since there is no more a \XINT_float_a macro. -% -% Attention about \XINTinFloatE: it is for use by xintexpr.sty. +% \added{1.07} +% \lverb|The fraction is the first argument contrarily to \xintTrunc and +% \xintRound.| +% \lverb|& +% Attention to \XINTinFloatE: it is for use by xintexpr.sty. % With input 0 it produces on output an 0[N], not 0[0]. % | % \begin{macrocode} @@ -35412,8 +35953,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINT_floate_zero #1]#2.#3{ 0.e0}% \def\XINT_floate_neg-{\expandafter-\romannumeral0\XINT_floate_pos}% % \end{macrocode} -% \lverb|& -% | % \begin{macrocode} \def\XINT_floate_pos #1#2[#3]#4.#5% {% @@ -35427,7 +35966,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINT_infloate_end #1.#2{ #2[#1]}% % \end{macrocode} % \subsection{\csh{XINTinFloatMod}} -% \lverb|1.1. Pour emploi dans xintexpr. Code shortened at 1.2p.| +% \added{1.1} +% \lverb|Pour emploi dans xintexpr. Code shortened at 1.2p.| % \begin{macrocode} \def\XINTinFloatMod {\romannumeral0\XINTinfloatmod [\XINTdigits]}% \def\XINTinfloatmod [#1]#2#3% @@ -35438,7 +35978,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{XINTinFloatDivFloor}} -% \lverb|1.2p. Formerly // and /: in \xintfloatexpr used \xintDivFloor and +% \added{1.2p} +% \lverb|Formerly // and /: in \xintfloatexpr used \xintDivFloor and % \xintMod, hence did not round their operands to float precision beforehand.| % \begin{macrocode} \def\XINTinFloatDivFloor {\romannumeral0\XINTinfloatdivfloor [\XINTdigits]}% @@ -35450,7 +35991,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{XINTinFloatDivMod}} -% \lverb|1.2p. Pour emploi dans xintexpr, donc je ne prends pas la peine de +% \added{1.2p} +% \lverb|Pour emploi dans xintexpr, donc je ne prends pas la peine de % faire l'expansion du modulo, qui se produira dans le \csname. % % Hésitation sur le quotient, faut-il l'arrondir immédiatement ? @@ -35475,7 +36017,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINT_infloatdivmod #1#2#3{\expanded{{#1}{\XINTinFloat[#3]{#2}}}}% % \end{macrocode} % \subsection{\csh{xintifFloatInt}} -% \lverb|1.3a for ifint() function in \xintfloatexpr.| +% \added{1.3a} +% \lverb|For ifint() function in \xintfloatexpr.| % \begin{macrocode} \def\xintifFloatInt {\romannumeral0\xintiffloatint}% \def\xintiffloatint #1{\expandafter\XINT_iffloatint @@ -35488,14 +36031,16 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{xintFloatIsInt}} -% \lverb|1.3d for isint() function in \xintfloatexpr.| +% \added{1.3d} +% \lverb|For isint() function in \xintfloatexpr.| % \begin{macrocode} \def\xintFloatIsInt {\romannumeral0\xintfloatisint}% \def\xintfloatisint #1{\expandafter\XINT_iffloatint \romannumeral0\xintrez{\XINTinFloatS[\XINTdigits]{#1}}10}% % \end{macrocode} % \subsection{\csh{xintFloatIntType}} -% \lverb|1.4e for fractional powers. Expands to \xint_c_mone if argument is not an +% \added{1.4e} +% \lverb|For fractional powers. Expands to \xint_c_mone if argument is not an % integer, to \xint_c_ if it is an even integer and to \xint_c_i if it is an % odd integer.| % \begin{macrocode} @@ -35515,15 +36060,13 @@ on input line \noexpand\the\inputlineno.&&J}}#2% }% % \end{macrocode} % \subsection{\csh{XINTinFloatdigits}, \csh{XINTinFloatSdigits}} -% \lverb|For \xintNewExpr/\xintdeffloatfunc matters, mainly. -% -% | % \begin{macrocode} \def\XINTinFloatdigits {\XINTinFloat [\XINTdigits]}% \def\XINTinFloatSdigits{\XINTinFloatS[\XINTdigits]}% % \end{macrocode} % \subsection{(WIP) \csh{XINTinRandomFloatS}, \csh{XINTinRandomFloatSdigits}} -% \lverb|1.3b. Support for random() function. +% \added{1.3b} +% \lverb|Support for random() function. % % Thus as it is a priori only for xintexpr usage, it expands inside \csname % context, but as we need to get rid of initial zeros we use \xintRandomDigits @@ -35547,8 +36090,6 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % ends up with trailing zeros. That did not feel right but I checked random() % in Python (which of course uses radix 2), and indeed this is what happens % there. -% -% % | % \begin{macrocode} \def\XINTinRandomFloatS{\romannumeral0\XINTinrandomfloatS}% @@ -35581,7 +36122,8 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\XINT_inrandomfloatS_zero#1]{ 0[0]}% % \end{macrocode} % \subsection{(WIP) \csh{XINTinRandomFloatSixteen}} -% \lverb|1.3b. Support for qrand() function.| +% \added{1.3b} +% \lverb|Support for qrand() function.| % \begin{macrocode} \def\XINTinRandomFloatSixteen% {% @@ -35668,7 +36210,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintseries}% - [2021/07/13 v1.4j Expandable partial sums with xint package (JFB)]% + [2022/05/18 v1.4k Expandable partial sums with xint package (JFB)]% % \end{macrocode} % \subsection{\csh{xintSeries}} % \begin{macrocode} @@ -36176,7 +36718,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintcfrac}% - [2021/07/13 v1.4j Expandable continued fractions with xint package (JFB)]% + [2022/05/18 v1.4k Expandable continued fractions with xint package (JFB)]% % \end{macrocode} % \subsection{\csh{xintCFrac}} % \begin{macrocode} @@ -37569,7 +38111,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % \begin{macrocode} \XINT_providespackage \ProvidesPackage{xintexpr}% - [2021/07/13 v1.4j Expandable expression parser (JFB)]% + [2022/05/18 v1.4k Expandable expression parser (JFB)]% \catcode`! 11 \let\XINT_Cmp \xintiiCmp \def\XINTfstop{\noexpand\XINTfstop}% @@ -37940,11 +38482,14 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % which now requires \xintfloatexprPrintOne[D]{x} usage, with first argument % in brackets. % -% | +% +% 1.4k has moved definition of \xintFracToSci to this macro file, so must +% delay \let\xintexprPrintOne\xintFracToSci to after it has been defined. +% | % \begin{macrocode} \protected\def\XINTexprprint.% {\XINT:NEhook:x:toblist\XINT:expr:toblistwith\xintexprPrintOne}% -\let\xintexprPrintOne\xintFracToSci +% \let\xintexprPrintOne\xintFracToSci \protected\def\XINTiexprprint.% {\XINT:NEhook:x:toblist\XINT:expr:toblistwith\xintiexprPrintOne}% \let\xintiexprPrintOne\xintDecToString @@ -38057,13 +38602,39 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % (and attention that \xintexpr\relax is now legal, and an empty ople can be % produced in output also from \xintexpr [17][1]\relax for example) % | +% \changed[2022/05/16]{1.4k} +% \lverb|The \xintieval and \xintfloateval optional bracketed argument can now +% be located outside the braces... took me years to finally make the step toward LaTeX +% users expectations for a decent interface.| % \begin{macrocode} +\let\xint_relax\relax \def\xinteval #1% {\expanded\expandafter\XINTexprprint\expandafter.\romannumeral0\xintbareeval#1\relax}% -\def\xintieval #1% - {\expanded\expandafter\xint_gobble_i\romannumeral`&&@\xintiexpr#1\relax}% -\def\xintfloateval #1% - {\expanded\expandafter\xint_gobble_i\romannumeral`&&@\xintfloatexpr#1\relax}% +\def\xintieval + {\expanded\expandafter\xint_ieval_chkopt\string}% +\def\xint_ieval_chkopt #1% +{% + \ifx [#1\expandafter\xint_ieval_opt + \else\expandafter\xint_ieval_noopt + \fi #1% +}% +\def\xint_ieval_opt [#1]#2% + {\expandafter\xint_gobble_i\romannumeral`&&@\xintiexpr[#1]#2\relax}% +\def\xint_ieval_noopt #1{\expandafter\xint_ieval\expandafter{\iffalse}\fi}% +\def\xint_ieval#1% + {\expandafter\xint_gobble_i\romannumeral`&&@\xintiexpr#1\relax}% +\def\xintfloateval {\expanded\expandafter\xint_floateval_chkopt\string}% +\def\xint_floateval_chkopt #1% +{% + \ifx [#1\expandafter\xint_floateval_opt + \else\expandafter\xint_floateval_noopt + \fi #1% +}% +\def\xint_floateval_opt [#1]#2% + {\expandafter\xint_gobble_i\romannumeral`&&@\xintfloatexpr[#1]#2\relax}% +\def\xint_floateval_noopt #1{\expandafter\xint_floateval\expandafter{\iffalse}\fi}% +\def\xint_floateval#1% + {\expandafter\xint_gobble_i\romannumeral`&&@\xintfloatexpr#1\relax}% \def\xintiieval #1% {\expanded\expandafter\XINTiiexprprint\expandafter.\romannumeral0\xintbareiieval#1\relax}% % \end{macrocode} @@ -38100,6 +38671,113 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \def\xintifsgnfloatexpr #1{\romannumeral0\xintiiifsgn {\xintthefloatexpr #1\relax}}% \def\xintifsgniiexpr #1{\romannumeral0\xintiiifsgn {\xinttheiiexpr #1\relax}}% % \end{macrocode} +% \subsubsection{\csh{xintFracToSci}} +% \added{1.4} +% \changed{1.4e} +% \lverb|Refactored and much simplified +% +% It only needs to be x-expandable, and indeed the implementation here is only +% x-expandable. +% | +% \lverb|& +% +% Finally for 1.4e release I modify. This is breaking change for all +% \xinteval output in case of scientific notation: it will not be with an +% integer mantissa, but with regular scientific notation, using the same rules +% as \xintPFloat. +% +% Of course no float rounding! Also, as [0] will always or almost always be +% present from an \xinteval, we want then to use integer not scientific +% notation. But expression contained decimal fixed point input, or uses +% scientific functions, then probably the N will not be zero and this will +% trigger usage of scientific notation in output. +% +% Implementing these changes sort of ruin our previous efforts to minimize +% grabbing the argument, but well. So the rules now are +% +%( Input: A, A/B, A[N], A/B[N] +%: Output: A, A/B, A if N=0, A/B if N=0 +%: If N is not zero, scientific notation like \xintPFloat,& +% i.e. behaviour like \xintfloateval apart from the rounding& +% to significands of width Digits.& +% At 1.4k, trimming of zeros is always done, i.e.& +% the \xintPFloatMinTrimmed is ignored to keep behaviour.& +% unchanged. +%: The zero gives 0, except in A[N] and A/B[N] cases, it may give& +% 0.0 +%) +% | +% \changed{1.4k} +% Moved from \xintfracnameimp to \xintexprnameimp. +% \begin{macrocode} +\def\xintFracToSci #1{\expandafter\XINT_FracToSci\romannumeral`&&@#1/\W[\R}% +\def\XINT_FracToSci #1/#2#3[#4% +{% + \xint_gob_til_W #2\XINT_FracToSci_noslash\W + \xint_gob_til_R #4\XINT_FracToSci_slash_noN\R + \XINT_FracToSci_slash_N #1/#2#3[#4% +}% +\def\XINT_FracToSci_noslash#1\XINT_FracToSci_slash_N #2[#3% +{% + \xint_gob_til_R #3\XINT_FracToSci_noslash_noN\R + \XINT_FracToSci_noslash_N #2[#3% +}% +\def\XINT_FracToSci_noslash_noN\R\XINT_FracToSci_noslash_N #1/\W[\R{#1}% +\def\XINT_FracToSci_noslash_N #1[#2]/\W[\R% +{% + \ifnum#2=\xint_c_ #1\else + \romannumeral0\expandafter\XINT_pfloat_keeptrimmed_fork\romannumeral0\xintrez{#1[#2]}% + \fi +}% +\def\XINT_FracToSci_slash_noN\R\XINT_FracToSci_slash_N #1#2/#3/\W[\R% +{% + #1\xint_gob_til_zero#1\expandafter\iffalse\xint_gobble_ii0\iftrue + #2\if\XINT_isOne{#3}1\else/#3\fi\fi +}% +\def\XINT_FracToSci_slash_N #1#2/#3[#4]/\W[\R% +{% + \ifnum#4=\xint_c_ #1#2\else + \romannumeral0\expandafter\XINT_pfloat_keeptrimmed_fork\romannumeral0\xintrez{#1#2[#4]}% + \fi + \if\XINT_isOne{#3}1\else\if#10\else/#3\fi\fi +}% +\let\xintexprPrintOne\xintFracToSci +% \end{macrocode} +% \subsubsection{\csh{xintFracToDecimal}} +% \added{1.4k} +% \begin{macrocode} +\def\xintFracToDecimal #1{\expandafter\XINT_FracToDecimal\romannumeral`&&@#1/\W[\R}% +\def\XINT_FracToDecimal #1/#2#3[#4% +{% + \xint_gob_til_W #2\XINT_FracToDecimal_noslash\W + \xint_gob_til_R #4\XINT_FracToDecimal_slash_noN\R + \XINT_FracToDecimal_slash_N #1/#2#3[#4% +}% +\def\XINT_FracToDecimal_noslash#1\XINT_FracToDecimal_slash_N #2[#3% +{% + \xint_gob_til_R #3\XINT_FracToDecimal_noslash_noN\R + \XINT_FracToDecimal_noslash_N #2[#3% +}% +\def\XINT_FracToDecimal_noslash_noN\R\XINT_FracToDecimal_noslash_N #1/\W[\R{#1}% +\def\XINT_FracToDecimal_noslash_N #1[#2]/\W[\R% +{% + \ifnum#2=\xint_c_ #1\else + \romannumeral0\expandafter\XINT_dectostr\romannumeral0\xintrez{#1[#2]}% + \fi +}% +\def\XINT_FracToDecimal_slash_noN\R\XINT_FracToDecimal_slash_N #1#2/#3/\W[\R% +{% + #1\xint_gob_til_zero#1\expandafter\iffalse\xint_gobble_ii0\iftrue + #2\if\XINT_isOne{#3}1\else/#3\fi\fi +}% +\def\XINT_FracToDecimal_slash_N #1#2/#3[#4]/\W[\R% +{% + \ifnum#4=\xint_c_ #1#2\else + \romannumeral0\expandafter\XINT_dectostr\romannumeral0\xintrez{#1#2[#4]}% + \fi + \if\XINT_isOne{#3}1\else\if#10\else/#3\fi\fi +}% +% \end{macrocode} % \subsubsection{Small bits we have to put somewhere} % \lverb|& % Some renaming and modifications here with release 1.2 to switch from @@ -41144,7 +41822,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % contains correctly nested parentheses} % % \lverb|Expands to \xint_c_mone in case a closing ) had no opening ( matching -% it, to \@ne if opening ) had no closing ) matching it, to \z@ if expression +% it, to \@ne if opening ( had no closing ) matching it, to \z@ if expression % was balanced. Call it as: % % \XINT_isbalanced_a \relax #1(\xint_bye)\xint_bye @@ -43376,8 +44054,19 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % \subsubsection{\csh{xintdefufunc}, \csh{xintdefiiufunc}, % \csh{xintdeffloatufunc}} % -% \lverb|1.4| -% +% \lverb|Added at 1.4| +% \changed[2022/05/15]{1.4k} +% \lverb+The \xintexprSafeCatcodes was not paired correctly with +% \xintexprRestoreCatcodes which was in only one branch of \xint_defufunc_b, +% and as a result sanitization of catcodes was never reverted. That the +% bug remained unseen and in particular did not break compilation of +% user manual (where the | must be active), was a sort of unhappy miracle +% due to the | ending up recovering its active catcode from some ulterior +% \xintdefiifunc whose Safe/Restore behaved as described in the user manual, +% i.e. it did a restore to the state before the first unpaired Safe, and this +% miraculous recovery happened before breakage had happened, by sheer luck, +% or rather lack of luck, else I would have seen and solved +% the problem two years ago...+ % \begin{macrocode} \def\XINT_tmpa #1#2#3#4#5#6% {% @@ -43393,11 +44082,11 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \ifnum\xintLength:f:csv{\XINT_defufunc_tmpd}=\xint_c_i \expandafter#6% \else - \xintMessage {xintexpr}{ERROR} + \xintMessage {xintexpr}{ERROR} {Universal functions must be functions of one argument only, but the declaration of \XINT_defufunc_tmpa\space - has \xintLength:f:csv{\XINT_defufunc_tmpd} of them. Cancelled.}% - \xintexprRestoreCatcodes + has \xintLength:f:csv{\XINT_defufunc_tmpd} of them. Canceled.}% + \xintexprRestoreCatcodes \fi }% end of \xint_defufunc_b \def #6{% @@ -43416,6 +44105,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2% with \ifxintglobaldefs global \fi meaning \expandafter\meaning \csname XINT_#2_userufunc_\XINT_defufunc_tmpa\endcsname}% \fi + \xintexprRestoreCatcodes }% end of \xint_defufunc_c }% \def\xintdefufunc {\xintexprSafeCatcodes\xintdefufunc_a}% @@ -44278,8 +44968,12 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % Up to and including 1.2c the definition was global. Starting with 1.2d it is % done locally. % -% Modified at 1.3c so that \XINT_NewFunc et al. do not execute the -% \xintexprSafeCatcodes, as it is now already done earlier by \xintdeffunc. +% The \xintexprSafeCatcodes inserted here by \xintNewExpr +% is not paired with an \xintexprRestoreCatcodes, +% but this happens within a scope limiting group so does not matter. +% At 1.3c, \XINT_NewFunc et al. do not even execute the +% \xintexprSafeCatcodes, as it gets already done by \xintdeffunc prior +% to arriving here. % % | % \begin{macrocode} @@ -44375,15 +45069,25 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \catcode`% 14 \XINTsetcatcodes % clean up to avoid surprises if something changes % \end{macrocode} -% \subsubsection{\csh{ifxintexprsafecatcodes}, \csh{xintexprSafeCatcodes}, \csh{xintexprRestoreCatcodes}} +% \subsubsection{\csh{xintexprSafeCatcodes}, \csh{xintexprRestoreCatcodes}} % \changed[2018/06/17]{1.3c} % \lverb|Added \ifxintexprsafecatcodes to allow nesting| -% \begin{macrocode} -\newif\ifxintexprsafecatcodes -\let\xintexprRestoreCatcodes\empty +% \changed[2022/05/15]{1.4k} +% \lverb|The "allow nesting" from the 2018 comment was strange, because +% the behaviour, as correctly documented in user manual, was that +% in case of a series of \xintexprSafeCatcodes, the \xintexprRestoreCatcodes +% would set catcodes to what they were before the *first* sanitization. +% But as \xintdefvar and \xintdeffunc used such a pair this meant +% that they would incomprehensibly for user reset catcodes to what +% they were before a possible user \xintexprSafeCatcodes located before... +% very lame situation. Anyway. I finally +% fix at 1.4k that by removing the silly \ifxintexprsafecatcodes thing +% and replace it by some stack-like method, avoiding extra macros +% thanks to the help of \unexpanded.| +% \begin{macrocode} +\def\xintexprRestoreCatcodes{}% \def\xintexprSafeCatcodes {% - \unless\ifxintexprsafecatcodes \edef\xintexprRestoreCatcodes {% \endlinechar=\the\endlinechar \catcode59=\the\catcode59 % ; @@ -44409,11 +45113,9 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \catcode44=\the\catcode44 % , \catcode61=\the\catcode61 % = \catcode96=\the\catcode96 % ` - \catcode32=\the\catcode32\relax % space - \noexpand\xintexprsafecatcodesfalse + \catcode32=\the\catcode32 % space + \def\noexpand\xintexprRestoreCatcodes{\unexpanded\expandafter{\xintexprRestoreCatcodes}}% }% - \fi - \xintexprsafecatcodestrue \endlinechar=13 % \catcode59=12 % ; \catcode34=12 % " @@ -44587,10 +45289,10 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \expandafter\xint_secondoftwo \fi {\immediate\write-1{Reloading xinttrig library using Digits=\xinttheDigits.}}% -{\expandafter\gdef\csname xintlibver@trig\endcsname{2021/07/13 v1.4j}% +{\expandafter\gdef\csname xintlibver@trig\endcsname{2022/05/18 v1.4k}% \XINT_providespackage \ProvidesPackage{xinttrig}% -[2021/07/13 v1.4j Trigonometrical functions for xintexpr (JFB)]% +[2022/05/18 v1.4k Trigonometrical functions for xintexpr (JFB)]% }% % \end{macrocode} % \subsection{Ensure used letters are dummy letters} @@ -45907,10 +46609,10 @@ on input line \noexpand\the\inputlineno.&&J}}#2% \expandafter\xint_secondoftwo \fi {\immediate\write-1{Reloading xintlog library using Digits=\xinttheDigits.}}% -{\expandafter\gdef\csname xintlibver@log\endcsname{2021/07/13 v1.4j}% +{\expandafter\gdef\csname xintlibver@log\endcsname{2022/05/18 v1.4k}% \XINT_providespackage \ProvidesPackage{xintlog}% -[2021/07/13 v1.4j Logarithms and exponentials for xintexpr (JFB)]% +[2022/05/18 v1.4k Logarithms and exponentials for xintexpr (JFB)]% }% % \end{macrocode} % \subsection{\csh{xintreloadxintlog}} @@ -46491,11 +47193,11 @@ on input line \noexpand\the\inputlineno.&&J}}#2% % function, those with D+10 digits are used to compute log10() function. This % is done with % an elevated precision for two reasons: -% (- handling of inputs near 1, -% :- in order for a^b = pow10(b*log10(a)) to keep accuracy& +%( - handling of inputs near 1, +%: - in order for a^b = pow10(b*log10(a)) to keep accuracy& % even with large exponents, say in absolute value up to 1e7,& % degradation beginning to show-up at 1e8. -% ) +%) % | % \begin{macrocode} \def\XINT_tmpa{1[0]}% @@ -47946,8 +48648,8 @@ xint.sty:205 xintbinhex.sty:53 xintcfrac.sty:183 xintcore.sty:272 -xintexpr.sty:453 -xintfrac.sty:511 +xintexpr.sty:465 +xintfrac.sty:522 xintgcd.sty:41 xintkernel.sty:17 xintlog.sty:150 @@ -47956,15 +48658,15 @@ xinttools.sty:157 xinttrig.sty:65 \fi % grep -o "^{%" xint*sty | wc -l -\def\totala{ 2155} +\def\totala{ 2178} \iffalse % grep -c -e "^}%" xint*sty xint.sty:204 xintbinhex.sty:52 xintcfrac.sty:183 xintcore.sty:269 -xintexpr.sty:436 -xintfrac.sty:515 +xintexpr.sty:448 +xintfrac.sty:527 xintgcd.sty:43 xintkernel.sty:17 xintlog.sty:151 @@ -47973,7 +48675,7 @@ xinttools.sty:156 xinttrig.sty:64 \fi % grep -o "^}%" xint*sty | wc -l -\def\totalb{ 2138} +\def\totalb{ 2162} \cleardoublepage \section{Cumulative line count} @@ -47997,8 +48699,8 @@ xinttrig.sty:64 \TeX\strut. Version {\xintbndlversion} of {\xintbndldate}.\par } -\CheckSum {38590}% 1.4j -% 38591 pour 1.4i, 38427 pour 1.4h +\CheckSum {38925}% 1.4j +% 38590 pour 1.4j, 38591 pour 1.4i, 38427 pour 1.4h % 38423 pour 1.4g, 38212 pour 1.4f, 38813 pour 1.4e, 35184 pour 1.4d % 35109 pour 1.4c, 35103 pour 1.4b, 34648 pour 1.4a, 34575 pour 1.4 % 33497 pour 1.3f, 33274 pour 1.3e, 31601 pour 1.3d, 31122 pour 1.3c |