diff options
author | Norbert Preining <norbert@preining.info> | 2021-05-18 03:01:12 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2021-05-18 03:01:12 +0000 |
commit | 97eca13a92a0b8ad423b606c8970c9ce64d9b2bf (patch) | |
tree | 7275ec8351efb8f8108d65ec87d4cc81512a295a /macros | |
parent | d999da47ff375df843c0c9bbfd5911236dd9d40a (diff) |
CTAN sync 202105180301
Diffstat (limited to 'macros')
69 files changed, 28686 insertions, 18579 deletions
diff --git a/macros/latex/contrib/bnumexpr/README.md b/macros/latex/contrib/bnumexpr/README.md index a7db8bf12c..cd161f7cb4 100644 --- a/macros/latex/contrib/bnumexpr/README.md +++ b/macros/latex/contrib/bnumexpr/README.md @@ -1,5 +1,5 @@ | Source: bnumexpr.dtx -| Version: v1.4a, 2021/05/13 (doc: 2021/05/13) +| Version: v1.5, 2021/05/17 (doc: 2021/05/17) | Author: Jean-Francois Burnol | Info: Expressions with big integers | License: LPPL 1.3c @@ -20,7 +20,8 @@ these extensions: - comma separated expressions, - the space character as well as the underscore may serve to separate groups of digits, -- optional conversion of output to hexadecimal. +- optional conversion of output to hexadecimal, +- customizability and extendibility of the syntax. The expression parser is a scaled-down variant from the `\xintiiexpr...\relax` @@ -55,21 +56,26 @@ Run `"etex bnumexpr.dtx"` to extract these files: : change history. `bnumexpr.tex` - : can be used to generate the documentation: + : can be used to generate the documentation - : - with latex+dvipdfmx: `"latex bnumexpr.tex"` (thrice) then - `"dvipdfmx bnumexpr.dvi"`. +To generate the documentation: - : - with pdflatex: `"pdflatex bnumexpr.tex"` (thrice). + - with latex+dvipdfmx: `"latex bnumexpr.tex"` (thrice) then + `"dvipdfmx bnumexpr.dvi"`. - : In both cases files `README.md` and `bnumexprchanges.tex` must - be located in the same repertory as `bnumexpr.tex` and `bnumexpr.dtx`. + - with pdflatex: `"pdflatex bnumexpr.tex"` (thrice). -without `bnumexpr.tex`: - : `"pdflatex bnumexpr.dtx"` (thrice) extracts all files and +In both cases files `README.md` and `bnumexprchanges.tex` must +be located in the same repertory as `bnumexpr.tex` and `bnumexpr.dtx`. + +Without `bnumexpr.tex`: + + - `"pdflatex bnumexpr.dtx"` (thrice) extracts all files and simultaneously generates the pdf documentation. -Finishing the installation: +Final steps: + +- move files to appropriate destination: bnumexpr.sty --> TDS:tex/latex/bnumexpr/ @@ -78,6 +84,8 @@ Finishing the installation: bnumexpr.pdf --> TDS:doc/latex/bnumexpr/ README.me --> TDS:doc/latex/bnumexpr/ +- discard auxiliary files generated during compilation. + License ======= @@ -96,9 +104,8 @@ This Work has the LPPL maintenance status "author-maintained". The Author and Maintainer of this Work is Jean-Francois Burnol. -This Work consists of the main source file `bnumexpr.dtx` -and the derived files +This Work consists of the main source file and its derived files - bnumexpr.sty, bnumexpr.pdf, bnumexpr.tex, bnumexprchanges.tex, - and README.md + bnumexpr.dtx, bnumexpr.sty, bnumexpr.pdf, bnumexpr.tex, + bnumexprchanges.tex, README.md diff --git a/macros/latex/contrib/bnumexpr/bnumexpr.dtx b/macros/latex/contrib/bnumexpr/bnumexpr.dtx index 23ead1e2e1..7c37bb2449 100644 --- a/macros/latex/contrib/bnumexpr/bnumexpr.dtx +++ b/macros/latex/contrib/bnumexpr/bnumexpr.dtx @@ -1,17 +1,17 @@ % -*- coding: utf-8-unix; time-stamp-format: "%02d-%02m-%:y %02H:%02M:%02S %Z"; sentence-end-double-space: t; -*- %<*dtx> -\def\bnedtxtimestamp {Time-stamp: <13-05-2021 12:37:08 CEST>} +\def\bnedtxtimestamp {Time-stamp: <17-05-2021 14:16:23 CEST>} \iffalse %</dtx> %<*drv> %% --------------------------------------------------------------- -\def\bnedocdate {2021/05/13}% package bnumexpr documentation date -\def\bnepackdate{2021/05/13}% package bnumexpr date -\def\bneversion {1.4a} % package bnumexpr version +\def\bnedocdate {2021/05/17}% package bnumexpr documentation date +\def\bnepackdate{2021/05/17}% package bnumexpr date +\def\bneversion {1.5} % package bnumexpr version %</drv> %<*readme>-------------------------------------------------------- | Source: bnumexpr.dtx -| Version: v1.4a, 2021/05/13 (doc: 2021/05/13) +| Version: v1.5, 2021/05/17 (doc: 2021/05/17) | Author: Jean-Francois Burnol | Info: Expressions with big integers | License: LPPL 1.3c @@ -32,7 +32,8 @@ these extensions: - comma separated expressions, - the space character as well as the underscore may serve to separate groups of digits, -- optional conversion of output to hexadecimal. +- optional conversion of output to hexadecimal, +- customizability and extendibility of the syntax. The expression parser is a scaled-down variant from the `\xintiiexpr...\relax` @@ -67,21 +68,26 @@ Run `"etex bnumexpr.dtx"` to extract these files: : change history. `bnumexpr.tex` - : can be used to generate the documentation: + : can be used to generate the documentation - : - with latex+dvipdfmx: `"latex bnumexpr.tex"` (thrice) then - `"dvipdfmx bnumexpr.dvi"`. +To generate the documentation: - : - with pdflatex: `"pdflatex bnumexpr.tex"` (thrice). + - with latex+dvipdfmx: `"latex bnumexpr.tex"` (thrice) then + `"dvipdfmx bnumexpr.dvi"`. - : In both cases files `README.md` and `bnumexprchanges.tex` must - be located in the same repertory as `bnumexpr.tex` and `bnumexpr.dtx`. + - with pdflatex: `"pdflatex bnumexpr.tex"` (thrice). -without `bnumexpr.tex`: - : `"pdflatex bnumexpr.dtx"` (thrice) extracts all files and +In both cases files `README.md` and `bnumexprchanges.tex` must +be located in the same repertory as `bnumexpr.tex` and `bnumexpr.dtx`. + +Without `bnumexpr.tex`: + + - `"pdflatex bnumexpr.dtx"` (thrice) extracts all files and simultaneously generates the pdf documentation. -Finishing the installation: +Final steps: + +- move files to appropriate destination: bnumexpr.sty --> TDS:tex/latex/bnumexpr/ @@ -90,6 +96,8 @@ Finishing the installation: bnumexpr.pdf --> TDS:doc/latex/bnumexpr/ README.me --> TDS:doc/latex/bnumexpr/ +- discard auxiliary files generated during compilation. + License ======= @@ -108,11 +116,10 @@ This Work has the LPPL maintenance status "author-maintained". The Author and Maintainer of this Work is Jean-Francois Burnol. -This Work consists of the main source file `bnumexpr.dtx` -and the derived files +This Work consists of the main source file and its derived files - bnumexpr.sty, bnumexpr.pdf, bnumexpr.tex, bnumexprchanges.tex, - and README.md + bnumexpr.dtx, bnumexpr.sty, bnumexpr.pdf, bnumexpr.tex, + bnumexprchanges.tex, README.md %</readme>-------------------------------------------------------- %<*!readme> @@ -122,12 +129,37 @@ and the derived files %% %</!readme> %<*changes>------------------------------------------------------- +\item[1.5 (2021/05/17)] + \begin{itemize} + \item \textbf{breaking change:} the power operators act now in a right + associative way; this has been announced at \xintexprname as a probable + future evolution, and is implemented in anticipation here now. + \item \textbf{fix two bugs} (imported from upstream \xintexprname) regarding + hexadecimal input: impossibility to use |"\foo| syntax (one had to do + |\expandafter"\foo| which is unexpected constraint; a very longstanding + \xintexprname bug) and issues with leading zeros (since \xintexprname |1.2m|). + \item renamed |\bnumexprsetup| into |\bnumsetup|; the former remains + available but is deprecated. + \item the customizability and extendibility is now total: + \begin{enumerate} + \item |\bnumprintone|, |\bnumprintonetohex|, |\bnumprintonesep|, |\bnumhextodec|, + \item |\bnumdefinfix| which allows to add extra infix operators, + \item |\bnumdefpostfix| which allows to add extra postfix operators. + \end{enumerate} + \item |\bnumsetup|, |\bnumdefinfix|, |\bnumdefpostfix| obey the + |\xintglobaldefstrue| and |\xintverbosetrue| settings. + \item documentation is extended, providing details regarding the precedence + model of the parser, as inherited from upstream \xintexprname; also an + example of usage of |\bnumsetup| is included on how to transform + |\bnumeval| into a calculator with fractions. + \end{itemize} + \item[1.4a (2021/05/13)] \begin{itemize} \item fix undefined control sequences errors encountered by the parser in case of either extra or missing closing parenthesis (due to a problem in technology transfer at |1.4| from upstream \xintexprname). - \item fix |\BNE_Op_opp| must now be f-expandable (also caused as a + \item fix |\BNE_Op_opp| must now be \emph{f}-expandable (also caused as a collateral to the technology transfer). \item fix user documentation regarding the constraints applying to the user replacement macros for the core algebra, as they have changed at |1.4|. @@ -366,6 +398,16 @@ pdfstartview=FitH,% pdfpagemode=UseOutlines} \usepackage{bookmark} +% importé de xint 2021/05/14 +\newcommand\RaisedLabel[2][6]{% +\vspace*{-#1\baselineskip}% +\begingroup + \let\leavevmode\relax\phantomsection + \label{#2}% +\endgroup +\vspace*{#1\baselineskip}% +} + %---- \verb, and verbatim like `environments'. \MicroFont et \MacroFont \makeatletter \def\MicroFont {\ttfamily\cdbx@SetSoftWrapBox\color{smallverbcolor}} @@ -397,43 +439,27 @@ pdfpagemode=UseOutlines} \def\makestarlowast {\let*\lowast\catcode`\*\active}% \catcode`* 12 -%------------obsolete------------ -%--- straight quotes, added (finally...) Nov 4, 2014 -% \begingroup\makeatletter -% \catcode`\'\active -% \catcode`\`\active -% \@firstofone {\endgroup -% \def\makequotesstraight {% textcomp package has been loaded by newtxtt -% \let`\textasciigrave -% \let'\textquotesingle -% \catcode39\active -% \catcode96\active }% -% } -%------------ - -% Tentative, mardi 09 septembre 2014 à 22:41:28 - -% Modifié mardi 13 octobre 2015 à 15:24:00 pour utilisable en -% argument, et en particulier dans un \footnote{}. Mais utilise -% \scantokens et macro délimitée maintenant. - -%\def\jf@makeletter #1{\catcode`#111\relax } - \def\verb #1% {% \relax\leavevmode\null \begingroup \MicroFont - \catcode`_ 11 \catcode`! 11 \catcode`: 11 - \catcode`< 11 \catcode`> 11 - % \scantokens will have a result of inserting a space after cs's. - % hence the need to have the catcodes of things like _ right. - % I also need < for > for one occasion in code comments - % naturally won't work in footnotes though. - % this code is truly not satisfying, but enough for my needs here. - \def\@jfverb ##1#1{\let\do\@makeother \dospecials + \def\@makeletter##1{\catcode`##1=11\relax}% + % \scantokens will have a result of inserting a space after cs's. + % hence the need to have the catcodes of things like _ right. + % I also need < for > for code comments + % \dospecials at begin document + % \do\ \do\\\do\{\do\}\do\$\do\&\do\#\do\^\do\_\do\%\do\~\do\| + \odef\dospecials{\dospecials\do\:\do\<\do\>\do\-\do\+}% + % naturally won't work in footnotes though. + % this code is truly not satisfying, but enough for my needs here. + \catcode`\\ 11 \catcode`## 11 + % I don't do \catcode`\% 11 to avoid surprises in code comments + % if my |...| has a linebreak + \def\@jfverb ##1#1{\let\do\@makeletter \dospecials + % lowering a bit the * \makestarlowast - %\let\do\do@noligs \verbatim@nolig@list % not needed here + %\let\do\do@noligs \verbatim@nolig@list % not needed here \@vobeyspaces\everyeof{\noexpand}% \expandafter\@@jfverb\scantokens{##1}\relax}% \@jfverb @@ -455,17 +481,49 @@ pdfpagemode=UseOutlines} \makeatother +% Lundi 17 mai 2021 à 13:58:27 +% J'ajoute un export automatique des exemples qui servira de poor man test +% suite +\newwrite\tests +\immediate\openout\tests=\jobname-out.txt + % mardi 13 octobre 2015 à 15:32:51 % le | n'est pas encore actif ici! \catcode`| \active +% first one uses \bnumexpr deliberately with no \bnethe to test 1.4 \def\bneshow #1% - {|\thebnumexpr#1\relax|$$\color{digitscolor}\bnumexpr#1\relax$$} + {|\thebnumexpr#1\relax|% + \edef\x{\bnumexpr#1\relax}% + \immediate\write\tests{\detokenize{\thebnumexpr#1\relax}^^J\x}% + $$\color{digitscolor}\x$$\ignorespaces} + \def\bneshowthe #1% + {|\bnethe\bnumexpr#1\relax|% + \edef\x{\bnethe\bnumexpr#1\relax}% + \immediate\write\tests{\detokenize{\bnethe\bnumexpr#1\relax}^^J\x}% + $$\color{digitscolor}\x$$\ignorespaces} \def\bneshoweval #1% - {|\bnumeval{#1}|$$\color{digitscolor}\bnumeval{#1}$$} + {|\bnumeval{#1}|% + \edef\x{\bnumeval{#1}}% + \immediate\write\tests{\detokenize{\bnumeval{#1}}^^J\x}% + $$\color{digitscolor}\x$$\ignorespaces} \def\bneshowevaltohex #1% - {|\evaltohex{#1}|$$\color{digitscolor}\evaltohex{#1}$$} + {|\evaltohex{#1}|% + \edef\x{\evaltohex{#1}}% + \immediate\write\tests{\detokenize{\evaltohex{#1}}^^J\x}% + $$\color{digitscolor}\x$$\ignorespaces} \catcode`| 12 +% toujours pénible de devoir se battre avec les espaces verticaux de TeX +\AtBeginDocument{% +% \message{ICI below: \the\belowdisplayskip^^J% +% belowshort: \the\belowdisplayshortskip^^J% +% above: \the\abovedisplayskip^^J% +% aboveshor: \the\abovedisplayshortskip^^J% +% }% + \belowdisplayskip\belowdisplayshortskip + \abovedisplayskip\abovedisplayshortskip +} + \DeclareRobustCommand\csa [1]{{\char92\detokenize{#1}}} \newcommand\csh[1]{\texorpdfstring{\csa{#1}}{\textbackslash\detokenize{#1}}} @@ -480,53 +538,30 @@ pdfpagemode=UseOutlines} {bnumexpr}% \xspace }% +\def\bnumnameuserdoc + {\texorpdfstring + {\hyperref[titlepage]{{\color{PineGreen}\ttzfamily bnumexpr}}} + {bnumexpr}% + \xspace }% + \def\xintkernelname {\href{http://www.ctan.org/pkg/xint}{xintkernel}\xspace }% -\def\xintname - {\href{http://www.ctan.org/pkg/xint}{xint}\xspace }% \def\xintcorename {\href{http://www.ctan.org/pkg/xint}{xintcore}\xspace }% +\def\xintname + {\href{http://www.ctan.org/pkg/xint}{xint}\xspace }% +\def\xintfracname + {\href{http://www.ctan.org/pkg/xint}{xintfrac}\xspace }% \def\xintexprname {\href{http://www.ctan.org/pkg/xintexpr}{xintexpr}\xspace }% \def\xintbinhexname {\href{http://www.ctan.org/pkg/xint}{xintbinhex}\xspace }% - -% \centeredline: OUR OWN LITTLE MACRO FOR CENTERING LINES -% ======================================================= - -% 7 mars 2013 -% ----------- -% -% This macro allows to conveniently center a line inside a paragraph and still -% allow use therein of \verb or other macros changing catcodes. -% A proposito, the \LaTeX \centerline uses \hsize and not \linewidth ! -% (which in my humble opinion is bad) - -% Actually my \centeredline works nicely in list environments. - -% \ignorespaces ajouté le 9 juin 2013. - -% Note: \centeredline creates a group - -\makeatletter -\newcommand*\centeredline {% - \ifhmode \\\relax - \def\centeredline@{\hss\egroup\hskip\z@skip\ignorespaces }% - \else - \def\centeredline@{\hss\egroup }% - \fi - \afterassignment\@centeredline - \let\next=} -\def\@centeredline - {\hbox to \linewidth \bgroup \hss \bgroup \aftergroup\centeredline@ } - - \frenchspacing \usepackage{bnumexpr} - +\usepackage{xintfrac} \usepackage{etoc} - +\usepackage{centeredline} \usepackage{framed} \makeatletter\let\check@percent\relax\makeatother \begin{document} @@ -540,6 +575,8 @@ pdfpagemode=UseOutlines} The \bnumname package\par } +\RaisedLabel{titlepage} + {\centering \textsc{Jean-François Burnol}\par \footnotesize @@ -563,12 +600,20 @@ it is analogous to \item it computes powers (with either |**| or |^| as infix operator), \item it computes factorials (with |!| as postfix operator), \item it has an operator |//| for floored division and |/:| for the - associated modulo, -\item the space character is ignored and can thus be used to separate in the + associated modulo (like {\catcode`\% 12 |%|} in Python which we can't use for obvious reasons), +\item the space character is ignored% +% +\footnote{It is not completely ignored, |\count37<space>| will automatically + be prefixed by |\number| and the space token delimits the integer indexing + the count register. Also, devious inputs using nested braces around spaces + may create unexpected internal situations and even break the parser.} +% +and can thus be used to separate in the source blocks of digits for better readability of long numbers, \item also the underscore |_| may be used as visual digit separator, -\item comma separated expressions are allowed. +\item comma separated expressions are allowed, +\item syntax is customizable and extendible. \end{itemize} There is also a more core-level |\bnumexpr...\relax| construct% \footnote{Since |1.4|, one can use |\bnumexpr...\relax| directly in @@ -596,22 +641,165 @@ installations for \verb?latex|pdflatex? and also for \verb?xelatex|lualatex?. Further, at |1.4| (|2021/05/12|) the |\expanded| primitive is required. It is available in all engines since \TeX Live 2019. -By default the arithmetic operations are executed via the \xintcorename -macros, but via option |custom| and usage of |\bnumexprsetup| it is -possible to replace them by expandable macros of a custom origin. - \section{Examples} +With certain languages, Babel with PDF\LaTeX\ may make some characters active, for example the +|!| with the French language. It must then be input as |\string!|. \noindent\bneshow {---1 208 637 867 * (2 187 917 891 - 3 109 197 072)}% -\bneshoweval {(13_8089_1090-300_1890_2902)*(1083_1908_3901-109_8290_3890)}% +\bneshowthe {(13_8089_1090-300_1890_2902)*(1083_1908_3901-109_8290_3890)}% \bneshoweval {(92_874_927_979**5-31_9792_7979**6)/30!}% \bneshoweval {30!/20!/21/22/23/24/25/(26*27*28*29)}% \bneshoweval {13^50//12^50, 13^50/:12^50}% \bneshoweval {13^50/12^50, 12^50}% \bneshoweval {(1^10+2^10+3^10+4^10+5^10+6^10+7^10+8^10+9^10)^3}% \bneshoweval {100!/36^100}% -\bneshoweval {"10*"100*"1000*"A0000, 16^(1+2+3+4)*10}% -\bneshowevaltohex{"7FFFFFFF+1, "400^3, "ABCDEF*"FEDCBA}% +\bneshoweval {"0010*"0100*"1000*"A0000, 16^(1+2+3+4)*10}% +\bneshowevaltohex{"7FFFFFFF+1, "0400^3, "ABCDEF*"0000FEDCBA, 1234}% +\bneshoweval {"\evaltohex{12345678}FFFF, 000012345679*16**4-1} + +\section{The \texttt{custom} package option and \csh{bnumsetup}} + +Package \bnumname needs that some \emph{big integer engine} provides the macros doing +the actual computations. By default, it loads package \xintcorename (a subset +of \href{http://www.ctan.org/pkg/xint}{xint}) and uses \csa{bnumsetup} in +the following way: +\begin{verbatim} + \usepackage{xintcore} + \bnumsetup{add=\xintiiAdd, sub=\xintiiSub, mul=\xintiiMul, + divround=\xintiiDivRound, div=\xintiiDivFloor, + mod=\xintiiMod, pow=\xintiiPow, fac=\xintiiFac, + opp=\xintiiOpp} +\end{verbatim} + +If +using \csa{bnumsetup}, it is not necessary to specify all keys, +for example one can do |\bnumsetup{mul=\MySlowerMul}|, and only +multiplication will be changed. + +Naturally it is up to the user to load the appropriate package for +the alternative macros. + +The macros serving as custom user replacements% +% +\footnote{% + The replacement macros will by default receive arguments composed of + explicit digit tokens, with no leading zeros, with at most one leading minus + sign and no plus sign. + + The format of these arguments will depend on what the other customized + macros do. For example if |opp=\foo| is used and the custom |\foo| inserts a + |+| when taking the opposite of a negative number, then the other custom + macros for arithmetic (and the |\foo| macro itself) must be able to handle + arguments starting optionally with such a |+|.% +} +must be \emph{f}-expandable, +except for the computation of factorials, which only has to be +\emph{x}-expandable.% +% +\footnote{Prior to |1.4|, only \emph{x}-expandability was required. It is easy however to use an |\expanded| based wrapper to convert \emph{x}-expandable macros into \emph{f}-expandable ones.} +% + +Macro |\bnumsetup| can be used multiple times in the same document, thus +allowing to switch math engines or to remap operators to some other arithmetic +macros of the same math engine. Its effect obeys the local scope.% +% +\footnote{The effect is global if under |\xintglobaldefstrue| setting.} + +The hexadecimal input via the |"| prefix is converted internally to decimal +notation using |\xintHexToDec| from package \xintbinhexname, and customization +is possible via redefinition of |\bnumhextodec|, whose default is to be an +alias to |\xintHexToDec|. + +The final conversion back to hexadecimal done by |\evaltohex| is handled by +|\bnumprintonetohex| which defaults to |\xintDecToHex|. + +These two steps can thus be customized as will. But the loading of package +\xintbinhexname can not be canceled. + +\section{\csh{bnumprintone}, \csh{bnumprintonetohex}, \csh{bnumprintonesep}} + +The computed values are printed one by one, separated by a comma and a space +(this is customizable as |\bnumprintonesep|), and each value being handed over +to |\bnumprintone|. By default this does nothing else than producing its +argument as is, it can be redefined at will (perhaps using macros such as in +\autoref{sec:printing} to handle the case of very long numbers). + +There is also |\bnumprintonetohex| which is used by |\evaltohex| (this is its +sole difference from |\bnumeval|). Its default definition makes it an alias +to |\xintDecToHex| from package \xintbinhexname. + +\section{Example of customization: let the syntax handle fractions!} + +I will show how to transform |\bnumeval| into a calculator with fractions! We +will use the \xintfracname macros, but coerce them into always producing +fractions in lowest terms (except for powers). For optimization we use +the |[0]| post-fix which speeds-up the input parsing by the \xintfracname +macros. We remove it on output via a custom |\bnumprintone|. + +Note that the |/| operator is associated to |divround| key but of course here +the used macro will simply do an exact division of fractions, not a rounded-to-% +an integer division. This is the whole point of using a macro of our own +choosing! +\begin{verbatim} +\usepackage{xintfrac} +\newcommand\myIrrAdd[2]{\xintIrr{\xintAdd{#1}{#2}}[0]} +\newcommand\myIrrSub[2]{\xintIrr{\xintSub{#1}{#2}}[0]} +\newcommand\myIrrMul[2]{\xintIrr{\xintMul{#1}{#2}}[0]} +\newcommand\myDiv[2]{\xintIrr{\xintDiv{#1}{#2}}[0]} +\newcommand\myDivFloor[2]{\xintDivFloor{#1}{#2}[0]} +\newcommand\myMod[2]{\xintIrr{\xintMod{#1}{#2}}[0]} +\newcommand\myPow[2]{\xintPow{#1}{#2}}% will have trailing [0] +\newcommand\myFac[1]{\xintFac{#1}}% produces trailing [0] +\bnumsetup{add=\myIrrAdd, sub=\myIrrSub, mul=\myIrrMul, + divround=\myDiv, div=\myDivFloor, + mod=\myMod, pow=\myPow, fac=\myFac}% +% % if any operation happened, the result is already irreducible +% % (except power of non-irreducible) so this is overhead: +% \let\bnumprintone\xintIrr +% % but it is safe way to get rid of the trailing [0] +% % else we have to take care of case with no [0] because of no operations +% % well let's do it: +\makeatletter +\def\myPrintOne#1{\@myPrintOne#1[0]\relax} +\def\@myPrintOne#1[0]#2\relax{#1} +\let\bnumprintone\myPrintOne +\makeatother +\end{verbatim} +\begingroup +\newcommand\myIrrAdd[2]{\xintIrr{\xintAdd{#1}{#2}}[0]} +\newcommand\myIrrSub[2]{\xintIrr{\xintSub{#1}{#2}}[0]} +\newcommand\myIrrMul[2]{\xintIrr{\xintMul{#1}{#2}}[0]} +\newcommand\myDiv[2]{\xintIrr{\xintDiv{#1}{#2}}[0]} +\newcommand\myDivFloor[2]{\xintDivFloor{#1}{#2}[0]} +\newcommand\myMod[2]{\xintIrr{\xintMod{#1}{#2}}[0]} +\newcommand\myPow[2]{\xintPow{#1}{#2}}% will have trailing [0] +\newcommand\myFac[1]{\xintFac{#1}}% produces trailing [0] +\bnumsetup{add=\myIrrAdd, sub=\myIrrSub, mul=\myIrrMul, divround=\myDiv, + div=\myDivFloor, mod=\myMod, pow=\myPow, fac=\myFac}% +\makeatletter +\def\myPrintOne#1{\@myPrintOne#1[0]\relax}% +\def\@myPrintOne#1[0]#2\relax{#1}% +\let\bnumprintone\myPrintOne +\makeatother +\bneshoweval{1000000*(1/100+1/2^7-20/5^4)/(1/3-5/7+9/11)^2} +\bneshoweval{(1-1/2)(1-1/3)(1-1/4)(1-1/5)(1-1/6)(1-1/7)} +\bneshoweval{(1-1/3+1/9-1/27-1/81+1/243-1/729+1/2187)^5} +\bneshoweval{(1+1/10)^10 /: (1-1/10)^10} +\bneshoweval{2^-3^4} +\endgroup + +This last example is computed differently than it would be with \xintexprname +|1.4f| because \bnumname |1.5| already applies right associativity to powers, +whereas \xintexprname |1.4f| still applies left associativity. + +Note also that the above changes break |\evaltohex| whose output routine uses +by default |\xintDecToHex| which will choke on fractional input. However it is +not difficult to write a macro applying separately to numerator and +denominator. + +Computations with fractions quickly give birth to big results, see +\autoref{sec:printing} on how to modify |\bnumprintone| to coerce \TeX\ into +wrapping numbers too long for the available width. \section{Differences from \csh{numexpr}} \label{sec:differences} @@ -692,12 +880,12 @@ syntax as in ... \fi \end{verbatim} -the end of line will insert a terminating space token. Again, here -|\bnumeval{...}| must produce an integer acceptable to \TeX, i.e. at most -{\number"7FFFFFFF} in absolute value. +the end of line will (under the normal \LaTeX\ configuration) insert a +terminating space token. Again, here |\bnumeval{...}| must produce an integer +acceptable to \TeX, i.e. at most {\number"7FFFFFFF} in absolute value. \section{Printing big numbers} - +\label{sec:printing} \LaTeX{} will not split long numbers at the end of lines. I personally often use helper macros (not in the package) of the following type: @@ -714,95 +902,254 @@ often use helper macros (not in the package) of the following type: \noindent|\thebnumexpr 1000!\relax=|\phantom{0}{\color{digitscolor}\printnumber{\thebnumexpr 1000!\relax}}\par -\section{Expression syntax} - -It is the expected one with infix operators and parentheses, the -recognized operators being |+|, |-|, |*|, |/| (rounded division), -|^| (power), |**| (power), |//| (by default floored division), -|/:| (the associated modulo) and |!| (factorial). One can input hexadecimal -numbers as in \TeX\ syntax for number assignments, i.e. using a |"| prefix and -only uppercase letters |ABCDEF|. +\section{Expression syntax and its customizability} + +The implemented syntax is the expected one with infix operators and +parentheses, the recognized operators being |+|, |-|, |*|, |/| (rounded +division), |^| (power), |**| (power), |//| (by default floored division), |/:| +(the associated modulo) and |!| (factorial). One can input hexadecimal numbers +as in \TeX\ syntax for number assignments, i.e. using a |"| prefix and only +uppercase letters |ABCDEF|. + +Different computations may be separated by commas. The whole expression is +handled token by token, any component (digit, operator, parentheses... even +the ending |\relax|) may arise on the spot from macro expansions. The +underscore |_| can be used to separate digits in long numbers, for readability +of the input. + +The precedence rules are as expected and detailed in the next section. +Operators on the same level of precedence (like |*|, |/|, |//|, |/:|) behave +in a left-associative way, and these examples behave as e.g.\@ with Python +analogous operators:\newline \bneshoweval{100//3*4, 100*4//3, 100/:3*4, + 100*4/:3, 100//3/:5} + +At |1.5| a change was made to the power operators which became +right-associative. Again, this matches the behaviour e.g.\@ of Python:% +% +\footnote{It had been announced at \xintexprname \texttt{1.4} that probably in + future power operator would become right-associative, so we experiment it + here in \bnumname in advance.}% +% +\newline +\bneshoweval{2^3^4, 2^(3^4)} -The modulo |/:| is by default associated with the floored division |//|, but -using |\bnumexprsetup{mod=...}| it can, like the other operators, be remapped -to any macro of one's choice. +It is possible to customize completely the behaviour of the parser, in two ways: +\begin{itemize} +\item via |\bnumsetup| which has a simple interface to replace the macros + associated to the operators |+|, |-|, |*|, |/|, |//|, |/:|, |**| and |^| by + custom macros, +\item or even more completely via |\bnumdefinfix| and |\bnumdefpostfix| which + allow to add new operators to the syntax! (or overwrite existing ones...) +\end{itemize} -Different computations may be separated by commas. The whole -expression is handled token by token, any component (digit, operator, -parenthesis... even the ending |\relax|) may arise on the spot from -macro expansions. +\section{Precedences} -The precedence rules are the expected ones. Tacit multiplication applies in -front of parentheses, and after them, and it has an elevated precedence -compared to multiplication explicitly induced by |*|. +The parser implements precedence rules based on concepts which are summarized +below. I am providing them for users who will use the customizing macros. +\begin{itemize} +\item an infix operator has two associated precedence levels, say |L| and + |R|, +\item the parser proceeds from left to right, pausing each time it has found a + new number and an operator following it, +\item the parser compares the left-precedence |L| of the new found operator to + the right-precedence |R_last| of the last delayed operation (which already + has one argument and would like to know if it can use the new found one): if + |L| is at most equal to it, the delayed operation is now executed, else the + new-found operation is kept around to be executed first, once it will have + gathered its arguments, of which only one is known at this stage. +\end{itemize} -There is currently no user interface to change precedence levels. The -three operators |/|, |//|, |/:| are at the same level of precedence as the -multiplication |*|. The factorial postfix |!| has highest precedence. The -minus signs inherit the precedence level of the previously encountered infix -operators. +Although there is thus internally all the needed room for sophistication, the +implemented table of precedences simply puts all of multiplication and +division related operations at the same level, which means that left +associativity will apply with these operators. I could see that Python behaves +the same way for its analogous operators. -In case of equal precedence the operations are left-associative,% -% -\footnote{But it has been announced at \xintexprname \texttt{1.4} that - probably in future power operator will become right-associative, and if this - is done, this will be transferred to \bnumname also.} +Here is the default table of precedences as implemented by the package: +\begin{center} +\DeleteShortVerb{\|}% + \begin{tabular}{|c|c|c|} + \multicolumn3{c}{Table of precedences}\\\hline +\MakeShortVerb{\|}% + operator& left &right\\\hline + |+|,|-|& 12&12\\ + |*|,|/|,|//|,|/:|& 14&14\\ + tacit |*|&16&14\\ + |**|, |^|& 18&17\\ + |!| &20&n/a\\\hline + \end{tabular} +\end{center} +Tacit multiplication applies in front of parentheses, and after them, also in +front of count variables or registers. As shown in the table it has an +elevated precedence compared to multiplication explicitly induced by |*|, so +|100/4(9)| is computed as |100/36| and not as |25*9|:\newline +\bneshoweval{100/4(9), (100/4)9, 1000 // (100/4) 9 (1+1) * 13} +More generally |A/B(C)(D)(E)*F| will compute |(A/(B*C*D*E))*F|.% % -hence:\newline \bneshoweval{2^3^4, (2^3)^4, 2^(3^4)} +\footnote{The |B(C)(D)(E)| product will be computed as |B*(C*(D*E))| because + the right-precedence of tacit multiplication is |14| but its left-precedence + is |16|, creating right associativity. As the underlying mathematical + operation is associative this is irrelevant to final result.} + +The unary |-|, as prefix, has a special behaviour: after an infix operator it +will acquire a right-precedence which is the minimum of |12| (i.e.\@ the +precedence of addition and subtraction) and of the right-precedence of the +infix operator. For example |2^-3^4| will be parsed as |2^(-(3^4))|, raising +an error because the parser is by default integer only, but see the section +about |\bnumsetup| which explains how to let |\bnumeval| computes fractions! -The underscore |_| can be used to separate digits in long numbers, for -readability of the input. -\section{Options} +\section{\csh{bnumdefinfix}} -The sole package option is |custom|: it tells \bnumname not to load -package \xintcorename. +It is possible to define infix binary operators of one's own choosing.% +% +\footnote{The effect of |\bnumdefinfix| is global if under |\xintglobaldefstrue| setting.} +% +The syntax is +\centeredline{|\bnumdefinfix|\marg{operator}\marg{\string\macro}\marg{L-prec}\marg{R-prec}} +\begin{description} +\item[\marg{operator}] The characters for the operator, they may be letters or + non-letters, and must not be active or among the special characters |\|, + \textcolor{smallverbcolor}{\{}, \textcolor{smallverbcolor}{\}}, |#| and + {\catcode`\% 12 |%|}. Also, + spaces will be removed.% +% +\footnote{The |_| can be used, but not as first character of the operator, as + it would be mis-construed on usage as part of the previous number, and + ignored as such.}% +% +$^{,}$% +% +{\catcode`# 12 \footnote{It is actually possible to use |#| as an operator + name or a character in such a name but the definition with |\bnumdefinfix| + must then be done either with \expandafter|\string\string#| or + |####|...}}% +$^{,}$% +% +\footnote{Active characters must be prefixed by |\string| both at the time of + the definition and at the time of use. It is probably better to use a toggle which + will turn off the activity, both at time of definition and at time of use.}% +\item[\marg{\string\macro}] The expandable macro (expecting two mandatory + arguments) which is to assign to the infix operator. This macro must be + \emph{f}-expandable. Also it must (if the default package configuration is + not modified for the core operators) produce integers in the ``strict'' + format which is expected by the \xintcorename macros for arithmetic: no + leading zeros, at most one minus sign, no plus sign, no spaces. +\item[\marg{L-prec}] An integer, minimal |4|, maximal |22|, which governs + the left-\hskip0pt precedence of the infix operator. +\item[\marg{R-prec}] An integer, minimal |4|, maximal |22|, which governs the + right-\hskip0pt precedence of the infix operator. +\end{description} +Generally, the two precedences are set to the same value. -\section{\csh{bnumexprsetup}} +Once a multi-character operator is defined, the first characters of its name +can be used if no ambiguity. In case of ambiguity, it is the earliest defined +shortcut which prevails, except for the full name. So for example if |$abc| +operator is defined, and |$ab| is defined next, then |$| and |$a| will still +serve as shortcuts to the original |$abc|, but |$ab| will refer to the newly +defined operator. -Package \bnumname needs that some big integer engine provides the macros doing -the actual computations. By default, it loads package \xintcorename (a subset -of \href{http://www.ctan.org/pkg/xint}{xint}) and uses \csa{bnumexprsetup} in -the following way: +Fully qualified names are never ambiguous, and a shortcut once defined will +change meaning under only these two possibilities: +\begin{itemize} +\item it is re-defined as the full name of a new operator, +\item the original operator to which the shortcut refers is defined again; then + the shortcut is automatically updated to point to the new meaning. +\end{itemize} \begin{verbatim} - \usepackage{xintcore} - \bnumexprsetup{add=\xintiiAdd, sub=\xintiiSub, mul=\xintiiMul, - divround=\xintiiDivRound, div=\xintiiDivFloor, - mod=\xintiiMod, pow=\xintiiPow, fac=\xintiiFac, - opp=\xintiiOpp}% +\def\equals#1#2{\ifnum\pdfstrcmp{#1}{#2}=0 \expandafter1\else + \expandafter0\fi} +% or: +\def\equals#1#2{\expanded{\ifnum\pdfstrcmp{#1}{#2}=0 1\else0\fi}} +\def\differ#1#2{\expanded{\ifnum\pdfstrcmp{#1}{#2}=0 0\else1\fi}} +\bnumdefinfix{==}{\equals}{10}{10} +\bnumdefinfix{!=}{\differ}{10}{10} +\bnumdefinfix{times}{\xintiiMul}{14}{14} +\bnumdefinfix{++}{\xintiiAdd}{19}{19} \end{verbatim} - -If -using \csa{bnumexprsetup}, it is not necessary to specify all keys, -for example one can do |\bnumexprsetup{mul=\MyFasterMul}|, and only -multiplication will be changed. - -Naturally it is up to the user to load the appropriate package for -the alternative macros. - -The macros serving as custom user replacements must be \emph{f}-expandable.% +%\def\equals#1#2{\ifnum\pdfstrcmp{#1}{#2}=0 \expandafter1\else\expandafter0\fi} +\def\equals#1#2{\expanded{\ifnum\pdfstrcmp{#1}{#2}=0 1\else0\fi}} +\def\differ#1#2{\expanded{\ifnum\pdfstrcmp{#1}{#2}=0 0\else1\fi}} +\bnumdefinfix{==}{\equals}{10}{10} +\bnumdefinfix{!=}{\differ}{10}{10} +\bnumdefinfix{times}{\xintiiMul}{14}{14} +\bnumdefinfix{++}{\xintiiAdd}{19}{19} % -\footnote{Prior to |1.4|, only \emph{x}-expandability was required. The author - could relax again the constraint, if asked to do so. Or perhaps simply add - an option for it.} +\bneshoweval{2 + 3! = 5, 2 + (3!) == 8} Notice in the |2+3! = 5| example that +the existence of |!=| prevails on applying the factorial, so this is test +whether |2+3| and |5| differ; it is not a matter of precedence here, but of +input parsing ignoring spaces. And |2+3! == 8| would create an error as after +having found the |!=| operator and now expecting a digit (as there is no |!==| +operator) the parser would find an unexpected |=| and report an error. Hence +the usage of parentheses in the input.% % -(except for the computation of factorials, which only has to be -\emph{x}-expandable). +\footnote{As |!=| is indeed defined out-of-the-box in the \xintexprname + syntax, the |3! == 8| issue applies with |\xinteval| and perhaps I should + add it to the user documentation, as warning.}\newline +\bneshoweval{2^5 == 4 times 8, 11 t 14} +\bneshoweval{100 ++ -10 ^ 3, (100 - 10)^3, 2 ** 5 ++ 3, 2^(5+3)} -They will by default receive arguments composed of explicit digit tokens, with -no leading zeros, with at most one leading minus sign and no plus sign. -The format of these arguments may depend on what the |opp=\foo| replacement -macro does. If the custom |\foo| inserts a |+| when taking the opposite of a -negative number, then the custom macros for arithmetic (and the |\foo| macro -itself) must be able to handle arguments starting optionally with such a |+|. +\section{\csh{bnumdefpostfix}} -Macro |\bnumexprsetup| can be used multiple times in the same document, thus -allowing to switch math engines or to remap operators to some other arithmetic -macros of the same math engine. Its effect obeys the local scope. +It is possible to define postfix unary operators of one's own choosing.% +% +\footnote{The effect of |\bnumdefpostfix| is global if under |\xintglobaldefstrue| setting.} +% +The syntax is +\centeredline{|\bnumdefpostfix|\marg{operator}\marg{\string\macro}\marg{L-prec}} +\begin{description} +\item[\marg{operator}] The characters for the operator name: same + conditions as for |\bnumdefinfix|. Postfix and infix operators share the + same name-space, regarding abbreviated names. +\item[\marg{\string\macro}] The one argument expandable macro to assign to + the postfix operator. This macro only needs to be \emph{x}-expandable. +\item[\marg{L-prec}] An integer, minimal |4|, maximal |22|, which governs the + left-\hskip0pt precedence of the infix operator. +\end{description} +Examples below which use the maximal precedence are typical of what is +expected of a ``function'' (and I even used |.len()| notation with parentheses +in one example, the parentheses are part of the postfix operator name). And +indeed such postfix operators are thus a way to implement functions in +disguise, circumventing the fact that the \bnumname parser will never be +extended to work with functional syntax (for this, see \xintexprname). With +the convention (followed in some examples) that such postfix operators start +with a full stop, but never contain another one, we can chain simply by using +concatenation (no need for parentheses), as there will be no +ambiguity. +\begin{verbatim} +\usepackage{xint}% for \xintiiSum, \xintiiSqrt +\def\myRev#1{\xintNum{\xintReverseOrder{#1}}}% reverse and trim leading zeros +\bnumdefpostfix{$}{\myRev}{22}% the $ will have top precedence +\bnumdefpostfix{:}{\myRev}{4}% the : will have lowest precedence +\bnumdefpostfix{::}{\xintiiSqr}{4}% the :: is a completely different operator +\bnumdefpostfix{.len()}{\xintLength}{22}% () for fun but a single . will be enough! +\bnumdefpostfix{.sumdigits}{\xintiiSum}{22}% .s will abbreviate +\bnumdefpostfix{.sqrt}{\xintiiSqrt}{22}% .sq will be unambiguous (but confusing) +\bnumdefpostfix{.rep}{\xintReplicate3}{22}% .r will be unambiguous +\end{verbatim} +\def\myRev#1{\xintNum{\xintReverseOrder{#1}}}% reverse digits and trim leading zeros +\bnumdefpostfix{$}{\myRev}{22}% $ +\bnumdefpostfix{:}{\myRev}{4}% +\bnumdefpostfix{::}{\xintiiSqr}{4}% +\bnumdefpostfix{.len()}{\xintLength}{22}% +\bnumdefpostfix{.sumdigits}{\xintiiSum}{22}% +\bnumdefpostfix{.sqrt}{\xintiiSqrt}{22}% +\bnumdefpostfix{.rep}{\xintReplicate3}{22}% +\bneshoweval{(2^31).len(), (2^31)., 2^31$, 2^31:, (2^31)$} +\bneshoweval{(2^31).sqrt, 100000000.sq.sq} +\bneshoweval{(2^31).sumdigits, 123456789.s, 123456789.s.s, 123456789.s.s.s} +\bneshoweval{10^10+10000+2000+300+40+5:} +\bneshoweval{1+2+3+4+5+6+7+8+9+10 :: +1 :: *2 :: :: :} +\bneshoweval{123456789.r}\par\vspace*{-\baselineskip}% Toujours LaTeX avec ses + % espaces verticaux TROP GRANDS DEPUIS 30 ANS +\begin{verbatim} +\bnumdefpostfix{.rep}{\xintReplicate5}{22}% .rep modified --> .r too +\end{verbatim} +\bnumdefpostfix{.rep}{\xintReplicate5}{22}% +\bneshoweval{123456789.r} -At |1.4| release there is no option to customize how the hexadecimal input and -output is handled, it goes necessarily via the \xintbinhexname macros. +\clearpage \section{Readme} \begingroup @@ -819,7 +1166,7 @@ output is handled, it goes necessarily via the \xintbinhexname macros. \noindent\kern\parindent\input README.md \endgroup }\x -%\clearpage +\clearpage \section{Changes} %\small @@ -841,61 +1188,53 @@ output is handled, it goes necessarily via the \xintbinhexname macros. %</dtx> %<*package> % -% \section{Package \bnumnameimp implementation} +% \section{\bnumname implementation} % \label{sec:bnumexprcode} % \etocdefaultlines % \localtableofcontents -% \etocmarkbothnouc{Package \bnumnameimp implementation} -% -% Comments are sparse. Actually at |1.4|, there are simply no comments. I -% transferred from \xintexprname its |\expanded| based infra-structure from -% its own |1.4| release of January 2020. +% \etocmarkbothnouc{\bnumnameuserdoc \hyperref[sec:bnumexprcode]{implementation}} % -% Error handling by the parser is kept to a minimum; if something goes wrong, -% the offensive token gets discarded, and it is not even always the case that -% some expandable error message is issued. +% I transferred mid-May 2021 from \xintexprname its |\expanded| based +% infra-structure from its own |1.4| release of January 2020 and bumped +% version to |1.4|. Also I added support for hexadecimal input and output, via +% unconditional loading of \xintbinhexname. % -% A few comments at |1.4a|: +% A few comments added here at |1.4a|: % \begin{itemize} % \item It looked a bit costly and probably would have been mostly useless to % end users to integrate in \bnumname support for nested structures via % square brackets [, ], which is in \xintexprname since its January 2020 -% |1.4| release. But some underlying related architecture remains here; we -% could make some micro-gains probably but diverging from upstream code +% |1.4| release. But some of the related architecture remains here; we +% could make some gains probably but diverging from upstream code % would make maintenance a nightmare. +% \item Formerly, the |\csname...\endcsname| encapsulation technique had the +% after-effect to allow the macros supporting the infix operators to be only +% \emph{x}-expandable. At |1.4|, I could have still allowed support macros +% being only \emph{x}-expandable, but, keeping in sync with upstream, I have +% used only a |\romannumeral| trigger and did not insert an |\expanded|, so +% now the support macros must be \emph{f}-expandable. The |1.4a| release +% fixes the related user documentation of |\bnumsetup| which was not +% updated at |1.4|. The support macro for the factorial however needs only +% be \emph{x}-expandable. +% \item Also, I simply do not understand why the legacy (|1.2e|) user documentation +% said that the support macros were supposed to \emph{f}-expand their arguments, as +% they are used only with arguments being explicit digit tokens (and +% optional minus sign). % \item The |\bnumexpr\relax| syntax creating an empty ople is by itself now % legal, and can be injected (comma separated) in an expression, keeping it % invariant, however |\bnumeval{}| ends in a |File ended while scanning use % of \BNE_print_c| error because |\BNEprint| makes the tacit requirement % that the 1D ople to output has at least one item. -% \item Formerly, the |\csname...\endcsname| encapsulation technique had the -% after-effect to allow the macros supporting the infix operators to be only -% x-expandable. At |1.4|, I could have still allowed only x-expandable -% macros, but, keeping in sync with upstream, I have used only a -% |\romannumeral| trigger and did not insert an |\expanded|, so now the -% support macros must be f-expandable. The |1.4a| release fixes the related -% user documentation of |\bnumexprsetup| which was not updated at |1.4|. -% The support macro for the factorial however needs only be x-expandable. -% \item Also, I simply do not understand why the legacy user documentation -% said that the support macros were supposed to f-expand their arguments, as -% they are used only with arguments being explicit digit tokens (and -% optional minus sign). -% \item I hesitated a bit about making the decimal to hexadecimal and -% hexadecimal to decimal support macros customizable, but dropped the -% idea. Loading \xintbinhexname unconditionally has also the advantage to -% not have to define some \xintkernelname provided helper macros; and it -% still does not load \xintcorename, so is keeping dependencies somewhat low -% and the |custom| option significant. -% \item I had fleetingly consider a parser |\hexexpr| where input is -% hexadecimal with no |"| prefix, but implementing this basically means -% duplicating with new names a large chunk of the parser code to have parser -% specific |"getnext"| macros for example. Not worth it. % \end{itemize} % -% \subsection{Package identification and catcode setup} +% At |1.5|, right-associativity is implemented for powers in anticipation of +% upstream, and the customizability and extendibility of the package is made +% total via added |\bnumdefinfix| and |\bnumdefpostfix|. +% +% \subsection{Package identification}\leavevmode % \begin{macrocode} \NeedsTeXFormat{LaTeX2e}% -\ProvidesPackage{bnumexpr}[2021/05/13 v1.4a Expressions with big integers (JFB)]% +\ProvidesPackage{bnumexpr}[2021/05/17 v1.5 Expressions with big integers (JFB)]% % \end{macrocode} % \subsection{Load unconditionally xintbinhex} % Newly done at |1.4|. Formerly, \bnumname had no dependency if loaded @@ -908,46 +1247,81 @@ output is handled, it goes necessarily via the \xintbinhexname macros. % \begin{macrocode} \RequirePackage{xintbinhex}[2021/05/10]% % \end{macrocode} -% \subsection{\csh{bnumexprsetup}} +% \subsection{Package options}\leavevmode +% \begin{macrocode} +\def\BNEtmpa {0}% +\DeclareOption {custom}{\def\BNEtmpa {1}}% +\ProcessOptions\relax +% \end{macrocode} +% \subsection{\csh{bnumsetup} and conditional loading of \xintcorename} +% The keys should have been |Add|, |Sub|, \dots, not |add|, |sub|, \dots, so +% internally macros |\BNE_Op_Add| etc\dots\ macro names would be used, but well, +% let's simply live with this. +% +% |\bnumsetup| replaces at |1.5| deprecated |\bnumexprsetup| which is kept as an alias. % \begin{macrocode} {\catcode`! 3 \catcode`_ 11 % - \gdef\bnumexprsetup #1{\BNE_parsekeys #1,=!,}% + \gdef\bnumsetup #1{\BNE_parsekeys #1,=!,}% \gdef\BNE_parsekeys #1=#2#3,% {% \ifx!#2\expandafter\BNE_parsedone\fi + \XINT_global \expandafter \let\csname BNE_Op_\xint_zapspaces #1 \xint_gobble_i\endcsname% - =#2\BNE_parsekeys + =#2% + \ifxintverbose + \PackageInfo{bnumexpr}{assigned + \ifxintglobaldefs globally \fi + \string#2 to \xint_zapspaces #1 \xint_gobble_i\MessageBreak +% \end{macrocode} +% Workaround the space inserted by |\on@line|. +% \begin{macrocode} + \expandafter\xint_firstofone}% + \fi + \BNE_parsekeys }% \gdef\BNE_parsedone #1\BNE_parsekeys {}% }% -% \end{macrocode} -% \subsection{Package options} -% The keys should have been |Add|, |Sub|, \dots, not |add|, |sub|, \dots, so -% internally macros |\BNE_Op_Add| etc\dots\ macro names would be used, but well, -% let's simply leave with this. -% \begin{macrocode} -\def\BNEtmpa {0}% -\DeclareOption {custom}{\def\BNEtmpa {1}}% -\ProcessOptions\relax -\edef\BNErestorecatcodes{\XINTrestorecatcodes}% -\XINTsetcatcodes% -\if0\BNEtmpa\expandafter\xint_secondoftwo\fi -\xint_gobble_i{% +\let\bnumexprsetup\bnumsetup +\if0\BNEtmpa\expandafter\@secondoftwo\fi +\@gobble{% \RequirePackage{xintcore}[2021/05/10]% - \bnumexprsetup{add=\xintiiAdd, sub=\xintiiSub, mul=\xintiiMul, + \bnumsetup{add=\xintiiAdd, sub=\xintiiSub, mul=\xintiiMul, divround=\xintiiDivRound, div=\xintiiDivFloor, mod=\xintiiMod, pow=\xintiiPow, fac=\xintiiFac, opp=\xintiiOpp}% }% % \end{macrocode} +% \subsection{Activate usual \xintname catcodes for code source}\leavevmode +% \begin{macrocode} +\edef\BNErestorecatcodes{\XINTrestorecatcodes}% +\XINTsetcatcodes% +% \end{macrocode} % Strangely those three are not defined in xintkernel.sty, but only in xint.sty % \begin{macrocode} \long\def\xint_firstofthree #1#2#3{#1}% \long\def\xint_secondofthree #1#2#3{#2}% \long\def\xint_thirdofthree #1#2#3{#3}% % \end{macrocode} -% \subsection{\csh{bnumexpr}, \csh{thebnumexpr}, \csh{bnethe}, \csh{bnumeval}} +% For the mechanism of |\bnumdefinfix| we need [1] precedence levels to be +% available as |\chardef|'s. \xintkernelname already provides 0-10, 12, 14, +% 16, 18, 20, 22. Admittedly they could be created only dynamically, and then +% I would not have to set a cap at 22, but well, that's already a large +% supported range for a functionality nobody will use, as nobody probably uses +% the package to start with. +% +% .. [1] left levels need to be represented by one token; right levels are +% hard-coded into |checkp_<op>| macros and could have been there explicit +% digit tokens but we will use the |\xint_c_...| |\char|-tokens. +% \begin{macrocode} +\chardef\xint_c_xi 11 +\chardef\xint_c_xiii 13 +\chardef\xint_c_xv 15 +\chardef\xint_c_xvii 17 +\chardef\xint_c_xix 19 +\chardef\xint_c_xxi 21 +% \end{macrocode} +% \subsection{\csh{bnumexpr}, \csh{thebnumexpr}, \csh{bnethe}, \csh{bnumeval}}\leavevmode % \begin{macrocode} \def\XINTfstop {\noexpand\XINTfstop}% \def\bnumexpr {\romannumeral0\bnumexpro}% @@ -962,26 +1336,32 @@ output is handled, it goes necessarily via the \xintbinhexname macros. \def\bnebareeval{\BNE_start}% \def\bnethe#1{\expanded\expandafter\xint_gobble_i\romannumeral`&&@#1}% \protected\def\BNEprint.#1{{\BNE_print#1.}}% -\def\BNE_print#1{#1\expandafter\BNE_print_a\string}% +\def\BNE_print#1{\bnumprintone{#1}\expandafter\BNE_print_a\string}% \def\BNE_print_a#1{\unless\if#1.\expandafter\BNE_print_b\fi}% \def\BNE_print_b {\expandafter\BNE_print_c\expandafter{\expandafter\xint_gobble_i\string}}% -\def\BNE_print_c#1{, #1\expandafter\BNE_print_a\string}% +\def\BNE_print_c#1{\bnumprintonesep\bnumprintone{#1}\expandafter\BNE_print_a\string}% \protected\def\BNEprinthex.#1{{\BNE_printhex#1.}}% -\def\BNE_printhex#1{\xintDecToHex{#1}\expandafter\BNE_printhex_a\string}% +\def\BNE_printhex#1{\bnumprintonetohex{#1}\expandafter\BNE_printhex_a\string}% \def\BNE_printhex_a#1{\unless\if#1.\expandafter\BNE_printhex_b\fi}% \def\BNE_printhex_b {\expandafter\BNE_printhex_c\expandafter{\expandafter\xint_gobble_i\string}}% -\def\BNE_printhex_c#1{, \xintDecToHex{#1}\expandafter\BNE_printhex_a\string}% +\def\BNE_printhex_c#1{\bnumprintonesep\bnumprintonetohex{#1}\expandafter\BNE_printhex_a\string}% +\let\bnumprintone\xint_firstofone +\let\bnumprintonetohex\xintDecToHex +\def\bnumprintonesep{, }% % \end{macrocode} % \subsection{\csh{BNE_getnext}} +% The upstream |\BNE_put_op_first| has a string of included |\expandafter|, +% which was imported here at |1.4| and |1.4a| but they serve nothing in our +% context. Removed this useless overhead at |1.5|. % \begin{macrocode} \def\BNE_getnext #1% {% \expandafter\BNE_put_op_first\romannumeral`&&@% \expandafter\BNE_getnext_a\romannumeral`&&@#1% }% -\def\BNE_put_op_first #1#2#3{\expandafter#2\expandafter#3\expandafter{#1}}% +\def\BNE_put_op_first #1#2#3{#2#3{#1}}% \def\BNE_getnext_a #1% {% \ifx\relax #1\xint_dothis\BNE_foundprematureend\fi @@ -1021,8 +1401,7 @@ output is handled, it goes necessarily via the \xintbinhexname macros. % In the case of hitting a |(|, previous release inserted directly a % |\BNE_oparen|. But the expansion architecture imported from upstream % |\xintiiexpr| has been refactored, and the |..._oparen| meaning and -% usage evolved. We stick with |{}\xint_c_ii^v (| from upstream, -% which works (I am 15 months away from \xintexprname |1.4|). +% usage evolved. We stick with |{}\xint_c_ii^v (| from upstream. % \begin{macrocode} \def\BNE_getnextfork #1{% \if#1+\xint_dothis \BNE_getnext_a \fi @@ -1031,7 +1410,7 @@ output is handled, it goes necessarily via the \xintbinhexname macros. \xint_orthat {\BNE_scan_number #1}% }% % \end{macrocode} -% \subsection{Parsing an integer in decimal or hexadecimal notation} +% \subsection{Parsing an integer in decimal or hexadecimal notation}\leavevmode % \begin{macrocode} \def\BNE_scan_number #1% {% @@ -1039,7 +1418,22 @@ output is handled, it goes necessarily via the \xintbinhexname macros. \ifnum \xint_c_ix<1\string#1 \xint_dothis \BNE_startint\fi \xint_orthat \BNE_notadigit #1% }% -\def\BNE_notadigit#1{\BNE_getnext }% +% \end{macrocode} +% If user employs |\bnumdefinfix| with |\string#|, and then tries |100##3|, +% the first |#| will be interpreted as operator (assuming no +% operator starting with |##| has actually been defined) and the error +% "message" (which is not using |\message| or a |\write|) +% will then be +% \centeredline{|Digit? (got `##')|} +% because the parser is actually looking for a digit but finds the second |#|, +% and TeX displays it doubled. This is doubly +% confusing, but well, let's not dwell on that. +% \begin{macrocode} +\def\BNE_notadigit#1% +{% + \expandafter\BNE_scan_number + \romannumeral`&&@\XINT_expandableerror{Digit? (got `#1'). Hit I<RET><digit>}% +}% \def\BNE_startint #1% {% \if #10\expandafter\BNE_gobz_a\else\expandafter\BNE_scanint_a\fi #1% @@ -1060,15 +1454,18 @@ output is handled, it goes necessarily via the \xintbinhexname macros. {% \expandafter\BNE_scanint_main\romannumeral`&&@#1% }% +% \end{macrocode} +% Upstream (at |1.4f|) has |_getop| here, but let's jump directly to |BNE_getop_a|. +% \begin{macrocode} \def\BNE_scanint_hit_cs \ifnum#1\fi#2\BNE_scanint_again {% - \iffalse{{{\fi}}\expandafter}\romannumeral`&&@\BNE_getop#2% + \iffalse{{{\fi}}\expandafter}\romannumeral`&&@\BNE_getop_a#2% }% \def\BNE_scanint_next #1\BNE_scanint_again {% \if _#1\xint_dothis\BNE_scanint_again\fi \xint_orthat - {\iffalse{{{\fi}}\expandafter}\romannumeral`&&@\BNE_getop#1}% + {\iffalse{{{\fi}}\expandafter}\romannumeral`&&@\BNE_getop_a#1}% }% \def\BNE_gobz_scanint_main #1% {% @@ -1080,29 +1477,72 @@ output is handled, it goes necessarily via the \xintbinhexname macros. {% \expandafter\BNE_gobz_scanint_main\romannumeral`&&@#1% }% +% \end{macrocode} +% Upstream (at |1.4f|) has |_getop| here, but let's jump directly to |BNE_getop_a|. +% \begin{macrocode} \def\BNE_gobz_scanint_hit_cs\ifnum#1\fi#2\BNE_scanint_again {% - 0\iffalse{{{\fi}}\expandafter}\romannumeral`&&@\BNE_getop#2% + 0\iffalse{{{\fi}}\expandafter}\romannumeral`&&@\BNE_getop_a#2% }% \def\BNE_gobz_scanint_next #1\BNE_scanint_again {% \if _#1\xint_dothis\BNE_gobz_scanint_again\fi \if 0#1\xint_dothis\BNE_gobz_scanint_again\fi \xint_orthat - {0\iffalse{{{\fi}}\expandafter}\romannumeral`&&@\BNE_getop#1}% + {0\iffalse{{{\fi}}\expandafter}\romannumeral`&&@\BNE_getop_a#1}% }% \def\BNE_hex_in #1.% {% - \expanded{{{\xintHexToDec{#1}}}\expandafter}\romannumeral`&&@\BNE_getop + \expanded{{{\bnumhextodec{#1}}}\expandafter}\romannumeral`&&@\BNE_getop +}% +\let\bnumhextodec\xintHexToDec +% \end{macrocode} +% Upstream (until |1.4f|) had a long-standing bug in its hexadecimal input, +% which was inherited here at |1.4|: the |\BNE_scanhex| triggered +% |\BNE_scanhex_a| which then grabbed an unexpanded token and used it as is +% in an |\ifcat|... this made syntax such as |"\foo| broken. Fixed here at +% |1.5|. +% +% And there was a further long-standing bug in upstream (from |1.2m| to +% |1.4f|) about leading hexadecimal zeros not being trimmed. This was +% inherited here at |1.4|. Fixed also at |1.5|. +% \begin{macrocode} +\def\BNE_scanhex #1#2% #1=" +{% + \expandafter\BNE_hex_in\expanded\bgroup + \expandafter\BNE_scanhexgobz_a\romannumeral`&&@#2% +}% +\def\BNE_scanhexgobz_a #1% +{% + \ifcat #1\relax0.\iffalse{\fi\expandafter}\expandafter\xint_gobble_i\fi + \BNE_scanhexgobz_aa #1% +}% +\def\BNE_scanhexgobz_aa #1% +{% + \if\ifnum`#1>`0 + \ifnum`#1>`9 + \ifnum`#1>`@ + \ifnum`#1>`F + 0\else1\fi\else0\fi\else1\fi\else0\fi 1% + \xint_dothis\BNE_scanhex_b + \fi + \if 0#1\xint_dothis\BNE_scanhexgobz_bgob\fi + \if _#1\xint_dothis\BNE_scanhexgobz_bgob\fi + \if .#1\xint_dothis\BNE_scanhexgobz_toII\fi + \xint_orthat + {\XINT_expandableerror + {HexDigit was expected but saw `#1'. Using 0, hit <RET>}% + 0.>;\iffalse{\fi}}% + #1% }% -\def\BNE_scanhex #1% #1=" +\def\BNE_scanhexgobz_bgob #1#2% {% - \expandafter\BNE_hex_in\expanded\bgroup\BNE_scanhex_a + \expandafter\BNE_scanhexgobz_a\romannumeral`&&@#2% }% \def\BNE_scanhex_a #1% {% - \ifcat #1\relax\xint_dothis{.\iffalse{\fi}#1}\fi - \xint_orthat {\BNE_scanhex_aa #1}% + \ifcat #1\relax.\iffalse{\fi\expandafter}\expandafter\xint_gobble_i\fi + \BNE_scanhex_aa #1% }% \def\BNE_scanhex_aa #1% {% @@ -1114,7 +1554,7 @@ output is handled, it goes necessarily via the \xintbinhexname macros. \expandafter\BNE_scanhex_b \else \if _#1\xint_dothis{\expandafter\BNE_scanhex_bgob}\fi - \xint_orthat {\xint_afterfi {.\iffalse{\fi}}}% + \xint_orthat {.\iffalse{\fi\expandafter}}% \fi #1% }% @@ -1128,6 +1568,14 @@ output is handled, it goes necessarily via the \xintbinhexname macros. }% % \end{macrocode} % \subsection{\csh{BNE_getop}} +% The upstream analog to |\BNE_getop_a| applies |\string| to |#1| in its +% thirdofthree branch before handing over to analog of |\BNE_scanop_a|, but I +% see no reason for doing it here (and I do have to check if upstream has +% any valid reason to do it). Removed. First branch was a |\BNE_foundend|, +% used only here, and expanding to |\xint_c_\relax|, let's move the +% |#1| (which will be |\relax|) last and simply insert |\xint_c_|. +% +% The |_scanop| macros have been refactored at upstream and here |1.5|. % \begin{macrocode} \def\BNE_getop #1% {% @@ -1141,50 +1589,59 @@ output is handled, it goes necessarily via the \xintbinhexname macros. \ifnum\xint_c_ix<1\string#1 \xint_dothis\xint_secondofthree\fi \if (#1\xint_dothis \xint_secondofthree\fi %) \xint_orthat \xint_thirdofthree - {\BNE_foundend}% - {\BNE_precedence_*** *#1}% - {\expandafter\BNE_scanop_a \string#1}% + \xint_c_ + {\BNE_prec_tacit *}% + \BNE_scanop_a + #1% }% \catcode`* 12 -\def\BNE_foundend {\xint_c_ \relax}% \def\BNE_scanop_a #1#2% {% \expandafter\BNE_scanop_b\expandafter#1\romannumeral`&&@#2% }% \def\BNE_scanop_b #1#2% {% - \ifcat#2\relax\xint_dothis{\BNE_foundop_a #1#2}\fi - \ifcsname BNE_itself_#1#2\endcsname - \xint_dothis - {\expandafter\BNE_scanop_c\csname BNE_itself_#1#2\endcsname}\fi - \xint_orthat {\BNE_foundop_a #1#2}% + \unless\ifcat#2\relax + \ifcsname BNE_itself_#1#2\endcsname + \BNE_scanop_c + \fi\fi + \BNE_foundop_a #1#2% }% -\def\BNE_scanop_c #1#2% +\def\BNE_scanop_c #1#2#3#4#5% #1#2=\fi\fi {% - \expandafter\BNE_scanop_d\expandafter#1\romannumeral`&&@#2% + #1#2% + \expandafter\BNE_scanop_d\csname BNE_itself_#4#5\expandafter\endcsname + \romannumeral`&&@% }% \def\BNE_scanop_d #1#2% {% - \ifcat#2\relax \xint_dothis{\BNE_foundop #1#2}\fi - \ifcsname BNE_itself_#1#2\endcsname - \xint_dothis - {\expandafter\BNE_scanop_c\csname BNE_itself_#1#2\endcsname }\fi - \xint_orthat {\csname BNE_precedence_#1\endcsname #1#2}% + \unless\ifcat#2\relax + \ifcsname BNE_itself_#1#2\endcsname + \BNE_scanop_c + \fi\fi + \BNE_foundop #1#2% }% +% \end{macrocode} +% If a postfix say |?s| is defined and |?r| is encountered the |?| will have +% been interpreted as a shortcut to |?s| and then the |r| will be found with +% the parser (after having executed the already found postfix) now looking for +% another operator so the error message will be |Operator? (got `r')| which is +% doubly confusing... well, let's not dwell on that. +% \begin{macrocode} \def\BNE_foundop_a #1% {% \ifcsname BNE_precedence_#1\endcsname \csname BNE_precedence_#1\expandafter\endcsname \expandafter #1% \else - \xint_afterfi{\BNE_getop\romannumeral0% - \XINT_expandableerror - {"#1" is unknown as operator. (I)nsert one:} }%<<deliberate space - \fi + \expandafter\BNE_getop_a\romannumeral`&&@% + \xint_afterfi{\XINT_expandableerror + {Operator? (got `#1'). Hit I<RET><operator>}}% + \fi }% \def\BNE_foundop #1{\csname BNE_precedence_#1\endcsname #1}% % \end{macrocode} -% \subsection{Expansion spanning; opening and closing parentheses} +% \subsection{Expansion spanning; opening and closing parentheses}\leavevmode % \begin{macrocode} \def\BNE_tmpa #1#2#3#4#5% {% @@ -1211,7 +1668,7 @@ output is handled, it goes necessarily via the \xintbinhexname macros. \def#5% {% \XINT_expandableerror - {An extra ) has been removed. Hit Return, fingers crossed.}% + {An extra ) has been removed. Hit <RET>, fingers crossed.}% \expandafter#2\romannumeral`&&@\expandafter\BNE_put_op_first \romannumeral`&&@\BNE_getop_legacy }% @@ -1267,13 +1724,13 @@ output is handled, it goes necessarily via the \xintbinhexname macros. \csname BNE_op_-xii\endcsname \let\BNE_precedence_)\xint_c_i \def\BNE_missing_) - {\XINT_expandableerror{Sorry to report a missing ) at the end of this journey.}% + {\XINT_expandableerror{Missing ). Hit <RET> to proceed}% \xint_c_ \BNE_done }% \catcode`) 12 % \end{macrocode} % \subsection{The comma as binary operator} % At |1.4|, it is simply a union operator for 1D oples. Inserting directly -% here a |<space><comma>| separator (as in earlier releases) in accumulated +% here a |<comma><space>| separator (as in earlier releases) in accumulated % result would avoid having to do it on output but to the cost of diverging % from \xintexprname upstream code, and to have to let the |\evaltohex| output % routine handle comma separated values rather than braced values. @@ -1312,36 +1769,53 @@ output is handled, it goes necessarily via the \xintbinhexname macros. \expandafter\let\csname BNE_precedence_,\endcsname\xint_c_iii % \end{macrocode} % \subsection{The minus as prefix operator of variable precedence level} -% This |\BNE_Op_opp| causes trouble as at |1.4| it must be f-expandable, +% This |\BNE_Op_opp| caused trouble at |1.4| as it must be \emph{f}-expandable, % whereas earlier it expanded inside |\csname...\endcsname| context, so I -% could define it as {\catcode`\#12 |\if-#1\else\if0#10\else-#1\fi\fi|} where -% {\catcode`\#12 |#1|} was the +% could define it as \centeredline{|\if-#1\else\if0#10\else-#1\fi\fi|} where +% |#1| was the % first token of unbraced argument but this meant at |1.4| an added % |\xint_firstofone| here. Well let's return to sanity at |1.4a| and not add % the |\xint_firstofone| and simply default |\BNE_Op_opp| to |\xintiiOpp|, % which it should have been all along! And on this occasion let's trim user -% documentation of irrelevant complications. +% documentation of complications. +% +% The package used to need to define unary minus operator with precedences 12, +% 14, and 18. It also defined it at level 16 but this was unneedeed actually, +% no operator possibly generating usage of an |op_-xvi|. +% +% At |1.5| the right precedence of powers was lowered to 17, so we now need +% here only 12, 14, and 17. +% +% Due to |\bnumdefinfix| it is needed to support also, perhaps, the other +% levels 13, 15, 16, 18, .... This will be done only if necessary and is the +% reason why the macros |\BNE_defminus_a| and |\BNE_defminus_b| are given +% permanent names. In fact it is now |\BNE_defbin_b| which will decide to invoke +% or not the |\BNE_defminus_a|, and we activate it here only for the base +% precedence 12. +% +% The |\XINT_global| are inexistent in upstream at |1.4f| as it does not +% incorporate yet some analog to |\bnumdefinfix/\bnumdefpostfix|. % \begin{macrocode} -\def\BNE_tmpb #1#2#3#4#5% +\def\BNE_defminus_b #1#2#3#4#5% {% - \def #1% \BNE_op_-<level> + \XINT_global\def #1% \BNE_op_-<level> {% \expandafter #2\romannumeral`&&@\expandafter#3% \romannumeral`&&@\BNE_getnext }% - \def #2##1##2##3% \BNE_exec_-<level> + \XINT_global\def #2##1##2##3% \BNE_exec_-<level> {% \expandafter ##1\expandafter ##2\expandafter {\expandafter{\romannumeral`&&@\BNE_Op_opp##3}}% }% - \def #3##1% \BNE_check-_-<level> + \XINT_global\def #3##1% \BNE_check-_-<level> {% \xint_UDsignfork ##1{\expandafter #4\romannumeral`&&@#1}% -{#4##1}% \krof }% - \def #4##1##2% \BNE_checkp_-<level> + \XINT_global\def #4##1##2% \BNE_checkp_-<level> {% \ifnum ##1>#5% \expandafter #4% @@ -1351,51 +1825,71 @@ output is handled, it goes necessarily via the \xintbinhexname macros. \fi }% }% -\def\BNE_tmpa #1% +\def\BNE_defminus_a #1% {% -\expandafter\BNE_tmpb + \expandafter\BNE_defminus_b \csname BNE_op_-#1\expandafter\endcsname \csname BNE_exec_-#1\expandafter\endcsname \csname BNE_check-_-#1\expandafter\endcsname \csname BNE_checkp_-#1\expandafter\endcsname \csname xint_c_#1\endcsname }% -\BNE_tmpa {xii}% -\BNE_tmpa {xiv}% -\BNE_tmpa {xvi}% -\BNE_tmpa {xviii}% +\BNE_defminus_a {xii}% % \end{macrocode} % \subsection{The infix operators.} % I could have at the |1.4| refactoring injected usage of |\expanded| here, -% but kept in sync with upstream \xintexprname code. +% but kept in sync with upstream \xintexprname code. Any \emph{x}-expandable +% macro can easily be converted into an \emph{f}-expandable one using +% |\expanded|, so this is no serious limitation. % % Macro names are somewhat bad and there is much risk of confusion in future % maintenance of |\BNE_Op_| prefix (used for |\BNE_Op_add| etc...; besides % this should have been |\BNE_Op_Add|) and |\BNE_op_| prefix (used for -% {\catcode`+ 11 |\BNE_op_+|} etc...). +% |\BNE_op_+| etc...). +% +% At |1.5| decision is made to anticipate the announced upstream change to let +% the power operators be right associative, matching Python behaviour. This +% change is simply implemented by hardcoding in |\BNE_checkp_<op>| the right +% precedence which so far, for such operators, had been identical with the +% left precedence (upstream has examples of direct coding without +% formalization). In fact the right precedence existed already as argument to +% |\BNE_defbin_b| as the precedence to assign to unary minus following |<op>|. +% +% Note1: although it is easy to change the left precedence at user level, the +% right precedence is now more inaccessible. But on the other hand \bnumname +% provides |\bnumdefinfix| so all is customizable at user level. +% +% Note2: Tacit multiplication is not really a separate operator, it is +% the |*| with an elevated left precedence, which costs nothing to create and +% this precedence is stored in chardef token |\BNE_prec_tacit|. +% +% Compared to upstream, we use here numbers as arguments to |\BNE_defbin_b|, +% and convert to roman numerals internally, also the operator macro is passed +% as a control sequence not as its name (and |#6| and |#7| are permuted in +% |\BNE_defbin_c|). % \begin{macrocode} \def\BNE_defbin_c #1#2#3#4#5#6#7% {% - \def #1##1% \BNE_op_<op> + \XINT_global\def #1##1% \BNE_op_<op> {% \expanded{\unexpanded{#2{##1}}\expandafter}% \romannumeral`&&@\expandafter#3\romannumeral`&&@\BNE_getnext }% - \def #2##1##2##3##4% \BNE_exec_<op> + \XINT_global\def #2##1##2##3##4% \BNE_exec_<op> {% \expandafter##2\expandafter##3\expandafter - {\expandafter{\romannumeral`&&@#6##1##4}}% + {\expandafter{\romannumeral`&&@#7##1##4}}% }% - \def #3##1% \BNE_check-_<op> + \XINT_global\def #3##1% \BNE_check-_<op> {% \xint_UDsignfork ##1{\expandafter#4\romannumeral`&&@#5}% -{#4##1}% \krof }% - \def #4##1##2% \BNE_checkp_<op> + \XINT_global\def #4##1##2% \BNE_checkp_<op> {% - \ifnum ##1>#7% + \ifnum ##1>#6% \expandafter#4% \romannumeral`&&@\csname BNE_op_##2\expandafter\endcsname \else @@ -1405,51 +1899,138 @@ output is handled, it goes necessarily via the \xintbinhexname macros. }% \def\BNE_defbin_b #1#2#3#4% {% - \expandafter\BNE_defbin_c - \csname BNE_op_#1\expandafter\endcsname - \csname BNE_exec_#1\expandafter\endcsname - \csname BNE_check-_#1\expandafter\endcsname - \csname BNE_checkp_#1\expandafter\endcsname - \csname BNE_op_-#3\expandafter\endcsname - \csname #4\expandafter\endcsname - \csname BNE_precedence_#1\endcsname - \expandafter - \let\csname BNE_precedence_#1\expandafter\endcsname - \csname xint_c_#2\endcsname + \expandafter\BNE_defbin_c + \csname BNE_op_#1\expandafter\endcsname + \csname BNE_exec_#1\expandafter\endcsname + \csname BNE_check-_#1\expandafter\endcsname + \csname BNE_checkp_#1\expandafter\endcsname + \csname BNE_op_-\romannumeral\ifnum#3>12 #3\else 12\fi + \expandafter\endcsname + \csname xint_c_\romannumeral#3\endcsname #4% + \XINT_global + \expandafter + \let\csname BNE_precedence_#1\expandafter\endcsname + \csname xint_c_\romannumeral#2\endcsname + \unless + \ifcsname BNE_exec_-\romannumeral\ifnum#3>12 #3\else 12\fi\endcsname +% \end{macrocode} +% This will execute only for |#3>12| as |\BNE_exec_-xii| exists. +% \begin{macrocode} + \expandafter\BNE_defminus_a\expandafter{\romannumeral#3}% + \fi }% -\BNE_defbin_b {//} {xiv}{xiv}{BNE_Op_div}% -\BNE_defbin_b {/:} {xiv}{xiv}{BNE_Op_mod}% -\BNE_defbin_b + {xii}{xii}{BNE_Op_add}% -\BNE_defbin_b - {xii}{xii}{BNE_Op_sub}% -\BNE_defbin_b * {xiv}{xiv}{BNE_Op_mul}% -\BNE_defbin_b / {xiv}{xiv}{BNE_Op_divround}% -\BNE_defbin_b ^ {xviii}{xviii}{BNE_Op_pow}% -\expandafter\def\csname BNE_itself_**\endcsname {^}% +\BNE_defbin_b + {12} {12} \BNE_Op_add +\BNE_defbin_b - {12} {12} \BNE_Op_sub +\BNE_defbin_b * {14} {14} \BNE_Op_mul +\BNE_defbin_b / {14} {14} \BNE_Op_divround +\BNE_defbin_b {//} {14} {14} \BNE_Op_div +\BNE_defbin_b {/:} {14} {14} \BNE_Op_mod +\BNE_defbin_b ^ {18} {17} \BNE_Op_pow +% \end{macrocode} +% At upstream, we can use shortcut +% \centeredline{|\expandafter\def\csname BNE_itself_**\endcsname {^}|} +% but it means then that any redefinition of |^| propagates to |**|, besides it +% creates a special case which would need consideration by +% |\BNE_dotheitselves|, or special restrictions to add to user documentation. +% Better to simply handle |**| as a full operator. +% \begin{macrocode} +\BNE_defbin_b {**} {18} {17} \BNE_Op_pow +\expandafter\def\csname BNE_itself_**\endcsname {**}% \expandafter\def\csname BNE_itself_//\endcsname {//}% \expandafter\def\csname BNE_itself_/:\endcsname {/:}% -\expandafter\let\csname BNE_precedence_***\endcsname \xint_c_xvi +\let\BNE_prec_tacit\xint_c_xvi +% \end{macrocode} +% \subsection{\csh{bnumdefinfix}: extending the syntax}\leavevmode +% |#1| gives the operator characters, |#2| the associated macro, |#3| its +% left-precedence and |#4| its right precedence (as integers). +% +% The "itself" definitions are done in such a way that unambiguous abbreviations +% work; but in case of ambiguity the first defined operator is used. +% +% However, if for example operator |$a| was defined after |$ab|, then although +% |$| will use |$ab| which was defined first, |$a| will use as expected the +% second defined operator. +% +% The mismatch |\BNE_defminus_a| vs |\BNE_defbin_b| is inherited from +% upstream, I keep it to simplify maintenance. +% \begin{macrocode} +\def\bnumdefinfix #1#2#3#4% +{% + \edef\BNE_tmpa{#1}% + \edef\BNE_tmpa{\xint_zapspaces_o\BNE_tmpa}% + \edef\BNE_tmpL{\the\numexpr#3\relax}% + \edef\BNE_tmpL{\ifnum\BNE_tmpL<4 4\else\ifnum\BNE_tmpL<23 \BNE_tmpL\else 22\fi\fi}% + \edef\BNE_tmpR{\the\numexpr#4\relax}% + \edef\BNE_tmpR{\ifnum\BNE_tmpR<4 4\else\ifnum\BNE_tmpR<23 \BNE_tmpR\else 22\fi\fi}% + \BNE_defbin_b \BNE_tmpa\BNE_tmpL\BNE_tmpR #2% + \expandafter\BNE_dotheitselves\BNE_tmpa\relax + \ifxintverbose + \PackageInfo{bnumexpr}{infix operator \BNE_tmpa\space + \ifxintglobaldefs globally \fi + does + \unexpanded{#2}\MessageBreak with precedences \BNE_tmpL, \BNE_tmpR;}% + \fi +}% +\def\BNE_dotheitselves#1#2% +{% + \if#2\relax\expandafter\xint_gobble_ii + \else + \XINT_global + \expandafter\edef\csname BNE_itself_#1#2\endcsname{#1#2}% + \unless\ifcsname BNE_precedence_#1\endcsname + \XINT_global + \expandafter\edef\csname BNE_precedence_#1\endcsname + {\csname BNE_precedence_\BNE_tmpa\endcsname}% + \XINT_global + \expandafter\odef\csname BNE_op_#1\endcsname + {\csname BNE_op_\BNE_tmpa\endcsname}% + \fi + \fi + \BNE_dotheitselves{#1#2}% +}% % \end{macrocode} -% \subsection{! as postfix factorial operator} -% This one uses |\expanded|. +% \subsection{\csh{bnumdefpostfix}} +% Support macros for postfix operators only need to be \emph{x}-expandable. % \begin{macrocode} -\catcode`! 11 -\let\BNE_precedence_! \xint_c_xx -\def\BNE_op_! #1% +\def\bnumdefpostfix #1#2#3% {% - \expandafter\BNE_put_op_first - \expanded{{{\BNE_Op_fac#1}}\expandafter}\romannumeral`&&@\BNE_getop + \edef\BNE_tmpa{#1}% + \edef\BNE_tmpa{\xint_zapspaces_o\BNE_tmpa}% + \edef\BNE_tmpL{\the\numexpr#3\relax}% + \edef\BNE_tmpL{\ifnum\BNE_tmpL<4 4\else\ifnum\BNE_tmpL<23 \BNE_tmpL\else 22\fi\fi}% + \XINT_global + \expandafter\let\csname BNE_precedence_\BNE_tmpa\expandafter\endcsname + \csname xint_c_\romannumeral\BNE_tmpL\endcsname + \XINT_global + \expandafter\def\csname BNE_op_\BNE_tmpa\endcsname ##1% + {% + \expandafter\BNE_put_op_first + \expanded{{{#2##1}}\expandafter}\romannumeral`&&@\BNE_getop + }% + \expandafter\BNE_dotheitselves\BNE_tmpa\relax + \ifxintverbose + \PackageInfo{bnumexpr}{postfix operator \BNE_tmpa\space + \ifxintglobaldefs globally \fi + does \unexpanded{#2}\MessageBreak + with precedence \BNE_tmpL;}% + \fi }% % \end{macrocode} -% \subsection{Cleanup} +% \subsection{! as postfix factorial operator}\leavevmode % \begin{macrocode} -\let\BNEtmpa\relax \let\BNE_tmpa\relax \let\BNE_tmpb\relax \let\BNE_tmpc\relax +\bnumdefpostfix{!}{\BNE_Op_fac}{20}% +% \end{macrocode} +% \subsection{Cleanup}\leavevmode +% \begin{macrocode} +\let\BNEtmpa\relax +\let\BNE_tmpa\relax \let\BNE_tmpb\relax \let\BNE_tmpc\relax +\let\BNE_tmpR\relax \let\BNE_tmpL\relax \BNErestorecatcodes% % \end{macrocode} % \MakePercentComment %</package> %<*dtx> -\DeleteShortVerb{\|}% -\CheckSum {947}% +\CheckSum {1205}% \makeatletter\check@checksum\makeatother% \Finale% %% End of file xint.dtx diff --git a/macros/latex/contrib/bnumexpr/bnumexpr.pdf b/macros/latex/contrib/bnumexpr/bnumexpr.pdf Binary files differindex 79f259f3f2..912ef2e948 100644 --- a/macros/latex/contrib/bnumexpr/bnumexpr.pdf +++ b/macros/latex/contrib/bnumexpr/bnumexpr.pdf diff --git a/macros/latex/contrib/easybook/easybook.dtx b/macros/latex/contrib/easybook/easybook.dtx index 10a1336759..8d861d4773 100644 --- a/macros/latex/contrib/easybook/easybook.dtx +++ b/macros/latex/contrib/easybook/easybook.dtx @@ -24,11 +24,11 @@ % \changes{v1.20}{2021/01/09}{修改和完善用户文档。} % \changes{v1.20}{2021/01/09}{模板更改为使用 CC-BY 许可协议。} % \changes{v1.23}{2021/03/19}{修复在 \pkg{ctex} v2.5.6 更新后 \cls{easybook} 与 \pkg{hyperref} 冲突问题。} -% \changes{v1.25j}{2021/05/03}{取消附带的示例文件,可查看历史版本及其它来源的使用样例。} +% \changes{v1.25k}{2021/05/03}{取消附带的示例文件,可查看历史版本及其它来源的使用样例。} % % \title{\sffamily easybook 文档类手册} % \author{瞿毅} -% \date{2021/05/15\hskip\ccwd\relax v1.25j\thanks{\url{https://gitee.com/texl3/easybook}}} +% \date{2021/05/17\hskip\ccwd\relax v1.25k\thanks{\url{https://gitee.com/texl3/easybook}}} % % \maketitle % \begin{abstract} @@ -118,7 +118,7 @@ % \end{syntax} % 传递给 \cls{ctexbook} 设置字体,最好不要使用原有的 \opt{fontset} 选项,默认情况下使用自定义字体而不开启这个选项,可根据安装的字体及电脑系统选取。\opt{noto} 与 \opt{none} 选项的相关描述见小节 \ref{subsec:font settings},\opt{overleaf} 是一个各系统通用选项,会检测系统环境选取对应字体。 % \changes{v1.21}{2021/01/12}{默认字体与 \CTeX 一致,不再是自定义字体。} -% \changes{v1.25j}{2021/05/04}{修复使用 \pkg{xeCJK} 与 \pkg{fontspec} 宏包的字体设置命令在 \hologo{LuaLaTeX} 下失效的问题。} +% \changes{v1.25k}{2021/05/04}{修复使用 \pkg{xeCJK} 与 \pkg{fontspec} 宏包的字体设置命令在 \hologo{LuaLaTeX} 下失效的问题。} % \end{function} % % \begin{function}[rEXP,added = 2021-01-05,updated = 2021-01-13]{paper} @@ -169,7 +169,7 @@ % \tn{listoflistings*+}\oarg{键值列表} % \end{syntax} % \tn{listoffigures} 命令输出图片目录,\tn{listoftables} 输出表格目录,\tn{listoflistings} 输出代码目录。带有星号的目录命令不将标题添加进主文档目录,带有+号的目录命令可以使当前标题编号。\tn{tableofcontents+} 与其它命令不同是用于输出双语目录,需要与双语目录标题命令 \tn{bichapter} 等或设置图片、表格和代码等英文目录的标题配合使用,附加代码是中文与英文目录之间的代码,可以插入文本和换页命令等。目录的键值列表选项如下 -% \changes{v1.25j}{2021/05/05}{命令 \tn{tableofcontents} 可以输出双语目录。} +% \changes{v1.25k}{2021/05/05}{命令 \tn{tableofcontents} 可以输出双语目录。} % \end{function} % % \begin{function}{multoc,title,format,aftertitle,pagestyle,book,article} @@ -200,7 +200,7 @@ % 双语目录的标题命令目前设置了常用的三个级别,它们将中文标题正常输出,并使中英文标题加入双语目录,这个功能是为国内一些大学的学位论文模板的要求设计,在一般情况和英文模式下不需要使用。 % % 它们的星号变体命令使文中标题不编号,但是仍然加入双语目录,若英文标题参数空置那么仅加入中文目录而不加入英文目录,这一特点与 \tn{chapter*} 等命令的行为不太一样,在一些情况下会用到。可选参数是目录中的中文标题,默认与中文标题一致,正文标题过长时可用它设置在目录中显示的标题。双语目录的格式是一致的,共享使用 \tn{tocset} 的设置,英文目录的章级别标题名及编号的修改方式如下 -% \changes{v1.25j}{2021/05/05}{增加与双语目录配合的标题命令。} +% \changes{v1.25k}{2021/05/05}{增加与双语目录配合的标题命令。} % \end{function} % % \begin{function}{biname,binmuber} @@ -240,7 +240,7 @@ % % \subsection{风格} % \label{subsec:style} -% \begin{function}[EXP,added = 2021-01-05,updated = 2021-04-11]{color,color-all,multoc,withpart,footwith,notomath,rulewidth,uppercase,figure-sep,table-sep,listing-sep,equation-sep,number-sep} +% \begin{function}[EXP,added = 2021-01-05,updated = 2021-05-17]{color,color-all,multoc,withpart,footwith,notomath,rulewidth,uppercase,figure-sep,table-sep,listing-sep,equation-sep,number-sep,figpath} % \begin{syntax} % color = <(none)|seaside|energy|cyberpunk> % color-all = <HTML颜色代码> @@ -255,6 +255,7 @@ % listing-sep = <(.)> % equation-sep = <(.)> % number-sep = <(.)> +% figpath = \{\{路径名1\}\{路径名2\}\} % \end{syntax} % \ding{229} 以上选项路径为 \opt{style/...} % \changes{v1.10}{2021/01/08}{更改颜色实现方式与选项名。} @@ -284,6 +285,7 @@ % \item[listing-sep] 代码标题编号的连接符。 % \item[equation-sep] 公式编号的连接符。 % \item[number-sep] 统一设置所有编号的连接符。 +% \item[figpath] 设置插入图片的文件夹路径名,可以有多个路径名,但需要包含在括号内作为间隔,即使只有一个路径。 % \end{optdesc} % % \subsection{超链接} @@ -299,7 +301,7 @@ % \opt{refset} 将超链接选项(包括以上选项)交给 \pkg{hyperref} 处理,除了一些关于 pdf 书签的选项可能会失效,其它由键值选项命令 \tn{hypersetup} 支持的多数选项可用。 % \changes{v1.10}{2021/01/08}{修复了 \opt{linktopage} 选项关闭时目录中标题编号无超链接的问题。} % \changes{v1.24}{2021/04/05}{增加 \pkg{hyperref} 超链接选项完整的支持。} -% \changes{v1.25j}{2021/05/06}{模块名 \opt{link} 改为 \opt{refset},\opt{link} 作为兼容性保留。} +% \changes{v1.25k}{2021/05/06}{模块名 \opt{link} 改为 \opt{refset},\opt{link} 作为兼容性保留。} % \end{function} % % \begin{optdesc} @@ -318,7 +320,7 @@ % % \subsection{行距} % \label{subsec:spacing} -% \begin{function}[EXP,added = 2021-01-05,updated = 2021-04-19]{line,table,math,caption,footnote,spread-all} +% \begin{function}[EXP,added = 2021-01-05,updated = 2021-05-17]{line,table,math,caption,footnote,spread-all} % \begin{syntax} % line = <数值|(1.3)> % table = <数值|(1.05)> @@ -335,7 +337,7 @@ % % \begin{optdesc} % \item[line] 正文行距,\tn{ctexset} 原有的行距选项 \opt{linespread} 失效。 -% \item[table] 表格行距。 +% \item[table] 表格行距,对传统表格环境 \env{tabular}、\env{tabularx} 以及 \pkg{tabularray} 宏包的 \env{tblr} 环境生效,同时 \env{tblr} 也自带有 \opt{stretch} 选项设置行距。 % \item[math] 数学环境行距,包括 \pkg{amsmath} 和 \pkg{mathtools} 宏包附带的环境,但并未加载 \pkg{mathtools} 宏包。 % \item[caption] 图表代码标题行距。 % \item[footnote] 脚注行距。 @@ -378,7 +380,7 @@ % \changes{v1.21}{2021/01/11}{增加 \opt{bibset} 选项,可以使用 \hologo{BibTeX} 或 \hologo{biber} 编译参考文献。} % \changes{v1.23}{2021/02/23}{使用 \opt{bibset} 选项时可设置标注风格。} % \changes{v1.24}{2021/04/09}{可以不载入参考文献包手动配置参考文献格式。} -% \changes{v1.25j}{2021/05/12}{取消 \opt{bib-loadpkg} 选项,由是否设置参考文献数据库来决定载入宏包。} +% \changes{v1.25k}{2021/05/12}{取消 \opt{bib-loadpkg} 选项,由是否设置参考文献数据库来决定载入宏包。} % \end{function} % % \begin{optdesc} @@ -572,7 +574,7 @@ % 上面几个选项用于设置脚注格式,\opt{fnparskip} 和 \opt{fnparindent} 选项仅在 \opt{fnhang = true} 时有效。\opt{fnhang} 用于将脚注设置为悬挂缩进的格式,\opt{fnmark-pos} 选项设置脚注编号的位置,正常文本或是上标形式。\opt{fnmark-num} 选项设置脚注编号的格式,默认为原生样式 \opt{plain},还可以改为 \opt{pifont} 的各个版本,从左往右依次为普通版、阴文衬线版、阳文无衬线版和阴文无衬线版,缺点是它们的编号仅包括1-10。 % % \opt{fnmark-form} 是脚注标记的格式,默认为空,在此设置字体命令会覆盖 \opt{elsefont/footnote} 的设置,最后一个格式命令可以带有一个参数,这个参数接受脚注编号,一般配合 \opt{fnmark-num = plain} 使用。\opt{afterfnmark} 是脚注标记后的代码,一般用于设置标记与文本间的距离。 -% \changes{v1.25j}{2021/05/12}{增加脚注样式设置选项。} +% \changes{v1.25k}{2021/05/12}{增加脚注样式设置选项。} % \end{function} % % \subsection{目录样式} @@ -591,7 +593,7 @@ % \opt{format} 是目录中标题的格式,可以设置字体和加入垂直间距等,垂直间距最好使用无间距重合的 \tn{addvspace} 命令,带有加号的 \opt{format+} 选项用于在已有的格式命令后附加内容。\opt{indent} 是目录中标题在页面左侧的缩进距离,应该有长度单位。\opt{rule} 选项中一般应当使用 \tn{tocrule} 命令,将会在接下来介绍。\opt{numsep} 是有编号的标题在目录中编号与标题的间距。 % \changes{v1.21}{2021/01/13}{增加配置目录样式的选项。} % \changes{v1.24}{2021/04/20}{增加目录中编号与标题的间距选项 \opt{numsep}。} -% \changes{v1.25j}{2021/05/14}{可以分别设置图片、表格和代码目录的格式。} +% \changes{v1.25k}{2021/05/14}{可以分别设置图片、表格和代码目录的格式。} % \end{function} % % \begin{function}[added = 2021-01-13,updated = 2021-04-20]{\tocrule,\EbNumberline} @@ -668,6 +670,17 @@ % \pkg{amsmath} 宏包提供了一系列数学环境,它们可以排布各种对齐或不对齐的公式组。\env{multline} 环境用于一行无法放下的长公式,\env{gather} 环境用于每行居中的公式组,\env{align} 环境用于多列对齐的公式组。 % \end{function} % +% \subsection{表格} +% \begin{function}[added = 2021-05-17]{tblr,tabularx,tabular} +% \begin{syntax} +% \tn{begin}\marg{环境名}\marg{环境选项} +% \ <表格内容> +% \tn{end}\marg{环境名} +% \end{syntax} +% \pkg{tabularray} 是一个较新的宏包,不仅提供了 \pkg{tabularx}、\pkg{multirow}、和 \pkg{booktabs} 宏包的功能,并且不依赖其它宏包与它们同时使用不会产生冲突,还实现了用简便的键值列表方式设置表格样式。目前除了表头斜线以及跨页功能存在不足,其它方面已满足对表格绝大多数格式的需求,具体用法可见宏包的说明文档。 +% \changes{v1.25k}{2021/05/17}{使用功能更便捷齐全的 \pkg{tabularray} 宏包设置表格样式。} +% \end{function} +% % \subsection{列表} % \begin{function}[added = 2021-01-05,updated = 2021-04-08]{enumerate,enumerate*,itemize,itemize*,description,description*} % \begin{syntax} @@ -949,9 +962,7 @@ % \item[fancyhdr] 广泛控制页面的页眉和页脚。 % \item[titletoc] 设置目录中的标题格式。 % \item[caption] 在浮动环境中自定义题注。 -% \item[tabularx] 带有可调整宽度的列的表格。 -% \item[multirow] 创建跨越多行的表格单元格。 -% \item[booktabs] 为表格提供三线表式的命令。 +% \item[tabularray] 完全分离表格的内容和样式,并且可以通过键值方式完全设置表格。 % \item[enumitem] 提供列表环境的布局控制。 % \item[listings] 可以在 \LaTeX 中排版程序/编程代码。 % \item[hyperref] 处理交叉引用命令以及在文档中生成超文本链接。 @@ -967,12 +978,13 @@ %<*class> \NeedsTeXFormat{LaTeX2e}[2020/10/01] \RequirePackage{l3keys2e,etoolbox} -\ProvidesExplClass{easybook}{2021/05/15}{1.25j}{beta} +\ProvidesExplClass{easybook}{2021/05/17}{1.25k}{beta} \cs_generate_variant:Nn \eb_ctex_define:nn { nx } \cs_generate_variant:Nn \int_to_arabic:n { v } \cs_generate_variant:Nn \dim_add:Nn { NV } \cs_generate_variant:Nn \eb_put_hyperref:n { x } +\cs_generate_variant:Nn \seq_set_from_clist:Nn { No } \cs_new_protected:Npn \eb_ctex_define:nn #1 { \keys_define:nn { ctex/#1 } } \cs_new_protected:Npn \eb_put_ctexbook:n #1 @@ -982,15 +994,21 @@ \ctex_patch_cmd_once:NnnnTF #1 { } {#2} {#3} { } { \ctex_patch_failure:N #1 } } +\cs_new_protected:Npn \eb_preto_cmd:Nn #1#2 + { + \ctex_preto_cmd:NnnTF #1 { } {#2} + { } { \ctex_patch_failure:N #1 } + } \cs_new_protected:Npn \eb_appto_cmd:Nn #1#2 { \ctex_appto_cmd:NnnTF #1 { } {#2} { } { \ctex_patch_failure:N #1 } } -\cs_new_protected:Npn \eb_preto_cmd:Nn #1#2 +\cs_new_protected:Npn \eb_at_begin_environment:nn #1#2 { - \ctex_preto_cmd:NnnTF #1 { } {#2} - { } { \ctex_patch_failure:N #1 } + \seq_set_from_clist:No \l__eb_env_hook_name_seq {#1} + \seq_map_inline:Nn \l__eb_env_hook_name_seq + { \AtBeginEnvironment{##1}{#2} } } \cs_new_protected:Npn \eb_at_end_preamble:n { \ctex_gadd_ltxhook:nn { env/document/before } } @@ -1117,6 +1135,7 @@ uppercase .bool_set:N = \l__eb_uppercase_bool, uppercase .default:n = true, uppercase .initial:n = true, + figpath .tl_set:N = \l_eb_graphics_path_tl, footwith .choices:nn = { part,page,chapter } @@ -1142,12 +1161,12 @@ { xcolor, footmisc,setspace, - amsmath,amsthm,thmtools,cases, + amsmath,amsthm,thmtools, chemformula,siunitx,ulem,pifont, geometry,marginnote,nccfoots, pdfpages,graphicx, fancyhdr,titletoc,caption, - tabularx,multirow,booktabs, + tabularray, enumitem, listings } @@ -1465,6 +1484,8 @@ \easyfoot[C]{\color{SlateGray}\sffamily\today} \geometry{showframe} } + \tl_if_empty:NF \l_eb_graphics_path_tl + { \exp_args:No \graphicspath { \l_eb_graphics_path_tl } } } \eb_at_end_preamble:n @@ -2100,6 +2121,34 @@ marginpar .initial:n = \rmfamily\footnotesize } +\fp_new:N \l__eb_spread_line_fp +\fp_new:N \l__eb_spread_table_fp +\fp_new:N \l__eb_spread_math_fp +\fp_new:N \l__eb_spread_caption_fp +\fp_new:N \l__eb_spread_footnote_fp + +\eb_ctex_define:nn { spread } + { + line .fp_set:N = \l__eb_spread_line_fp, + line .initial:n = 1.3, + table .fp_set:N = \l__eb_spread_table_fp, + table .initial:n = 1.05, + math .fp_set:N = \l__eb_spread_math_fp, + math .initial:n = 1.05, + caption .fp_set:N = \l__eb_spread_caption_fp, + caption .initial:n = 1, + footnote .fp_set:N = \l__eb_spread_footnote_fp, + footnote .initial:n = 1, + spread-all .meta:n = + { + line = #1, + table = #1, + math = #1, + caption = #1, + footnote = #1 + } + } + \DeclareCaptionLabelSeparator{ccwd}{\hspace{\ccwd}} \DeclareCaptionLabelFormat{parens}{\bothIfFirst{#1}{~}(#2)} \DeclareCaptionFont{eb@table@font}{\l__eb_font_table_tl} @@ -2130,6 +2179,19 @@ \captionsetup[figure][bi-second]{name = Figure} \captionsetup[table][bi-second]{name = Table} } +\prop_gset_from_keyval:Nn \g__tblr_default_tblr_table_prop + { stretch = \fp_use:N \l__eb_spread_table_fp } +\SetTblrDefault{rows = {abovesep = 4pt,belowsep = 2pt}} +\eb_at_begin_environment:nn { tabular,tabularx } + { + \exp_args:Nx \linespread { \fp_use:N \l__eb_spread_table_fp } + \selectfont\ignorespaces + } +\ctex_after_end_preamble:n + { + \exp_args:Nx \linespread { \fp_use:N \l__eb_spread_line_fp } + \selectfont\ignorespaces + } \cs_new:Npn \eb_arabic:n #1 { \int_to_arabic:v { c@#1 } } \cs_gset:cpn { thesection } @@ -2152,50 +2214,6 @@ } } -\AtBeginEnvironment{tabularx} - { - \exp_args:Nx \linespread { \fp_use:N \l__eb_spread_table_fp } - \selectfont\ignorespaces - } -\AtBeginEnvironment{tabular} - { - \exp_args:Nx \linespread { \fp_use:N \l__eb_spread_table_fp } - \selectfont\ignorespaces - } -\ctex_after_end_preamble:n - { - \exp_args:Nx \linespread { \fp_use:N \l__eb_spread_line_fp } - \selectfont\ignorespaces - } - -\fp_new:N \l__eb_spread_line_fp -\fp_new:N \l__eb_spread_table_fp -\fp_new:N \l__eb_spread_math_fp -\fp_new:N \l__eb_spread_caption_fp -\fp_new:N \l__eb_spread_footnote_fp - -\eb_ctex_define:nn { spread } - { - line .fp_set:N = \l__eb_spread_line_fp, - line .initial:n = 1.3, - table .fp_set:N = \l__eb_spread_table_fp, - table .initial:n = 1.05, - math .fp_set:N = \l__eb_spread_math_fp, - math .initial:n = 1.05, - caption .fp_set:N = \l__eb_spread_caption_fp, - caption .initial:n = 1, - footnote .fp_set:N = \l__eb_spread_footnote_fp, - footnote .initial:n = 1, - spread-all .meta:n = - { - line = #1, - table = #1, - math = #1, - caption = #1, - footnote = #1 - } - } - \skip_set:Nn \parskip { 0pt plus 2pt minus 1pt } \skip_set:Nn \floatsep { 12pt plus 2pt minus 2pt } \skip_set:Nn \intextsep { 14pt plus 2pt minus 2pt } @@ -2209,11 +2227,8 @@ \tl_gset:Nn \topfraction { 0.85 } \tl_gset:Nn \bottomfraction { 0.65 } \tl_gset:Nn \floatpagefraction { 0.60 } - -\newcolumntype{L}{X} -\newcolumntype{C}{>{\centering\arraybackslash}X} -\newcolumntype{R}{>{\raggedleft\arraybackslash}X} -\graphicspath{{figures/}} +\tl_gset:Nn \ULthickness { 0.75pt } +\allowdisplaybreaks[4] \DeclareGraphicsExtensions{.pdf,.png,.jpg,.eps,.tif} \cs_new_protected:Npn \eb_enumitem_labelval_set:nn #1#2 @@ -2375,23 +2390,16 @@ range-units = single, group-digits = false } -\allowdisplaybreaks[4] -\tl_gset:Nn \ULthickness { 0.75pt } -\skip_set:Nn \jot { 4pt plus 1pt minus 1pt } -\seq_const_from_clist:Nn \c__eb_math_spread_env_seq +\eb_at_begin_environment:nn { array,matrix,pmatrix,bmatrix,Bmatrix,vmatrix,Vmatrix, matrix*,pmatrix*,bmatrix*,Bmatrix*,vmatrix*,Vmatrix*, cases,cases*,dcases,dcases*,rcases,rcases*,drcases,drcases*, aligned,alignedat,gathered,multlined,lgathered,rgathered } -\seq_map_inline:Nn \c__eb_math_spread_env_seq { - \AtBeginEnvironment{#1} - { - \linespread{\fp_use:N \l__eb_spread_math_fp} - \selectfont\ignorespaces - } + \linespread{\fp_use:N \l__eb_spread_math_fp} + \selectfont\ignorespaces } \eb_patch_cmd:Nnn \start@gather { \collect@body } diff --git a/macros/latex/contrib/easybook/easybook.pdf b/macros/latex/contrib/easybook/easybook.pdf Binary files differindex 863d95ede8..308ff83a69 100644 --- a/macros/latex/contrib/easybook/easybook.pdf +++ b/macros/latex/contrib/easybook/easybook.pdf diff --git a/macros/latex/contrib/euclideangeometry/README.txt b/macros/latex/contrib/euclideangeometry/README.txt index bd63054ff7..e2bf9e75db 100644 --- a/macros/latex/contrib/euclideangeometry/README.txt +++ b/macros/latex/contrib/euclideangeometry/README.txt @@ -1,52 +1,29 @@ -%% -%% This is file `README.txt', -%% generated with the docstrip utility. -%% -%% The original source files were: -%% -%% euclideangeometry.dtx (with options: `readme') -%% -%% Copyright (C) 2020 Claudio Beccari all rights reserved. -%% License information appended -%% File README.txt for package euclideangeometry - [2020-04-15 v.0.1.8 Extension package for curve2e] + [2021-05-16 v.0.2.0 Extension package for curve2e] -The package bundle euclideangeometry is composed of the following files -euclideangeometry.dtx -euclideangeometry.pdf -euclideangeometry-man.tex -euclideangeometry-man.pdf -README.txt +This work is "maintained" + +This work consists of files: +1) euclideangeometry.dtx, and the derived files + euclideangeometry.sty and euclideangeometry.pdf, +2) euclideangeometry-man.tex and the derived file + euclideangeometry-man.pdf, +3) README.txt euclideangeometry.dtx is the documented TeX source file of package -euclideangeometry.sty; you get euclideangeometry.sty, -euclideangeometry.pdf by running pdflatex on euclideangeometry.dtx. +euclideangeometry.sty obtained by running pdflatex on euclideangeometry.dtx +euclideangeometry.pdf obtained by running pdflatex on euclideangeometry.dtx. README.txt, this file, contains general information. euclideangeometry-man.tex and euclideangeometry-man.pdf are -the source file and the readable document containing the end -user manual. +the source file and the readable document containing the +end-user manual. + In other words euclideangeometry.pdf is oriented towards the -developers and euclideangeometry-man.pdf to the end users. +developers and euclideangeometry-man.pdf to the end-users. Claudio Beccari claudio dot beccari at gmail dot com -%% -%% Distributable under the LaTeX Project Public License, -%% version 1.3c or higher (your choice). The latest version of -%% this license is at: http://www.latex-project.org/lppl.txt -%% -%% This work is "maintained" -%% -%% This work consists of files: -%% 1) euclideangeometry.dtx, and the derived files euclideangeometry.sty -%% and euclideangeometry.pdf, -%% 2) euclideangeometry-man.tex and the derived file euclideangeometry-man.pdf, -%% 3) the auxiliary derived file README.txt -%% -%% -%% End of file `README.txt'. diff --git a/macros/latex/contrib/euclideangeometry/euclideangeometry-man.pdf b/macros/latex/contrib/euclideangeometry/euclideangeometry-man.pdf Binary files differindex 1b4b2cb7a5..a441c7fccb 100644 --- a/macros/latex/contrib/euclideangeometry/euclideangeometry-man.pdf +++ b/macros/latex/contrib/euclideangeometry/euclideangeometry-man.pdf diff --git a/macros/latex/contrib/euclideangeometry/euclideangeometry-man.tex b/macros/latex/contrib/euclideangeometry/euclideangeometry-man.tex index ac066c69d0..1a640af462 100644 --- a/macros/latex/contrib/euclideangeometry/euclideangeometry-man.tex +++ b/macros/latex/contrib/euclideangeometry/euclideangeometry-man.tex @@ -6,8 +6,8 @@ \usepackage[utf8]{inputenc} \usepackage[english]{babel} \usepackage{lmodern,textcomp,mflogo} -\usepackage{amsmath,fancyvrb,graphicx,verbatim,afterpage,trace} -\usepackage{etoolbox,enumitem,xspace,xcolor,euclideangeometry} +\usepackage{amsmath,fancyvrb,graphicx,afterpage,etoolbox,trace} +\usepackage{enumitem,xspace,xcolor,euclideangeometry,pm-isomath} \usepackage{url} \providecommand\file{} @@ -98,13 +98,12 @@ g\raisebox{-0.715ex}{\kern-0.26em u}\kern-0.13em\I\kern-0.14em t}\xspace} \def\hz{\hskip0pt} \makeatletter -\newwrite\example@out \newlength\Wboxu \newlength\Wboxd -% Attention! +% Caution! % -% This is the latest version of the Esempio/Example environment -% It differs from the previous versions because it accepts an optional +% This is the latest version of the Esempio (Example) environment +% It differs from the previous ones because it accepts an optional % first argument asterisk; if the asterisk is not specified, the % environment produces the code and the typeset result side by side. % If the asterisk is specified, the code is typeset first, and its typeset @@ -120,31 +119,44 @@ g\raisebox{-0.715ex}{\kern-0.26em u}\kern-0.13em\I\kern-0.14em t}\xspace} % When the asterisk is NOT specified, the \textwidth fraction for the % code may be specified: default is (0.40); the remaining fraction minus % \columnsep is used for the code typeset result. +% For some reasons the optional code is not so optional, although the +% argument descriptor is D()(0.40); it is not a burden to specify it +% every time: % -\newwrite\example@out -\DeclareDocumentEnvironment{Esempio}{s O{\normalsize} D(){0.40}} -{\par\addvspace{3.0ex plus 0.8ex minus 0.5ex}\vskip -\parskip -\Wboxu=#3\textwidth\relax -\Wboxd=\dimexpr\linewidth-\columnsep-\Wboxu\relax -\begingroup -\@bsphack -\immediate\openout\example@out\jobname-temp.tex -\let\do\@makeother\dospecials\catcode`\^^M\active -\def\verbatim@processline{% - \immediate\write\example@out{\the\verbatim@line}}% -\verbatim@start\relax}% -{\immediate\closeout\example@out\@esphack\endgroup -\begin{minipage}{\textwidth}% -\IfBooleanTF{#1}{\begin{minipage}{\textwidth}}{\begin{minipage}{\Wboxu}}% -#2\relax -\verbatiminput{\jobname-temp.tex} -\end{minipage}% -\IfBooleanTF{#1}{\par\bigskip}{\hfill}% -\IfBooleanTF{#1}{\begin{minipage}{\textwidth}}{\begin{minipage}{\Wboxd}}% -\raggedleft -\input{\jobname-temp} -\end{minipage} -\end{minipage}\par +% Warning! +% The \begin and \end statements must be on a line by themselves: +% +% Correct: +% \begin{Esempio}*[...](...) +% code +% \end{Esempio} +% +% Wrong: +% \begin{Esempio}*[...](...) +% code\end{Esempio} +% +% The code end-of-line characters are part of the code to be saved +% and reused + +\DeclareDocumentEnvironment{Esempio}{ s O{\normalsize} D(){0.40} }% +{% + \par%\addvspace{3.0ex plus 0.8ex minus 0.5ex}\vskip -\parskip + \Wboxu=#3\textwidth + \Wboxd=\dimexpr\linewidth-\columnsep-\Wboxu\relax + \VerbatimOut{\jobname-temp.tex}% +}{% + \endVerbatimOut + \begin{minipage}{\textwidth}% + \IfBooleanTF{#1}{\begin{minipage}{\textwidth}}{\begin{minipage}{\Wboxu}}% + #2\relax + \VerbatimInput{\jobname-temp.tex} + \end{minipage}% + \IfBooleanTF{#1}{\par\bigskip}{\hfill}% + \IfBooleanTF{#1}{\begin{minipage}{\textwidth}}{\begin{minipage}{\Wboxd}}% + \raggedleft + \input{\jobname-temp} + \end{minipage} + \end{minipage}\par } \makeatother @@ -184,10 +196,10 @@ Version \fileversion\ of \filedate \end{titlepage} \begin{abstract} - This file further extends the functionalities of the \pack{curve2e} - package, which, on turn, is an extension of the \pack{pict2e} package - to the standard \env{picture} environment as defined in the \LaTeX\ - kernel source file. + The \pack{euclideangeometry} package further extends the functionalities + of the \pack{curve2e} package, which, on turn, is an extension of the + \pack{pict2e} package for the standard \env{picture} environment as + defined in the \LaTeX\ kernel source file. The \pack{curve2e} package was upgraded a the beginning of 2020; the material of this new package, might have been included in the former one, @@ -195,7 +207,7 @@ Version \fileversion\ of \filedate package takes care of requesting the packages it depends from. The purpose is to provide the tools to draw most of the geometrical - constructions that a high school instructor or bachelor degree professor + constructions that a high school teacher or bachelor degree professor might need in order to teach geometry. The connection to Euclide depends on the fact that in its times calculations were made with ruler, compass, and, apparently, also with ellipsograph. @@ -203,7 +215,7 @@ Version \fileversion\ of \filedate The user of this package has available all the machinery provided by the \pack{pict2e} and \pack{curve2e} packages, in order to define new functionalities and build macros that draw the necessary lines, circles, - and other such objects, as they would have done in the ancient times. + and other such objects, as they would have done in the old times. Actually just one macro is programmed to solve a linear system of equations \end{abstract} @@ -219,7 +231,7 @@ The \pack{euclideangeometry} package requires the advanced functionalities of th \section{Introduction} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% The \pack{picture} environment has been available since the very beginning - of \LaTeX in 1985. At that time it was a very simple environment + of \LaTeX in 1985. At that time it was a really simple environment that allowed to draw very simple line graphics with many limitations. When \LaTeX was upgraded from \LaTeX\!2.09 to \LaTeXe in 1994, Leslie Lamport announced an upgrade that eventually became available in 2003 @@ -238,7 +250,16 @@ The \pack{euclideangeometry} package requires the advanced functionalities of th \pack{pict2e} and \pack{curve2e}, but extends the functionalities with a very smart handling of coordinate systems, that allow to draw many line drawings suitable for teaching geometry in high schools and introductory - courses in the university bachelor degree programs. + courses in the university bachelor degree programs. It is worth mentioning + that an extension of \pack{TikZ}, called \pack{tkz-euclide} is also + available in a complete and updated \TeX system installation; at the + moment its documentation needs some refinements, at least to + consistently use a single language, without switching from English + to French and viceversa. It aims at the same readership, but it allows + to do many more geometrical constructions, than \pack{euclideangeometry}. + The real difference is that \pack{euclideangemetry} may be easily + expanded without the need of knowing the complex machinery and coding + of the \pack{tkz-euclide} underlaying \pack{TikZ} package. This package \pack{euclideangeomery} apparently follows the same path of \pack{xpicture}, but it avoids defining a new user language @@ -248,7 +269,7 @@ The \pack{euclideangeometry} package requires the advanced functionalities of th It is worth mentioning that now \pack{curve2e} accepts coordinates in both cartesian and polar form; it allows to identify specific points of the drawing with macros, so the same macro can be used over and over again to - address the same points. The package can draw lines, vectors, arcs + address the same point. The package can draw lines, vectors, arcs with no arrow tips, or with one arrow tip, or with arrow tips at both ends, arcs included. The macros for drawing poly lines, polygons, circles, generic curves (by means of Bézier cubic or quadratic splines) are @@ -262,8 +283,9 @@ The \pack{euclideangeometry} package requires the advanced functionalities of th This grid is useful also to the end user, while s/he is working on a particular drawing, but when the drawing is finished, the user can delete the grid command or comment out that line of code. - For what regards the commands used to render the images, their codes can - be found in the documented code file \pack{euclideangeometry.pdf}. + For what regards the commands used to render the images, their + \emph{codes} can be found in the documented code file + \pack{euclideangeometry.pdf}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Installing \pack{euclideangeometry}} @@ -273,9 +295,20 @@ The \pack{euclideangeometry} package requires the advanced functionalities of th installation, otherwise this package won't work; this means that you have done your updating after 2020-01-18. And this package is already present in any modern updated complete installation of the \TeX system. - Otherwise the package will load \pack{curve2e} with an old version - and file date, and this package will abort its own loading, besides - aborting the whole job. + If \pack{curve2e} has a date earlier then 2020-01-018, the \pack{curve2e} + itself will load \pack{curve2ev161}, an older version, and this package + \pack{euclideangeomentry} will abort its own loading, besides + aborting the whole job. + + We remember the package dependencies; the primary dependence is package + \pack{curve2e} with a version date more recent or equal to 2020-01-18. + On turn \pack{curve2e} requires packages \pack{xparse} and \pack{xfp}; + missing these two package, it loads its own previous version, that does + not use such packages, but their absence forbids it working, so that, + after a very visible error message, it directly aborts. It also depends + on \pack{etoolbox}. + The chain of dependencies of the above first level packages may be + controlled directly on those packages documentation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Loading \pack{euclideangeometry}} @@ -286,7 +319,7 @@ The \pack{euclideangeometry} package requires the advanced functionalities of th \cs{usepackage}\oarg{options}\Marg{euclideangeomery} \end{flushleft} The package will take care of managing the possible \meta{options} - and to call \pack{curve2e} with the such specified options; on turn + and to call \pack{curve2e} with such specified options; on turn \pack{curve2e} calls \pack{pict2e} passing on the \meta{options}; such \meta{options} are only those usable by \pack{pict2e} because neither \pack{curve2e} nor \pack{euclideangeometry} use any option. If the @@ -315,8 +348,8 @@ The \pack{euclideangeometry} package requires the advanced functionalities of th same restrictions; in particular there are the following improvements. \begin{enumerate}[noitemsep] \item Lines and vectors are drawn as usual by \cs{put}ting in place - their forms, but their inclinations are not limited to a limited - number of slope parameters, originally specified with reciprocally + their forms, but their inclinations are not limited to a small set of + slope parameters, originally specified with reciprocally prime single digit values not exceeding~6 for lines, and~4 for vectors; the length of these sloped objects is still their horizontal component; now, the slopes may be described with any signed fractional number not @@ -326,7 +359,7 @@ The \pack{euclideangeometry} package requires the advanced functionalities of th \item There is no restriction on the minimum length of lines and vectors. % \item Circles and dots can be drawn at any size, not at that dozen - or so of finite sizes that were accepted with the original environment. + or so finite sizes that were accepted with the original environment. % \item Ovals may be specified the corner curvature; the default size of the quarter circles that make up the oval corners may be @@ -372,7 +405,7 @@ The \pack{euclideangeometry} package requires the advanced functionalities of th There were also the low level commands user interfaces to the various drivers; these drivers really exist, but \pack{pict2e} - knows how to detect the correct language of the necessary drive; + knows how to detect the correct language of the necessary driver; the user is therefore allowed to pretend to ignore the existence of such drivers, and s/he can simply use these low level commands; their names are almost self explanatory. @@ -390,7 +423,7 @@ The \pack{euclideangeometry} package requires the advanced functionalities of th initial point are among the specified arguments, but the reader should check on the \pack{pict2e} documentation for the details. -\item[]\mbox{\bfseries Attention!} Notice that these commands produce +\item[]\mbox{\bfseries Warning!} Notice that these commands produce just information to trace lines, but by themselves they do not trace anything; in order to actually trace the curve or do other operations with what has been done after the user finished describing the line to be @@ -405,7 +438,7 @@ The \pack{euclideangeometry} package requires the advanced functionalities of th \item If a \cs{fillpath} command is used, the line loop is filled with the current color. Notice, if the described line is not a closed loop, - this filling command acts as if the line first point and last point were + this filling command acts as if the line first and last points were joined by a straight line. \end{enumerate} @@ -444,7 +477,7 @@ The \pack{euclideangeometry} package requires the advanced functionalities of th better to declare the \cs{roundcap} for the whole document. We do not go further in the description of the new \pack{pict2e} - modified and new new commands; the reader unfamiliar with programmable + modified and new commands; the reader unfamiliar with programmable drawing and the \pack{pic2e} extensions can consult that package documentation. Actually all commands have been redefined or modified by \pack{curve2e} in order to render them at least compatible with @@ -454,7 +487,7 @@ The \pack{euclideangeometry} package requires the advanced functionalities of th \begin{figure}[!htb] \centering \makebox[\textwidth]{\unitlength=0.009\textwidth \begin{picture}(130,50) - \GraphGrid(130,50) + \AutoGrid \linethickness{4mm} \buttcap\miterjoin \put(10,10){\polyline[\miterjoin](0,0)(30,0)(30,30) @@ -518,7 +551,7 @@ z_1/z_2 &=( m_1/m_2) \eu^{\iu(\phi_1 - \phi_2)} \end{align*} Squares and square roots\footnote{The square root of a complex number has two complex values; here we do not go into the details on how - \pack{curve2e} choses one or the other value. In practice, the + \pack{curve2e} choses which value. In practice, the \pack{curve2e} macros that use square roots, work mostly on scalars to find magnitudes that are always positive.} are simply done with: \begin{align*} @@ -529,7 +562,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ asterisk: \[\text{if } z= x+\iu y \text{ then } z^\star = x- \iu y\] and from these simple formal rules many results can be obtained; - and therefore several macros must be defined. + and therefore several macros have been defined. But let us summarise. Here is a short list with a minimum of explanation of the commands functionalities introduced by @@ -565,8 +598,8 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ macros are used, instead of explicit numerical values, but for input vector macros it is possible to use the comma or colon separated ordered pair; “versor” means “unit vector”; angles are always expressed in - degrees; output quantities are everything follows the key word - \texttt{to}; output quantities are alway supposed to be in the form + degrees; output quantities are everything that follows the key word + \texttt{to}; output quantities are always supposed to be in the form of control sequences. \begin{itemize}\small \item \cs{MakeVectorFrom}\meta{number,number}\meta{numeric macro} to\meta{vector macro} @@ -629,7 +662,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ \item Command \cs{polyline}, \cs{polygon} and \cs{polygon*} are redefined to accept both coordinate kinds. -\item Commands \cs{VECTOR}\parg{$P_1$}\parg{$P_2$} (and \cs{VVECTOR}, with the same syntax) draw vectors with one arrow tip at the end, or arrow tips at both ends respectively. +\item Commands \cs{VECTOR}\parg{$P_1$}\parg{$P_2$} (and \cs{VVECTOR}, with the same syntax) draw vectors with one arrow tip at the end, or arrow tips at both ends respectively.l \item New commands \cs{Arc}\parg{center}\parg{start}\marg{angle} and, with the same syntax, \cs{VectorArc} and \cs{VectorARC} draw @@ -646,19 +679,19 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ \cs{multiput}\oarg{shift}\parg{origin}\parg{step}\marg{number}\marg{object}\oarg{handler} \end{flushleft} where, if you neglect the first and the last (optional) arguments, - you have the original syntax; the \meta{origin} point is where the first - \meta{object} is placed; \meta{step} is the displacement of a new - \meta{object} relative to the previous one; \meta{number} is the - total number of \meta{object}s put in place by the command; possibly - the number may be an integer expression computed with the \cs{inteval} - function of the L3~language, accessed through the \pack{xfp} package - already loaded by \pack{curve2e}. The new features are \meta{shift}, - that is used to displace the whole drawing somewhere else (in case - some fine tuning is required), and \meta{handler}; the latter is a - powerful means to control both the object to be set in place and its - position; further on there will be examples that show that the object - can be put not only on straight paths, but also un other curves, - including parabolas, circles, and other shapes. + you have the original syntax; the \meta{origin} point is where the + first \meta{object} is placed; \meta{step} is the displacement of a + new \meta{object} relative to the previous one; \meta{number} is the + total number of \meta{object}s put in place by the command; it is + possible to specify the number trough an integer expression computed + with the \cs{inteval} function of the L3~language, accessed through + the \pack{xfp} package already loaded by \pack{curve2e}. The new + features are \meta{shift}, that is used to displace the whole drawing + somewhere else (in case some fine tuning is required), and \meta{handler}; + the latter is a powerful means to control both the object to be set in + place and its position; further on there will be examples that show + that the object can be put not only on straight paths, but also un + other curves, including parabolas, circles, and other shapes. \item Another version of repetitive commands \cs{xmultiput} is very similar to \cs{multiput} but the iterations are controlled in a @@ -675,31 +708,34 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ \cs{inteval}, it can use many mathematical functions, from square roots, to exponentials, logarithms, trigonometric and hyperbolic direct and inverse functions\footnote{The implementation of inverse hyperbolic - function is on the L3~Team “to do” list.}, plus other ones. Normally - fractional numbers are operated on decimal strings, with 16 fractional - places, and 14 integer places but the L3~functions accept also scientific - notation. The user can specify truncation or rounding to a specified - number of digits. Such integer and fractional mathematical operations - are already integrated in most computations performed by \pack{curve2e}. - -\item \pack{curve2e} provides two more L3 functions: \cs{fptest} and + function at the moment is on the L3~Team “to do” list.}, plus other ones. + Normally fractional numbers are operated on decimal strings, with 16 + fractional places, and 14 integer places but the L3~functions accept also + scientific notation. The user can specify truncation or rounding to a + specified number of digits. Such integer and fractional mathematical + operations are already integrated in most computations performed by + \pack{curve2e}. + +\item \pack{curve2e} provides three more L3 functions: \cs{fptest} and \cs{fpdowhile} with the following syntax: \begin{flushleft}\obeylines \cs{fptest}\marg{test}\marg{true}\marg{false} \cs{fpdowhile}\marg{test}\marg{actions} +\cs{fowhiledo}\marg{test}\marg{actions} \end{flushleft} - For both macros the \meta{test} is a logical F3~expression; its operands - are logical constants, logical values, logical numeric comparisons; its - operators are the typical \texttt{||}, \texttt{\&\&}, and \texttt{!}, - respectively for OR, AND, and NOT. The logical numerical comparisons - are mathematical constants or expressions connected with relation - operators, such as \texttt{>, =, <}; such operators may be negated with - the NOT operator; therefore, for example, \texttt{!>} means “not greater - than”, therefore “lower or equal to”. + For all these macros the \meta{test} is a logical L3~expression; its + operands are logical constants, logical values, logical numeric + comparisons; its operators are the typical \texttt{||}, \texttt{\&\&}, + and \texttt{!}, respectively for OR, AND, and NOT. The logical numerical + comparisons are mathematical constants or expressions connected with + relation operators, such as \texttt{>, =, <}; such operators may be + negated with the NOT operator; therefore, for example, \texttt{!>} means + “not greater than”, therefore “lower or equal to”. \item The above tests are very useful to control both \cs{fptest} and - \cs{fpdowhile}. The logical \meta{test} result lets \cs{fptest} execute - only the \meta{true} or the \meta{false} code. Before using \cs{fpdowhile} + \cs{fpdowhile} and \cs{fowhiledo}. The logical \meta{test} result lets + \cs{fptest} execute only the \meta{true} or the \meta{false} code. + Before using \cs{fpdowhile} or \cs{fpwhiledo} the \meta{test} expression must be initialised to be \texttt{true}; the \meta{actions} should contain some code to be iteratively executed, but they must contain some assignments, typically a change in an @@ -707,11 +743,21 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ expression becomes \texttt{false}. Lacking this assignments, the loop continues to infinity, or better, until a fatal error message is issued that informs that the program working memory is exhausted. + The difference between \cs{fpdowhile} and \cs{fpwhiledo} ie the order + in which the \meta{test} and the first\meta{action} is executed; in facts + \cs{fpdowhile} first does the \meta{action} then the \meta{test}, while + \cs{fpwhiledo} first executes the \meta{test} then the \meta{action}. + Since the modification of the test logical value is done by the commands + contained in the \meta{actions} this switching of the \meta{test} and + \meta{action} produces different results. Adjusting the \meta{test} it is + possible to get the same results, but the expressiveness of the \meta{test} + may be easier to understand in one way rather than the other. Some of the + examples show the such different \meta{test} syntaxes. \item Such new commands are already used to code the \cs{multiput} and \cs{xmultiput} commands, but they are available also to the user who can operate in a very advanced way; further on, some examples will show - some advanced drawings. + certain advanced drawings. \item General curves can be drawn by \pack{pic2e} command \cs{curve} that is sort of difficult to use, because the user has to specify @@ -823,7 +869,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ \begin{Esempio}[\setfontsize{7}](0.40) \unitlength=0.005\linewidth \begin{picture}(170,140)(0,-70) -\GraphGrid(0,-70)(170,140) +\AutoGrid \VECTOR(0,0)(170,0) \Pbox(170,0)[t]{x}[0] \Pbox(100,0)[t]{\mathrm{1}}[2] @@ -846,6 +892,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ \end{Esempio} \caption{The golden section $x_2$ and the golden number $x_1$}\label{fig:aureo} \end{figure} + By the way figure~\ref{fig:aureo} shows also the code that is used for the drawing done completely with the facilities available just with \pack{curv2e}. It is also a usage example of several commands. @@ -855,7 +902,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ Mathematicians in the classical times B.C. up to the artists in the Renaissance, had no other means but to use geometrical constructions with ruler and compass. Even today in schools where calculus is not yet - taught as a normal subject, possibly not in certainly high school degree + taught as a normal subject, possibly not in certain high school degree courses, but certainly not in elementary and junior high schools, the instructors have to recourse to geometrical constructions. Sometimes, as in Italy, access to public universities is open with no restrictions to @@ -878,6 +925,9 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ section~\ref{sec:examples} we show their usage by means examples. \begin{enumerate}[noitemsep] +% +\item Command \cs{polyvector} is simple extension of the \cs{polyline} command introduced by \pack{pict2e}: draws a polyline with an arrow tip at its end; it turns out to be very handy while drawing block diagrams. +% \item Command \cs{IntersectionOfLines} is a fundamental one; its syntax is the following: \begin{ttsyntax} @@ -886,9 +936,9 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ \end{ttsyntax} were each line is identified with its \meta{point} and its \emph{direction} \meta{dir}; the intersection coordinates go to the output \meta{vector}. - +% \item A second command\cs{IntersectionOfSegments} does almost the same - work, but the coordinates of a segment define also its direction, + work, but the coordinates of a segment end points define also its direction, which is the argument of the difference of the terminal nodes of each segment; the syntax therefore is the following: \begin{ttsyntax} @@ -898,31 +948,35 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ Again the intersection point coordinates go to the output \meta{vector}. The first segment is between points 11 and 12, and, similarly, the second segment is between points 21 and 22. +% \item Another “intersection” command is \cs{IntersectionsOfLine} to determine the two intersection of a line with a circle. The syntax is: \begin{ttsyntax} -\cs{IntersectionsOfLine}\parg{point}\parg{dir}WithCircle\parg{center}\marg{radius}to\meta{int1} and\meta{int2} +\cs{IntersectionsOfLine}\parg{point}\parg{dir} +\qquad WithCircle\parg{center}\marg{radius}to\meta{int1} and\meta{int2} \end{ttsyntax} where \meta{point} and \meta{dir} identify a line with a given direction and passing through a given point; the circle is identified with its \meta{center} and \meta{radius}; the intersection points \meta{int1} and - \meta{int2} are the coordinates of the intersection points; If the line + \meta{int2} are the coordinates of the intersection points; if the line and circle do not intersect, a warning message is issued, shown in the console and written to the \file{.log} file; the intersection points are assigned the default values \texttt{0,0}, which evidently produce strange results in the output document, so as to remind the user to give a look to the \file{.log} file and to review his/her data. +% \item It is difficult to numerically determine the coordinates of the intersection points of two circles; it becomes easier if one of the - intersections is known; To this end, a macro to draw a circle with a + intersections is known; to this end, a macro to draw a circle with a given center and passing through a given point is handy: \begin{ttsyntax} \cs{CircleThrough}\meta{point}WithCenter\marg{center} \end{ttsyntax} draws such circumference. +% \item With the above macro it becomes easy to draw two circumferences with different centers and passing through the same point; therefore - it becomes determine the other intersection point by means of the + it becomes easy to determine the other intersection point by means of the following macro: \begin{ttsyntax} \cs{Segment}\parg{endpoint1}\parg{endpoint2}SymmetricPointOF\meta{p1} @@ -932,6 +986,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ symmetrical point \meta{p2} of \meta{p1} with respect to the segment that joins the centers of the given circles intersecting one another in \meta{p1}. +% \item It would be interesting to solve the same problem with help of the following macro relating to right triangles identified with their hypothenuse and one of its legs; the other leg is found by means of this @@ -943,14 +998,15 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ since the intersection points of two circles define their common chord; this chord and the two circle centers define two isosceles triangles with the same base; therefore the segment joining the circle radii, - coincides whit the chord axis and divides each isosceles triangle in + coincides whith the chord axis and divides each isosceles triangle in two right triangles, where the hypotenuse is one of two radii and the first leg is the distance from the chord middle point, intersection of the chord and the segment joining the circle centers; at this point the distance of the second point intersection from the chord middle point and the coordinates of the second intersection may be easily computed; of course this is a much clumsier way to determine the second - intersection, but it is useful to solve this right triangle easy problem. + intersection, but it is useful to solve this right triangle easy problem. +% \item Command \cs{ThreePointCircle} draws a circle that goes through three given points; the syntax is the following: \begin{ttsyntax} @@ -966,7 +1022,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ \end{ttsyntax} computes the three point circle center assigning its coordinates to \meta{vector}. - +% \item Command \cs{CircleWithCenter} draws a circle given its center and it radius; in facts the syntax is the following: \begin{ttsyntax} @@ -974,7 +1030,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ \end{ttsyntax} This macro does not require the \cs{put} command to put the circle in place. - +% \item A similar macro \cs{Circlewithcenter} does almost the same; its syntax is the following: \begin{ttsyntax} @@ -985,7 +1041,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ modulus of which is computed and used as the radius; in the latter command the \meta{radius} is a scalar and (its magnitude) is directly used. - +% \item Command with syntax: \begin{ttsyntax} \cs{AxisOf}\meta{point1} and\meta{point2} to \meta{point3} and\meta{point4} @@ -1004,7 +1060,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ totally equivalent, aliases to one another; sometimes it is more convenient to use a name, sometimes the other; it helps reading the code and maintaining it. - +% \item Given a triangle and a specific vertex, it is possible to determine the middle point of the opposite side; it is not very difficult, but it is very handy to have all the necessary elements to draw the median line. @@ -1013,44 +1069,44 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ \cs{TriangleMedianBase}\meta{vertex} on\meta{base1} and\meta{base2} \qquad to\meta{base middle point} \end{ttsyntax} - +% \item A similar command \cs{TriangleHeightBase} is used to determine the - intersection of the height segment from one vertex to the opposite base; + intersection of the height segment from one vertex to the opposite side; with triangles that have an obtuse angle, the height base might lay externally to one of the bases adjacent to such an angle. The syntax is the following \begin{ttsyntax} \cs{TriangleHeigthtBase}\meta{vertex} on\meta{base1} and\meta{base2} to\meta{height base} \end{ttsyntax} - +% \item Similarly there is the \cs{TriangleBisectorBase} macro with a similar syntax: \begin{ttsyntax} \cs{TriangleBisectorBase}\meta{vertex} on\meta{base1} and\meta{base2} \qquad to\meta{bisector base} \end{ttsyntax} - +% \item A triangle \emph{barycenter} is the point where its median lines intersect; command \cs{TriangleBarycenter} determines its coordinates with the following syntax. \begin{ttsyntax} \cs{TriangleBarycenter}\parg{vertex1}\parg{vertex2}\parg{vertex3} to\meta{barycenter} \end{ttsyntax} - +% \item A triangle \emph{orthocenter} is the point where its height lines intersect; command \cs{TriangleOrthocenter} determines its coordinates with the following syntax: \begin{ttsyntax} \cs{TriangleOrthocenter}\parg{vertex1}\parg{vertex2}\parg{vertex3} to\meta{orthocenter} \end{ttsyntax} - +% \item A triangle \emph{incenter} is the point where its bisector lines intersect; command \cs{TriangleIncenter} determines its coordinates with the following syntax: \begin{ttsyntax} \cs{TriangleIncenter}\parg{vertex1}\parg{vertex2}\parg{vertex3} to\meta{incenter} \end{ttsyntax} - +% \item The distance of a specified point from a given segment or line is computed with the following command \begin{ttsyntax} @@ -1059,7 +1115,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ where \meta{point} specifies the point and \meta{point1} and \meta{point2} identify two points on a segment or a line; \meta{distance} is a scalar value. - +% \item In a construction that will be examined in section~\ref{sec:examples} we need to determine an ellipse axis if the other axis and the focal distance are know; actually it solves the relation @@ -1082,7 +1138,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ again when dealing with the specific problem referred to at the beginning of this list item; the description is going to be more detailed and another macro is added to avoid possible errors. - +% \item Given a segment, i.e. the coordinates of its end points, it is useful to have a macro that computes its length; at the same time it is useful to to compute its direction; this operation is not the same as to @@ -1097,7 +1153,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ +180^\circ$; it represents the argument of the vector that goes from \meta{point1} to \meta{point2}, therefore the user must pay attention to the order s/he enters the end point coordinates. - +% \item The next command \cs{SymmetricalPointOf} is used to find the reflection of a specified point with respect to a fixed point; of course the latter is the middle point of the couple, but the unknown to be @@ -1106,7 +1162,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ \begin{ttsyntax} \cs{SymmetricalPointOf}\meta{point1} respect\meta{fixed} to\meta{point2} \end{ttsyntax} - +% \item Command \cs{RegPolygon} draws a regular polygon inscribed within a circle of given radius and center, with a specified number of sides; optional arguments allow to specify color and thickness of the sides, @@ -1136,8 +1192,9 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ argument is specified, the polygon center is displaced accordingly. The number of sides in theory may be very high, but it is not wise to exceed a couple of dozen sides; if the number of sides is too - high, a polygon (completely contained in an A4 page) may become undistinguishable from a circumference. - + high, a polygon (completely contained in an A4 page) may become + undistinguishable from a circumference. +% \item Several macros are dedicated to ellipses; their names are spelled in Italian, “ellisse”, because the name “ellipse” is already taken by other packages; with an Italian user command names there should be no @@ -1178,13 +1235,14 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ \end{minipage} \caption{The effect of shearing an ellipse with its bounding rectangle}\label{fig:shear} \end{figure} - +% \item The syntax of those six commands are the following: \begin{ttsyntax} \cs{Sellisse}\meta{$\star$}\marg{semiaxis-h}\marg{semiaxis-v}\oarg{shear} \cs{ellisse}\meta{$\star$}\marg{semiaxis-h}\marg{semiaxis-v} -\cs{XSellisse}\meta{$\star$}\parg{center}\oarg{angle}\aarg{shear}\marg{semiaxis-h}\% -\qquad \marg{semiaxis-v}\meta{$\star$}\oarg{settings1}\oarg{settings2} +\cs{XSellisse}\meta{$\star$}\parg{center}\oarg{angle}\% +\qquad \aarg{shear}\marg{semiaxis-h}\marg{semiaxis-v}\meta{$\star$}\% +\qquad \oarg{settings1}\oarg{settings2} \cs{Xellisse}\meta{$\star$}\parg{center}\oarg{angle}\marg{semiaxis-h}\% \qquad\marg{semiaxis-v}\oarg{settings1}\marg{settings2} \cs{EllipseWithFocus}\meta{$\star$}\parg{vertex1}\parg{vertex2}\parg{vertex3}\parg{focus} @@ -1193,7 +1251,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ All require the semi axis lengths; the \meta{semiaxis-h} and \meta{semiaxis-v} refer to the semi axes before possible rotation by \meta{angle} degrees, and do not make assumptions on which axis is the - bigger one. The optional parameter \meta{shear} is the angle in degrees + largger one. The optional parameter \meta{shear} is the angle in degrees by which the vertical coordinate lines are slanted by effect of shearing. If \meta{shear}, that by default equals zero, is not set to another value, the asterisks of command \cs{Sellisse} and @@ -1213,7 +1271,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ requires less data, in the sense that such ellipse is unique; it is the ellipse internally tangent to the triangle at its side middle points. - +% \end{enumerate} @@ -1228,14 +1286,14 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Figure~\ref{fig:vectors} shows some vectors and vector arcs with the - code used to draw them; as usual some points are described with cartesian + code used to draw them; some points are described with cartesian coordinates and some with polar ones. \begin{figure}[!htb] \begin{Esempio}[\setfontsize{8.5}](0.45) \unitlength=0.01\linewidth \begin{picture}(100,60) -\GraphGrid(100,60) +\AutoGrid \put(0,30){\vector(1,2){10}} \put(20,30){\Vector(10,20)} \VECTOR(40,30)(50,50) @@ -1251,7 +1309,8 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ \begin{figure*}[!tb] -\begin{Esempio}*[\setfontsize{10}]\centering +\begin{Esempio}*[\setfontsize{10}](0.40) +\centering \unitlength=0.006\linewidth\begin{picture}(120,90) % \RegPolygon(9,20){20}{6}<\linethickness{3pt}\color{red}> @@ -1308,7 +1367,10 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Dashed and dotted lines} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - For dotted lines it is possible to specify the dot size; + For dashedl ines it is mandatory to specify the dash length, that + is just as long as the gap between dashes. For dotted lines it is + mandatory to specify the dot gap. + For dotted lines it is also possible to specify the dot size; it can be specified with an explicit unit of measure, or, if no unit is specified, it is assumed to be “points”. The \cs{Dotline} takes care of transforming the implied or the explicit dimension in multiples of @@ -1319,7 +1381,7 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ \begin{Esempio}[\setfontsize{10}](0.45) \unitlength=0.02\linewidth \begin{picture}(40,40) -\GraphGrid(40,40) +\AutoGrid \Dashline(0,0)(40,10){4} \put(0,0){\circle*{1}} \Dashline(40,10)(0,25){4} @@ -1338,15 +1400,15 @@ z^2 &= m^2\eu^{\iu 2\phi}\\ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Generic curves} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -With the \cs{Curve} macro it is possible to make line art or filled shapes. Figures~\ref{fig:hearts} show the same shape, the first just stroked and the second color filled. +With the \cs{Curve} macro it is possible to make line art or filled shapes. The hearts drawn in figure~\ref{fig:hearts} show the same shape, the first just stroked and the second color filled. -\begin{figure}[!htp] +\begin{figure}[!htb] \begin{Esempio}[\setfontsize{9}](0.65) \unitlength=8mm\relax \begin{picture}(5,5) \put(0,0){\framebox(5,5){}}\thicklines\roundcap \Curve(2.5,0)<0.1,1>(5,3.5)<0,1>% - (4,5)<-1,0>(2.5,3.5)<-0.1,-1.2>[-0.1,1.2]% + (4,5)<-1,0>(2.5,3.5)<-0.01,-1.2>[-0.01,1.2]% (1,5)<-1,0>(0,3.5)<0,-1>(2.5,0)<0.1,-1> \end{picture} \end{Esempio} @@ -1359,7 +1421,7 @@ With the \cs{Curve} macro it is possible to make line art or filled shapes. Figu \put(0,0){\framebox(5,5){}}\thicklines\roundcap \color{orange}\relax \Curve*(2.5,0)<0.1,1>(5,3.5)<0,1>% -(4,5)<-1,0>(2.5,3.5)<-0.1,-1.2>[-0.1,1.2]% +(4,5)<-1,0>(2.5,3.5)<-0.01,-1.2>[-0.01,1.2]% (1,5)<-1,0>(0,3.5)<0,-1>(2.5,0)<0.1,-1> \end{picture} \end{Esempio} @@ -1379,13 +1441,13 @@ With the \cs{Curve} macro it is possible to make line art or filled shapes. Figu the green filled squares are along a sloping down line inclined by $15^\circ$ as specified by the polar coordinates of the \meta{increment}; the blue filled triangles are distributed along a parabola; the red - stroked diamonds are distributed along a half sine wave. + stroked diamonds are distributed along a half sine wave.\enlargethispage*{\baselineskip} \noindent\begin{figure}[!htb] \begin{Esempio}[\setfontsize{8}](0.55) \unitlength=0.01\linewidth \begin{picture}(100,100) -\GraphGrid(100,100) +\AutoGrid \multiput(0,0)(10,10){11}{\circle*{2}} \color{blue!70!white} \multiput(0,0)(10,0){11}{% @@ -1415,7 +1477,7 @@ With the \cs{Curve} macro it is possible to make line art or filled shapes. Figu \begin{Esempio}[\setfontsize{9.5}](0.525) \unitlength=0.0095\linewidth \begin{picture}(100,100) -\GraphGrid(100,100) +\AutoGrid \put(50,50){\thicklines\circle{100}} \xmultiput[50,50](60:35)(-30:1){12}% {\makebox(0,0){\circle*{2}}}% @@ -1448,10 +1510,10 @@ With the \cs{Curve} macro it is possible to make line art or filled shapes. Figu do the job with \cs{xmultiput}. \begin{figure*}[!tp] -\begin{Esempio}[\setfontsize{9}](0.5)% +\begin{Esempio}[\setfontsize{9}](0.5) \unitlength=0.008\linewidth \begin{picture}(100,100) -\GraphGrid(100,100) +\AutoGrid \VECTOR(0,0)(100,0)\Pbox(100,0)[tr]{x}[0] \VECTOR(0,0)(0,100)\Pbox(0,100)[tr]{y}[0] \Pbox(0,0)[r]{O}[3pt] @@ -1480,7 +1542,7 @@ because it is easy to code the $x$ and the $y$ component and use the A heart shaped mathematical function taken from the internet \footnote{\url{http://mathworld.wolfram.com/HeartCurve.html} reports several formulas, including the cardioid, but the one we use here is - a different function} is the following + a different function.} is the following \begin{align*} x(t) &= \sin^3(t)\\ y(t) &= \dfrac{13\cos(t)-5\cos(2t)-2\cos(3t)-\cos(4t)}{16} @@ -1508,7 +1570,7 @@ y(t) &= \dfrac{13\cos(t)-5\cos(2t)-2\cos(3t)-\cos(4t)}{16} % Drawing \unitlength=0,005\linewidth \begin{picture}(200,200)(-100,-100) -\GraphGrid(-100,-100)(200,200) +\AutoGrid \VECTOR(-100,0)(100,0)\Pbox(100,0)[tr]{x}[0] \VECTOR(0,-100)(0,100)\Pbox(0,100)[tl]{y}[0] \Pbox(0,0)[tr]{O}\linethickness{1pt}\bgroup @@ -1531,7 +1593,7 @@ y(t) &= \dfrac{13\cos(t)-5\cos(2t)-2\cos(3t)-\cos(4t)}{16} % \unitlength=0,005\linewidth \begin{picture}(200,200)(-100,-100) -\GraphGrid(-100,-100)(200,200) +\AutoGrid \VECTOR(-100,0)(100,0)\Pbox(100,0)[tr]{x}[0] \VECTOR(0,-100)(0,100)\Pbox(0,100)[tl]{y}[0] \Pbox(0,0)[tr]{O}\linethickness{1pt}\bgroup @@ -1554,8 +1616,8 @@ Determining the intersection of two circles is difficult; algebraically it requi Figure~\ref{fig:circle-and-line} shows the simple geometrical construction that leads to the determination of the intersections; one of the lines is tangent to the circle and the intersection points $P_3$ and $P_4$ coincide. -\begin{figure} -\begin{Esempio}[\setfontsize{9}] +\begin{figure}[!htb] +\begin{Esempio}[\setfontsize{9}](0,40) \unitlength=0.007\linewidth \begin{picture}(100,100) \AutoGrid @@ -1584,8 +1646,8 @@ Figure~\ref{fig:circle-and-line} shows the simple geometrical construction that Figure~\ref{fig:two-intersecting-circles} shows the geometrical construction to determine the second intersection point $P_2$ of two circles that already have a first common point $P_1$. The common chord and the segment joining the centers are not shown, but the code, although with “strange” point names, shows all the steps necessary to find the second intersection point -\begin{figure}\centering -\begin{Esempio}[\setfontsize{9}] +\begin{figure}[!htb]\centering +\begin{Esempio}[\setfontsize{9}](0.40) \unitlength0.007\linewidth \begin{picture}(100,100) \AutoGrid @@ -1605,24 +1667,25 @@ Figure~\ref{fig:two-intersecting-circles} shows the geometrical construction to \caption{Second intersection point $P_2$ of two circles sharing a first intersection point $P_1$}\label{fig:two-intersecting-circles} \end{figure} -The following macro allows to determine both intersections, if they exist, of two generic circles; of corse the maro is a little more complicated than the above macro need to find the second intersection when one is already known. Even the reasoning behind the macro is quite different and slightly “creative”. +The following macro allows to determine both intersections, if they exist, of two generic circles; of course the macro is a little more complicated than the above macro that has to find the second intersection when one is already known. Even the reasoning behind the macro is quite different and slightly “creative”. In facts the reasoning is to avoid any or most analytical computations; analytically it would be quite simple to set up a system of two second degree polynomial equations; after processing such a system it is necessary to solve a second degree equation, but in order to control if there are intersections it should be necessary to discuss the value and sign of the discriminant; it is nothing special when doing all this by hand, but it involves a complicated code in terms of the \LaTeX\ language. -It is much simpler to reason geometrically; imagine to draw two circles; let $a$ be the distance of their centers, and let $R_1$ and $R_2$ be their radii. Then if + +It is much simpler to reason geometrically; imagine to draw two circles; let $a>0$ be the distance of their centers\footnote{If $a=0$ the circles are concentric and do not intersect.}, and let $R_1$ and $R_2$ be their radii. Then if \[ -|R_1 -R_2| \leq a \leq R_1+R_2 +|R_1 - R_2| \leq a \leq R_1 + R_2 \] -the intersections do exist, even if it is possible that the circles are tangent to one another and the two intersection points become a (double) one; this takes place when either ‘equals’ sign applies. I f the left boundary is not satisfied the centers are too close one another and the internal circle is too small compared to the external one. On the opposite if the upper bound is not satisfied the second circle is outside the first one and too far away. +the intersections do exist, even if it is possible that the circles are tangent to one another and the two intersection points become a (double) one; this takes place when either ‘equals’ sign applies. If the left boundary is not satisfied the centers are too close to one another and the internal circle is too small compared to the external one. On the opposite if the upper bound is not satisfied the second circle is outside the first one and too far away. -The macro controls the above range, and if the the input data do not satisfy the range boundaries, there are no intersections: a warning message is issued, but computations go on with non sense values for both output coordinates; may be other errors or produced, but in any case the successive drawing lines will not be acceptable; a good sign to the user who may have not noticed the warning message in his/her console, but is immediately “forced” to consult this manual and find out this explanation; s/he will then review his/her code in oder to change the drawing data. +The macro controls the above range, and if the the input data do not satisfy the range boundaries, there are no intersections: a warning message is issued, but computations go on with non sense values for both output coordinates; may be other errors are produced, but in any case the successive drawing lines will not be acceptable; a good sign to the user who may have not noticed the warning message in his/her console, but is immediately “forced” to consult this manual and find out this explanation; s/he will then review his/her code in oder to change the drawing data. -If the data cope with the above range, the computations go on along this simple reasoning, that it drawn in the left part of figure~\ref{fig;Intersections-of-two-circles}. There you see the segment that joins the two centers, and the intersection points to be found. They are the end points of the chord common to both circles; using as vertices the two centers and such chord as the base, two isosceles triangles are formed; the segment joining the centers bisects both triangles forming four right triangles where the hypotenuse is formed by the pertinent radius, and one leg is half the chord; with reference to the right triangles $IC_1P_1$ and $IC_2P_1$, Pithagoras' theorem lets us determine the relation between the common leg $IP_1$ and the other triangle sides; this s the small analytical computation we have to execute, so as to compute the distance $c$ from the center $C_1$ and the common leg length $h$. These two values are sufficient, together with the direction of segment $C_1C_2$ to find the intersection points coordinates. +If the data cope with the above range, the computations go on along this simple reasoning, that it drawn in the left part of figure~\ref{fig;Intersections-of-two-circles}. There you see the segment that joins the two centers, and the intersection points to be found. They are the end points of the chord common to both circles; using as vertices the two centers and such chord as the base, two isosceles triangles are formed; the segment joining the centers bisects both triangles forming four right triangles where the hypotenuse is formed by the pertinent radius, and one leg is half the chord; with reference to the triangles $IC_1P_1$ and $IC_2P_1$, Pithagoras' theorem lets us determine the relation between the common leg $IP_1$ and the other triangle sides; this is the small analytical computation we have to execute, so as to compute the distance $c$ from the center $C_1$ and the common leg length $h$. These two values are sufficient, together with the direction of segment $C_1C_2$ to find the intersection points coordinates. The syntax il the following \begin{ttsyntax} \cs{TwoCirclesIntersections}\parg{C1}\parg{C2}withradii\marg{R1} and\marg{R2} to\meta{P1} and\meta{P2} \end{ttsyntax} -Th symbols are self explanatory; as usual, input data (those entered before the keyword \texttt{to}) may be control sequences defined with the necessary data, or explicit data; on the opposite the output ones must be control sequences. +Th symbols are self explanatory; as usual, input data (those entered before the keyword \texttt{to}) may be control sequences (defined with the necessary data), or explicit data; on the opposite the output ones must be control sequences. \begin{figure}[!htb] \begin{minipage}{0.475\linewidth} @@ -1675,7 +1738,7 @@ Th symbols are self explanatory; as usual, input data (those entered before the The code for drawing figure~\ref{fig;Intersections-of-two-circles} is the following. \begin{Verbatim} -\begin{minipage}{0.475\linewidth} +\begin{minipage}{0.475\linewidth}% Geometrical construcion \unitlength0.01\linewidth \begin{picture}(100,100)(-50,-50) \AutoGrid @@ -1689,7 +1752,7 @@ The code for drawing figure~\ref{fig;Intersections-of-two-circles} is the follow \thinlines \TwoCirclesIntersections(\Kuno)(\Kdue)withradii\RKuno and\RKdue to\Puno and\Pdue -\Pbox(\Kuno)[br]{C_1}[4] \Pbox(\Kdue)[bl]{C_2}[4] +\Pbox(\Kuno)[br]{C_1}[4] \Pbox(\Kdue)[bl]{C_2}[4] \Pbox(\Puno)[tl]{P_1}[4] \Pbox(\Pdue)[bc]{P_2}[4] \put(\Kuno){\Vector(-45:\RKuno)}\Pbox(5,-27)[bl]{R_1}[0] \put(\Kdue){\Vector(-45:\RKdue)}\Pbox(25, 3)[bl]{R_2}[0] @@ -1701,7 +1764,7 @@ The code for drawing figure~\ref{fig;Intersections-of-two-circles} is the follow \end{picture} \end{minipage} \hfill -\begin{minipage}{0.475\linewidth} +\begin{minipage}{0.475\linewidth}% Clean final result \unitlength0.01\linewidth \begin{picture}(100,100)(-50,-50) \AutoGrid @@ -1736,7 +1799,7 @@ The code for drawing figure~\ref{fig;Intersections-of-two-circles} is the follow special lines relative to a specific vertex. Thanks to the macros described earlier in this list, this drawing is particularly simple; most of the code is dedicated to labelling the various points and to - assign coordinate values to the macros that are going to be use + assign coordinate values to the macros that are going to be used in a symbolic way. The generic triangle (not a regular polygon) requires one line of code, and the determination of the intersections of the lines with the suitable triangle side, and their tracing requires two code lines @@ -1746,20 +1809,20 @@ The code for drawing figure~\ref{fig;Intersections-of-two-circles} is the follow \begin{Esempio}[\setfontsize{6.9}](0.4) \unitlength=0.008\linewidth \begin{picture}(100,100)(0,-10) -\GraphGrid(0,-10)(100,100) -\def\Puno{0,0} \def\Pdue{0,80} \def\Ptre{100,60} +\AutoGrid +\def\Puno{0,0} \def\Pdue{0,80} \def\Ptre{100,55} {\thicklines\polygon(\Puno)(\Pdue)(\Ptre)}% - \Pbox(\Puno)[tc]{P_1}[1] -\Pbox(\Pdue)[bc]{P_2}[1]\Pbox(\Ptre)[bc]{P_3}[1] - % Median + \Pbox(\Puno)[tc]{P_1}[2] +\Pbox(\Pdue)[bc]{P_2}[2]\Pbox(\Ptre)[bc]{P_3}[2] +% Median \TriangleMedianBase\Puno on \Pdue and \Ptre to\M - \Pbox(\M)[bc]{M}[1.5]\segment(\Puno)(\M) + \Pbox(\M)[bc]{M}[2]\segment(\Puno)(\M) % Height \TriangleHeightBase\Puno on \Pdue and\Ptre to\H \Dotline(\Puno)(\H){2}[1.5]\Pbox(\H)[bc]{H}[1.5] % Bisector \TriangleBisectorBase\Puno on\Pdue and\Ptre to\B - \Dashline(\Puno)(\B){3}\Pbox(\B)[b]{B}[1.5] + \Dashline(\Puno)(\B){1.5}\Pbox(\B)[b]{B}[2] \end{picture} \end{Esempio} \caption{A triangle with the median, the height, and the bisector lines @@ -1787,8 +1850,8 @@ The code for drawing figure~\ref{fig;Intersections-of-two-circles} is the follow \begin{Esempio}[\setfontsize{6.5}](0.45) \unitlength=0.008\linewidth \begin{picture}(100,100)(0,-10) -\GraphGrid(0,-10)(100,100) -\def\Puno{0,0}\def\Pdue{0,80}\def\Ptre{100,60} +\AutoGrid +\def\Puno{0,0}\def\Pdue{0,80}\def\Ptre{100,55} {\linethickness{0.6pt}\polygon(\Puno)(\Pdue)(\Ptre)}% \Pbox(\Puno)[tl]{P_1}[1.5]% \Pbox(\Pdue)[bl]{P_2}[1.5]\Pbox(\Ptre)[bc]{P_3}[1.5] @@ -1809,8 +1872,8 @@ The code for drawing figure~\ref{fig;Intersections-of-two-circles} is the follow \begin{Esempio}[\setfontsize{6.5}](0.45) \unitlength=0.008\linewidth \begin{picture}(100,100)(0,-10) -\GraphGrid(0,-10)(100,100) -\def\Puno{0,0}\def\Pdue{0,80}\def\Ptre{100,60} +\AutoGrid +\def\Puno{0,0}\def\Pdue{0,80}\def\Ptre{100,55} {\linethickness{0.6pt}\polygon(\Puno)(\Pdue)(\Ptre)}% \Pbox(\Puno)[tl]{P_1}[1.5]% \Pbox(\Pdue)[bl]{P_2}[1.5]\Pbox(\Ptre)[bc]{P_3}[1.5] @@ -1831,8 +1894,8 @@ The code for drawing figure~\ref{fig;Intersections-of-two-circles} is the follow \begin{Esempio}[\setfontsize{6}](0.45) \unitlength=0.008\linewidth \begin{picture}(100,100)(0,-10) -\GraphGrid(0,-10)(100,100) -\def\Puno{0,0}\def\Pdue{0,80}\def\Ptre{100,60} +\AutoGrid +\def\Puno{0,0}\def\Pdue{0,80}\def\Ptre{100,55} {\linethickness{0.6pt}% \polygon(\Puno)(\Pdue)(\Ptre)}% \Pbox(\Puno)[tl]{P_1}[1.5]% @@ -1858,7 +1921,7 @@ The code for drawing figure~\ref{fig;Intersections-of-two-circles} is the follow \begin{Esempio}[\setfontsize{6.25}](0.45) \unitlength=0.01\linewidth \begin{picture}(100,110) -\GraphGrid(100,110) +\AutoGrid \CopyVect20,10to\Pu \Pbox(\Pu)[t]{P_1} \CopyVect10,90to\Pd \Pbox(\Pd)[br]{P_2} \CopyVect100,70to\Pt \Pbox(\Pt)[l]{P_3} @@ -1870,20 +1933,21 @@ The code for drawing figure~\ref{fig;Intersections-of-two-circles} is the follow \AddVect\Mu and\Du to\Du\Dotline(\Mu)(\Du){3}[2] \AddVect\Md and\Dd to\Dd\Dotline(\Md)(\Dd){3}[2] \AddVect\Mt and\Dt to\Dt\Dotline(\Mt)(\Dt){3}[2] -\Pbox(\C)[t]{C}[2.5] +\Pbox(\C)[l]{C}[3.5] \ThreePointCircle*(\Pu)(\Pd)(\Pt) -\end{picture}\end{Esempio} +\end{picture} +\end{Esempio} \caption{Determination of the circumcenter and of the circumcircle}\label{fig:circumcenter} \end{figure} - Although these examples require some new simple macros, described - in the previous sections; some more more examples can be made that require - more complex macros. Even these macros are just examples. For other - applications it is probably necessary to add even more macros. + These examples require some new simple macros, described in the previous + sections; some more more examples can be made that require more complex + macros. Even these macros are just examples. For other applications it is + probably necessary to add even more macros. Let us proceed with the construction of the Steiner ellipse: given a triangle, there exists only one ellipse that is internally tangent to - the side middle points. + the side mid-points. The geometrical construction goes on this way; suppose you have to draw the Steiner ellipse of triangle $T$; finding the side middle points @@ -1910,9 +1974,10 @@ The code for drawing figure~\ref{fig;Intersections-of-two-circles} is the follow \begin{Esempio}[\setfontsize{8}](0.5) \unitlength=0.01\linewidth \begin{picture}(100,110) -\GraphGrid(100,110)% +\AutoGrid \SteinerEllipse(10,10)(90,20)(60,105)[2] -\end{picture}\end{Esempio} +\end{picture} +\end{Esempio} \caption{The Steiner ellipse of a given triangle} \label{fig:Steiner-finale} \end{figure} @@ -1924,9 +1989,10 @@ The code for drawing figure~\ref{fig;Intersections-of-two-circles} is the follow \begin{Esempio}[\setfontsize{8}](0.5) \unitlength=0.01\linewidth \begin{picture}(100,110)(0,-10) -\GraphGrid(0,-10)(100,110)% +\AutoGrid \SteinerEllipse*(10,10)(90,20)(60,105)[2] -\end{picture}\end{Esempio} +\end{picture} +\end{Esempio} \caption{The construction of the Steiner ellipse of a given triangle} \label{fig:Steiner-intermedio} \end{figure} @@ -1934,41 +2000,54 @@ The code for drawing figure~\ref{fig;Intersections-of-two-circles} is the follow %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{The tangent to an ellipse}\label{ssec:diretriz} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -Ellipses have mani interesting properties. One that I was not able to find anywhere in the documentation I examined (of course not the totality of available on ellipses, except an on-line document written in Portuguese by Sergio Alvez, \url{https://docplayer.com.br/345411-Elipses-inscritas-num-triangulo.html}, is the \emph{director circumference}, literal translation of the Portuguese definition \emph{circunfência diretriz}. +Ellipses have many interesting properties. One that I was not able to find anywhere in the documentation I examined (of course not the totality of available documents on ellipses) except an on-line document written in Portuguese by Sergio Alvez, +\begin{flushleft}\setfontsize{10}% +\url{https://docplayer.com.br/345411-Elipses-inscritas-num-triangulo.html}\end{flushleft} +is the \emph{director circumference}, literal translation of the Portuguese definition \emph{circunfência diretriz}. Consider an ellipse with its foci $F$ en $F'$, and a generic point $P$ on its contour. -Trace a segment from $F\,P$ and another segment for $P\,F'$; these segments measure the distanced from point $P$ to each focus: their sum is the length of the main ellipse axis $2a$, being $a$ the semi axis. Now lengthen the segment $P\,F'$ to point $S$ by the length of $F\,P$; the length of $S\,F'$ is therefore equal to $2a$; now trace the circumference with center in $F'$ and radius $2a$; this is the \emph{director circumference}, that is labelled with~$\Gamma$. +Trace a segment from $F\,P$ and another segment for $P\,F'$; these segments measure the distances from point $P$ to each focus: their sum is the length of the main ellipse axis $2a$, where $a$ is the semi axis. Now lengthen the segment $P\,F'$ to point $S$ by the length of $F\,P$; the length of $S\,F'$ is therefore equal to $2a$; now trace the circumference with center in $F'$ and radius $2a$; this is the \emph{director circumference}, that is labelled with~$\Gamma$. By construction, then, the circle $\gamma$ centred in $F$ and radius equal to $F\,P$ is tangent to $\Gamma$ in $S$ and passes through $F$. This allows to say that: \begin{itemize}[noitemsep] \item the ellipse is the locus of the centres of all circles passing through focus $F$ and internally tangent to the circle $\Gamma$ centred in the other focus $F'$ and with radius $2a$; \item the axis of segment $S\,F$ is tangent to the ellipse; \item the tangency point is the point $P$; -\item since this axis passes through the midpoint $M$ of segment $S\,F$ and it is perpendicular to it, the segment $M\,P$ has the same direction of the tangent to the ellipse; +\item since this axis passes through the midpoint $M$ of segment $S\,F$ and it is perpendicular to it, the segment $M\,P$ determines the direction of the tangent to the ellipse; \item notice that points $S$ and $F$ are symmetrical with respect to the tangent in point $P$. \end{itemize} Such properties can be viewed and controlled in figure~\ref{fig:diretriz}. -\begin{figure}[!tb]\centering +\begin{figure}[!tbp]\centering \begin{Esempio}*[\setfontsize{8.2}](0.40) \unitlength=0.005\linewidth \begin{picture}(170,160)(-60,-80) -\GraphGrid(-60,-80)(170,160) +\AutoGrid \VECTOR(0,-80)(0,80)\Pbox(0,80)[r]{y}[0] \VECTOR(-60,0)(110,0)\Pbox(110,0)[t]{x}[0] +% Ellipse with given semi axes \edef\A{40}\edef\B{30}\Xellisse{\A}{\B}[\thicklines] +% Point P on the ellipse \edef\X{\fpeval{\A*cosd(120)}}\edef\Y{\fpeval{\B*sind(120)}} \edef\P{\X,\Y}\Pbox(\P)[b]{P}[3] -\edef\C{\fpeval{sqrt(\A**2-\B**2)}}% Inter focal semi distance +% Foci coordinates +\edef\C{\fpeval{sqrt(\A**2-\B**2)}} \CopyVect-\C,0 to\F \CopyVect\C,0 to\Fp\Pbox(\Fp)[t]{F'}[3] \Pbox(\F)[t]{F}[3]\Pbox(0,0)[tr]{O}[3] -\edef\Raggio{\fpeval{2*\A}}\Circlewithcenter\Fp radius\Raggio -\SegmentLength(\P)(\F)to\raggio\Circlewithcenter\P radius\raggio +% Director circumference +\edef\Raggio{\fpeval{2*\A}} +\Circlewithcenter\Fp radius\Raggio \Pbox(80,60)[tr]{\ISOGamma{lmss}}[0] +% Tangent construction +\SegmentLength(\P)(\F)to\raggio +\Circlewithcenter\P radius\raggio \Pbox(-10,50)[bl]{\ISOgamma{lmss}}[0] \SegmentArg(\Fp)(\P)to\Arg\AddVect\Fp and\Arg:\Raggio to\S \segment(\Fp)(\S)\Pbox(\S)[br]{S}[3] \segment(\F)(\S)\SegmentCenter(\F)(\S)to\M \Pbox(\M)[r]{M}[3]\SegmentArg(\F)(\S)to\Arg -\edef\Arg{\fpeval{\Arg-90}}\AddVect\M and \Arg:50 to\D\segment(\M)(\D) +% Tangent +\edef\Arg{\fpeval{\Arg-90}} +\AddVect\M and \Arg:50 to\D \Pbox(\D)[l]{D}[3] +\segment(\M)(\D) \end{picture} \end{Esempio} \caption{The director circumference}\label{fig:diretriz} @@ -1982,23 +2061,24 @@ Of course the geometrical construction of figure~\ref{fig:diretriz} can be used It is possible to draw an ellipse that is internally tangent to a triangle if one of its foci is specified; without this specification - the problem is not definite, and the number o such ellipses is countless. + the problem is not definite, and the number of such ellipses is countless. But with the focus specification, just one ellipse exists with that tangency constraint. It suffices to find the other focus and at least one point of tangency, because the focal distance and the sum of distances of that tangency point from the foci, is sufficient to determine all the parameters required to draw the ellipse. - As seen in the previous subsection~\ref{ssec:diretriz}, it is sufficient to find the threes symmetrical point of The given focus with respect to to the three sides, i.e. the three lines that pass through the triangle vertices; and the constructions gives simultaneously the major axis length and the three tangency points, therefore all the elements required to draw the ellipse. to draw + As seen in the previous subsection~\ref{ssec:diretriz}, it is sufficient to find the three symmetrical points of the given focus with respect to the three sides, i.e. the three lines that pass through the triangle vertices; and the constructions gives simultaneously the major axis length and the three tangency points, therefore all the elements required to draw the ellipse to be drawn. \begin{figure}[!tb]\centering \begin{Esempio}[\setfontsize{7}](0.375) \unitlength=0.0065\linewidth \begin{picture}(150,150)(-30,-20) -\GraphGrid(-30,-20)(150,150) +\AutoGrid \EllipseWithFocus% (10,40)(110,10)(0,110)(20,60) -\end{picture}\end{Esempio} +\end{picture} +\end{Esempio} \caption{An ellipse internally tangent to a triangle, given a focus} \label{fig:ellisse-interna-finale} \end{figure} @@ -2007,22 +2087,23 @@ Of course the geometrical construction of figure~\ref{fig:diretriz} can be used \begin{Esempio}[\setfontsize{7}](0.375) \unitlength0.0065\linewidth \begin{picture}(150,150)(-30,-20) -\GraphGrid(-30,-20)(150,150) +\AutoGrid \EllipseWithFocus*% (10,40)(110,10)(0,110)(20,60) -\end{picture}\end{Esempio} +\end{picture} +\end{Esempio} \caption{Construction of the ellipse of figure~\ref{fig:ellisse-interna-finale}}\label{fig:ellisse-interna} \end{figure} - The geometrical construction with help of what has been explained in - subsection~\ref{ssub:diretriz} is easy; the steps to follow, therefore + The geometrical construction, with help of what has been explained in + subsection~\ref{ssec:diretriz}, is easy; the steps to follow, therefore are the following:\enlargethispage*{\baselineskip} \begin{itemize}[noitemsep] \item draw the triangle and the given focus $\mathsf{F}$; -\item Find the symmetrical points $\mathsf S_i$ of this +\item find the symmetrical points $\mathsf S_i$ of this focus with respect to the sides of the triangle; \item use these three points $\mathsf S_i$ as the vertices of a triangle @@ -2035,7 +2116,7 @@ focus with respect to the sides of the triangle; with the triangle sides; they represent the tangency points of the ellipse to be drawn; -\item the radius of the director circumference is the ellipse major axix; +\item the radius of the director circumference is the ellipse major axis; \item equation~\eqref{equ:axes-foci} allows to find the second axis length; the segment that joins the foci has the required inclination @@ -2068,8 +2149,8 @@ focus with respect to the sides of the triangle; difficult the problem, the greater the satisfaction in solving it. -\begin{center} - Have fun with \LaTeX and its potential applications! +\begin{center}\bfseries + Have fun with \LaTeX and its possible applications! \end{center} \end{document}
\ No newline at end of file diff --git a/macros/latex/contrib/euclideangeometry/euclideangeometry.dtx b/macros/latex/contrib/euclideangeometry/euclideangeometry.dtx index af615d4b55..f8850eef50 100644 --- a/macros/latex/contrib/euclideangeometry/euclideangeometry.dtx +++ b/macros/latex/contrib/euclideangeometry/euclideangeometry.dtx @@ -6,30 +6,18 @@ \keepsilent \preamble - Copyright (C) 2020 Claudio Beccari all rights reserved. - License information appended + Copyright (C) 2020-2021 Claudio Beccari all rights reserved. + + Distributable under the LaTeX Project Public License, + version 1.3c or higher (your choice). The latest version of + this license is at: http://www.latex-project.org/lppl.txt \endpreamble -\postamble - -Distributable under the LaTeX Project Public License, -version 1.3c or higher (your choice). The latest version of -this license is at: http://www.latex-project.org/lppl.txt - -This work is "maintained" - -This work consists of files: -1) euclideangeometry.dtx, and the derived files euclideangeometry.sty - and euclideangeometry.pdf, -2) euclideangeometry-man.tex and the derived file euclideangeometry-man.pdf, -3) the auxiliary derived file README.txt - -\endpostamble \askforoverwritefalse \generate{\file{euclideangeometry.sty}{\from{euclideangeometry.dtx}{package}}} -\generate{\file{README.txt}{\from{euclideangeometry.dtx}{readme}}} +%\generate{\file{README.txt}{\from{euclideangeometry.dtx}{readme}}} \def\tmpa{plain} \ifx\tmpa\fmtname\endgroup\expandafter\bye\fi @@ -45,7 +33,7 @@ This work consists of files: %<package>\ProvidesPackage{euclideangeometry}% %<readme>File README.txt for package euclideangeometry %<*package|readme> - [2020-04-15 v.0.1.8 Extension package for curve2e] + [2021-05-016 v.0.2.0 Extension package for curve2e] %</package|readme> %<*driver> \documentclass{ltxdoc}\errorcontextlines=100 @@ -93,7 +81,9 @@ This work consists of files: \fontfamily{lmr}\fontseries{m}\fontshape{sc}\selectfont g\raisebox{-0.715ex}{\kern-0.26em u}\kern-0.13em\I\kern-0.14em t}\xspace} \RequirePackage{etoolbox} + \makeatletter + \AfterEndPreamble{% \DeclareRobustCommand{\TeX}{T\kern-.1667em \lower.5ex\hbox{E}\kern-.125emX\@\xspace} @@ -108,6 +98,7 @@ g\raisebox{-0.715ex}{\kern-0.26em u}\kern-0.13em\I\kern-0.14em t}\xspace} \kern-.15em% \TeX}} \makeatother + \DeclareRobustCommand*\TeXLive{\TeX\ Live\xspace} \DeclareRobustCommand*\MikTeX{Mik\TeX} \DeclareRobustCommand*\MacTeX{Mac\TeX} @@ -130,6 +121,7 @@ g\raisebox{-0.715ex}{\kern-0.26em u}\kern-0.13em\I\kern-0.14em t}\xspace} \IfValueTF{#2}{\put(#1){\originalGraphGrid(#2)}}% {\put(0,0){\originalGraphGrid(#1)}}}\fi + \begin{document}\errorcontextlines=100 \GetFileInfo{euclideangeometry.dtx} \title{The \textsf{euclideangeometry} package} @@ -154,7 +146,7 @@ g\raisebox{-0.715ex}{\kern-0.26em u}\kern-0.13em\I\kern-0.14em t}\xspace} % installed with your updated complete \TeX system installation. % Please refer to the user manual before using this package. -% \CheckSum{1296} +% \CheckSum{1294} %^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %\StopEventually{} %^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -167,7 +159,7 @@ g\raisebox{-0.715ex}{\kern-0.26em u}\kern-0.13em\I\kern-0.14em t}\xspace} %^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% \subsection{Checking the date of a sufficiently recent \texttt{curve2e} +% \subsection{Test the date of a sufficiently recent \texttt{curve2e} % package} %^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % This package has been already identified by the commands extracted @@ -175,7 +167,7 @@ g\raisebox{-0.715ex}{\kern-0.26em u}\kern-0.13em\I\kern-0.14em t}\xspace} % In any case, if the test checks that the |curve2e| file date is too old; % it warns the user with an emphasised error message on the console, % loading this |euclideangeometry| package is stopped and the whole -% job aborts. The emphasised error message appears like this: +% job aborts. The emphasised error message appears like this:\\~ %\begin{flushleft}\ttfamily\obeylines %************************************************************* %Package curve2e too old @@ -205,10 +197,10 @@ g\raisebox{-0.715ex}{\kern-0.26em u}\kern-0.13em\I\kern-0.14em t}\xspace} %^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % While doing any graphical geometrical drawing it is necessary to label -% points, lines, angles and other such items. Non measurable labels should -% be in upright sans serif font, according to the ISO regulations, but here -% we are dealing witt point identified by macros the contain their -% (cartesian or polar) coordinates that very often are both labels +% points, lines, angles and other such items. Non measurable labels +% should be in upright sans serif font, according to the ISO regulations, +% but here we are dealing with point identified by macros the contain +% their (cartesian or polar) coordinates that very often are both labels % and math variables. % % Here we provide a versatile macro that can do several things. Its name @@ -228,20 +220,21 @@ g\raisebox{-0.715ex}{\kern-0.26em u}\kern-0.13em\I\kern-0.14em t}\xspace} % incoherent, as well as \texttt{lr}), but in absence of this optional % specification, the couple \texttt{cc} is assumed; most often than % not, the label position becomes such that when the user reviews the -% document drafts, s/he understands immediately that s/he forgot to specify -% some reasonable \meta{alignment} codes; in any case the \texttt{cc} code -% works fine to just put the dot of a specified diameter but with an empty -% label. Think of the \meta{alignment} +% document drafts, s/he understands immediately that s/he forgot to +% specify some reasonable \meta{alignment} codes; in any case the +% \texttt{cc} code works fine to just put the dot of a specified +% diameter but with an empty label. Think of the \meta{alignment} % letters as the position of the reference point with respect to the % the \meta{label} optical center. The optional \meta{angle} argument % produces a rotation of the whole label by that angle; it may be used % in several circumstances, especially when the label is just text, to % produce, for example, a sideways legend. It is useful also when the -% labels are produced within a rotated box, in order to counterrotate them. +% labels are produced within a rotated box, in order to counterrotate +% them. % -% The optional asterisk draws a frame around the \emph{label}. Notice that -% the separator between the visible or the invisible frame and the box -% contents varies according the the fact that the \meta{alignment} +% The optional asterisk draws a frame around the \emph{label}. Notice +% that the separator between the visible or the invisible frame and the +% box contents varies according the the fact that the \meta{alignment} % specification contains just one or two letter codes; this is useful, % because the diagonal position of the label should be optically equal % to the gap that exists between the reference point and the \meta{label} @@ -264,7 +257,6 @@ g\raisebox{-0.715ex}{\kern-0.26em u}\kern-0.13em\I\kern-0.14em t}\xspace} % a sloping line. % \begin{macrocode} \providecommand\Pbox{} -\newlength\PbDim \RenewDocumentCommand\Pbox{D(){0,0} O{cc} m O{0.5ex} s D<>{0}}{% \put(#1){\rotatebox{#6}{\makebox(0,0){% \settowidth\PbDim{#2}% @@ -296,11 +288,11 @@ g\raisebox{-0.715ex}{\kern-0.26em u}\kern-0.13em\I\kern-0.14em t}\xspace} % fonts; with Type~1 fonts the only scalable fonts I know of, are the % LibertinusMath fonts, usable through the LibertinusT1math package, are % also the only ones that have 8~bit encoded math fonts (256 -% glyph fonts), while the standard default Type~1 math fonts are just +% glyph fonts), while the standard default math fonts are just % 7~bit encoded (128 glyphs fonts). % % Another useful labelling command is |Zbox|; this command is an -% evolution of a command that I been using for years in several +% evolution of a command that I have been using for years in several % documents of mine. It uses some general text, not necessarily % connected to a particular point of the |picture| environment, % as a legend; It can draw short text as a simple horizontal box, @@ -310,7 +302,7 @@ g\raisebox{-0.715ex}{\kern-0.26em u}\kern-0.13em\I\kern-0.14em t}\xspace} %\begin{ttsyntax} %\cs{Zbox}\parg{position}\parg(dimensions)\oarg{alignment}\marg{text} %\end{ttsyntax} -% where \meta{position} is where the reference point of the box has +% where \meta{position} is where the box reference point has % to be put in the picture; \meta{dimensions} are optional; if not % specified, the box is a horizontal one, and it is as wide as its % contents; if it is specified, it must be a comma separated list @@ -753,7 +745,7 @@ g\raisebox{-0.715ex}{\kern-0.26em u}\kern-0.13em\I\kern-0.14em t}\xspace} \edef\TCIdiffR{\fpeval{\Runo-\Rdue}}\edef\TCIsumR{\fpeval{\Runo+\Rdue}} \fptest{\TCIdiffR > \A || \A > \TCIsumR}{% \edef#5{0,0}\edef#6{0,0}% Valori assurdi se i cerchi non si intersecano - \PackageWarning{TestFP}{% + \PackageWarning{euclideangeometry}{% ***********************************\MessageBreak Circles do not intersect \MessageBreak Check centers and radii and retry \MessageBreak @@ -1513,65 +1505,27 @@ g\raisebox{-0.715ex}{\kern-0.26em u}\kern-0.13em\I\kern-0.14em t}\xspace} % document |euclideangeometry-man.pdf| describes much clearly with % examples what you can do with the macros described in this package. % In facts, this file just describes the package macros, and it gives -% some ideas on how to extend the ability of |curve2e| to draw geometrical -% diagrams. +% some ideas on how to extend the ability of |curve2e| to draw +% geometrical diagrams. % The users who would like to modify or to add some functionalities % are invited to do so; I will certainly acknowledge their contributions % and even add their names to the list of authors. % -% As long as I can, I enjoy playing with \LaTeX and its wonderful +% As long as I can, I enjoy playing with \LaTeX\ and its wonderful % facilities; but, taking into consideration my age, I would invite % the users to consider the possibility of assuming the maintenance % of this package. %^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%\section*{Aknowledgements} +%\section{Acknowledgements} %^^A%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % I am very grateful to Enrico Gregorio who let me know the several % glitches I made in my first version; besides being a real \TeX wizard, % he is a wise person and suggested me several things that was important -% to change, because they could offer risks of confusion with other packages. +% to change, because they could offer risks of confusion with other +% packages. % %\iffalse %</package> %\fi -% -%\iffalse -%<*readme> -%^^A\fi -% \section{The \texttt{README.txt} file} -% The following is the text that forms the contents of the |README.txt| -% file that accompanies the package. We found it handy to have it in -% the documented source, because in this way certain pieces of -% information don't need to be repeated again and again in different -% files. -% \begin{macrocode} -The package bundle euclideangeometry is composed of the following files - -euclideangeometry.dtx -euclideangeometry.pdf -euclideangeometry-man.tex -euclideangeometry-man.pdf -README.txt - -euclideangeometry.dtx is the documented TeX source file of package -euclideangeometry.sty; you get euclideangeometry.sty, -euclideangeometry.pdf by running pdflatex on euclideangeometry.dtx. - -README.txt, this file, contains general information. - -euclideangeometry-man.tex and euclideangeometry-man.pdf are -the source file and the readable document containing the end -user manual. -In other words euclideangeometry.pdf is oriented towards the -developers and euclideangeometry-man.pdf to the end users. - - -Claudio Beccari - -claudio dot beccari at gmail dot com -% \end{macrocode} -%^^A\iffalse -%</readme> -%\fi % \Finale -%^^A <driver>\endinput +%
\ No newline at end of file diff --git a/macros/latex/contrib/euclideangeometry/euclideangeometry.pdf b/macros/latex/contrib/euclideangeometry/euclideangeometry.pdf Binary files differindex 4b3c5051ab..2dec94adc2 100644 --- a/macros/latex/contrib/euclideangeometry/euclideangeometry.pdf +++ b/macros/latex/contrib/euclideangeometry/euclideangeometry.pdf diff --git a/macros/latex/contrib/siunitx/2.8 b/macros/latex/contrib/siunitx/2.8 deleted file mode 100644 index e69de29bb2..0000000000 --- a/macros/latex/contrib/siunitx/2.8 +++ /dev/null diff --git a/macros/latex/contrib/siunitx/CHANGELOG.md b/macros/latex/contrib/siunitx/CHANGELOG.md index 356f70b030..be1b3b2ac1 100644 --- a/macros/latex/contrib/siunitx/CHANGELOG.md +++ b/macros/latex/contrib/siunitx/CHANGELOG.md @@ -7,16 +7,197 @@ Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to ## [Unreleased] +## [v3.0.0] + +### Added +- `\complexnum` +- `\complexqty` +- `\qty` +- `\qtylist` +- `\qtypower` +- `\qtylist` +- Option `allow-quantity-breaks` +- Option `angle-mode` +- Option `angle-separator` +- Option `angle-symbol-degree` +- Option `angle-symbol-minute` +- Option `angle-symbol-second` +- Option `drop-exponent` +- Option `drop-uncertainty` +- Option `drop-zero-decimal` +- Option `evaluate-expression` +- Option `exponent-mode` +- Option `expression` +- Option `fill-angle-degrees` +- Option `fill-angle-minutes` +- Option `fill-angle-seconds` +- Option `fraction-command` +- Option `list-exponents` +- Option `minimum-decimal-digits` +- Option `minimum-integer-digits` +- Option `overwrite-commands` +- Option `prefix-mode` +- Option `print-implicit-plus` +- Option `print-unity-mantissa` +- Option `print-zero-exponent` +- Option `product-exponents` +- Option `product-mode` +- Option `product-phrase` +- Option `product-symbol` +- Option `qualifier-phrase` +- Option `quantity-product` +- Option `range-exponents` +- Option `round-pad` +- Option `number-angle-product` +- Option `propagate-math-font` +- Option `reset-math-version` +- Option `reset-text-family` +- Option `reset-text-series` +- Option `reset-text-shape` +- Option `separate-uncertainty-units` +- Option `series-version-mapping` +- Option `table-align-text-after` +- Option `table-align-text-before` +- Option `table-alignment-mode` +- Option `table-column-type` +- Option `text-family-to-math` +- Option `text-series-to-math` +- Option `uncertainty-mode` +- Option `unit-font-command` +- Option setting `list-mode = bracket` +- Option setting `mode = match` +- Option setting `number-mode = match` +- Option setting `per-mode = power-positive-first` +- Option setting `qualifier-mode = bracket` +- Option setting `qualifier-mode = phrase` +- Option setting `qualifier-mode = combine` +- Option setting `product-mode = bracket` +- Option setting `range-mode = bracket` +- Option setting `text-mode = match` +- Option setting `unit-mode = match` + +### Changed +- Modular re-write to provide code-level API +- Update unit support to 9th edition of SI Brochure + +### Deprecated +- `\DeclareSIPrePower` +- `\DeclareSIPostPower` +- `\SIUnitSymbolAngstrom` +- `\SIUnitSymbolArcminute` +- `\SIUnitSymbolArcsecond` +- `\SIUnitSymbolCelsius` +- `\SIUnitSymbolDegree` +- `\SIUnitSymbolMicro` +- `\SIUnitSymbolOhm` +- Option `add-decimal-zero` +- Option `allow-number-unit-break` +- Option `add-arc-degree-zero` +- Option `add-arc-minute-zero` +- Option `add-arc-second-zero` +- Option `arc-separator` +- Option `explicit-sign` +- Option `extract-mass-in-kilograms` +- Option `fraction-function` +- Option `omit-uncertainty` +- Option `overwrite-functions` +- Option `multi-part-units` +- Option `number-angle-product` +- Option `number-unit-product` +- Option `prefixes-as-symbols` +- Option `retain-unity-mantissa` +- Option `retain-zero-uncertainty` +- Option `retain-zero-exponent` +- Option `scientific-notation` +- Option `separate-uncertainty` +- Option `table-align-text-post` +- Option `table-align-text-pre` +- Option `table-comparator` +- Option `table-figures-decimal` +- Option `table-figures-exponent` +- Option `table-figures-integer` +- Option `table-figures-uncertainty` +- Option `table-omit-exponent` +- Option `table-parse-only` +- Option `table-sign-exponent` +- Option `table-sign-mantissa` +- Option `table-space-text-post` +- Option `table-space-text-pre` +- Option `text-font-command` +- Option `zero-decimal-to-integer` +- Option setting `list-units = brackets` +- Option setting `per-mode = reciprocal` +- Option setting `per-mode = reciprocal-positive-first` +- Option setting `qualifier-mode = brackets` +- Option setting `qualifier-mode = space` +- Option setting `qualifier-mode = text` +- Option setting `product-mode = brackets` +- Option setting `range-units = brackets` +- Option setting `table-number-alignment = center-decimal-marker` + +### Removed +- Option `abbreviations` +- Option `add-integer-zero` +- Option `binary-units` +- Option `close-bracket` +- Option `detect-all` +- Option `detect-display-math` +- Option `detect-family` +- Option `detect-inline-family` +- Option `detect-inline-weight` +- Option `detect-mode` +- Option `detect-none` +- Option `detect-shape` +- Option `detect-weight` +- Option `input-protect-tokens` +- Option `input-quotient` +- Option `literal-superscript-as-power` +- Option `open-bracket` +- Option `quotient-mode` +- Option `math-angstrom` +- Option `math-arcminute` +- Option `math-arcsecond` +- Option `math-celsius` +- Option `math-degree` +- Option `math-micro` +- Option `math-ohm` +- Option `math-rm` +- Option `math-sf` +- Option `math-tt` +- Option `redefine-symbols` +- Option `number-math-rm` +- Option `number-math-sf` +- Option `number-math-tt` +- Option `number-text-rm` +- Option `number-text-sf` +- Option `number-text-tt` +- Option `table-unit-alignment` +- Option `text-angstrom` +- Option `text-arcminute` +- Option `text-arcsecond` +- Option `text-celsius` +- Option `text-degree` +- Option `text-micro` +- Option `text-ohm` +- Option `text-rm` +- Option `text-sf` +- Option `text-tt` +- Option `unit-math-rm` +- Option `unit-math-sf` +- Option `unit-math-tt` +- Option `unit-text-rm` +- Option `unit-text-sf` +- Option `unit-text-tt` +- Option `version-1-compatibility` + ## [v2.8e] - 2021-04-17 ### Fixed - - Missing setting in emulation of v1 option `repeatunits` ## [v2.8d] - 2021-04-09 ### Changed - - Correct file dates for configuration files ## [v2.8c] - 2021-03-27 @@ -326,7 +507,7 @@ Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to - Option name wrong in v1 table (issue #240) - Use `\textpm` in text mode if `textcomp` package is loaded (issue #249) - Ignore hard spaces in `\num` (issue #256) -- Use `\mathord for tight spacing on 'in line' exponent (issue #257) +- Use `\mathord` for tight spacing on 'in line' exponent (issue #257) ## [v2.5s] - 2013-07-31 @@ -479,7 +660,7 @@ Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to ## [v2.4k] - 2012-03-22 ### Fixed -- Interaction of `^` and `_` with `brenw (issue #191) +- Interaction of `^` and `_` with `breqn` (issue #191) - Adapted `list-pair-separator` for `translator` package (issue #190) - Check for `round-minimum` with large values @@ -1058,7 +1239,9 @@ Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to ### Added - First public testing release (as `si`) -[Unreleased]: https://github.com/josephwright/siunitx/compare/v2.8d...stable +[Unreleased]: https://github.com/josephwright/siunitx/compare/v3.0.0...HEAD +[v3.0.0]: https://github.com/josephwright/siunitx/compare/v2.8e...v3.0.0 +[v2.8e]: https://github.com/josephwright/siunitx/compare/v2.8d...v2.8e [v2.8d]: https://github.com/josephwright/siunitx/compare/v2.8c...v2.8d [v2.8c]: https://github.com/josephwright/siunitx/compare/v2.8b...v2.8c [v2.8b]: https://github.com/josephwright/siunitx/compare/v2.8a...v2.8b diff --git a/macros/latex/contrib/siunitx/README.md b/macros/latex/contrib/siunitx/README.md index 93244686b6..a57e22745b 100644 --- a/macros/latex/contrib/siunitx/README.md +++ b/macros/latex/contrib/siunitx/README.md @@ -1,5 +1,5 @@ siunitx - A comprehensive (SI) units package -============================================== +============================================ Physical quantities have both numbers and units, and each physical quantity should be expressed as the product of a number @@ -15,41 +15,3 @@ of configuration options which make it possible to follow varying typographic conventions with the same input syntax. The package includes automated processing of numbers and units, and the ability to control tabular alignment of numbers. - -Installation ------------- - -The package is supplied in `dtx` format and as a pre-extracted -zip file, `siunitx.tds.zip`. The later is most convenient for -most users: simply unzip this in your local texmf directory . If -you want to unpack the `.dtx` yourself, running `tex -siunitx.dtx` will extract the package whereas `latex -siunitx.dtx` will extract it and also typeset the documentation. - -The package requires LaTeX3 support as provided in the -`l3kernel` and `l3packages` bundles. Both of these are available -on [CTAN](http://www.ctan.org/) as ready-to-install zip files. -Suitable versions are available in MiKTeX 2.9 and TeX Live 2015 -(updating the relevant packages online may be necessary). -LaTeX3, and so `siunitx`, requires the e-TeX extensions: these -are available on all modern TeX systems. - -Typesetting the documentation requires a number of packages in -addition to those needed to use the package. This is mainly -because of the number of demonstration items included in the -text. To compile the documentation without error, you will -need the packages: - - `amsmath` - - `booktabs` - - `cancel` - - `caption` - - `cleveref` - - `colortbl` - - `csquotes` - - `datatool` - - `helvet` - - `mathpazo` - - `multirow` - - `listings` - - `pgfplots` - - `xcolor`
\ No newline at end of file diff --git a/macros/latex/contrib/siunitx/siunitx-abbreviation.dtx b/macros/latex/contrib/siunitx/siunitx-abbreviation.dtx new file mode 100644 index 0000000000..9fc5ddb2a5 --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-abbreviation.dtx @@ -0,0 +1,331 @@ +% \iffalse meta-comment +% +% File: siunitx-abbreviation.dtx Copyright (C) 2018,2019 Joseph Wright +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-abbreviations} -- Abbreviatons^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \begin{function}{\A, \pA, \nA, \uA, \mA, \kA} +% Abbreviations for currents. +% \end{function} +% +% \begin{function}{\fg, \pg, \ng, \ug, \mg, \g, \kg} +% Abbreviations for masses. +% \end{function} +% +% \begin{function}{\K} +% Abbreviations for temperature. +% \end{function} +% +% \begin{function}{\m, \pm, \nm, \um, \mm, \cm, \dm, \km} +% Abbreviations for lengths. +% \end{function} +% +% \begin{function}{\s, \as, \fs, \ps, \ns, \us, \ms} +% Abbreviations for times. +% \end{function} +% +% \begin{function}{\Hz, \mHz, \kHz, \MHz, \GHz, \THz} +% Abbreviations for frequencies. +% \end{function} +% +% \begin{function}{\mol, \fmol, \pmol, \nmol, \umol, \mmol, \kmol} +% Abbreviations for moles. +% \end{function} +% +% \begin{function}{\V, \pV, \nV, \uV, \mV, \kV} +% Abbreviations for potentials. +% \end{function} +% +% \begin{function}{\hl, \l, \ml, \ul, \hL, \L, \mL, \uL} +% Abbreviations for volumes. +% \end{function} +% +% \begin{function}{\W, \uW, \mW, \kW, \MW, \GW} +% Abbreviations for powers. +% \end{function} +% +% \begin{function}{\kJ, \J, \mJ, \uJ, \eV, \meV, \keV, \MeV, \GeV, \TeV} +% Abbreviations for energies. +% \end{function} +% +% \begin{function}{\N, \mN, \kN, \MN} +% Abbreviations for forces. +% \end{function} +% +% \begin{function}{\Pa, \kPa, \MPa, \GPa} +% Abbreviations for pressures. +% \end{function} +% +% \begin{function}{\mohm, \kohm, \Mohm} +% Abbreviations for resistance. +% \end{function} +% +% \begin{function}{\F, \fF, \pF, \nF, \uF} +% Abbreviations for capacitance. +% \end{function} +% +% \begin{function}{\dB} +% Abbreviation for decibel. +% \end{function} +% +% \begin{function}{\kWh} +% Abbreviation for kilowatt--hours. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-abbreviation} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% The abbreviation file contains a number of short (mainly two or +% three letter) versions of the usual long names. They are divided up +% into related groups, mainly to avoid an overly long list in one +% place. +% +% \begin{macro}{\A, \pA, \nA, \uA, \mA, \kA} +% Currents. +% \begin{macrocode} +\siunitx_declare_unit:Nn \A { \ampere } +\siunitx_declare_unit:Nn \pA { \pico \ampere } +\siunitx_declare_unit:Nn \nA { \nano \ampere } +\siunitx_declare_unit:Nn \uA { \micro \ampere } +\siunitx_declare_unit:Nn \mA { \milli \ampere } +\siunitx_declare_unit:Nn \kA { \kilo \ampere } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\Hz, \mHz, \kHz, \MHz, \GHz, \THz} +% Then frequencies. +% \begin{macrocode} +\siunitx_declare_unit:Nn \Hz { \hertz } +\siunitx_declare_unit:Nn \mHz { \milli \hertz } +\siunitx_declare_unit:Nn \kHz { \kilo \hertz } +\siunitx_declare_unit:Nn \MHz { \mega \hertz } +\siunitx_declare_unit:Nn \GHz { \giga \hertz } +\siunitx_declare_unit:Nn \THz { \tera \hertz } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mol, \fmol, \pmol, \nmol, \umol, \mmol, \kmol} +% Amounts of substance (moles). +% \begin{macrocode} +\siunitx_declare_unit:Nn \mol { \mole } +\siunitx_declare_unit:Nn \fmol { \femto \mole } +\siunitx_declare_unit:Nn \pmol { \pico \mole } +\siunitx_declare_unit:Nn \nmol { \nano \mole } +\siunitx_declare_unit:Nn \umol { \micro \mole } +\siunitx_declare_unit:Nn \mmol { \milli \mole } +\siunitx_declare_unit:Nn \kmol { \kilo \mole } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\V, \pV, \nV, \uV, \mV, \kV} +% Potentials. +% \begin{macrocode} +\siunitx_declare_unit:Nn \V { \volt } +\siunitx_declare_unit:Nn \pV { \pico \volt } +\siunitx_declare_unit:Nn \nV { \nano \volt } +\siunitx_declare_unit:Nn \uV { \micro \volt } +\siunitx_declare_unit:Nn \mV { \milli \volt } +\siunitx_declare_unit:Nn \kV { \kilo \volt } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\hl, \l, \ml, \ul, \hL, \L, \mL, \uL} +% Volumes. +% \begin{macrocode} +\siunitx_declare_unit:Nn \hl { \hecto \litre } +\siunitx_declare_unit:Nn \l { \litre } +\siunitx_declare_unit:Nn \ml { \milli \litre } +\siunitx_declare_unit:Nn \ul { \micro \litre } +\siunitx_declare_unit:Nn \hL { \hecto \liter } +\siunitx_declare_unit:Nn \L { \liter } +\siunitx_declare_unit:Nn \mL { \milli \liter } +\siunitx_declare_unit:Nn \uL { \micro \liter } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\fg, \pg, \ng, \ug, \mg, \g, \kg} +% Masses. +% \begin{macrocode} +\siunitx_declare_unit:Nn \fg { \femto \gram } +\siunitx_declare_unit:Nn \pg { \pico \gram } +\siunitx_declare_unit:Nn \ng { \nano \gram } +\siunitx_declare_unit:Nn \ug { \micro \gram } +\siunitx_declare_unit:Nn \mg { \milli \gram } +\siunitx_declare_unit:Nn \g { \gram } +\siunitx_declare_unit:Nn \kg { \kilo \gram } +% \end{macrocode} +% \end{macro} +% \begin{macro} +% { +% \W, \uW, \mW, \kW, \MW, \GW, +% \kJ, \J, \mJ, \uJ, +% \eV, \meV, \keV, \MeV, \GeV, \TeV, +% \kWh +% } +% Energies and powers +% \begin{macrocode} +\siunitx_declare_unit:Nn \W { \watt } +\siunitx_declare_unit:Nn \uW { \micro \watt } +\siunitx_declare_unit:Nn \mW { \milli \watt } +\siunitx_declare_unit:Nn \kW { \kilo \watt } +\siunitx_declare_unit:Nn \MW { \mega \watt } +\siunitx_declare_unit:Nn \GW { \giga \watt } +\siunitx_declare_unit:Nn \J { \joule } +\siunitx_declare_unit:Nn \uJ { \micro \joule } +\siunitx_declare_unit:Nn \mJ { \milli \joule } +\siunitx_declare_unit:Nn \kJ { \kilo \joule } +\siunitx_declare_unit:Nn \eV { \electronvolt } +\siunitx_declare_unit:Nn \meV { \milli \electronvolt } +\siunitx_declare_unit:Nn \keV { \kilo \electronvolt } +\siunitx_declare_unit:Nn \MeV { \mega \electronvolt } +\siunitx_declare_unit:Nn \GeV { \giga \electronvolt } +\siunitx_declare_unit:Nn \TeV { \tera \electronvolt } +\siunitx_declare_unit:Nnn \kWh { \kilo \watt \hour } + { inter-unit-product = } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\m, \pm, \nm, \um, \mm, \cm, \dm, \km} +% Lengths. +% \begin{macrocode} +\siunitx_declare_unit:Nn \m { \metre } +\siunitx_declare_unit:Nn \pm { \pico \metre } +\siunitx_declare_unit:Nn \nm { \nano \metre } +\siunitx_declare_unit:Nn \um { \micro \metre } +\siunitx_declare_unit:Nn \mm { \milli \metre } +\siunitx_declare_unit:Nn \cm { \centi \metre } +\siunitx_declare_unit:Nn \dm { \deci \metre } +\siunitx_declare_unit:Nn \km { \kilo \metre } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\K} +% Temperatures. +% \begin{macrocode} +\siunitx_declare_unit:Nn \K { \kelvin } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\dB} +% \begin{macrocode} +\siunitx_declare_unit:Nn \dB { \deci \bel } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\F, \fF, \pF, \nF, \uF} +% Capacitance. +% \begin{macrocode} +\siunitx_declare_unit:Nn \F { \farad } +\siunitx_declare_unit:Nn \fF { \femto \farad } +\siunitx_declare_unit:Nn \pF { \pico \farad } +\siunitx_declare_unit:Nn \nF { \nano \farad } +\siunitx_declare_unit:Nn \uF { \micro \farad } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\H, \mH, \uH} +% Capacitance. +% \begin{macrocode} +\siunitx_declare_unit:Nn \H { \henry } +\siunitx_declare_unit:Nn \mH { \milli \henry } +\siunitx_declare_unit:Nn \uH { \micro \henry } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\N, \mN, \kN, \MN} +% Forces. +% \begin{macrocode} +\siunitx_declare_unit:Nn \N { \newton } +\siunitx_declare_unit:Nn \mN { \milli \newton } +\siunitx_declare_unit:Nn \kN { \kilo \newton } +\siunitx_declare_unit:Nn \MN { \mega \newton } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\Pa, \kPa, \MPa, \GPa} +% Pressures. +% \begin{macrocode} +\siunitx_declare_unit:Nn \Pa { \pascal } +\siunitx_declare_unit:Nn \kPa { \kilo \pascal } +\siunitx_declare_unit:Nn \MPa { \mega \pascal } +\siunitx_declare_unit:Nn \GPa { \giga \pascal } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\mohm, \kohm, \Mohm} +% Resistances. +% \begin{macrocode} +\siunitx_declare_unit:Nn \mohm { \milli \ohm } +\siunitx_declare_unit:Nn \kohm { \kilo \ohm } +\siunitx_declare_unit:Nn \Mohm { \mega \ohm } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\s, \as, \fs, \ps, \ns, \us, \ms} +% Finally, times. +% \begin{macrocode} +\siunitx_declare_unit:Nn \s { \second } +\siunitx_declare_unit:Nn \as { \atto \second } +\siunitx_declare_unit:Nn \fs { \femto \second } +\siunitx_declare_unit:Nn \ps { \pico \second } +\siunitx_declare_unit:Nn \ns { \nano \second } +\siunitx_declare_unit:Nn \us { \micro \second } +\siunitx_declare_unit:Nn \ms { \milli \second } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex
\ No newline at end of file diff --git a/macros/latex/contrib/siunitx/siunitx-angle.dtx b/macros/latex/contrib/siunitx/siunitx-angle.dtx new file mode 100644 index 0000000000..a3d4608067 --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-angle.dtx @@ -0,0 +1,564 @@ +% \iffalse meta-comment +% +% File: siunitx-angle.dtx Copyright (C) 2016-2019,2021 Joseph Wright +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +\ProvideDocumentCommand\foreign{m}{\textit{#1}} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-angle} -- Formatting angles^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \section{Formatting angles} +% +% \begin{function}{\siunitx_angle:n, \siunitx_angle:nnn} +% \begin{syntax} +% \cs{siunitx_angle:n} \Arg{angle} +% \cs{siunitx_angle:nnn} \Arg{degrees} \Arg{minutes} \Arg{seconds} +% \end{syntax} +% Typeset the \meta{angle} (which may be given as separate \meta{degree}, +% \meta{minute} and \meta{second} components). The \meta{angle} (or components) +% may be given as expressions. The \meta{angle} should be a number as understood +% by \cs{siunitx_format_number:nN}, with no uncertainty, exponent or imaginary +% part. The unit symbols for degrees, minutes and seconds are |\degree|, +% |\arcminute| and |\arcsecond|, respectively +% \end{function} +% +% \subsection{Key--value options} +% +% The options defined by this submodule are available within the \pkg{l3keys} +% |siunitx| tree. +% +% \begin{function}{angle-mode} +% \begin{syntax} +% |angle-mode| = \meta{choice} +% \end{syntax} +% Selects how angles are formatted: a choice from +% the options |arc|, |decimal| and |input|. The option |arc| means that angles +% will always be typeset in arc (degree, minute, second) format, whilst +% |decimal| means that angles are typeset as a single decimal value. The +% |input| setting means that the input format (\foreign{i.e.}~difference +% between \cs{siunitx_angle:n} and \cs{siunitx_angle:nnn}) is maintained. The +% standard setting is |input|. +% \end{function} +% +% \begin{function} +% { +% angle-symbol-degree , +% angle-symbol-minute , +% angle-symbol-second +% } +% \begin{syntax} +% |angle-symbol-degree| = \meta{symbol} +% \end{syntax} +% Sets the symbol used for arc degrees, minutes or seconds, respectively. +% \end{function} +% +% \begin{function}{angle-symbol-over-decimal} +% \begin{syntax} +% |angle-symbol-over-decimal| = |true|\verb"|"|false| +% \end{syntax} +% Determines if the arc separator is printed over the decimal marker, a +% format used in astronomy. The standard setting is |false|. +% \end{function} +% +% \begin{function}{arc-separator} +% \begin{syntax} +% |arc-separator| = \meta{separator} +% \end{syntax} +% Inserted between arc parts (degree, minute and second components). +% The standard setting is |\,|. +% \end{function} +% +% \begin{function}{fill-angle-degrees} +% \begin{syntax} +% |fill-arc-degrees| = |true|\verb"|"|false| +% \end{syntax} +% Determines whether a missing degrees part is zero-filled when printing an +% arc. The standard setting is |false|. +% \end{function} +% +% \begin{function}{fill-angle-minutes} +% \begin{syntax} +% |fill-arc-minutes| = |true|\verb"|"|false| +% \end{syntax} +% Determines whether a missing minutes part is zero-filled when printing an +% arc. The standard setting is |false|. +% \end{function} +% +% \begin{function}{fill-angle-seconds} +% \begin{syntax} +% |fill-arc-seconds| = |true|\verb"|"|false| +% \end{syntax} +% Determines whether a missing seconds part is zero-filled when printing an +% arc. The standard setting is |false|. +% \end{function} +% +% \begin{function}{number-angle-product} +% \begin{syntax} +% |number-angle-product| = \meta{separator} +% \end{syntax} +% Inserted between the value of an angle and the unit (degree, minute or +% second component). The standard setting is |\,|. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-angle} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_angle> +% \end{macrocode} +% +% \begin{variable}{\l_@@_tmp_bool, \l_@@_tmp_dim, \l_@@_tmp_tl} +% Scratch space. +% \begin{macrocode} +\bool_new:N \l_@@_tmp_bool +\dim_new:N \l_@@_tmp_dim +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% { +% \l_@@_symbol_degree_tl , +% \l_@@_symbol_minute_tl , +% \l_@@_symbol_second_tl , +% \l_@@_force_arc_bool , +% \l_@@_force_decimal_bool , +% \l_@@_astronomy_bool , +% \l_@@_separator_tl , +% \l_@@_fill_degrees_bool , +% \l_@@_fill_minutes_bool , +% \l_@@_fill_seconds_bool , +% \l_@@_product_tl +% } +% \begin{macrocode} +\keys_define:nn { siunitx } + { + angle-mode .choice: , + angle-mode / arc .code:n = + { + \bool_set_true:N \l_@@_force_arc_bool + \bool_set_false:N \l_@@_force_decimal_bool + } , + angle-mode / decimal .code:n = + { + \bool_set_false:N \l_@@_force_arc_bool + \bool_set_true:N \l_@@_force_decimal_bool + } , + angle-mode / input .code:n = + { + \bool_set_false:N \l_@@_force_arc_bool + \bool_set_false:N \l_@@_force_decimal_bool + } , + angle-symbol-degree .tl_set:N = + \l_@@_symbol_degree_tl , + angle-symbol-minute .tl_set:N = + \l_@@_symbol_minute_tl , + angle-symbol-second .tl_set:N = + \l_@@_symbol_second_tl , + angle-symbol-over-decimal .bool_set:N = + \l_@@_astronomy_bool , + angle-separator .tl_set:N = + \l_@@_separator_tl , + fill-angle-degrees .bool_set:N = + \l_@@_fill_degrees_bool , + fill-angle-minutes .bool_set:N = + \l_@@_fill_minutes_bool , + fill-angle-seconds .bool_set:N = + \l_@@_fill_seconds_bool , + number-angle-product .tl_set:N = + \l_@@_product_tl + } +\bool_new:N \l_@@_force_arc_bool +\bool_new:N \l_@@_force_decimal_bool +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_angle:n} +% \begin{macro}{\siunitx_angle:nnn} +% \begin{macro}{\@@_arc_convert:n} +% The first step here is to force format conversion if required. Going to +% a decimal is easy, going to arc format is a bit more painful: avoid +% repeating calculations mainly for code readability. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_angle:n #1 + { + \bool_if:NTF \l_@@_force_arc_bool + { \exp_args:Ne \@@_arc_convert:n { \fp_eval:n {#1} } } + { + \siunitx_number_parse:nN {#1} \l_@@_degrees_tl + \tl_set:Nx \l_@@_degrees_tl + { \siunitx_number_output:NN \l_@@_degrees_tl \q_nil } + \@@_arc_print:VVV + \l_@@_degrees_tl + \c_empty_tl + \c_empty_tl + } + } +\cs_new_protected:Npn \siunitx_angle:nnn #1#2#3 + { + \bool_if:NTF \l_@@_force_decimal_bool + { + \exp_args:Ne \siunitx_angle:n + { \fp_eval:n { #1 + (#2) / 60 + (#3) / 3600 } } + } + { \@@_arc_sign:nnn {#1} {#2} {#3} } + } +\cs_new_protected:Npn \@@_arc_convert:n #1 + { + \use:x + { + \siunitx_angle:nnn + { \fp_eval:n { trunc(#1,0) } } + { \fp_eval:n { trunc((#1 - trunc(#1,0)) * 60,0) } } + { + \fp_eval:n + { + ( + (#1 - trunc(#1,0)) * 60 + - trunc((#1 - trunc(#1,0)) * 60,0) + ) + * 60 + } + } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{variable}{\l_@@_degrees_tl, \l_@@_minutes_tl, \l_@@_seconds_tl} +% Space for formatting parsed numbers. +% \begin{macrocode} +\tl_new:N \l_@@_degrees_tl +\tl_new:N \l_@@_minutes_tl +\tl_new:N \l_@@_seconds_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_sign_tl} +% For the \enquote{sign shuffle}. +% \begin{macrocode} +\tl_new:N \l_@@_sign_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_arc_sign:nnn} +% \begin{macro}{\@@_arc_sign:nn} +% \begin{macro}{\@@_extract_sign:nnnnnnnn} +% \begin{macro}[EXP]{\@@_sign:nnnnnnn} +% To get the sign in the right place whilst dealing with zero filling +% means doing some shuffling. That means doing processing of each number +% manually. +% \begin{macrocode} +\cs_new_protected:Npn \@@_arc_sign:nnn #1#2#3 + { + \group_begin: + \keys_set:nn { siunitx } + { + input-close-uncertainty = , + input-exponent-markers = , + input-open-uncertainty = , + input-uncertainty-signs = + } + \tl_clear:N \l_@@_sign_tl + \@@_arc_sign:nn {#1} { degrees } + \@@_arc_sign:nn {#2} { minutes } + \@@_arc_sign:nn {#3} { seconds } + \tl_if_empty:NF \l_@@_sign_tl + { + \clist_map_inline:nn { degrees , minutes , seconds } + { + \tl_if_empty:cF { l_@@_ ##1 _tl } + { + \tl_set:cx { l_@@_ ##1 _tl } + { + { } + { \exp_not:V \l_@@_sign_tl } + \exp_after:wN \exp_after:wN \exp_after:wN + \@@_sign:nnnnnnn + \cs:w l_@@_ ##1 _tl \cs_end: + } + \clist_map_break: + } + } + } + \clist_map_inline:nn { degrees , minutes , seconds } + { + \tl_if_empty:cF { l_@@_ ##1 _tl } + { + \tl_set:cx { l_@@_ ##1 _tl } + { + \exp_args:Nc \siunitx_number_output:NN + { l_@@_ ##1 _tl } \q_nil + } + } + } + \@@_arc_print:VVV + \l_@@_degrees_tl + \l_@@_minutes_tl + \l_@@_seconds_tl + \group_end: + } +\cs_new_protected:Npn \@@_arc_sign:nn #1#2 + { + \tl_if_blank:nTF {#1} + { + \bool_if:cTF { l_@@_fill_ #2 _bool } + { + \tl_set:cn { l_@@_ #2 _tl } + { { } { } { 0 } { } { } { } { 0 } } + } + { \tl_clear:c { l_@@_ #2 _tl } } + } + { + \siunitx_number_parse:nN {#1} \l_@@_tmp_tl + \exp_after:wN \@@_extract_sign:nnnnnnnn \l_@@_tmp_tl {#2} + } + } +\cs_new_protected:Npn \@@_extract_sign:nnnnnnnn #1#2#3#4#5#6#7#8 + { + \tl_if_blank:nTF {#2} + { \tl_set_eq:cN { l_@@_ #8 _tl } \l_@@_tmp_tl } + { + \tl_set:cn { l_@@_ #8 _tl } + { {#1} { } {#3} {#4} {#5} {#6} {#7} } + \tl_set:Nn \l_@@_sign_tl {#2} + \keys_set:nn { siunitx } + { input-comparators = , input-signs = } + } + } +\cs_new:Npn \@@_sign:nnnnnnn #1#2#3#4#5#6#7 + { \exp_not:n { {#3} {#4} {#5} {#6} {#7} } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{variable}{\l_@@_marker_box, \l_@@_unit_box} +% For \enquote{astronomy style} angles. +% \begin{macrocode} +\box_new:N \l_@@_marker_box +\box_new:N \l_@@_unit_box +% \end{macrocode} +% \end{variable} +% +% \begin{macro} +% { +% \@@_arc_print:nnn, \@@_arc_print:VVV, +% \@@_arc_print_auxi:nnn, \@@_arc_print_auxi:nVn +% } +% \begin{macro}{\@@_arc_print_auxii:w} +% \begin{macro}{\@@_arc_print_auxiii:n} +% \begin{macro}{\@@_arc_print_auxiv:NN} +% \begin{macro}{\@@_arc_print_auxv:w} +% \begin{macro}{\@@_arc_print_auxvi:n} +% The final stage of printing an angle is to put together the three parts: +% this works even for decimal angles as they will blank arguments for the +% other two parts The need to handle astronomy-style formatting means that +% the number has to be decomposed into parts. +% \begin{macrocode} +\cs_new_protected:Npn \@@_arc_print:nnn #1#2#3 + { + \@@_arc_print_auxi:nVn {#1} + \l_@@_symbol_degree_tl {#2#3} + \@@_arc_print_auxi:nVn {#2} + \l_@@_symbol_minute_tl {#3} + \@@_arc_print_auxi:nVn {#3} + \l_@@_symbol_second_tl { } + } +\cs_generate_variant:Nn \@@_arc_print:nnn { VVV } +\cs_new_protected:Npn \@@_arc_print_auxi:nnn #1#2#3 + { + \tl_if_blank:nF {#1} + { + \bool_if:NTF \l_@@_astronomy_bool + { \@@_arc_print_auxii:nw {#2} #1 \q_stop } + { + \@@_arc_print_auxv:w #1 \q_stop + \@@_arc_print_auxvi:n {#2} + } + \tl_if_blank:nF {#3} + { + \nobreak + \l_@@_separator_tl + } + } + } +\cs_generate_variant:Nn \@@_arc_print_auxi:nnn { nV } +% \end{macrocode} +% To align the two parts of the astronomy-style marker, we need to allow +% for the |\scriptspace|. +% \begin{macrocode} +\cs_new_protected:Npn \@@_arc_print_auxii:nw + #1#2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil #8 \q_stop + { + \mode_if_math:TF + { \bool_set_true:N \l_@@_tmp_bool } + { \bool_set_false:N \l_@@_tmp_bool } + \siunitx_print_number:n {#2#3#4} + \tl_if_blank:nTF {#6} + { \@@_arc_print_auxvi:n {#1} } + { + \hbox_set:Nn \l_@@_marker_box + { + \@@_arc_print_auxiii:n + { \siunitx_print_number:n {#5} } + } + \hbox_set:Nn \l_@@_unit_box + { + \@@_arc_print_auxiii:n + { + \siunitx_unit_format:nN {#1} \l_@@_tmp_tl + \siunitx_print_unit:V \l_@@_tmp_tl + \skip_horizontal:n { -\scriptspace } + } + } + \dim_compare:nNnTF { \box_wd:N \l_@@_marker_box } > + { \box_wd:N \l_@@_unit_box } + { + \@@_arc_print_auxiv:NN + \l_@@_marker_box + \l_@@_unit_box + } + { + \@@_arc_print_auxiv:NN + \l_@@_unit_box + \l_@@_marker_box + } + \hbox_set_to_wd:Nnn \l_@@_marker_box + \l_@@_tmp_dim + { + \hbox_overlap_right:n + { \box_use_drop:N \l_@@_marker_box } + \hbox_overlap_right:n + { \box_use_drop:N \l_@@_unit_box } + \tex_hfil:D + } + \box_use:N \l_@@_marker_box + \skip_horizontal:N \scriptspace + \siunitx_print_number:n {#6} + } + } +\cs_new_protected:Npn \@@_arc_print_auxiii:n #1 + { + \bool_if:NTF \l_@@_tmp_bool + { \ensuremath } + { \use:n } + {#1} + } +\cs_new_protected:Npn \@@_arc_print_auxiv:NN #1#2 + { + \dim_set:Nn \l_@@_tmp_dim { \box_wd:N #1 } + \hbox_set_to_wd:Nnn #2 + \l_@@_tmp_dim + { + \tex_hss:D + \hbox_unpack_drop:N #2 + \tex_hss:D + } + } +\cs_new_protected:Npn \@@_arc_print_auxv:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_stop + { \siunitx_print_number:n {#1#2#3#4#5} } +\cs_new_protected:Npn \@@_arc_print_auxvi:n #1 + { + \nobreak + \l_@@_product_tl + \siunitx_unit_format:nN {#1} \l_@@_tmp_tl + \siunitx_print_unit:V \l_@@_tmp_tl + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macrocode} +\keys_set:nn { siunitx } + { + angle-mode = input , + angle-symbol-degree = \degree , + angle-symbol-minute = \arcminute , + angle-symbol-over-decimal = false , + angle-symbol-second = \arcsecond , + angle-separator = , + fill-angle-degrees = false , + fill-angle-minutes = false , + fill-angle-seconds = false , + number-angle-product = + } +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/siunitx/siunitx-binary.cfg b/macros/latex/contrib/siunitx/siunitx-binary.cfg new file mode 100644 index 0000000000..be731abdf6 --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-binary.cfg @@ -0,0 +1,45 @@ +%% +%% This is file `siunitx-binary.cfg', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% siunitx-v2.dtx (with options: `config,binary') +%% --------------------------------------------------------------- +%% The siunitx package --- A comprehensive (SI) units package +%% Maintained by Joseph Wright +%% E-mail: joseph.wright@morningstar2.co.uk +%% Released under the LaTeX Project Public License v1.3c or later +%% See http://www.latex-project.org/lppl.txt +%% --------------------------------------------------------------- +%% +\ProvidesExplFile {siunitx-binary.cfg} {2021-04-17} {2.8e} + {siunitx: Binary units} +\DeclareBinaryPrefix \kibi { Ki } { 10 } +\DeclareBinaryPrefix \mebi { Mi } { 20 } +\DeclareBinaryPrefix \gibi { Gi } { 30 } +\DeclareBinaryPrefix \tebi { Ti } { 40 } +\DeclareBinaryPrefix \pebi { Pi } { 50 } +\DeclareBinaryPrefix \exbi { Ei } { 60 } +\DeclareBinaryPrefix \zebi { Zi } { 70 } +\DeclareBinaryPrefix \yobi { Yi } { 80 } +\DeclareSIUnit \bit { bit } +\DeclareSIUnit \byte { B } +%% Copyright (C) 2008-2021 by +%% Joseph Wright <joseph.wright@morningstar2.co.uk> +%% +%% It may be distributed and/or modified under the conditions of +%% the LaTeX Project Public License (LPPL), either version 1.3c of +%% this license or (at your option) any later version. The latest +%% version of this license is in the file: +%% http://www.latex-project.org/lppl.txt +%% +%% This work is "maintained" (as per LPPL maintenance status) by +%% Joseph Wright. +%% +%% This work consists of the file siunitx.dtx +%% and the derived files siunitx.pdf, +%% siunitx.sty and +%% siunitx.ins. +%% +%% End of file `siunitx-binary.cfg'. diff --git a/macros/latex/contrib/siunitx/siunitx-binary.dtx b/macros/latex/contrib/siunitx/siunitx-binary.dtx new file mode 100644 index 0000000000..f3e3afff3e --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-binary.dtx @@ -0,0 +1,112 @@ +% \iffalse meta-comment +% +% File: siunitx-binary.dtx Copyright (C) 2021 Joseph Wright +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-binary} -- Binary units^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% This submodule provides binary units and prefixes. These are not formally +% part of the \acro{SI} but are recommended by \acro{BIPM} as units of +% information. +% +% \begin{function}{\kibi, \mebi, \gibi, \tebi, \pebi, \exbi, \zebi, \yobi} +% Prefixes, all of which are integer powers of $2$: the powers are \emph{not} +% stored or available for conversion. +% \end{function} +% +% \begin{function}{\bit, \byte} +% Units for bits and bytes. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-binary} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \begin{macro}{\kibi, \mebi, \gibi, \tebi, \pebi, \exbi, \zebi, \yobi} +% All very simple. +% \begin{macrocode} +\siunitx_declare_prefix:Nn \kibi { Ki } +\siunitx_declare_prefix:Nn \mebi { Mi } +\siunitx_declare_prefix:Nn \gibi { Gi } +\siunitx_declare_prefix:Nn \tebi { Ti } +\siunitx_declare_prefix:Nn \pebi { Pi } +\siunitx_declare_prefix:Nn \exbi { Ei } +\siunitx_declare_prefix:Nn \zebi { Zi } +\siunitx_declare_prefix:Nn \yobi { Yi } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\bit, \byte} +% \begin{macrocode} +\siunitx_declare_unit:Nn \bit { bit } +\siunitx_declare_unit:Nn \byte { B } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex
\ No newline at end of file diff --git a/macros/latex/contrib/siunitx/siunitx-code.pdf b/macros/latex/contrib/siunitx/siunitx-code.pdf Binary files differnew file mode 100644 index 0000000000..7a34f865a8 --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-code.pdf diff --git a/macros/latex/contrib/siunitx/siunitx-code.tex b/macros/latex/contrib/siunitx/siunitx-code.tex new file mode 100644 index 0000000000..7396975f44 --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-code.tex @@ -0,0 +1,102 @@ +\iffalse meta-comment + +File: siunitx-code.tex Copyright (C) 2016-2021 Joseph Wright + +It may be distributed and/or modified under the conditions of the +LaTeX Project Public License (LPPL), either version 1.3c of this +license or (at your option) any later version. The latest version +of this license is in the file + + https://www.latex-project.org/lppl.txt + +This file is part of the "siunitx bundle" (The Work in LPPL) +and all files in that bundle must be distributed together. + +The released version of this bundle is available from CTAN. + +----------------------------------------------------------------------- + +The development version of the bundle can be found at + + https://github.com/josephwright/siunitx + +for those people who are interested. + +----------------------------------------------------------------------- + +\fi + +\documentclass{l3doc} + +% The next line is needed so that \GetFileInfo will be able to pick up +% version data. +\usepackage{siunitx} + +% Commands for this document +\ExplSyntaxOn +\cs_new_eq:NN \LowerCaseText \tl_lower_case:n +\ExplSyntaxOff +\NewDocumentCommand\acro{m}{\textsc{\LowerCaseText{#1}}} +\NewDocumentCommand\foreign{m}{\textit{#1}} + +\begin{document} + +\GetFileInfo{siunitx.sty} + +\title{% + \pkg{siunitx} -- A comprehensive (SI) units package% + \thanks{This file describes \fileversion, + last revised \filedate.}% +} + +\author{% + Joseph Wright% + \thanks{% + E-mail: + \href{mailto:joseph.wright@morningstar2.co.uk} + {joseph.wright@morningstar2.co.uk}% + }% +} + +\date{Released \filedate} + +\pagenumbering{roman} + +\maketitle +\tableofcontents +\clearpage +\pagenumbering{arabic} + +% Make the separate source files into a single whole, format-wise +\makeatletter +\RenewDocumentCommand\maketitle{}{% + \clearpage + \part{\@title}% +} +\makeatother +\renewcommand*\partname{Part} +\DeclareExpandableDocumentCommand\thanks{m}{} + +\let\DelayPrintIndex\PrintIndex +\RenewDocumentCommand\PrintIndex{}{} + +% Load the source files in order +\DocInput{siunitx.dtx} +\DocInput{siunitx-angle.dtx} +\DocInput{siunitx-compound.dtx} +\DocInput{siunitx-locale.dtx} +\DocInput{siunitx-number.dtx} +\DocInput{siunitx-print.dtx} +\DocInput{siunitx-quantity.dtx} +\DocInput{siunitx-symbol.dtx} +\DocInput{siunitx-table.dtx} +\DocInput{siunitx-unit.dtx} +\DocInput{siunitx-abbreviation.dtx} +\DocInput{siunitx-binary.dtx} +\DocInput{siunitx-command.dtx} +\DocInput{siunitx-emulation.dtx} +\clearpage + +\DelayPrintIndex + +\end{document} diff --git a/macros/latex/contrib/siunitx/siunitx-command.dtx b/macros/latex/contrib/siunitx/siunitx-command.dtx new file mode 100644 index 0000000000..20574f7252 --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-command.dtx @@ -0,0 +1,298 @@ +% \iffalse meta-comment +% +% File: siunitx-command.dtx Copyright (C) 2019,2021 Joseph Wright +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +\ProvideDocumentCommand\foreign{m}{\textit{#1}} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-command} -- Units as document command^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% This submodule provides support for creating free-standing document commands +% for unit macros. +% +% \section{Creating units as document commands} +% +% \begin{function}{\siunitx_command_create:} +% \begin{syntax} +% \cs{siunitx_command_create:} +% \end{syntax} +% Maps over the list of know unit commands and creates the appropriate +% document command to support them, as controlled by the options below. +% \end{function} +% +% \subsection{Key--value options} +% +% The options defined by this submodule are available within the \pkg{l3keys} +% |siunitx| tree. +% +% These options are all preamble-only. +% +% \begin{function}{free-standing-units} +% \begin{syntax} +% |free-standing-units| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine whether free standing document commands are created +% for symbolic units. This will include not only units themselves but also +% prefixes, \foreign{etc.} The standard setting is |false|. +% \end{function} +% +% \begin{function}{overwrite-commands} +% \begin{syntax} +% |overwrite-commands| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine whether when creating free standing document commands, +% any existing document commands are overwritten. The standard setting is +% |false|. +% \end{function} +% +% \begin{function}{space-before-unit} +% \begin{syntax} +% |space-before-unit| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine whether a space is inserted before free standing +% document commands. The standard setting is |false|. +% \end{function} +% +% \begin{function}{unit-optional-argument} +% \begin{syntax} +% |unit-optional-argument| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine whether free standing document commands take an +% optional argument (a number). The standard setting is |false|. +% \end{function} +% +% \begin{function}{use-xspace} +% \begin{syntax} +% |use-xspace| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine whether free standing document commands use the +% \pkg{xparse} package to insert space after the command names. The standard +% setting is |false|. When set |true|, the \pkg{xparse} package will be +% loaded at the start of the document if not already available. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-command} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_command> +% \end{macrocode} +% +% \begin{macro}{\l_@@_tmp_tl} +% \begin{macrocode} +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{macro} +% +% \subsection{Options} +% +% \begin{variable} +% { +% \l_@@_create_bool , +% \l_@@_overwrite_bool , +% \l_@@_prespace_bool , +% \l_@@_optarg_bool , +% \l_@@_xspace_bool +% } +% \begin{macrocode} +\keys_define:nn { siunitx } + { + free-standing-units .bool_set:N = + \l_@@_create_bool , + overwrite-commands .bool_set:N = + \l_@@_overwrite_bool , + space-before-unit .bool_set:N = + \l_@@_prespace_bool , + unit-optional-argument .bool_set:N = + \l_@@_optarg_bool , + use-xspace .bool_set:N = + \l_@@_xspace_bool + } +% \end{macrocode} +% \end{variable} +% +% These preamble-only options are all disabled at the start of the document. +% \begin{macrocode} +\AtBeginDocument + { + \clist_map_inline:nn + { + free-standing-units , + overwrite-commands , + space-before-unit , + unit-optional-argument , + use-xspace + } + { + \keys_define:nn { siunitx } + { + #1 .code:n = + { \msg_warning:nnn { siunitx } { option-preamble-only } {#1} } + } + } + } +\msg_new:nnn { siunitx } { option-preamble-only } + { Option~'#1'~only~available~in~the~preamble. } +% \end{macrocode} +% +% \subsection{Creation of unit document commands} +% +% \begin{macro}{\siunitx_command_create:, \@@_create:} +% \begin{macro}{\@@_create:N} +% Creating document commands is all done by a single function which is +% set up using expansion: that way the tests are only run once. Other than +% that, this is all just a question of picking up all the various routes. +% Where the \pkg{soulpos} package is loaded \emph{after} \pkg{siunitx}, the +% commands \cs{hl} and \cs{ul} will be created only after the hook is used. +% The \pkg{soul} package creates those using \tn{newcommand}, so we have to +% avoid an issue. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_command_create: + { + \bool_if:NT \l_@@_create_bool + { + \@@_create: + \@ifpackageloaded { soulpos } + { + \@ifpackageloaded { soul } + { } + { + \cs_undefine:N \hl + \cs_undefine:N \ul + } + } + { } + } +% \end{macrocode} +% At the beginning of table cells and inside \texttt{x}-type expansion, +% all symbolic units need to have \emph{some} definition. +% \begin{macrocode} + \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq + { + \cs_if_free:NT ##1 + { \cs_set_protected:Npn ##1 { \ERROR } } + } + } +\AtBeginDocument { \siunitx_command_create: } +\cs_new_protected:Npn \@@_create: + { + \bool_if:NT \l_@@_xspace_bool + { \RequirePackage { xspace } } + \bool_if:NT \l_@@_overwrite_bool + { + \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq + { \cs_undefine:N ##1 } + } + \cs_set_protected:Npx \@@_create:N ##1 + { + \ProvideDocumentCommand ##1 { \bool_if:NT \l_@@_optarg_bool { o } } + { + \mode_leave_vertical: + \group_begin: + \bool_if:NTF \l_@@_optarg_bool + { \exp_not:N \IfNoValueTF {####1} } + { \use_i:nn } + { + \siunitx_unit_options_apply:n {##1} + \bool_if:NT \l_@@_prespace_bool { \exp_not:N \ } + \siunitx_unit_format:nN {##1} + \exp_not:N \l_@@_tmp_tl + \siunitx_print_unit:V + \exp_not:N \l_@@_tmp_tl + } + { \siunitx_quantity:nn {####1} {##1} } + \group_end: + \bool_if:NT \l_@@_xspace_bool { \exp_not:N \xspace } + } + } + \seq_map_function:NN \l_siunitx_unit_seq \@@_create:N + } +\cs_new_protected:Npn \@@_create:N #1 { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Standard settings for module options} +% +% Some of these follow naturally from the point of definition +% (\foreign{e.g.}~boolean variables are always |false| to begin with), +% but for clarity everything is set here. +% \begin{macrocode} +\keys_set:nn { siunitx } + { + free-standing-units = false , + overwrite-commands = false , + space-before-unit = false , + unit-optional-argument = false , + use-xspace = false + } +% \end{macrocode} +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex
\ No newline at end of file diff --git a/macros/latex/contrib/siunitx/siunitx-complex.dtx b/macros/latex/contrib/siunitx/siunitx-complex.dtx new file mode 100644 index 0000000000..87c1b684ef --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-complex.dtx @@ -0,0 +1,849 @@ +% \iffalse meta-comment +% +% File: siunitx-complex.dtx Copyright (C) 2021 Joseph Wright +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +\ProvideDocumentCommand\foreign{m}{\textit{#1}} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-complex} -- Complex numbers^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% This submodule is concerned with formatting complex numbers. It augments the +% standard functions \cs{siunitx_number_format:nN} and \cs{siunitx_quantity:nn} +% by allowing parsing of numbers with a complex part. There are no additional +% assumptions concerning \LaTeXe{} commands in the submodule beyond those in the +% core number and unit submodules. +% +% \begin{function}{\siunitx_complex_number:n} +% \begin{syntax} +% \cs{siunitx_complex_number:n} \Arg{number} +% \end{syntax} +% Parses the \meta{number} and splits into real and complex parts, which are +% then formatted as described for \cs{siunitx_number_format:nN}. The results +% are combined and printed using the standard functions in the module. +% \end{function} +% +% \begin{function}{\siunitx_complex_quantity:nn} +% \begin{syntax} +% \cs{siunitx_complex_quantity:n} \Arg{number} \Arg{units} +% \end{syntax} +% Parses the \meta{number} and splits into real and complex parts, which are +% then formatted as described for \cs{siunitx_quantity:nn}. The results +% are combined and printed using the standard functions in the module. +% \end{function} +% +% \begin{function}{complex-root-position} +% \begin{syntax} +% |complex-root-position| = |after-number|\verb"|"|before-number| +% \end{syntax} +% Choice which determines where the complex root symbol is printed relative +% to the numbers. The standard setting is |after-number|. +% \end{function} +% +% \begin{function}{input-complex-root} +% \begin{syntax} +% |input-complex-root| = \meta{tokens} +% \end{syntax} +% The token(s) considered as complexes roots for number parsing. +% The standard setting is |ij|. +% \end{function} +% +% \begin{function}{output-complex-root} +% \begin{syntax} +% |output-complex-root| = \meta{tokens} +% \end{syntax} +% The token(s) used to show the complex root in output. The standard setting +% is |\mathrm{i}|. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \section{\pkg{siunitx-complex} implementation} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_complex> +% \end{macrocode} +% +% \subsection{General setup} +% +% \begin{variable}{\l_@@_tmp_tl} +% \begin{macrocode} +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_input_tl} +% The numerical input exactly as given by the user. +% \begin{macrocode} +\tl_new:N \l_@@_input_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_comparator_tl} +% A comparator, if found, is held here. +% \begin{macrocode} +\tl_new:N \l_@@_comparator_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_exp_tl} +% The exponent part of a parsed number. +% \begin{macrocode} +\tl_new:N \l_@@_exp_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_real_tl, \l_@@_img_tl} +% The real and imaginary parts of the number, respectively. +% \begin{macrocode} +\tl_new:N \l_@@_real_tl +\tl_new:N \l_@@_img_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_join_tl, \l_@@_sign_tl} +% Staging posts for a joining and leading sign, respectively. +% \begin{macrocode} +\tl_new:N \l_@@_join_tl +\tl_new:N \l_@@_sign_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_input_root_tl, \l_@@_output_root_tl} +% \begin{macrocode} +\bool_new:N \l_@@_root_after_bool +\keys_define:nn { siunitx } + { + complex-root-position .choice: , + complex-root-position / after-number .code:n = + { \bool_set_true:N \l_@@_root_after_bool } , + complex-root-position / before-number .code:n = + { \bool_set_false:N \l_@@_root_after_bool } , + input-complex-root .tl_set:N = + \l_@@_input_root_tl , + output-complex-root .tl_set:N = + \l_@@_output_root_tl + } +% \end{macrocode} +% \end{variable} +% +% \subsection{Parsing} +% +% \begin{macro}{\@@_parse:nNN} +% \begin{macro}{\@@_parse_end:} +% \begin{macro}{\@@_parse_clear:} +% Parsing for complex numbers needs some of the same approaches as the +% general parser. However, as the aim here is to do only enough to split +% the real and imaginary parts before handing off the the usual code, +% it's not a full repeat. Instead, we shortcut where we can. The |clear| +% function here is not only there to make this function shorter: it +% also allows a single way to zap any stored data if a parse error occurs. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse:nNN #1#2#3 + { + \group_begin: + \@@_parse_clear: + \protected@edef \l_@@_arg_tl {#1} + \tl_set_eq:NN \l_@@_input_tl \l_@@_arg_tl + \siunitx_number_normalize_symbols:N \l_@@_arg_tl + \tl_if_empty:NF \l_@@_arg_tl + { \@@_parse_comparator: } + \@@_parse_check: + \cs_set_protected:Npx \@@_parse_end: + { + \tl_set:Nn \exp_not:N #2 { \exp_not:V \l_@@_real_tl } + \tl_set:Nn \exp_not:N #3 { \exp_not:V \l_@@_img_tl } + } + \exp_after:wN \group_end: + \@@_parse_end: + } +\cs_new_protected:Npn \@@_parse_end: { } +\cs_new_protected:Npn \@@_parse_clear: + { + \tl_clear:N \l_@@_real_tl + \tl_clear:N \l_@@_img_tl + \tl_clear:N \l_@@_exp_tl + \tl_clear:N \l_@@_sign_tl + \tl_clear:N \l_@@_join_tl + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_check:, \@@_parse_finalise:} +% \begin{macro}{\@@_parse_finalise:N} +% Now we tidy up and do the main work: passing to the standard formatter for +% final parsing. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_check: + { + \bool_lazy_all:nTF + { + { \tl_if_empty_p:N \l_@@_real_tl } + { \tl_if_empty_p:N \l_@@_img_tl } + { \tl_if_empty_p:N \l_@@_exp_tl } + } + { + \msg_error:nnx { siunitx } { invalid-complex-number } + { \exp_not:V \l_@@_input_tl } + } + { \@@_parse_finalise: } + } +\cs_new_protected:Npn \@@_parse_finalise: + { + \tl_if_empty:NTF \l_@@_img_tl + { \@@_parse_finalise:N \l_@@_real_tl } + { + \tl_if_empty:NTF \l_@@_real_tl + { \@@_parse_finalise:N \l_@@_img_tl } + { + \@@_parse_finalise:N \l_@@_real_tl + \tl_set_eq:NN \l_@@_sign_tl \l_@@_join_tl + \@@_parse_finalise:N \l_@@_img_tl + } + } + } +\cs_new_protected:Npn \@@_parse_finalise:N #1 + { + \tl_set:Nx #1 + { + \exp_not:V \l_@@_comparator_tl + \exp_not:V \l_@@_sign_tl + \exp_not:V #1 + \exp_not:V \l_@@_exp_tl + } + \tl_clear:N \l_@@_comparator_tl + \tl_clear:N \l_@@_sign_tl + \siunitx_number_parse:VN #1 #1 + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_comparator:} +% \begin{macro}{\@@_parse_comparator_aux:Nw} +% The first step is to extract any comparator: this is the same as +% for a full number parse. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_comparator: + { + \exp_after:wN \@@_parse_comparator_aux:Nw + \l_@@_arg_tl \q_stop + } +\cs_new_protected:Npn \@@_parse_comparator_aux:Nw #1#2 \q_stop + { + \tl_if_in:NnTF \l_siunitx_number_input_comparator_tl {#1} + { + \tl_set:Nn \l_@@_comparator_tl {#1} + \tl_set:Nn \l_@@_arg_tl {#2} + } + { \tl_clear:N \l_@@_comparator_tl } + \tl_if_empty:NF \l_@@_arg_tl + { \@@_parse_sign: } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_exponent:} +% \begin{macro}{\@@_parse_exponent_auxi:w} +% \begin{macro}{\@@_parse_exponent_auxii:nn} +% An exponent part of a number has to come at the end and can only occur +% once. Thus it is relatively easy to parse. The code here is a simplified +% version of that in \pkg{siunitx-number}: we only need to find \emph{some} +% exponent, not check on the detail. Notice that we need to retain the +% exponent marker here: that is done using the short-lived temporary +% variable. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_exponent: + { + \tl_if_empty:NTF \l_siunitx_number_input_exponent_tl + { \@@_parse_root: } + { + \tl_set:Nx \l_@@_tmp_tl + { \tl_head:V \l_siunitx_number_input_exponent_tl } + \tl_map_inline:Nn \l_siunitx_number_input_exponent_tl + { + \tl_replace_all:NnV \l_@@_arg_tl + {##1} \l_@@_tmp_tl + } + \use:x + { + \cs_set_protected:Npn + \exp_not:N \@@_parse_exponent_auxi:w + ####1 \exp_not:V \l_@@_tmp_tl + ####2 \exp_not:V \l_@@_tmp_tl + ####3 \exp_not:N \q_stop + } + { \@@_parse_exponent_auxii:nn {##1} {##2} } + \use:x + { + \@@_parse_exponent_auxi:w + \exp_not:V \l_@@_arg_tl + \exp_not:V \l_@@_tmp_tl \exp_not:N \q_nil + \exp_not:V \l_@@_tmp_tl \exp_not:N \q_stop + } + } + } +\cs_new_protected:Npn \@@_parse_exponent_auxi:w { } +\cs_new_protected:Npn \@@_parse_exponent_auxii:nn #1#2 + { + \quark_if_nil:nF {#2} + { + \tl_set:Nn \l_@@_arg_tl {#1} + \tl_set:Nx \l_@@_exp_tl + { \exp_not:V \l_@@_tmp_tl \exp_not:n {#2} } + } + \@@_parse_root: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_root:} +% \begin{macro}{\@@_parse_root_auxi:w} +% \begin{macro}{\@@_parse_root_auxii:nn} +% Splitting at the complex root is much like splitting the exponent. +% After dealing with the case where there is no complex root allowed, +% use the first possible symbol to do the work. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_root: + { + \tl_if_empty:NTF \l_@@_input_root_tl + { \tl_set_eq:NN \l_@@_real_tl \l_@@_arg_tl } + { + \tl_set:Nx \l_@@_tmp_tl + { \tl_head:V \l_@@_input_root_tl } + \tl_map_inline:Nn \l_@@_input_root_tl + { + \tl_replace_all:NnV \l_@@_arg_tl + {##1} \l_@@_tmp_tl + } + \use:x + { + \cs_set_protected:Npn + \exp_not:N \@@_parse_root_auxi:w + ####1 \exp_not:V \l_@@_tmp_tl + ####2 \exp_not:V \l_@@_tmp_tl + ####3 \exp_not:N \q_stop + } + { \@@_parse_root_auxii:nn {##1} {##2} } + \use:x + { + \@@_parse_root_auxi:w + \exp_not:V \l_@@_arg_tl + \exp_not:V \l_@@_tmp_tl \exp_not:N \q_nil + \exp_not:V \l_@@_tmp_tl \exp_not:N \q_stop + } + } + } +\cs_new_protected:Npn \@@_parse_root_auxi:w { } +% \end{macrocode} +% This is where the business end lies. We have four possibilities: +% \begin{itemize} +% \item There was no complex root at all: |#2| will be |\q_nil| +% \item All of the number is in the complex part with a leading +% root: |#1| will be empty. This includes the case where +% the input was \emph{just} a root symbol (plus possibly sign, +% exponent): we need to cover that. +% \item All of the number was before the complex root: |#2| will +% be empty and we need to check |#1| fully to split out the two +% parts +% \item The input has a a real part with the complex part starting +% with the root symbol: just the last token needs to be separated. +% \end{itemize} +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_root_auxii:nn #1#2 + { + \quark_if_nil:nTF {#2} + { \tl_set:Nn \l_@@_real_tl {#1} } + { + \tl_set:Nn \l_@@_img_tl {#2} + \tl_if_blank:nTF {#1} + { + \tl_if_blank:nT {#2} + { \tl_set:Nn \l_@@_img_tl { 1 } } + } + { + \tl_if_blank:nTF {#2} + { \@@_parse_split:n {#1} } + { \@@_parse_sign_check:n {#1} } + } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_sign:} +% \begin{macro}{\@@_parse_sign_aux:Nw} +% The first token of a number after a comparator could be a sign. A quick +% check is made and if found stored. There is no need to worry about the +% nature of the sign: we keep them regardless. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_sign: + { + \exp_after:wN \@@_parse_sign_aux:Nw + \l_@@_arg_tl \q_stop + } +\cs_new_protected:Npn \@@_parse_sign_aux:Nw #1#2 \q_stop + { + \tl_if_in:NnT \l_siunitx_number_input_sign_tl {#1} + { + \tl_set:Nn \l_@@_sign_tl {#1} + \tl_set:Nn \l_@@_arg_tl {#2} + } + \tl_if_empty:NF \l_@@_arg_tl + { \@@_parse_exponent: } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_sign_check:n} +% \begin{macro}{\@@_parse_sign_check:nN} +% \begin{macro}{\@@_parse_sign_check:nNw} +% Here, we want to check that the last token in the input is a sign. +% There cannot be anything after the sign, and there has to be at one +% token before the sign: we can therefore signal a parsing error if we +% need to. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_sign_check:n #1 + { + \@@_parse_sign_check:nN { } #1 \q_recursion_tail \q_recursion_stop + } +\cs_new_protected:Npn \@@_parse_sign_check:nN #1#2 + { + \quark_if_recursion_tail_stop_do:Nn #2 + { \@@_parse_clear: } + \tl_if_in:NnTF \l_siunitx_number_input_sign_tl {#2} + { \@@_parse_sign_check:nNw {#1} #2 } + { \@@_parse_sign_check:nN {#1#2} } + } +\cs_new_protected:Npn \@@_parse_sign_check:nNw + #1#2 #3 \q_recursion_tail \q_recursion_stop + { + \tl_if_blank:nTF {#3} + { + \tl_if_blank:nTF {#1} + { \@@_parse_clear: } + { + \tl_set:Nn \l_@@_real_tl {#1} + \tl_set:Nn \l_@@_join_tl {#2} + } + } + { \@@_parse_clear: } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_split:n} +% \begin{macro}{\@@_parse_split:nN} +% \begin{macro}{\@@_parse_split:w} +% Checking for a sign inside the leading part of the number is a simple loop. +% There is the possibility that there is no number in the imaginary part +% needs to be allowed for. Notice that we do a check that there is some +% real part: this covers for example an original input |++1i|, which +% otherwise would not be trapped. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_split:n #1 + { + \@@_parse_split:nN { } #1 \q_recursion_tail \q_recursion_stop + } +\cs_new_protected:Npn \@@_parse_split:nN #1#2 + { + \quark_if_recursion_tail_stop_do:Nn #2 + { \tl_set:Nn \l_@@_img_tl {#1} } + \tl_if_in:NnTF \l_siunitx_number_input_sign_tl {#2} + { + \tl_set:Nn \l_@@_real_tl {#1} + \tl_set:Nn \l_@@_join_tl {#2} + \@@_parse_split:w + } + { \@@_parse_split:nN {#1#2} } + } +\cs_new_protected:Npn \@@_parse_split:w #1 \q_recursion_tail \q_recursion_stop + { + \tl_set:Nx \l_@@_img_tl + { + \tl_if_blank:nTF {#1} + { 1 } + { \exp_not:n {#1} } + } + \tl_if_empty:NT \l_@@_real_tl + { \@@_parse_clear: } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \section{Formatting} +% +% \begin{variable}{\l_@@_bracket_close_tl, \l_@@_bracket_open_tl} +% Purely internal for the present. +% \begin{macrocode} +\tl_new:N \l_@@_bracket_close_tl +\tl_new:N \l_@@_bracket_open_tl +\tl_set:Nn \l_@@_bracket_open_tl { ( } +\tl_set:Nn \l_@@_bracket_close_tl { ) } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_unit_tl} +% \begin{macrocode} +\tl_new:N \l_@@_unit_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_complex_number:n} +% \begin{macro}{\siunitx_complex_quantity:nn} +% The work here is pretty trivial. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_complex_number:n #1 + { + \group_begin: + \bool_if:NTF \l_siunitx_number_parse_bool + { + \@@_parse:nNN {#1} \l_@@_real_tl \l_@@_img_tl + \@@_format:n { } + } + { + \siunitx_number_format:nN {#1} \l_@@_tmp_tl + \siunitx_print_number:V \l_@@_tmp_tl + } + \group_end: + } +\cs_new_protected:Npn \siunitx_complex_quantity:nn #1#2 + { + \group_begin: + \bool_if:NTF \l_siunitx_number_parse_bool + { + \@@_parse:nNN {#1} \l_@@_real_tl \l_@@_img_tl + \@@_format:n {#2} + } + { \siunitx_quantity:nn {#1} {#2} } + \group_end: + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_format:n} +% \begin{macro}{\@@_format_auxi:n} +% \begin{macro}{\@@_format_unary:nnnnnnn} +% \begin{macro}{\@@_format_auxii:n} +% \begin{macro}{\@@_drop_exponent:nnnnnnn} +% \begin{macro}{\@@_format_sign:nnnnnnn} +% \begin{macro}{\@@_extract_exponent:nw} +% \begin{macro}{\@@_extract_exponent_aux:w} +% \begin{macro}[EXP]{\@@_format_bracket:n} +% We start here checking that there is something to do. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format:n #1 + { + \bool_lazy_and:nnF + { \tl_if_empty_p:N \l_@@_real_tl } + { \tl_if_empty_p:N \l_@@_img_tl } + { \@@_format_auxi:n {#1} } + } +% \end{macrocode} +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_auxi:n #1 + { + \tl_clear:N \l_@@_tmp_tl + \tl_if_empty:NTF \l_@@_real_tl + { + \@@_format_units:n {#1} + \exp_after:wN \@@_format_unary:nnnnnnn \l_@@_img_tl + \tl_set:Nx \l_@@_tmp_tl + { + \siunitx_number_output:N \l_@@_img_tl + \exp_not:V \l_@@_output_root_tl + } + } + { + \tl_if_empty:NTF \l_@@_img_tl + { + \siunitx_number_process:NN \l_@@_real_tl \l_@@_real_tl + \tl_set:Nx \l_@@_tmp_tl + { \siunitx_number_output:N \l_@@_real_tl } + } + { \@@_format_auxii:n {#1} } + } + \tl_if_blank:nTF {#1} + { \siunitx_print_number:V \l_@@_tmp_tl } + { \siunitx_quantity_print:VV \l_@@_tmp_tl \l_@@_unit_tl } + } +% \end{macrocode} +% An imaginary part that is exactly $1$ is omitted, with only the complex +% root printed. That means checking and removing a lone $1$ here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_unary:nnnnnnn #1#2#3#4#5#6#7 + { + \tl_set:Nx \l_@@_img_tl + { + \exp_not:n { {#1} {#2} } + \tl_if_blank:nTF {#4} + { + \str_if_eq:nnTF {#3} { 1 } + { { } { } } + { \exp_not:n { {#3} {#4} } } + } + { \exp_not:n { {#3} {#4} } } + \exp_not:n { {#5} {#6} {#7} } + } + } +% \end{macrocode} +% If we get to this stage we have both parts to a complex number. We +% need to process both and do some massaging, then it's just a question +% of reassembly with the right parts in the right places. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_auxii:n #1 + { + \@@_format_units:n {#1} + \exp_after:wN \@@_drop_exponent:nnnnnnn \l_@@_real_tl + \exp_after:wN \@@_format_sign:nnnnnnn \l_@@_img_tl + \tl_set:Nx \l_@@_tmp_tl + { \siunitx_number_output:NN \l_@@_img_tl \q_nil } + \exp_after:wN \@@_extract_exponent:w \l_@@_tmp_tl \q_stop + \tl_set:Nx \l_@@_tmp_tl + { + \bool_lazy_and:nnTF + { \l_siunitx_number_bracket_ambiguous_bool } + { ! \tl_if_empty_p:N \l_@@_exp_tl } + { \@@_format_bracket:n } + { \use:n } + { + \siunitx_number_output:N \l_@@_real_tl + \exp_not:V \l_@@_sign_tl + \bool_if:NF \l_@@_root_after_bool + { \exp_not:V \l_@@_output_root_tl } + \exp_not:V \l_@@_tmp_tl + \bool_if:NT \l_@@_root_after_bool + { \exp_not:V \l_@@_output_root_tl } + } + \exp_not:V \l_@@_exp_tl + } + } +% \end{macrocode} +% No exponent for the real part. +% \begin{macrocode} +\cs_new_protected:Npn \@@_drop_exponent:nnnnnnn #1#2#3#4#5#6#7 + { \tl_set:Nn \l_@@_real_tl { {#1} {#2} {#3} {#4} {#5} { } { 0 } } } +% \end{macrocode} +% Ensure the imaginary part has a sign, and also deal with the case +% where there is no mantissa to print (as it is $1$). +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_sign:nnnnnnn #1#2#3#4#5#6#7 + { + \tl_set:Nx \l_@@_img_tl + { + { } + { \tl_if_blank:nTF {#2} { + } { \exp_not:n {#2} } } + \tl_if_blank:nTF {#4} + { + \str_if_eq:nnTF {#3} { 1 } + { { } { } } + { \exp_not:n { {#3} {#4} } } + } + { \exp_not:n { {#3} {#4} } } + \exp_not:n { {#5} {#6} {#7} } + } + } +% \end{macrocode} +% Pull out the formatted exponent: we also need the sign. +% \begin{macrocode} +\cs_new_protected:Npn \@@_extract_exponent:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil #8 + \q_nil #9 \q_stop + { + \tl_set:Nn \l_@@_sign_tl {#1#2} + \@@_extract_exponent_aux:nw {#3#4#5#6#7#8} #9 \q_stop + } +\cs_new:Npn \@@_extract_exponent_aux:nw + #1#2 \q_nil #3 \q_nil #4 \q_stop + { + \tl_set:Nn \l_@@_tmp_tl {#1#2} + \tl_set:Nn \l_@@_exp_tl {#3#4} + } +\cs_new_protected:Npn \@@_format_bracket:n #1 + { + \exp_not:V \l_@@_bracket_open_tl + #1 + \exp_not:V \l_@@_bracket_close_tl + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_format_units:n} +% \begin{macro} +% { +% \@@_format_combine-exponent:n , +% \@@_format_extract-exponent:n , +% \@@_format_input:n +% } +% \begin{macro}{\@@_format_extract-exponent:N} +% \begin{macro}[EXP]{\@@_extract_exp:nnnnnnn} +% Formatting units needs to know the settings from the main module, and +% the flow is then much the same as in \pkg{siunitx-compound}. We only +% have to watch the fact there are two numbers to format. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_units:n #1 + { + \tl_if_blank:nTF {#1} + { + \siunitx_number_process:NN \l_@@_real_tl \l_@@_real_tl + \siunitx_number_process:NN \l_@@_img_tl \l_@@_img_tl + } + { + \use:c { @@_format_ \l_siunitx_quantity_prefix_mode_tl :n } {#1} + } + } +\cs_new_protected:cpn { @@_format_combine-exponent:n } #1 + { + \tl_if_empty:NF \l_@@_real_tl + { \siunitx_number_process:NN \l_@@_real_tl \l_@@_real_tl } + \siunitx_number_process:NN \l_@@_img_tl \l_@@_img_tl + \fp_set:Nn \l_@@_tmp_fp + { \exp_after:wN \@@_extract_exp:nnnnnnn \l_@@_img_tl } + \siunitx_unit_format_combine_exponent:nnN {#1} + \l_@@_tmp_fp \l_@@_unit_tl + } +\cs_new_protected:cpx { @@_format_extract-exponent:n } #1 + { + \exp_not:N \siunitx_unit_format_extract_prefixes:nNN {#1} + \exp_not:N \l_@@_unit_tl \exp_not:N \l_@@_tmp_fp + \exp_not:c { @@_format_extract-exponent:N } + \exp_not:N \l_@@_img_tl + \exp_not:N \tl_if_empty:NF \exp_not:N \l_@@_real_tl + { + \exp_not:c { @@_format_extract-exponent:N } + \exp_not:N \l_@@_real_tl + } + } +\cs_new_protected:cpn { @@_format_extract-exponent:N } #1 + { + \tl_set:Nx #1 + { \siunitx_number_adjust_exponent:Nn #1 \l_@@_tmp_fp } + \siunitx_number_process:NN #1 #1 + } +\cs_new_protected:Npn \@@_format_input:n #1 + { + \siunitx_number_process:NN \l_@@_real_tl \l_@@_real_tl + \siunitx_number_process:NN \l_@@_img_tl \l_@@_img_tl + \siunitx_unit_format:nN {#1} \l_@@_unit_tl + } +\cs_new:Npn \@@_extract_exp:nnnnnnn #1#2#3#4#5#6#7 { #6#7 } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Messages} +% +% \begin{macrocode} +\msg_new:nnnn { siunitx } { invalid-complex-number } + { Invalid~complex-number~'#1'. } + { + The~input~'#1'~could~not~be~parsed~as~a~complex|number~following~the~ + format~defined~in~module~documentation. + } +% \end{macrocode} +% +% \subsection{Standard settings for module options} +% +% Some of these follow naturally from the point of definition +% (\foreign{e.g.}~boolean variables are always |false| to begin with), +% but for clarity everything is set here. +% \begin{macrocode} +\keys_set:nn { siunitx } + { + complex-root-position = after-number , + input-complex-root = ij , + output-complex-root = \mathrm { i } + } +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/siunitx/siunitx-compound.dtx b/macros/latex/contrib/siunitx/siunitx-compound.dtx new file mode 100644 index 0000000000..83da873e6c --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-compound.dtx @@ -0,0 +1,1081 @@ +% \iffalse meta-comment +% +% File: siunitx-compound.dtx Copyright (C) 2018-2021 Joseph Wright +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +\ProvideDocumentCommand\foreign{m}{\textit{#1}} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-compound} -- Compound numbers and quantities^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \begin{function}{\siunitx_compound_number:n} +% \begin{syntax} +% \cs{siunitx_compound_number:n} \Arg{entries} +% \end{syntax} +% Prints a set of numbers in the \meta{entries}, each of which should +% be given as a \meta{balanced text}. Unlike \cs{siunitx_number_list:nn}, this +% function may semantically take any form +% \end{function} +% +% \begin{function}{\siunitx_compound_quantity:nn} +% \begin{syntax} +% \cs{siunitx_compound_quantity:nn} \Arg{entries} \Arg{unit} +% \end{syntax} +% Prints a set of quantities in the \meta{entries}, each of which should +% be given as a \meta{balanced text}. Unlike \cs{siunitx_quantity_list:nn}, this +% function may semantically take any form +% \end{function} +% +% \begin{function}{\siunitx_number_list:nn} +% \begin{syntax} +% \cs{siunitx_number_list:nn} \Arg{entries} +% \end{syntax} +% Prints the list of numbers in the \meta{entries}, each of which should +% be given as a \meta{balanced text}. +% \end{function} +% +% \begin{function}{\siunitx_quantity_list:nn} +% \begin{syntax} +% \cs{siunitx_quantity_list:nn} \Arg{entries} \Arg{unit} +% \end{syntax} +% Prints the list of quantities in the \meta{entries}, each of which should +% be given as a \meta{balanced text}. +% \end{function} +% +% \begin{function}{\siunitx_number_product:n} +% \begin{syntax} +% \cs{siunitx_number_product:n} \Arg{entries} +% \end{syntax} +% Prints the series of numbers in the \meta{entries}, each of which should +% be given as a \meta{balanced text}. +% \end{function} +% +% \begin{function}{\siunitx_quantity_product:nn} +% \begin{syntax} +% \cs{siunitx_number_product:n} \Arg{entries} \Arg{unit} +% \end{syntax} +% Prints the series of quantities in the \meta{entries}, each of which should +% be given as a \meta{balanced text}. +% \end{function} +% +% \begin{function}{\siunitx_number_range:nn} +% \begin{syntax} +% \cs{siunitx_number_range:nn} \Arg{start} \Arg{end} +% \end{syntax} +% Prints the range of numbers from the \meta{start} to the \meta{end}. +% \end{function} +% +% \begin{function}{\siunitx_quantity_range:nnn} +% \begin{syntax} +% \cs{siunitx_number_range:nn} \Arg{start} \Arg{end} \Arg{unit} +% \end{syntax} +% Prints the range of quantities from the \meta{start} to the \meta{end}. +% \end{function} +% +% \begin{variable} +% { +% \l_siunitx_list_separator_pair_tl, +% \l_siunitx_list_separator_tl, +% \l_siunitx_list_separator_final_tl +% } +% Separators for lists of numbers and quantities. +% \end{variable} +% +% \begin{variable}{\l_siunitx_range_phrase_tl} +% Phrase (or similar) used between limits of a range. +% \end{variable} +% +% \begin{function}{compound-exponents} +% \begin{syntax} +% |compound-exponents| = |combine|\verb"|"|combine-bracket|\verb"|"|individual| +% \end{syntax} +% \end{function} +% +% \begin{function}{compound-final-separator} +% \begin{syntax} +% |compound-final-separator| = \meta{text} +% \end{syntax} +% \end{function} +% +% \begin{function}{compound-pair-separator} +% \begin{syntax} +% |compound-pair-separator| = \meta{text} +% \end{syntax} +% \end{function} +% +% \begin{function}{compound-separator} +% \begin{syntax} +% |compound-separator| = \meta{text} +% \end{syntax} +% \end{function} +% +% \begin{function}{compound-separator-mode} +% \begin{syntax} +% |compound-separator-mode| = |number|\verb"|"|text| +% \end{syntax} +% \end{function} +% +% \begin{function}{compound-units} +% \begin{syntax} +% |compound-units| = |bracket|\verb"|"|repeat|\verb"|"|single| +% \end{syntax} +% \end{function} +% +% \begin{function}{list-exponents} +% \begin{syntax} +% |list-exponents| = |combine|\verb"|"|combine-bracket|\verb"|"|individual| +% \end{syntax} +% \end{function} +% +% \begin{function}{list-final-separator} +% \begin{syntax} +% |list-final-separator| = \meta{text} +% \end{syntax} +% \end{function} +% +% \begin{function}{list-pair-separator} +% \begin{syntax} +% |list-pair-separator| = \meta{text} +% \end{syntax} +% \end{function} +% +% \begin{function}{list-separator} +% \begin{syntax} +% |list-separator| = \meta{text} +% \end{syntax} +% \end{function} +% +% \begin{function}{list-units} +% \begin{syntax} +% |list-units| = |bracket|\verb"|"|repeat|\verb"|"|single| +% \end{syntax} +% \end{function} +% +% \begin{function}{product-exponents} +% \begin{syntax} +% |product-exponents| = |combine|\verb"|"|combine-bracket|\verb"|"|individual| +% \end{syntax} +% \end{function} +% +% \begin{function}{product-mode} +% \begin{syntax} +% |product-mode| = |phrase|\verb"|"|choice| +% \end{syntax} +% \end{function} +% +% \begin{function}{product-phrase} +% \begin{syntax} +% |product-phrase| = \meta{text} +% \end{syntax} +% \end{function} +% +% \begin{function}{product-symbol} +% \begin{syntax} +% |product-symbol| = \meta{symbol} +% \end{syntax} +% \end{function} +% +% \begin{function}{range-exponents} +% \begin{syntax} +% |range-exponents| = |combine|\verb"|"|combine-bracket|\verb"|"|individual| +% \end{syntax} +% \end{function} +% +% \begin{function}{range-phrase} +% \begin{syntax} +% |range-phrase| = \meta{text} +% \end{syntax} +% \end{function} +% +% \begin{function}{range-units} +% \begin{syntax} +% |range-units| = |bracket|\verb"|"|repeat|\verb"|"|single| +% \end{syntax} +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \section{\pkg{siunitx-compound} implementation} +% +% \begin{macrocode} +\cs_generate_variant:Nn \keys_set:nn { nx } +% \end{macrocode} +% +% \subsection{General mechanism} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_compound> +% \end{macrocode} +% +% Typesetting lists, ranges and products of numbers or quantities has shared +% features which mean they are best handled using a common mechanism. The aim +% therefore is to abstract out enough of the process such that output-specific +% aspects can be left to separate processes. +% +% \begin{variable}{\l_@@_tmp_fp, \l_@@_tmp_seq, \l_@@_tmp_tl} +% Scratch space. +% \begin{macrocode} +\fp_new:N \l_@@_tmp_fp +\seq_new:N \l_@@_tmp_seq +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_first_tl} +% The first number in the list in internal format. +% \begin{macrocode} +\tl_new:N \l_@@_first_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_exp_tl} +% For storing the combined exponent, if present. +% \begin{macrocode} +\tl_new:N \l_@@_exp_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_start_tl, \l_@@_end_tl} +% Data on the end-of-list. +% \begin{macrocode} +\tl_new:N \l_@@_start_tl +\tl_new:N \l_@@_end_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_count_int} +% Data on the length-of-list. +% \begin{macrocode} +\int_new:N \l_@@_count_int +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_unit_tl} +% \begin{macrocode} +\tl_new:N \l_@@_unit_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_bracket_close_tl, \l_@@_bracket_open_tl} +% Purely internal for the present. +% \begin{macrocode} +\tl_new:N \l_@@_bracket_close_tl +\tl_new:N \l_@@_bracket_open_tl +\tl_set:Nn \l_@@_bracket_open_tl { ( } +\tl_set:Nn \l_@@_bracket_close_tl { ) } +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% { +% \l_@@_separator_final_tl , +% \l_@@_separator_pair_tl , +% \l_@@_separator_tl , +% \l_@@_separator_text_bool , +% \l_@@_exp_bracket_bool , +% \l_@@_exp_combine_bool , +% \l_@@_unit_bracket_bool , +% \l_@@_unit_repeat_bool , +% \l_@@_unit_repeat_bool +% } +% List options. +% \begin{macrocode} +\bool_new:N \l_@@_exp_bracket_bool +\bool_new:N \l_@@_exp_combine_bool +\bool_new:N \l_@@_separator_text_bool +\bool_new:N \l_@@_unit_bracket_bool +\bool_new:N \l_@@_unit_power_bool +\bool_new:N \l_@@_unit_repeat_bool +\keys_define:nn { siunitx } + { + compound-exponents .choice: , + compound-exponents / combine .code:n = + { + \bool_set_false:N \l_@@_exp_bracket_bool + \bool_set_true:N \l_@@_exp_combine_bool + } , + compound-exponents / combine-bracket .code:n = + { + \bool_set_true:N \l_@@_exp_bracket_bool + \bool_set_true:N \l_@@_exp_combine_bool + } , + compound-exponents / individual .code:n = + { + \bool_set_false:N \l_@@_exp_bracket_bool + \bool_set_false:N \l_@@_exp_combine_bool + } , + compound-final-separator .tl_set:N = + \l_@@_separator_final_tl , + compound-pair-separator .tl_set:N = + \l_@@_separator_pair_tl , + compound-separator .tl_set:N = + \l_@@_separator_tl , + compound-separator-mode .choice: , + compound-separator-mode / number .code:n = + { \bool_set_false:N \l_@@_separator_text_bool } , + compound-separator-mode / text .code:n = + { \bool_set_true:N \l_@@_separator_text_bool } , + compound-units .choice: , + compound-units / bracket .code:n = + { + \bool_set_true:N \l_@@_unit_bracket_bool + \bool_set_false:N \l_@@_unit_power_bool + \bool_set_false:N \l_@@_unit_repeat_bool + } , + compound-units / bracket-power .code:n = + { + \bool_set_true:N \l_@@_unit_bracket_bool + \bool_set_true:N \l_@@_unit_power_bool + \bool_set_false:N \l_@@_unit_repeat_bool + } , + compound-units / power .code:n = + { + \bool_set_false:N \l_@@_unit_bracket_bool + \bool_set_true:N \l_@@_unit_power_bool + \bool_set_false:N \l_@@_unit_repeat_bool + } , + compound-units / repeat .code:n = + { + \bool_set_false:N \l_@@_unit_bracket_bool + \bool_set_false:N \l_@@_unit_power_bool + \bool_set_true:N \l_@@_unit_repeat_bool + } , + compound-units / single .code:n = + { + \bool_set_false:N \l_@@_unit_bracket_bool + \bool_set_false:N \l_@@_unit_power_bool + \bool_set_false:N \l_@@_unit_repeat_bool + } + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_compound_number:n} +% \begin{macro}{\@@_format:n} +% \begin{macro}{\@@_format:nnn} +% Printing a generic set starts with the question of whether we want to +% extract exponents. If we do, then there is the work to do with extraction. +% Either way, the printing is handed off to a common function. We do a quick +% count up-front to avoid excess work when there is not actually a list. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_compound_number:n #1 + { + \group_begin: + \@@_format:nn {#1} { } + \@@_print:N \siunitx_print_number:x + \group_end: + } +\cs_new_protected:Npn \@@_format:nn #1#2 + { + \seq_clear:N \l_@@_tmp_seq + \bool_if:NTF \l_siunitx_number_parse_bool + { + \exp_args:Nxx \@@_format:nnn + { \tl_head:n {#1} } + { \tl_tail:n {#1} } + {#2} + } + { \tl_map_function:nN {#1} \@@_unparsed:n } + } +% \end{macrocode} +% Formatting at a low level needs to know about units and numbers: we have to +% exchange data between the two. Most of the business of handling the units +% is left to a dedicated auxiliary. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format:nnn #1#2#3 + { + \siunitx_number_parse:nN {#1} \l_@@_tmp_tl + \tl_if_blank:nTF {#3} + { \siunitx_number_process:NN \l_@@_tmp_tl \l_@@_first_tl } + { \@@_format_units:nn {#2} {#3} } + \bool_lazy_and:nnTF + { \l_@@_exp_combine_bool } + { \int_compare_p:nNn { \tl_count:n {#2} } > 0 } + { \@@_extract_exponents: } + { + \tl_set:Nx \l_@@_tmp_tl + { \siunitx_number_output:N \l_@@_first_tl } + \seq_put_right:NV \l_@@_tmp_seq \l_@@_tmp_tl + } + \tl_map_function:nN {#2} \@@_parsed:n + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_extract_exponents:N} +% \begin{macro}{\@@_extract_exponents_auxi:w} +% \begin{macro}{\@@_extract_exponents_auxii:nw} +% \begin{macro}{\@@_extract_exponents_auxiii:nnnnnnn} +% Extracting exponents means dealing with the first entry as a special case. +% After that, apply fixed processing to all other entries, tidying up using +% the number formatter. +% \begin{macrocode} +\cs_new_protected:Npn \@@_extract_exponents: + { + \tl_set:Nx \l_@@_tmp_tl + { \siunitx_number_output:NN \l_@@_first_tl \q_nil } + \exp_after:wN \@@_extract_exponents_auxi:w + \l_@@_tmp_tl \q_stop + } +\cs_new_protected:Npn \@@_extract_exponents_auxi:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil #8 + \q_nil #9 \q_stop + { + \@@_extract_exponents_auxii:nw {#1#2#3#4#5#6#7#8} #9 \q_stop + } +\cs_new_protected:Npn \@@_extract_exponents_auxii:nw + #1#2 \q_nil #3 \q_nil #4 \q_stop + { + \seq_put_right:Nn \l_@@_tmp_seq { #1#2 } + \tl_set:Nn \l_@@_exp_tl { #3#4 } + \exp_after:wN \@@_extract_exponents_auxiii:nnnnnnn + \l_@@_first_tl + } +\cs_new_protected:Npn \@@_extract_exponents_auxiii:nnnnnnn + #1#2#3#4#5#6#7 + { + \keys_set:nn { siunitx } + { + drop-exponent = true , + exponent-mode = fixed , + fixed-exponent = #6#7 + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parsed:n, \@@_unparsed:n} +% The simple cases for parsing (or not) all entries. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parsed:n #1 + { + \siunitx_number_format:nN {#1} \l_@@_tmp_tl + \seq_put_right:NV \l_@@_tmp_seq \l_@@_tmp_tl + } +\cs_new_protected:Npn \@@_unparsed:n #1 + { + \seq_put_right:Nn \l_@@_tmp_seq { \ensuremath {#1} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_format_units:nn} +% \begin{macro} +% { +% \@@_format_combine-exponent:n , +% \@@_format_extract-exponent:n , +% \@@_format_input:n +% } +% \begin{macro} +% { +% \@@_format_combine-exponent:nn , +% \@@_format_extract-exponent:nn +% } +% \begin{macro} +% { +% \@@_format_combine-exponent_aux:n , +% \@@_format_extract-exponent_aux:n +% } +% \begin{macro}{\@@_extract_exp:nN} +% \begin{macro}{\@@_extract_exp:nnnnnnnN} +% Actually formatting the units is much the same as is done in +% the quantities module, except that we have to cover the multiplication +% cases too: gets a bit repetitive. Notice that when combining exponents, +% there is no adjustment to the original exponent: we purely need to +% extract it. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_units:nn #1#2 + { + \bool_if:NTF \l_@@_unit_power_bool + { + \use:c { @@_format_ \l_siunitx_quantity_prefix_mode_tl :nn } + {#2} { \tl_count:n {#1} + 1 } + } + { + \use:c { @@_format_ \l_siunitx_quantity_prefix_mode_tl :n } {#2} + } + } +\cs_new_protected:cpx { @@_format_combine-exponent:n } #1 + { + \exp_not:c { @@_format_combine-exponent_aux:n } + { + \exp_not:N \siunitx_unit_format_combine_exponent:nnN + {#1} + } + } +\cs_new_protected:cpx { @@_format_combine-exponent:nn } #1#2 + { + \exp_not:c { @@_format_combine-exponent_aux:n } + { + \exp_not:N \siunitx_unit_format_multiply_combine_exponent:nnnN + {#1} {#2} + } + } +\cs_new_protected:cpn { @@_format_combine-exponent_aux:n } #1 + { + \bool_set_true:N \l_@@_exp_combine_bool + \siunitx_number_process:NN \l_@@_tmp_tl \l_@@_first_tl + \exp_args:NV \@@_extract_exp:nN + \l_@@_first_tl \l_@@_tmp_fp + #1 \l_@@_tmp_fp \l_@@_unit_tl + } +\cs_new_protected:cpx { @@_format_extract-exponent:n } #1 + { + \exp_not:c { @@_format_extract-exponent_aux:n } + { \exp_not:N \siunitx_unit_format_extract_prefixes:nNN {#1} } + } +\cs_new_protected:cpx { @@_format_extract-exponent:nn } #1#2 + { + \exp_not:c { @@_format_extract-exponent_aux:n } + { + \exp_not:N \siunitx_unit_format_multiply_extract_prefixes:nnNN + {#1} {#2} + } + } +\cs_new_protected:cpn { @@_format_extract-exponent_aux:n } #1 + { + #1 \l_@@_unit_tl \l_@@_tmp_fp + \tl_set:Nx \l_@@_tmp_tl + { \siunitx_number_adjust_exponent:Nn \l_@@_tmp_tl \l_@@_tmp_fp } + \siunitx_number_process:NN \l_@@_tmp_tl \l_@@_first_tl + \bool_set_true:N \l_@@_exp_combine_bool + } +\cs_new_protected:Npn \@@_format_input:n #1 + { + \siunitx_number_process:NN \l_@@_tmp_tl \l_@@_first_tl + \siunitx_unit_format:nN {#1} \l_@@_unit_tl + } +\cs_new_protected:Npn \@@_format_input:nn #1#2 + { + \siunitx_number_process:NN \l_@@_tmp_tl \l_@@_first_tl + \siunitx_unit_format_multiply:nnN {#1} {#2} \l_@@_unit_tl + } +\cs_new_protected:Npn \@@_extract_exp:nN #1#2 + { \@@_extract_exp:nnnnnnnN #1 #2 } +\cs_new_protected:Npn \@@_extract_exp:nnnnnnnN #1#2#3#4#5#6#7#8 + { \fp_set:Nn #8 {#6#7} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\siunitx_compound_quantity:nn} +% For quantities, life is more complex as there are interactions between the +% options for exponents and units. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_compound_quantity:nn #1#2 + { + \group_begin: + \bool_if:NT \l_@@_unit_bracket_bool + { \bool_set_true:N \l_@@_exp_bracket_bool } + \bool_if:NT \l_@@_unit_repeat_bool + { \bool_set_false:N \l_@@_exp_combine_bool } + \bool_lazy_or:nnT + { \l_@@_unit_bracket_bool } + { ! \l_@@_unit_repeat_bool } + { \bool_set_false:N \l_siunitx_number_bracket_ambiguous_bool } + \@@_format:nn {#1} {#2} + \str_if_eq:VnT \l_siunitx_quantity_prefix_mode_tl { combine-exponent } + { \tl_clear:N \l_@@_exp_tl } + \bool_if:NTF \l_@@_unit_repeat_bool + { \@@_print:N \@@_print_quantity:n } + { + \bool_lazy_and:nnTF + { \l_@@_unit_bracket_bool } + { \tl_if_empty_p:N \l_@@_exp_tl } + { + \siunitx_print_number:V \l_@@_bracket_open_tl + \@@_print:N \siunitx_print_number:x + \siunitx_print_number:V \l_@@_bracket_close_tl + } + { \@@_print:N \siunitx_print_number:x } + \@@_print_quantity:n { } + } + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_print:N} +% \begin{macro}{\@@_print:nnN, \@@_print:xxN} +% \begin{macro}{\@@_print:nnnN} +% \begin{macro}{\@@_print_aux:n} +% \begin{macro}{\@@_print_aux:nn} +% We now need to know how many entries there are: the reason we don't use +% \cs{seq_use:Nnnn} is that we want to be able to insert +% \cs{siunitx_print_\dots:n} in a controlled way. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print:N #1 + { + \bool_lazy_and:nnTF + { \l_@@_exp_bracket_bool } + { ! \tl_if_empty_p:N \l_@@_exp_tl } + { + \@@_print:xxN + { \exp_not:V \l_@@_bracket_open_tl } + { + \exp_not:V \l_@@_bracket_close_tl + \exp_not:V \l_@@_exp_tl + } + #1 + } + { \@@_print:xxN { } { \exp_not:V \l_@@_exp_tl } #1 } + } +\cs_new_protected:Npn \@@_print:nnN #1#2#3 + { + \exp_args:Nx \@@_print:nnnN + { \seq_count:N \l_@@_tmp_seq } {#1} {#2} #3 + } +\cs_generate_variant:Nn \@@_print:nnN { xx } +% \end{macrocode} +% A rather long auxiliary as we want a way to have the brackets/exponent +% available. The actual flow is simple enough: see how many entries there are +% and print as required. To keep everything generic, we have some slightly +% tricky saving of data to allow everything to go to the mapping. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print:nnnN #1#2#3#4 + { + \int_case:nnF {#1} + { + { 0 } { } + { 1 } + { + #4 + { \seq_item:Nn \l_@@_tmp_seq { 1 } } + } + { 2 } + { + #4 + { + \exp_not:n {#2} + \seq_item:Nn \l_@@_tmp_seq { 1 } + } + \@@_print_separator:V \l_@@_separator_pair_tl + #4 + { + \seq_item:Nn \l_@@_tmp_seq { 2 } + \exp_not:n {#3} + } + } + } + { + \int_set:Nn \l_@@_count_int {#1} + \tl_set:Nn \l_@@_start_tl {#2} + \tl_set:Nn \l_@@_end_tl {#3} + \cs_set_eq:NN \@@_print_aux:n #4 + \seq_map_indexed_function:NN + \l_@@_tmp_seq + \@@_print_aux:nn + } + } +\cs_new_protected:Npn \@@_print_aux:n #1 { } +\cs_new_protected:Npn \@@_print_aux:nn #1#2 + { + \int_case:nnF {#1} + { + { 1 } + { + \@@_print_aux:n + { + \exp_not:V \l_@@_start_tl + \exp_not:n {#2} + } + \@@_print_separator:V \l_@@_separator_tl + } + { \l_@@_count_int - 1 } + { + \@@_print_aux:n { \exp_not:n {#2} } + \@@_print_separator:V \l_@@_separator_final_tl + } + { \l_@@_count_int } + { + \@@_print_aux:n + { + \exp_not:n {#2} + \exp_not:V \l_@@_end_tl + } + } + } + { + \@@_print_aux:n { \exp_not:n {#2} } + \@@_print_separator:V \l_@@_separator_tl + } + } +\cs_new_protected:Npn \@@_print_quantity:n #1 + { \siunitx_quantity_print:nV {#1} \l_@@_unit_tl } +\cs_new_protected:Npn \@@_print_separator:n #1 + { + \bool_if:NTF \l_@@_separator_text_bool + { #1 } + { \siunitx_print_number:n {#1} } + } +\cs_generate_variant:Nn \@@_print_separator:n { V } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Lists} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_list> +% \end{macrocode} +% +% \begin{variable} +% { +% \l_siunitx_list_separator_tl , +% \l_siunitx_list_separator_final_tl , +% \l_siunitx_list_separator_pair_tl , +% \l_@@_exp_tl , +% \l_@@_units_tl +% } +% Options for products. +% \begin{macrocode} +\tl_new:N \l_@@_exp_tl +\tl_new:N \l_@@_units_tl +\keys_define:nn { siunitx } + { + list-exponents .choices:nn = + { combine , combine-bracket , individual } + { \tl_set_eq:NN \l_@@_exp_tl \l_keys_choice_tl } , + list-final-separator .tl_set:N = \l_siunitx_list_separator_final_tl , + list-pair-separator .tl_set:N = \l_siunitx_list_separator_pair_tl , + list-separator .tl_set:N = \l_siunitx_list_separator_tl , + list-units .choices:nn = + { bracket , repeat , single } + { \tl_set_eq:NN \l_@@_units_tl \l_keys_choice_tl } + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_number_list:nn} +% \begin{macro}{\siunitx_quantity_list:nn} +% \begin{macro}{\@@_aux:} +% Simply recover the settings and use as a list. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_number_list:nn #1 + { + \group_begin: + \@@_aux: + \siunitx_compound_number:n {#1} + \group_end: + } +\cs_new_protected:Npn \siunitx_quantity_list:nn #1#2 + { + \group_begin: + \@@_aux: + \siunitx_compound_quantity:nn {#1} {#2} + \group_end: + } +\cs_new_protected:Npn \@@_aux: + { + \keys_set:nx { siunitx } + { + compound-exponents = \l_@@_exp_tl , + compound-final-separator = + { \exp_not:V \l_siunitx_list_separator_final_tl } , + compound-pair-separator = + { \exp_not:V \l_siunitx_list_separator_pair_tl } , + compound-separator = + { \exp_not:V \l_siunitx_list_separator_tl } , + compound-separator-mode = text , + compound-units = \l_@@_units_tl + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Products} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_product> +% \end{macrocode} +% +% \begin{variable} +% { +% \l_@@_exp_tl , +% \l_@@_phrase_bool , +% \l_@@_phrase_tl , +% \l_@@_symbol_tl , +% \l_@@_units_tl +% } +% Options for products. +% \begin{macrocode} +\tl_new:N \l_@@_exp_tl +\bool_new:N \l_@@_phrase_bool +\tl_new:N \l_@@_units_tl +\keys_define:nn { siunitx } + { + product-exponents .choices:nn = + { combine , combine-bracket , individual } + { \tl_set_eq:NN \l_@@_exp_tl \l_keys_choice_tl } , + product-mode .choice: , + product-mode / phrase .code:n = + { \bool_set_true:N \l_@@_phrase_bool } , + product-mode / symbol .code:n = + { \bool_set_false:N \l_@@_phrase_bool } , + product-phrase .tl_set:N = \l_@@_phrase_tl , + product-symbol .tl_set:N = \l_@@_symbol_tl , + product-units .choices:nn = + { bracket , bracket-power , power , repeat , single } + { \tl_set_eq:NN \l_@@_units_tl \l_keys_choice_tl } + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_number_product:n} +% \begin{macro}{\siunitx_quantity_product:nn} +% \begin{macro}{\@@_aux:} +% \begin{macro}{\@@_aux:n, \@@_aux:x} +% Simply recover the settings and use as a list. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_number_product:n #1 + { + \group_begin: + \@@_aux: + \siunitx_compound_number:n {#1} + \group_end: + } +\cs_new_protected:Npn \siunitx_quantity_product:nn #1#2 + { + \group_begin: + \@@_aux: + \siunitx_compound_quantity:nn {#1} {#2} + \group_end: + } +\cs_new_protected:Npn \@@_aux: + { + \bool_if:NTF \l_@@_phrase_bool + { \@@_aux:x { \exp_not:V \l_@@_phrase_tl } } + { \@@_aux:x { { } \exp_not:V \l_@@_symbol_tl { } } } + } +\cs_new_protected:Npn \@@_aux:n #1 + { + \keys_set:nx { siunitx } + { + compound-exponents = \l_@@_exp_tl , + compound-final-separator = { \exp_not:n {#1} } , + compound-pair-separator = { \exp_not:n {#1} } , + compound-separator = { \exp_not:n {#1} } , + compound-separator-mode = + \bool_if:NTF \l_@@_phrase_bool { text } { number } , + compound-units = \l_@@_units_tl + } + } +\cs_generate_variant:Nn \@@_aux:n { x } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Ranges} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_range> +% \end{macrocode} +% +% \begin{variable} +% { +% \l_@@_exp_tl , +% \l_siunitx_range_phrase_tl , +% \l_@@_units_tl +% } +% Options for products. +% \begin{macrocode} +\tl_new:N \l_@@_exp_tl +\tl_new:N \l_@@_units_tl +\keys_define:nn { siunitx } + { + range-exponents .choices:nn = + { combine , combine-bracket , individual } + { \tl_set_eq:NN \l_@@_exp_tl \l_keys_choice_tl } , + range-phrase .tl_set:N = \l_siunitx_range_phrase_tl , + range-units .choices:nn = + { bracket , repeat , single } + { \tl_set_eq:NN \l_@@_units_tl \l_keys_choice_tl } + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_number_range:nn} +% \begin{macro}{\siunitx_quantity_range:nnn} +% \begin{macro}{\@@_aux:} +% Simply recover the settings and use as a list. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_number_range:nn #1#2 + { + \group_begin: + \@@_aux: + \siunitx_compound_number:n { {#1} {#2} } + \group_end: + } +\cs_new_protected:Npn \siunitx_quantity_range:nnn #1#2#3 + { + \group_begin: + \@@_aux: + \siunitx_compound_quantity:nn { {#1} {#2} } {#3} + \group_end: + } +\cs_new_protected:Npn \@@_aux: + { + \keys_set:nx { siunitx } + { + compound-exponents = \l_@@_exp_tl , + compound-pair-separator = { \exp_not:V \l_siunitx_range_phrase_tl } , + compound-separator-mode = text , + compound-units = \l_@@_units_tl + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Standard settings for module options} +% +% Some of these follow naturally from the point of definition +% (\foreign{e.g.}~boolean variables are always |false| to begin with), +% but for clarity everything is set here. +% \begin{macrocode} +\keys_set:nn { siunitx } + { + compound-exponents = individual , + compound-final-separator = + { + \ifmmode \ \else \space \fi + \text { and } + \ifmmode \ \else \space \fi + } , + compound-pair-separator = + { + \ifmmode \ \else \space \fi + \text { and } + \ifmmode \ \else \space \fi + } , + compound-separator = + { , \ifmmode \ \else \space \fi } , + compound-separator-mode = text , + compound-units = repeat , + list-exponents = individual , + list-final-separator = + { + \ifmmode \ \else \space \fi + \text { and } + \ifmmode \ \else \space \fi + } , + list-pair-separator = + { + \ifmmode \ \else \space \fi + \text { and } + \ifmmode \ \else \space \fi + } , + list-separator = + { , \ifmmode \ \else \space \fi } , + list-units = repeat , + product-exponents = individual , + product-mode = symbol , + product-phrase = + { + \ifmmode \ \else \space \fi + \text { by } + \ifmmode \ \else \space \fi + } , + product-symbol = \times , + product-units = repeat , + range-exponents = individual , + range-phrase = + { + \ifmmode \ \else \space \fi + \text { to } + \ifmmode \ \else \space \fi + } , + range-units = repeat + } +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/siunitx/siunitx-emulation.dtx b/macros/latex/contrib/siunitx/siunitx-emulation.dtx new file mode 100644 index 0000000000..40f145a6c6 --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-emulation.dtx @@ -0,0 +1,978 @@ +% \iffalse meta-comment +% +% File: siunitx-emulation.dtx Copyright (C) 2016-2019,2021 Joseph Wright +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-emulation} -- Emulation^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-emulation} implementation} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention). In contrast +% to other parts of the bundle, the functions here may need to redefine those +% from various submodules. +% \begin{macrocode} +%<@@=siunitx> +% \end{macrocode} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% \begin{macrocode} +%<*options> +% \end{macrocode} +% +% Some messages. +% \begin{macrocode} +\msg_new:nnn { siunitx } { option-deprecated } + { + Option~"#1"~has~been~deprecated~in~this~release.\\ \\ + Use~"#2"~as~a~replacement. + } +\msg_new:nnn { siunitx } { option-removed } + { Option~"#1"~has~been~removed~in~this~release. } +% \end{macrocode} +% +% \begin{macro}{\@@_option_deprecated:nn} +% \begin{macro}{\@@_option_deprecated:nnn, \@@_option_deprecated:nnV} +% Abstract out a simple wrapper. +% \begin{macrocode} +\cs_new_protected:Npn \@@_option_deprecated:nn #1#2 + { + \msg_info:nnnn { siunitx } { option-deprecated } {#1} {#2} + \keys_set:nn { siunitx } {#2} + } +\cs_new_protected:Npn \@@_option_deprecated:nnn #1#2#3 + { + \msg_info:nnnn { siunitx } { option-deprecated } {#1} {#2} + \keys_set:nn { siunitx } { #2 = #3 } + } +\cs_generate_variant:Nn \@@_option_deprecated:nnn { nnV } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_option_removed:n, \@@_option_removed:V} +% Abstract out a simple wrapper. +% \begin{macrocode} +\cs_new_protected:Npn \@@_option_removed:n #1 + { + \msg_warning:nnx { siunitx } { option-removed } + {#1} + } +\cs_generate_variant:Nn \@@_option_removed:n { V } +% \end{macrocode} +% \end{macro} +% +% \subsection{Load-time option} +% +% \begin{macrocode} +\clist_map_inline:nn { abbreviations , binary-units , version-1-compatibility } + { + \keys_define:nn { siunitx } { #1 .code:n = \@@_option_removed:n {#1} } + } +% \end{macrocode} +% +% \subsection{Angle options} +% +% All straight-forward emulation. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + add-arc-degree-zero .code:n = + { + \@@_option_deprecated:nnV + { add-arc-degree-zero } + { fill-angle-degrees } + \l_keys_value_tl + } , + add-arc-degree-zero .default:n = true , + add-arc-minute-zero .code:n = + { + \@@_option_deprecated:nnV + { add-arc-minute-zero } + { fill-angle-minutes } + \l_keys_value_tl + } , + add-arc-minute-zero .default:n = true , + add-arc-second-zero .code:n = + { + \@@_option_deprecated:nnV + { add-arc-second-zero } + { fill-angle-seconds } + \l_keys_value_tl + } , + add-arc-second-zero .default:n = true , + arc-separator .code:n = + { + \@@_option_deprecated:nnV + { arc-separator } + { angle-separator } + \l_keys_value_tl + } + } +% \end{macrocode} +% +% \subsection{Combination functions options} +% +% \begin{macrocode} +\keys_define:nn { siunitx } + { + list-units / brackets .code:n = + { + \@@_option_deprecated:nn + { list-units~=~brackets } + { list-units~=~bracket } + } , + range-units / brackets .code:n = + { + \@@_option_deprecated:nn + { range-units~=~brackets } + { range-units~=~bracket } + } , + product-units / brackets .code:n = + { + \@@_option_deprecated:nn + { product-units~=~brackets } + { product-units~=~bracket } + } + } +% \end{macrocode} +% +% \subsection{Command options} +% +% \begin{macrocode} +\keys_define:nn { siunitx } + { + overwrite-functions .code:n = + { + \@@_option_deprecated:nnV + { overwrite-functions } + { overwrite-commands } + \l_keys_value_tl + } , + overwrite-functions .default:n = true + } +% \end{macrocode} +% +% \subsection{Print options} +% +% \begin{macrocode} +\keys_define:nn { siunitx } + { + detect-all .code:n = + { + \@@_option_deprecated:nn + { detect-all } + { + mode~=~match , ~ + propagate-math-font~=~true , ~ + reset-math-version~=~false , ~ + reset-text-family~=~false , ~ + reset-text-series~=~false , ~ + text-family-to-math~=~true , ~ + text-series-to-math~=~true + } + } , + detect-family .code:n = + { + \@@_option_deprecated:nn + { detect-family } + { + reset-text-family~=~false , ~ + text-family-to-math~=~true + } + } , + detect-mode .code:n = + { + \@@_option_deprecated:nn + { detect-mode } + { mode~=~match } + } , + detect-none .code:n = + { + \@@_option_deprecated:nn + { detect-none } + { + mode~=~math , ~ + propagate-math-font~=~false , ~ + reset-math-version~=~true , ~ + reset-text-family~=~true , ~ + reset-text-series~=~true , ~ + text-family-to-math~=~false , ~ + text-series-to-math~=~false + } + } , + detect-shape .code:n = + { + \@@_option_deprecated:nn + { detect-shape } + { reset-text-shape~=~false } + } , + detect-weight .code:n = + { + \@@_option_deprecated:nn + { detect-weight } + { + reset-text-series~=~false , ~ + text-series-to-math~=~true + } + } + } +\clist_map_inline:nn + { + detect-display-math , + detect-inline-family , + detect-inline-weight + } + { + \keys_define:nn { siunitx } { #1 .code:n = \@@_option_removed:n {#1} } + } +% \end{macrocode} +% +% The old font insertion options. +% \begin{macrocode} +\clist_map_inline:nn + { + math-rm , + math-sf , + math-tt , + number-math-rm , + number-math-sf , + number-math-tt , + number-text-rm , + number-text-sf , + number-text-tt , + text-rm , + text-sf , + text-tt , + unit-math-rm , + unit-math-sf , + unit-math-tt , + unit-text-rm , + unit-text-sf , + unit-text-tt + } + { + \keys_define:nn { siunitx } { #1 .code:n = \@@_option_removed:n {#1} } + } +% \end{macrocode} +% +% \subsection{Symbol options} +% +% \begin{macrocode} +\clist_map_inline:nn + { + math-angstrom , + math-arcminute , + math-arcsecond , + math-celsius , + math-degree , + math-micro , + math-ohm , + text-angstrom , + text-arcminute , + text-arcsecond , + text-celsius , + text-degree , + text-micro , + text-ohm , + } + { + \keys_define:nn { siunitx } { #1 .code:n = \@@_option_removed:n {#1} } + } +% \end{macrocode} +% +% \subsection{Number options} +% +% \begin{macrocode} +\keys_define:nn { siunitx } + { + separate-uncertainty .choice: , + separate-uncertainty / false .code:n = + { + \@@_option_deprecated:nn + { separate-uncertainty } + { uncertainty-mode~=~compact } + } , + separate-uncertainty / true .code:n = + { + \@@_option_deprecated:nn + { separate-uncertainty } + { uncertainty-mode~=~separate } + } , + separate-uncertainty .default:n = true + } +% \end{macrocode} +% +% A small number of removed options. +% \begin{macrocode} +\clist_map_inline:nn + { + input-protect-tokens , + input-quotient , + quotient-mode + } + { + \keys_define:nn { siunitx } { #1 .code:n = \@@_option_removed:n {#1} } + } +% \end{macrocode} +% +% Options for number processing: largely removals. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + add-decimal-zero .choice: , + add-decimal-zero / false .code:n = + { + \@@_option_deprecated:nn + { add-decimal-zero } + { minimum-decimal-digits~=~0 } + } , + add-decimal-zero / true .code:n = + { + \@@_option_deprecated:nn + { add-decimal-zero } + { minimum-decimal-digits~=~1 } + } , + add-decimal-zero .default:n = true , + add-integer-zero .code:n = + { \@@_option_removed:V \l_keys_key_tl } , + close-bracket .code:n = + { \@@_option_removed:V \l_keys_key_tl } , + bracket-numbers .choice: , + bracket-numbers / false .code:n = + { + \@@_option_deprecated:nn + { bracket-numbers } + { bracket-ambiguous-numbers~=~false } + } , + bracket-numbers / true .code:n = + { + \@@_option_deprecated:nn + { bracket-numbers } + { bracket-ambiguous-numbers~=~true } + } , + bracket-numbers .default:n = true , + explicit-sign .code:n = + { + \str_if_eq:nnTF {#1} { + } + { + \@@_option_deprecated:nn + { explicit-sign } + { print-implicit-plus~=~true } + } + { \@@_option_removed:V \l_keys_key_tl } + } , + omit-uncertainty .code:n = + { + \@@_option_deprecated:nnV + { omit-uncertainty } + { drop-uncertainty } + \l_keys_value_tl + } , + omit-uncertainty .default:n = true , + open-bracket .code:n = + { \@@_option_removed:V \l_keys_key_tl } , + retain-unity-mantissa .code:n = + { + \@@_option_deprecated:nnV + { retain-unity-mantissa } + { print-unity-mantissa } + \l_keys_value_tl + } , + retain-unity-mantisa .default:n = true , + retain-zero-exponent .code:n = + { + \@@_option_deprecated:nnV + { retain-zero-exponent } + { print-zero-exponent } + \l_keys_value_tl + } , + retain-zero-exponent .default:n = true , + round-integer-to-decimal .code:n = + { \@@_option_removed:V \l_keys_key_tl } , + scientific-notation .choice: , + scientific-notation / engineering .code:n = + { + \@@_option_deprecated:nn + { scientific-notation~=~engineering } + { exponent-mode~=~engineering } + } , + scientific-notation / fixed .code:n = + { + \@@_option_deprecated:nn + { scientific-notation~=~fixed } + { exponent-mode~=~fixed } + } , + scientific-notation / false .code:n = + { + \@@_option_deprecated:nn + { scientific-notation~=~false } + { exponent-mode~=~input } + } , + scientific-notation / true .code:n = + { + \@@_option_deprecated:nn + { scientific-notation~=~true } + { exponent-mode~=~scientific } + } , + scientific-notation .default:n = true , + zero-decimal-to-integer .code:n = + { + \@@_option_deprecated:nnV + { zero-decimal-to-integer } + { drop-zero-decimal } + \l_keys_value_tl + } , + zero-decimal-to-integer .default:n = true + } +% \end{macrocode} +% +% \subsubsection{Table options} +% +% All straight-forward emulation. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + table-align-text-post .code:n = + { + \@@_option_deprecated:nnV + { table-align-text-post } + { table-align-text-after } + \l_keys_value_tl + } , + table-align-text-post .default:n = true , + table-align-text-pre .code:n = + { + \@@_option_deprecated:nnV + { table-align-text-pre } + { table-align-text-before } + \l_keys_value_tl + } , + table-align-text-pre .default:n = true , + table-number-alignment / center-decimal-marker .code:n = + { + \msg_info:nnnn { siunitx } { option-deprecated } + { table-number-alignment~=~center-decimal-marker } + { table-alignment-mode~=~marker } + \keys_set:nn + { siunitx } + { table-alignment-mode = marker } + } , + table-omit-exponent .code:n = + { + \@@_option_deprecated:nnV + { table-omit-exponent } + { drop-exponent } + \l_keys_value_tl + } , + table-omit-exponent .default:n = true , + table-parse-only .code:n = + { + \msg_info:nnnn { siunitx } { option-deprecated } + { table-parse-only } + { table-alignment-mode~=~none } + \str_if_eq:VnTF \l_keys_value_tl { false } + { + \keys_set:nn + { siunitx } + { table-alignment-mode = marker } + } + { + \keys_set:nn + { siunitx } + { table-alignment-mode = none } + } + } , + table-space-text-post .code:n = + { + \msg_info:nnnn { siunitx } { option-deprecated } + { table-space-text-post } + { table-format } + \tl_set:Nn \l_@@_table_after_model_tl {#1} + } , + table-space-text-pre .code:n = + { + \msg_info:nnnn { siunitx } { option-deprecated } + { table-space-text-post } + { table-format } + \tl_set:Nn \l_@@_table_before_model_tl {#1} + } + } +% \end{macrocode} +% +% \begin{macro}{\@@_option_table_format:n} +% \begin{macro} +% { +% \@@_option_table_comparator:nnnnnnn , +% \@@_option_table_figures-decimal:nnnnnnnn , +% \@@_option_table_figures-exponent:nnnnnnnn , +% \@@_option_table_figures-integer:nnnnnnnn , +% \@@_option_table_figures-uncertainty:nnnnnnnn , +% \@@_option_table_sign-exponent:nnnnnnnn , +% \@@_option_table_sign-mantissa:nnnnnnnn +% } +% \begin{macrocode} +\cs_new_protected:Npn \@@_option_table_format:n #1 + { + \msg_info:nnnn { siunitx } { option-deprecated } + { table- #1 } + { table-format } + \tl_set:Nx \l_@@_table_format_tl + { + \cs:w @@_option_table_ #1 :nnnnnnnn + \exp_after:wN \exp_after:wN \exp_after:wN \cs_end: + \exp_after:wN \l_@@_table_format_tl + \exp_after:wN { \l_keys_value_tl } + } + \exp_after:wN \@@_table_generate_model:nnnnnnn + \l_@@_table_format_tl + } +\cs_new:Npn \@@_option_table_comparator:nnnnnnnn #1#2#3#4#5#6#7#8 + { \exp_not:n { {#8} {#2} {#3} {#4} {#5} {#6} {#7} } } +\cs_new:cpn { @@_option_table_figures-decimal:nnnnnnnn } + #1#2#3#4#5#6#7#8 + { \exp_not:n { {#1} {#2} {#3} {#8} {#5} {#6} {#7} } } +\cs_new:cpn { @@_option_table_figures-exponent:nnnnnnnn } + #1#2#3#4#5#6#7#8 + { \exp_not:n { {#1} {#2} {#3} {#4} {#5} {#6} {#8} } } +\cs_new:cpn { @@_option_table_figures-integer:nnnnnnnn } + #1#2#3#4#5#6#7#8 + { \exp_not:n { {#1} {#2} {#8} {#4} {#5} {#6} {#7} } } +\cs_new:cpn { @@_option_table_figures-uncertainty:nnnnnnnn } + #1#2#3#4#5#6#7#8 + { \exp_not:n { {#1} {#2} {#3} {#4} { { S } {#8} } {#6} {#7} } } +\cs_new:cpn { @@_option_table_sign-exponent:nnnnnnnn } + #1#2#3#4#5#6#7#8 + { \exp_not:n { {#1} {#2} {#3} {#4} {#5} {#8} {#7} } } +\cs_new:cpn { @@_option_table_sign-mantissa:nnnnnnnn } + #1#2#3#4#5#6#7#8 + { \exp_not:n { {#1} {#8} {#3} {#4} {#5} {#6} {#7} } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% Options which all use the same emulation set up. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + table-comparator .code:n = + { \@@_option_table_format:n { comparator } } , + table-figures-decimal .code:n = + { \@@_option_table_format:n { figures-decimal } } , + table-figures-exponent .code:n = + { \@@_option_table_format:n { figures-exponent } } , + table-figures-integer .code:n = + { \@@_option_table_format:n { figures-integer } } , + table-figures-uncertainty .code:n = + { \@@_option_table_format:n { figures-uncertainty } } , + table-sign-exponent .code:n = + { \@@_option_table_format:n { sign-exponent } } , + table-sign-mantissa .code:n = + { \@@_option_table_format:n { sign-mantissa } } + } +% \end{macrocode} +% +% \subsection{Unit options} +% +% \begin{macrocode} +\keys_define:nn { siunitx } + { + fraction-function .code:n = + { + \@@_option_deprecated:nnV + { fraction-function } + { fraction-command } + \l_keys_value_tl + } , + literal-superscript-as-power .code:n = + { \@@_option_removed:V \l_keys_key_tl } , + per-mode / reciprocal .code:n = + { + \@@_option_deprecated:nn + { per-mode~=~reciprocal } + { per-mode~=~power } + } , + per-mode / reciprocal-positive-first .code:n = + { + \@@_option_deprecated:nn + { per-mode~=~reciprocal-positive-first } + { per-mode~=~power-positive-first } + } , + power-font .code:n = + { \@@_option_removed:V \l_keys_key_tl } , + qualifier-mode / brackets .code:n = + { + \@@_option_deprecated:nn + { qualifier-mode~=~brackets } + { qualifier-mode~=~bracket } + } , + qualifier-mode / space .code:n = + { + \msg_info:nnnn { siunitx } { option-deprecated } + { qualifier-mode~=~space } + { qualifier-mode~=~phrase"~plus~"qualifier-phrase=\ } + \keys_set:nn + { siunitx } + { qualifier-mode = phrase, qualifier-phrase = \ } + } , + qualifier-mode / text .code:n = + { + \@@_option_deprecated:nn + { qualifier-mode~=~text } + { qualifier-mode~=~combine } + } + } +% \end{macrocode} +% +% \subsection{Quantity units} +% +% \begin{macrocode} +\keys_define:nn { siunitx } + { + allow-number-unit-breaks .code:n = + { + \@@_option_deprecated:nnV + { allow-number-unit-breaks } + { allow-quantity-breaks } + \l_keys_value_tl + } , + allow-number-unit-breaks .default:n = true , + exponent-to-prefix .choice: , + exponent-to-prefix / false .code:n = + { + \@@_option_deprecated:nn + { exponent-to-prefix~=~false } + { prefix-mode~=~input } + } , + exponent-to-prefix / true .code:n = + { + \@@_option_deprecated:nn + { exponent-to-prefix~=~true } + { prefix-mode~=~combine-exponent } + } , + exponent-to-prefix .default:n = true , + multi-part-units .choice: , + multi-part-units / brackets . code:n = + { + \@@_option_deprecated:nn + { multi-part-units~=~brackets } + { separate-uncertainty-units~=~bracket } + } , + multi-part-units / repeat . code:n = + { + \@@_option_deprecated:nn + { multi-part-units~=~repeat } + { separate-uncertainty-units~=~repeat } + } , + multi-part-units / single . code:n = + { + \@@_option_deprecated:nn + { multi-part-units~=~single } + { separate-uncertainty-units~=~single } + } , + number-unit-product .code:n = + { + \@@_option_deprecated:nnV + { number-unit-product } + { quantity-product } + \l_keys_value_tl + } , + prefixes-as-symbols .choice: , + prefixes-as-symbols / false . code:n = + { + \@@_option_deprecated:nn + { prefixes-as-symbols~=~false } + { prefix-mode~=~extract-exponent } + } , + prefixes-as-symbols / true . code:n = + { + \@@_option_deprecated:nn + { prefixes-as-symbols~=~true } + { prefix-mode~=~input } + } , + prefixes-as-symbols .default:n = true + } +% \end{macrocode} +% +% \begin{macrocode} +%</options> +% \end{macrocode} +% +% \subsection{Preamble commands} +% +% \begin{macrocode} +%<*interfaces> +% \end{macrocode} +% +% \begin{macro}{\DeclareBinaryPrefix} +% We simply drop |#3|. +% \begin{macrocode} +\NewDocumentCommand \DeclareBinaryPrefix { +m m m } + { + \siunitx_declare_prefix:Nn #1 {#2} + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DeclareSIPrePower, \DeclareSIPostPower} +% Simply use a throw-away command for the part we do not need: this can +% be followed by some clean-up. +% \begin{macrocode} +\NewDocumentCommand \DeclareSIPrePower { +m m } + { + \siunitx_declare_power:NNn #1 \@@_tmp:w {#2} + \seq_remove_all:Nn \l_siunitx_unit_symbolic_seq { \@@_tmp:w } + } +\NewDocumentCommand \DeclareSIPostPower { +m m } + { + \siunitx_declare_power:NNn \@@_tmp:w #1 {#2} + \seq_remove_all:Nn \l_siunitx_unit_symbolic_seq { \@@_tmp:w } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Document commands} +% +% \begin{macro}{\si} +% A straight copy of \cs{unit}. +% \begin{macrocode} +\NewDocumentCommand \si { O { } m } + { + \mode_leave_vertical: + \group_begin: + \keys_set:nn { siunitx } {#1} + \siunitx_unit_format:nN {#2} \l_@@_tmp_tl + \siunitx_print_unit:V \l_@@_tmp_tl + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SI} +% Almost the same as \cs{qty}, but with the addition pre-unit. +% \begin{macrocode} +\NewDocumentCommand \SI { O { } m o m } + { + \mode_leave_vertical: + \group_begin: + \keys_set:nn { siunitx } {#1} + \IfNoValueF {#3} + { + \siunitx_unit_format:nN {#3} \l_@@_tmp_tl + \siunitx_print_unit:V \l_@@_tmp_tl + \nobreak + } + \siunitx_quantity:nn {#2} {#4} + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SIlist, \SIrange} +% Straight copies. +% \begin{macrocode} +\NewDocumentCommand \SIlist + { O { } > { \SplitList { ; } } m > { \TrimSpaces } m } + { + \mode_leave_vertical: + \group_begin: + \siunitx_unit_options_apply:n {#3} + \keys_set:nn { siunitx } {#1} + \siunitx_quantity_list:nn {#2} {#3} + \group_end: + } +\NewDocumentCommand \SIrange { O { } m m > { \TrimSpaces } m } + { + \mode_leave_vertical: + \group_begin: + \siunitx_unit_options_apply:n {#4} + \keys_set:nn { siunitx } {#1} + \siunitx_quantity_range:nnn {#2} {#3} {#4} + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Symbol commands} +% +% \begin{macrocode} +%<@@=siunitx_emulation> +% \end{macrocode} +% +% \begin{macro}{\@@_non_latin:n} +% \begin{macro}{\@@_non_latin:nnnn} +% As in \pkg{siunitx-unit}, but internal in both cases as it's rather +% specialised. +% \begin{macrocode} +\bool_lazy_or:nnTF + { \sys_if_engine_luatex_p: } + { \sys_if_engine_xetex_p: } + { + \cs_new:Npn \@@_non_latin:n #1 + { \char_generate:nn {#1} { \char_value_catcode:n {#1} } } + } + { + \cs_new:Npn \@@_non_latin:n #1 + { + \exp_last_unbraced:Nf \@@_non_latin:nnnn + { \char_to_utfviii_bytes:n {#1} } + } + \cs_new:Npn \@@_non_latin:nnnn #1#2#3#4 + { + \exp_after:wN \exp_after:wN \exp_after:wN + \exp_not:N \char_generate:nn {#1} { 13 } + \exp_after:wN \exp_after:wN \exp_after:wN + \exp_not:N \char_generate:nn {#2} { 13 } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% { +% \SIUnitSymbolAngstrom , +% \SIUnitSymbolArcminute , +% \SIUnitSymbolArcsecond , +% \SIUnitSymbolCelsius , +% \SIUnitSymbolDegree , +% \SIUnitSymbolMicro , +% \SIUnitSymbolOhm +% } +% The same setup as elsewhere but localised to the emulation module +% \begin{macrocode} +\AtBeginDocument + { + \cs_new_protected:Npn \SIUnitSymbolArcminute + { \ensuremath { { } ' } } + \cs_new_protected:Npn \SIUnitSymbolArcsecond + { \ensuremath { { } '' } } + \@ifpackageloaded { fontspec } + { + \cs_new_protected:Npx \SIUnitSymbolAngstrom + { \@@_non_latin:n { "00C5 } } + \cs_new_protected:Npx \SIUnitSymbolDegree + { \@@_non_latin:n { "00B0 } } + \cs_new_protected:Npx \SIUnitSymbolCelsius + { \@@_non_latin:n { "00B0 } C } + } + { + \cs_new_protected:Npx \SIUnitSymbolAngstrom + { + \siunitx_print_text:n + { \@@_non_latin:n { "00C5 } } + } + \cs_new_protected:Npx \SIUnitSymbolCelsius + { + \siunitx_print_text:n + { \@@_non_latin:n { "00B0 } } C + } + \cs_new_protected:Npx \SIUnitSymbolDegree + { + \siunitx_print_text:n + { \@@_non_latin:n { "00B0 } } + } + } + \cs_new_protected:Npx \SIUnitSymbolMicro + { + \siunitx_print_text:n + { + \bool_lazy_or:nnTF + { \sys_if_engine_luatex_p: } + { \sys_if_engine_xetex_p: } + { \@@_non_latin:n { "00B5 } } + { \exp_not:N \textmu } + } + } + \cs_new_protected:Npx \SIUnitSymbolOhm + { + \exp_not:N \ifmmode + \cs_if_exist:NTF \upOmega + { \exp_not:N \upOmega } + { \exp_not:N \Omega } + \exp_not:N \else + \siunitx_print_text:n + { + \bool_lazy_or:nnTF + { \sys_if_engine_luatex_p: } + { \sys_if_engine_xetex_p: } + { \@@_non_latin:n { "03A9 } } + { \exp_not:N \textohm } + } + \exp_not:N \fi + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</interfaces> +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/siunitx/siunitx-locale.dtx b/macros/latex/contrib/siunitx/siunitx-locale.dtx new file mode 100644 index 0000000000..07a934b2fe --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-locale.dtx @@ -0,0 +1,169 @@ +% \iffalse meta-comment +% +% File: siunitx-locale.dtx Copyright (C) 2020,2021 Joseph Wright +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-locale} -- Localisation^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% This submodule is concerned with localisation of \pkg{siunitx} output +% based on the locale. If the \pkg{translations} package is available, this +% is loaded here and used to provide various fixed strings for output. +% +% \begin{function}{locale} +% \begin{syntax} +% |locale| = \meta{locale} +% \end{syntax} +% Selects the \meta{locale} used to apply standard settings for other +% keys, principally |exponent-product|, |inter-unit-product| +% and |output-decimal-marker|. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-locale} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_locale> +% \end{macrocode} +% +% \subsection{Locales} +% +% The basics for defining locales are easy: these are just meta keys. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + locale .choice: , + locale / DE .meta:n = + { + exponent-product = \cdot , + inter-unit-product = \, , + output-decimal-marker = { , } + } , + locale / FR .meta:n = + { + exponent-product = \times , + inter-unit-product = \, , + output-decimal-marker = { , } + } , + locale / UK .meta:n = + { + exponent-product = \times , + inter-unit-product = \, , + output-decimal-marker = . + }, + locale / US .meta:n = + { + exponent-product = \times , + inter-unit-product = \, , + output-decimal-marker = . + } , + locale / ZA .meta:n = + { + exponent-product = \times , + inter-unit-product = \cdot , + output-decimal-marker = { , } + } + } +% \end{macrocode} +% +% \subsection{Localisation} +% +% Localisation makes use of the \pkg{translator} package. This only happens +% if it is available, and is transparent to the user. +% \begin{macrocode} +\file_if_exist:nT { translations.sty } + { + \RequirePackage { translations } + \DeclareTranslation { English } { to~(numerical~range) } { to } + \DeclareTranslation { French } { to~(numerical~range) } { á } + \DeclareTranslation { German } { to~(numerical~range) } { bis } + \DeclareTranslation { Spanish } { to~(numerical~range) } { a } + \keys_set:nn { siunitx } + { + list-final-separator = + { + \ifmmode \ \else \space \fi + \text { \GetTranslation { and } } + \ifmmode \ \else \space \fi + } , + list-pair-separator = + { + \ifmmode \ \else \space \fi + \text { \GetTranslation { and } } + \ifmmode \ \else \space \fi + } , + range-phrase = + { + \ifmmode \ \else \space \fi + \text { \GetTranslation { to~(numerical~range) } } + \ifmmode \ \else \space \fi + } + } + } +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/siunitx/siunitx-number.dtx b/macros/latex/contrib/siunitx/siunitx-number.dtx new file mode 100644 index 0000000000..adc798fb2c --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-number.dtx @@ -0,0 +1,3549 @@ +% \iffalse meta-comment +% +% File: siunitx-number.dtx Copyright (C) 2014-2019,2021 Joseph Wright +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +\ProvideDocumentCommand\foreign{m}{\textit{#1}} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-number} -- Parsing and formatting numbers^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \section{Formatting numbers} +% +% \begin{function}{\siunitx_number_parse:nN, \siunitx_number_parse:VN} +% \begin{syntax} +% \cs{siunitx_number_parse:nN} \Arg{number} \meta{tl~var} +% \end{syntax} +% Parses the \emph{number} and stores the resulting internal representation +% in the \meta{tl~var}. The parsing is influenced by the various key--value +% settings for numerical input. The \meta{number} should comprise a single +% real value, possibly with comparator, uncertainty and exponent parts. +% If the number is invalid, or if number parsing is disabled, the result will +% be an entirely empty \meta{tl~var}. +% +% The structure of a valid number is: +% \begin{quote} +% \marg{comparator}\marg{sign}\marg{integer}\marg{decimal} +% \marg{uncertainty}\\ +% \marg{exponent sign}\marg{exponent} +% \end{quote} +% where the two sign parts must be single tokens if present, +% and all other components +% must be given in braces. The number will have at least one digit for both the +% \meta{integer} and \meta{exponent} parts: these are required. The +% \meta{uncertainty} part should either be blank or contain an +% \meta{identifier} (as a brace group), followed by one or more data entries. +% Valid \meta{identifiers} currently are +% \begin{itemize} +% \item[\texttt{S}] A single symmetrical uncertainty (\foreign{e.g.}~a +% statistical standard uncertainty) +% \end{itemize} +% \end{function} +% +% \begin{function}{\siunitx_number_process:NN} +% \begin{syntax} +% \cs{siunitx_number_process:N} \meta{tl~var1} \meta{tl~var2} +% \end{syntax} +% Applies a set of number processing operations to the \meta{internal +% number} stored in the \meta{tl~var1}, \foreign{viz.}~in order +% \begin{enumerate} +% \item Dropping uncertainty +% \item Converting to scientific mode (or similar) +% \item Rounding +% \item Dropping zero decimal part +% \item Forcing a minimum number of digits +% \end{enumerate} +% with the result stored in \meta{tl~var2}. +% \end{function} +% +% \begin{function}[rEXP] +% { +% \siunitx_number_output:N, \siunitx_number_output:n, +% \siunitx_number_output:NN, \siunitx_number_output:nN +% } +% \begin{syntax} +% \cs{siunitx_number_output:N} \meta{number} +% \cs{siunitx_number_output:NN} \meta{number} \meta{marker} +% \end{syntax} +% Formats the \meta{number} (in the \pkg{siunitx} internal format), +% producing the result in a form suitable for typesetting in math mode. +% The details for the formatting are controlled by a number of key--value +% options. Note that \emph{formatting} does not apply any manipulation +% (processing) to the number. This function is usable in an \texttt{e}- +% or \texttt{x}-type expansion, and further uncontrolled expansion is +% prevented by appropriate use of |\exp_not:n| internally. +% +% In the \texttt{NN} version, the \meta{marker} token is inserted at each +% possible alignment position in the output, \foreign{viz.} +% \begin{itemize} +% \item Between the comparator and the integer (\emph{before} any +% sign for the integer) +% \item Between the sign and the first digit of the integer +% \item Both sides of the decimal marker +% \item Both sides of the separated uncertainty sign (\foreign{i.e.}~after +% the decimal part and before any integer uncertainty part) +% \item Both sides of the decimal marker for a separated uncertainty +% \item Both sides of the multiplication symbol for the exponent part. +% \end{itemize} +% +% The \texttt{n} and \texttt{nN} version take a token list, which should +% be in the internal \pkg{siunitx} format. +% \end{function} +% +% \begin{function}{\siunitx_number_format:nN} +% \begin{syntax} +% \cs{siunitx_number_format:nN} \Arg{number} \meta{tl~var} +% \end{syntax} +% Carries out a combination of \cs{siunitx_number_parse:nN}, +% \cs{siunitx_number_process:NN} and \cs{siunitx_number_output:N} using +% \texttt{x}-type expansion to place the result in the \meta{tl~var}. If +% \cs{l_siunitx_number_parse_bool} if \texttt{false}, the input is simply +% stored inside the \meta{tl~var} inside \cs{ensuremath}. +% \end{function} +% +% \begin{function}[EXP] +% { +% \siunitx_number_adjust_exponent:Nn , +% \siunitx_number_adjust_exponent:nn +% } +% \begin{syntax} +% \cs{siunitx_number_adjust_exponent:Nn} \meta{number} \Arg{fp~expr} +% \end{syntax} +% Adjusts the exponent of the \meta{number} (in internal format) by the +% \meta{fp~expr} and leaves the result in the input stream. +% \end{function} +% +% \begin{function}{\siunitx_number_normalize_symbols:N} +% \begin{syntax} +% \cs{siunitx_number_normalize_symbols:N} \meta{tl~var} +% \end{syntax} +% Replaces all multi-token signs and comparators in the \meta{tl~var} +% with their single-token equivalents. Replaces any active hyphen tokens +% with non-active versions. +% \end{function} +% +% \begin{function}[pTF, EXP]{\siunitx_if_number:n} +% \begin{syntax} +% \cs{siunitx_if_number_token:NTF} \Arg{tokens} +% \Arg{true code} \Arg{false code} +% \end{syntax} +% Determines if the \meta{tokens} form a valid number which can be fully +% parsed by \pkg{siunitx}. +% \end{function} +% +% \begin{function}[TF]{\siunitx_if_number_token:N} +% \begin{syntax} +% \cs{siunitx_if_number_token:NTF} \Arg{token} +% \Arg{true code} \Arg{false code} +% \end{syntax} +% Determines if the \meta{token} is valid in a number based on those +% tokens currently set up for detection in a number. +% \end{function} +% +% \begin{variable}{\l_siunitx_bracket_ambiguous_bool} +% A switch to control whether ambiguous numbers are bracketed: this can +% also be covered in quantity formatting by a setting there. +% \end{variable} +% +% \begin{variable}{\l_siunitx_number_parse_bool} +% A switch to control whether any parsing is attempted for numbers. +% \end{variable} +% +% \begin{variable} +% { +% \l_siunitx_number_comparator_tl , +% \l_siunitx_number_exponent_tl , +% \l_siunitx_number_sign_tl +% } +% The list of possible input comparators, exponent markers and signs. +% \end{variable} +% +% \begin{variable} +% {\l_siunitx_number_input_decimal_tl, \l_siunitx_number_output_decimal_tl} +% The list of possible input decimal marker(s), and the output marker. +% \end{variable} +% +% \subsection{Key--value options} +% +% The options defined by this submodule are available within the \pkg{l3keys} +% |siunitx| tree. +% +% \begin{function}{bracket-ambiguous-numbers} +% \begin{syntax} +% |bracket-ambiguous-numbers| = |true|\verb"|"|false| +% \end{syntax} +% \end{function} +% +% \begin{function}{bracket-negative-numbers} +% \begin{syntax} +% |bracket-negative-numbers| = |true|\verb"|"|false| +% \end{syntax} +% \end{function} +% +% \begin{function}{drop-exponent} +% \begin{syntax} +% |drop-exponent| = |true|\verb"|"|false| +% \end{syntax} +% \end{function} +% +% \begin{function}{drop-uncertainty} +% \begin{syntax} +% |drop-uncertainty| = |true|\verb"|"|false| +% \end{syntax} +% \end{function} +% +% \begin{function}{drop-zero-decimal} +% \begin{syntax} +% |drop-zero-decimal| = |true|\verb"|"|false| +% \end{syntax} +% \end{function} +% +% \begin{function}{evaluate-expression} +% \begin{syntax} +% |evaluate-expression| = |true|\verb"|"|false| +% \end{syntax} +% \end{function} +% +% \begin{function}{exponent-base} +% \begin{syntax} +% |exponent-base| = \meta{base} +% \end{syntax} +% \end{function} +% +% \begin{function}{exponent-mode} +% \begin{syntax} +% |exponent-mode| = |engineering|\verb"|"|fixed|\verb"|"|input|\verb"|"|scientific| +% \end{syntax} +% \end{function} +% +% \begin{function}{exponent-product} +% \begin{syntax} +% |exponent-product| = \meta{symbol} +% \end{syntax} +% \end{function} +% +% \begin{function}{expression} +% \begin{syntax} +% |expression| = \meta{expression} +% \end{syntax} +% \end{function} +% +% \begin{function}{fixed-exponent} +% \begin{syntax} +% |fixed-exponent| = \meta{exponent} +% \end{syntax} +% \end{function} +% +% \begin{function}{group-digits} +% \begin{syntax} +% |group-digits| = |all|\verb"|"|decimal|\verb"|"|integer|\verb"|"|none| +% \end{syntax} +% \end{function} +% +% \begin{function}{group-minimum-digits} +% \begin{syntax} +% |group-minimum-digits| = \meta{value} +% \end{syntax} +% \end{function} +% +% \begin{function}{group-separator} +% \begin{syntax} +% |group-separator| = \meta{symbol} +% \end{syntax} +% \end{function} +% +% \begin{function}{input-close-uncertainty} +% \begin{syntax} +% |input-close-uncertainty| = \meta{tokens} +% \end{syntax} +% \end{function} +% +% \begin{function}{input-comparators} +% \begin{syntax} +% |input-comparators| = \meta{tokens} +% \end{syntax} +% \end{function} +% +% \begin{function}{input-close-uncertainty} +% \begin{syntax} +% |input-close-uncertainty| = \meta{tokens} +% \end{syntax} +% \end{function} +% +% \begin{function}{input-decimal-markers} +% \begin{syntax} +% |input-decimal-markers| = \meta{tokens} +% \end{syntax} +% \end{function} +% +% \begin{function}{input-digits} +% \begin{syntax} +% |input-digits| = \meta{tokens} +% \end{syntax} +% \end{function} +% +% \begin{function}{input-exponent-markers} +% \begin{syntax} +% |input-exponent-markers| = \meta{tokens} +% \end{syntax} +% \end{function} +% +% \begin{function}{input-open-uncertainty} +% \begin{syntax} +% |input-open-uncertainty| = \meta{tokens} +% \end{syntax} +% \end{function} +% +% \begin{function}{input-signs} +% \begin{syntax} +% |input-signs| = \meta{tokens} +% \end{syntax} +% \end{function} +% +% \begin{function}{input-uncertainty-signs} +% \begin{syntax} +% |input-uncertainty-signs| = \meta{tokens} +% \end{syntax} +% \end{function} +% +% \begin{function}{minimum-decimal-digits} +% \begin{syntax} +% |minimum-decimal-digits| = \meta{min} +% \end{syntax} +% \end{function} +% +% \begin{function}{minimum-integer-digits} +% \begin{syntax} +% |minimum-integer-digits| = \meta{min} +% \end{syntax} +% \end{function} +% +% \begin{function}{negative-color} +% \begin{syntax} +% |negative-color| = \meta{color} +% \end{syntax} +% \end{function} +% +% \begin{function}{output-close-uncertainty} +% \begin{syntax} +% |output-close-uncertainty| = \meta{symbol} +% \end{syntax} +% \end{function} +% +% \begin{function}{output-decimal-marker} +% \begin{syntax} +% |output-decimal-marker| = \meta{symbol} +% \end{syntax} +% \end{function} +% +% \begin{function}{output-open-uncertainty} +% \begin{syntax} +% |output-open-uncertainty| = \meta{symbol} +% \end{syntax} +% \end{function} +% +% \begin{function}{parse-numbers} +% \begin{syntax} +% |parse-numbers| = |true|\verb"|"|false| +% \end{syntax} +% \end{function} +% +% \begin{function}{print-implicit-plus} +% \begin{syntax} +% |print-implicit-plus| = |true|\verb"|"|false| +% \end{syntax} +% \end{function} +% +% \begin{function}{print-unity-mantissa} +% \begin{syntax} +% |print-unity-mantissa| = |true|\verb"|"|false| +% \end{syntax} +% \end{function} +% +% \begin{function}{print-zero-exponent} +% \begin{syntax} +% |print-zero-exponent| = |true|\verb"|"|false| +% \end{syntax} +% \end{function} +% +% \begin{function}{retain-explicit-plus} +% \begin{syntax} +% |retain-explicit-plus| = |true|\verb"|"|false| +% \end{syntax} +% \end{function} +% +% \begin{function}{retain-zero-uncertainty} +% \begin{syntax} +% |retain-zero-uncertainty| = |true|\verb"|"|false| +% \end{syntax} +% \end{function} +% +% \begin{function}{round-half} +% \begin{syntax} +% |round-half| = |even|\verb"|"|up| +% \end{syntax} +% \end{function} +% +% \begin{function}{round-minimum} +% \begin{syntax} +% |round-minimum| = \meta{min} +% \end{syntax} +% \end{function} +% +% \begin{function}{round-mode} +% \begin{syntax} +% |round-mode| = |figures|\verb"|"|none|\verb"|"|places|\verb"|"|uncertainty| +% \end{syntax} +% \end{function} +% +% \begin{function}{round-pad} +% \begin{syntax} +% |round-pad| = |true|\verb"|"|false| +% \end{syntax} +% \end{function} +% +% \begin{function}{round-precision} +% \begin{syntax} +% |round-precision| = \meta{precision} +% \end{syntax} +% \end{function} +% +% \begin{function}{separate-uncertainty} +% \begin{syntax} +% |separate-uncertainty| = |true|\verb"|"|false| +% \end{syntax} +% \end{function} +% +% \begin{function}{tight-spacing} +% \begin{syntax} +% |tight-spacing| = |true|\verb"|"|false| +% \end{syntax} +% \end{function} +% +% \begin{function}{uncertainty-mode} +% \begin{syntax} +% |uncertainty-mode| = |compact|\verb"|"|compact-marker|\verb"|"|full|\verb"|"|separate| +% \end{syntax} +% \end{function} +% +% \begin{function}{uncertainty-separator} +% \begin{syntax} +% |uncertainty-separator| = \meta{separator} +% \end{syntax} +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-number} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_number> +% \end{macrocode} +% +% \subsection{Initial set-up} +% +% Variants not provided by \pkg{expl3}. +% \begin{macrocode} +\cs_generate_variant:Nn \tl_if_blank:nTF { f } +\cs_generate_variant:Nn \tl_if_blank_p:n { f } +\cs_generate_variant:Nn \tl_if_in:NnTF { NV } +\cs_generate_variant:Nn \tl_replace_all:Nnn { NnV } +% \end{macrocode} +% +% \begin{variable}{\l_@@_tmp_tl} +% Scratch space. +% \begin{macrocode} +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{variable} +% +% \subsection{Main formatting routine} +% +% \begin{variable}{\l_@@_outputted_tl} +% A token list for the final formatted result: may or may not be generated +% by the parser, depending on settings which are active. +% \begin{macrocode} +\tl_new:N \l_@@_outputted_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_siunitx_number_parse_bool} +% Tracks whether to parse numbers: public as this may affect other +% behaviors. +% \begin{macrocode} +\tl_new:N \l_siunitx_number_parse_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_siunitx_number_parse_bool} +% Top-level options. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + parse-numbers .bool_set:N = \l_siunitx_number_parse_bool + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_number_format:nN} +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_number_format:nN #1#2 + { + \group_begin: + \bool_if:NTF \l_siunitx_number_parse_bool + { + \siunitx_number_parse:nN {#1} \l_@@_parsed_tl + \siunitx_number_process:NN \l_@@_parsed_tl \l_@@_parsed_tl + \tl_set:Nx \l_@@_outputted_tl + { \siunitx_number_output:N \l_@@_parsed_tl } + } + { \tl_set:Nn \l_@@_outputted_tl { \ensuremath {#1} } } + \exp_args:NNNV \group_end: + \tl_set:Nn #2 \l_@@_outputted_tl + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Parsing numbers} +% +% Before numbers can be manipulated or formatted they need to be parsed into +% an internal form. In particular, if multiple code paths are to be avoided, +% it is necessary to do such parsing even for relatively simple cases such +% as converting |1e10| to |1 \times 10^{10}|. +% +% Storing the result of such parsing can be done in a number of ways. In the +% first version of \pkg{siunitx} a series of separate data stores were used. +% This is potentially quite fast (as recovery of items relies only on \TeX{}'s +% hash table) but makes managing the various data entries somewhat tedious and +% error-prone. For version two of the package, a single data structure +% (property list) was used for each part of the parsed number. Whilst this is +% easy to manage and extend, it is somewhat slower as at a \TeX{} level there +% are repeated pack--unpack steps. In particular, the fact that there are a +% limited number of items to track for a \enquote{number} means that a more +% efficient approach is desirable (contrast parsing units, which is open-ended +% and therefore fits well with using a property list). +% +% In this release, the structure of a valid number is: +% \begin{quote} +% \marg{comparator}\meta{sign}\marg{integer}\marg{decimal} +% \marg{uncertainty}\\ +% \meta{exponent sign}\marg{exponent} +% \end{quote} +% where all components must be given in braces. \emph{All} of the components +% must be present in a stored number (\foreign{i.e.}~at the end of parsing). +% The number must have at least one digit for both the \meta{integer} and +% \meta{exponent} parts. +% +% A non-empty \meta{uncertainty} must contain one leading brace group +% containing an identifier, then zero or more brace groups which contain +% the uncertainty data. In this release, the known uncertainty types are +% \begin{itemize} +% \item \texttt{S}: A symmetrical statistical uncertainty made up of +% a single value. These are stored as uncertainty in significant digits, +% with no radix point in the stored value. +% \end{itemize} +% +% \begin{variable}{\l_siunitx_number_input_decimal_tl} +% The input decimal markers(s). +% \begin{macrocode} +\tl_new:N \l_siunitx_number_input_decimal_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% { +% \l_@@_expression_bool , +% \l_@@_input_uncert_close_tl , +% \l_siunitx_number_input_comparator_tl , +% \l_@@_input_digit_tl , +% \l_siunitx_number_input_exponent_tl , +% \l_@@_input_ignore_tl , +% \l_@@_input_uncert_open_tl , +% \l_siunitx_number_input_sign_tl , +% \l_@@_input_uncert_sign_tl , +% \l_@@_explicit_plus_bool , +% \l_@@_zero_uncert_bool +% } +% \begin{macro}[EXP]{\@@_expression:n} +% Options which determine the various valid parts of a parsed number. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + evaluate-expression .bool_set:N = + \l_@@_expression_bool , + expression .code:n = + \cs_set:Npn \@@_expression:n ##1 {#1} , + input-close-uncertainty .tl_set:N = + \l_@@_input_uncert_close_tl , + input-comparators .tl_set:N = + \l_siunitx_number_input_comparator_tl , + input-decimal-markers .tl_set:N = + \l_siunitx_number_input_decimal_tl , + input-digits .tl_set:N = + \l_@@_input_digit_tl , + input-exponent-markers .tl_set:N = + \l_siunitx_number_input_exponent_tl , + input-ignore .tl_set:N = + \l_@@_input_ignore_tl , + input-open-uncertainty .tl_set:N = + \l_@@_input_uncert_open_tl , + input-signs .tl_set:N = + \l_siunitx_number_input_sign_tl , + input-uncertainty-signs .code:n = + { + \tl_set:Nn \l_@@_input_uncert_sign_tl {#1} + \tl_map_inline:nn {#1} + { + \tl_if_in:NnF \l_siunitx_number_input_sign_tl {##1} + { \tl_put_right:Nn \l_siunitx_number_input_sign_tl {##1} } + } + } , + parse-numbers .bool_set:N = + \l_siunitx_number_parse_bool , + retain-explicit-plus .bool_set:N = + \l_@@_explicit_plus_bool , + retain-zero-uncertainty .bool_set:N = + \l_@@_zero_uncert_bool + } +\cs_new:Npn \@@_expression:n #1 { } +\tl_new:N \l_@@_input_uncert_sign_tl +% \end{macrocode} +% \end{macro} +% \end{variable} +% +% \begin{variable}{\l_@@_arg_tl} +% The input argument or a part thereof, depending on the position in +% the parsing routine. +% \begin{macrocode} +\tl_new:N \l_@@_arg_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_comparator_tl} +% A comparator, if found, is held here. +% \begin{macrocode} +\tl_new:N \l_@@_comparator_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_exponent_tl} +% The exponent part of a parsed number. It is easiest to find this +% relatively early in the parsing process, but as it needs to go at +% the end of the internal format is held separately until required. +% \begin{macrocode} +\tl_new:N \l_@@_exponent_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_flex_tl} +% In a number with an uncertainty, the exact meaning of a second part is +% not fully resolved until parsing is complete. That is handled using +% this \enquote{flexible} store. +% \begin{macrocode} +\tl_new:N \l_@@_flex_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_parsed_tl} +% The number parsed into internal format. +% \begin{macrocode} +\tl_new:N \l_@@_parsed_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_input_tl} +% The numerical input exactly as given by the user. +% \begin{macrocode} +\tl_new:N \l_@@_input_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_partial_tl} +% To avoid needing to worry about the fact that the final data stores are +% somewhat tricky to add to token-by-token, a simple store is used to build +% up the parsed part of a number before transferring in one go. +% \begin{macrocode} +\tl_new:N \l_@@_partial_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_validate_bool} +% Used to set up for validation with no error production. +% \begin{macrocode} +\bool_new:N \l_@@_validate_bool +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_number_normalize_symbols:N} +% \begin{macro}{\@@_normalize_aux:nN} +% \begin{macro}{\@@_normalize_sign:N} +% \begin{variable}{\c_@@_normalize_tl} +% There are two parts to the replacement code. First, any active +% hyphens signs are normalised: these can come up with some packages and +% cause issues. Multi-token signs then are converted to the single token +% equivalents so that everything else can work on a one token basis. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_number_normalize_symbols:N #1 + { + \@@_normalize_minus:N #1 + \exp_after:wN \@@_normalize_aux:NnN \exp_after:wN #1 + \c_@@_normalize_tl + { ? } \q_recursion_tail + \q_recursion_stop + } +\cs_set_protected:Npn \@@_normalize_aux:NnN #1#2#3 + { + \quark_if_recursion_tail_stop:N #3 + \tl_replace_all:Nnn #1 {#2} {#3} + \@@_normalize_aux:NnN #1 + } +\tl_const:Nn \c_@@_normalize_tl + { + { -+ } \mp + { +- } \pm + { << } \ll + { <= } \le + { >> } \gg + { >= } \ge + } +\group_begin: + \char_set_catcode_active:N \- + \cs_new_protected:Npx \@@_normalize_minus:N #1 + { + \tl_replace_all:Nnn #1 + { \exp_not:N - } { \token_to_str:N - } + } +\group_end: +% \end{macrocode} +% \end{variable} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\siunitx_number_parse:nN, \siunitx_number_parse:VN} +% \begin{macro}{\@@_parse:nN} +% After some initial set up, the parser expands the input and then replaces +% as far as possible tricky tokens with ones that can be handled using +% delimited arguments. To avoid multiple conditionals here, the parser is +% set up as a chain of commands initially, with a loop only later. This +% avoids more conditionals than are necessary. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_number_parse:nN #1#2 + { + \bool_if:NTF \l_siunitx_number_parse_bool + { \@@_parse:nN {#1} #2 } + { \tl_clear:N #2 } + } +\cs_generate_variant:Nn \siunitx_number_parse:nN { V } +\cs_new_protected:Npn \@@_parse:nN #1#2 + { + \group_begin: + \tl_clear:N \l_@@_parsed_tl + \protected@edef \l_@@_arg_tl + { + \bool_if:NTF \l_@@_expression_bool + { \fp_eval:n { \@@_expression:n {#1} } } + {#1} + } + \tl_set_eq:NN \l_@@_input_tl \l_@@_arg_tl + \siunitx_number_normalize_symbols:N \l_@@_arg_tl + \tl_if_empty:NF \l_@@_arg_tl + { \@@_parse_comparator: } + \@@_parse_check: + \exp_args:NNNV \group_end: + \tl_set:Nn #2 \l_@@_parsed_tl + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_check:} +% After the loop there is one case that might need tidying up. If a +% separated uncertainty was found it will be currently in \cs{l_@@_flex_tl} +% and needs moving. A series of tests pick up that case, then the check is +% made that some content was found +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_check: + { + \tl_if_empty:NF \l_@@_flex_tl + { + \bool_lazy_and:nnTF + { + \tl_if_blank_p:f + { \exp_after:wN \use_iv:nnnn \l_@@_parsed_tl } + } + { + \tl_if_blank_p:f + { \exp_after:wN \use_iv:nnnn \l_@@_flex_tl } + } + { + \tl_set:Nx \l_@@_tmp_tl + { \exp_after:wN \use_i:nnnn \l_@@_flex_tl } + \tl_if_in:NVTF \l_@@_input_uncert_sign_tl + \l_@@_tmp_tl + { \@@_parse_combine_uncert: } + { \tl_clear:N \l_@@_parsed_tl } + } + { \tl_clear:N \l_@@_parsed_tl } + } + \tl_if_empty:NTF \l_@@_parsed_tl + { + \bool_if:NF \l_@@_validate_bool + { + \msg_error:nnx { siunitx } { invalid-number } + { \exp_not:V \l_@@_input_tl } + } + } + { \@@_parse_finalise: } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_parse_combine_uncert:} +% \begin{macro}{\@@_parse_combine_uncert_auxi:nnnnnnnn} +% \begin{macro} +% { +% \@@_parse_combine_uncert_auxii:nnnnn, +% \@@_parse_combine_uncert_auxii:fnnnn +% } +% \begin{macro} +% { +% \@@_parse_combine_uncert_auxiii:nnnnnn, +% \@@_parse_combine_uncert_auxiii:fnnnnn +% } +% \begin{macro}{\@@_parse_combine_uncert_auxiv:nnnn} +% \begin{macro}[EXP]{\@@_parse_combine_uncert_auxv:w} +% \begin{macro}[EXP]{\@@_parse_combine_uncert_auxvi:w} +% Conversion of a second numerical part to an uncertainty needs a bit of +% work. The first step is to extract the useful information from the two +% stores: the sign, integer and decimal parts from the real number and the +% integer and decimal parts from the second number. That is done using the +% input stack to avoid lots of assignments. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_combine_uncert: + { + \exp_after:wN \exp_after:wN \exp_after:wN + \@@_parse_combine_uncert_auxi:nnnnnnnn + \exp_after:wN \l_@@_parsed_tl \l_@@_flex_tl + } +% \end{macrocode} +% Here, |#4|, |#5| and |#8| are all junk arguments simply there to mop up +% tokens, while |#1| will be recovered later from \cs{l_@@_parsed_tl} so does +% not need to be passed about. The difference in places between the two +% decimal parts is now found: this is done just once to avoid having to +% parse token lists twice. The value is then used to generate a number of +% filler |0| tokens, and these are added to the appropriate part of the +% number. Finally, everything is recombined: the integer part only needs +% a test to avoid an empty main number. +% \begin{macrocode} +\cs_new_protected:Npn + \@@_parse_combine_uncert_auxi:nnnnnnnn #1#2#3#4#5#6#7#8 + { + \int_compare:nNnTF { \tl_count:n {#6} } > { \tl_count:n {#2} } + { + \tl_clear:N \l_@@_parsed_tl + \tl_clear:N \l_@@_flex_tl + } + { + \@@_parse_combine_uncert_auxii:fnnnn + { \int_eval:n { \tl_count:n {#3} - \tl_count:n {#7} } } + {#2} {#3} {#6} {#7} + } + } +\cs_new_protected:Npn + \@@_parse_combine_uncert_auxii:nnnnn #1 + { + \@@_parse_combine_uncert_auxiii:fnnnnn + { \prg_replicate:nn { \int_abs:n {#1} } { 0 } } + {#1} + } +\cs_generate_variant:Nn \@@_parse_combine_uncert_auxii:nnnnn { f } +\cs_new_protected:Npn + \@@_parse_combine_uncert_auxiii:nnnnnn #1#2#3#4#5#6 + { + \int_compare:nNnTF {#2} > 0 + { + \@@_parse_combine_uncert_auxiv:nnnn + {#3} {#4} {#5} { #6 #1 } + } + { + \@@_parse_combine_uncert_auxiv:nnnn + {#3} { #4 #1 } {#5} {#6} + } + } +\cs_generate_variant:Nn + \@@_parse_combine_uncert_auxiii:nnnnnn { f } +\cs_new_protected:Npn + \@@_parse_combine_uncert_auxiv:nnnn #1#2#3#4 + { + \tl_set:Nx \l_@@_parsed_tl + { + { \tl_head:V \l_@@_parsed_tl } + { \exp_not:n {#1} } + { + \bool_lazy_and:nnTF + { \tl_if_blank_p:n {#2} } + { ! \tl_if_blank_p:n {#4} } + { 0 } + { \exp_not:n {#2} } + } + { + \@@_parse_combine_uncert_auxv:w #3#4 + \q_recursion_tail \q_recursion_stop + } + } + } +% \end{macrocode} +% A short routine to remove any leading zeros in the uncertainty part, +% which are not needed for the compact representation used by the module. +% \begin{macrocode} +\cs_new:Npn \@@_parse_combine_uncert_auxv:w #1 + { + \quark_if_recursion_tail_stop_do:Nn #1 + { + \bool_if:NT \l_@@_zero_uncert_bool + { { S } { 0 } } + } + \str_if_eq:nnTF {#1} { 0 } + { \@@_parse_combine_uncert_auxv:w } + { \@@_parse_combine_uncert_auxvi:w #1 } + } +\cs_new:Npn \@@_parse_combine_uncert_auxvi:w + #1 \q_recursion_tail \q_recursion_stop + { { S } { \exp_not:n {#1} } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_comparator:} +% \begin{macro}{\@@_parse_comparator_aux:Nw} +% A comparator has to be the very first token in the input. A such, the +% test for this can be very fast: grab the first token, do a check and +% if appropriate store the result. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_comparator: + { + \exp_after:wN \@@_parse_comparator_aux:Nw + \l_@@_arg_tl \q_stop + } +\cs_new_protected:Npn \@@_parse_comparator_aux:Nw #1#2 \q_stop + { + \tl_if_in:NnTF \l_siunitx_number_input_comparator_tl {#1} + { + \tl_set:Nn \l_@@_comparator_tl {#1} + \tl_set:Nn \l_@@_arg_tl {#2} + } + { \tl_clear:N \l_@@_comparator_tl } + \tl_if_empty:NF \l_@@_arg_tl + { \@@_parse_sign: } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_exponent:} +% \begin{macro}{\@@_parse_exponent_auxi:w} +% \begin{macro}{\@@_parse_exponent_auxii:nn} +% \begin{macro}{\@@_parse_exponent_auxiii:Nw} +% \begin{macro}{\@@_parse_exponent_auxiv:nn} +% \begin{macro} +% {\@@_parse_exponent_zero_test:N, \@@_parse_exponent_check:N} +% \begin{macro}{\@@_parse_exponent_cleanup:N} +% An exponent part of a number has to come at the end and can only occur +% once. Thus it is relatively easy to parse. First, there is a check that +% an exponent part is allowed, and if so a split is made (the previous +% part of the chain checks that there is some content in \cs{l_@@_arg_tl} +% before calling this function). After splitting, if there is no exponent +% then simply save a default. Otherwise, check for a sign and then store +% either this or an implicit plus, and the digits after a check that nothing +% else is present after the~|e|. The only slight complication to all of +% this is allowing an arbitrary token in the input to represent the exponent: +% this is done by setting any exponent tokens to the first of the allowed +% list, then using that in a delimited argument set up. Once an exponent +% part is found, there is a loop to check that each of the tokens is a digit +% then a tidy up step to remove any leading zeros. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_exponent: + { + \tl_if_empty:NTF \l_siunitx_number_input_exponent_tl + { + \tl_set:Nn \l_@@_exponent_tl { { } 0 } + \tl_if_empty:NF \l_@@_parsed_tl + { \@@_parse_loop: } + } + { + \tl_set:Nx \l_@@_tmp_tl + { \tl_head:V \l_siunitx_number_input_exponent_tl } + \tl_map_inline:Nn \l_siunitx_number_input_exponent_tl + { + \tl_replace_all:NnV \l_@@_arg_tl + {##1} \l_@@_tmp_tl + } + \use:x + { + \cs_set_protected:Npn + \exp_not:N \@@_parse_exponent_auxi:w + ####1 \exp_not:V \l_@@_tmp_tl + ####2 \exp_not:V \l_@@_tmp_tl + ####3 \exp_not:N \q_stop + } + { \@@_parse_exponent_auxii:nn {##1} {##2} } + \use:x + { + \@@_parse_exponent_auxi:w + \exp_not:V \l_@@_arg_tl + \exp_not:V \l_@@_tmp_tl \exp_not:N \q_nil + \exp_not:V \l_@@_tmp_tl \exp_not:N \q_stop + } + } + } +\cs_new_protected:Npn \@@_parse_exponent_auxi:w { } +\cs_new_protected:Npn \@@_parse_exponent_auxii:nn #1#2 + { + \quark_if_nil:nTF {#2} + { \tl_set:Nn \l_@@_exponent_tl { { } 0 } } + { + \tl_set:Nn \l_@@_arg_tl {#1} + \tl_if_blank:nTF {#2} + { \tl_clear:N \l_@@_parsed_tl } + { \@@_parse_exponent_auxiii:Nw #2 \q_stop } + } + \tl_if_empty:NF \l_@@_parsed_tl + { \@@_parse_loop: } + } +\cs_new_protected:Npn \@@_parse_exponent_auxiii:Nw #1#2 \q_stop + { + \tl_if_in:NnTF \l_siunitx_number_input_sign_tl {#1} + { \@@_parse_exponent_auxiv:nn {#1} {#2} } + { \@@_parse_exponent_auxiv:nn { } {#1#2} } + \tl_if_empty:NT \l_@@_exponent_tl + { \tl_clear:N \l_@@_parsed_tl } + } +\cs_new_protected:Npn \@@_parse_exponent_auxiv:nn #1#2 + { + \bool_lazy_or:nnTF + { \l_@@_explicit_plus_bool } + { ! \str_if_eq_p:nn {#1} { + } } + { \tl_set:Nn \l_@@_exponent_tl { {#1} } } + { \tl_set:Nn \l_@@_exponent_tl { { } } } + \tl_if_blank:nTF {#2} + { \tl_clear:N \l_@@_parsed_tl } + { + \@@_parse_exponent_zero_test:N #2 + \q_recursion_tail \q_recursion_stop + } + } +\cs_new_protected:Npn \@@_parse_exponent_zero_test:N #1 + { + \quark_if_recursion_tail_stop_do:Nn #1 + { \tl_set:Nn \l_@@_exponent_tl { { } 0 } } + \str_if_eq:nnTF {#1} { 0 } + { \@@_parse_exponent_zero_test:N } + { \@@_parse_exponent_check:N #1 } + } +\cs_new_protected:Npn \@@_parse_exponent_check:N #1 + { + \quark_if_recursion_tail_stop:N #1 + \tl_if_in:NnTF \l_@@_input_digit_tl {#1} + { + \tl_put_right:Nn \l_@@_exponent_tl {#1} + \@@_parse_exponent_check:N + } + { \@@_parse_exponent_cleanup:wN } + } +\cs_new_protected:Npn \@@_parse_exponent_cleanup:wN + #1 \q_recursion_stop + { \tl_clear:N \l_@@_parsed_tl } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_finalise:} +% \begin{macro}{\@@_parse_finalise:nw} +% Combine all of the bits of a number together: both the real and +% imaginary parts contain all of the data. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_finalise: + { + \tl_if_empty:NF \l_@@_parsed_tl + { + \tl_set:Nx \l_@@_parsed_tl + { + { \exp_not:V \l_@@_comparator_tl } + \exp_not:V \l_@@_parsed_tl + \exp_after:wN \@@_parse_finalise:nw + \l_@@_exponent_tl \q_stop + } + } + } +\cs_new:Npn \@@_parse_finalise:nw #1#2 \q_stop + { + { \exp_not:n {#1} } + { \exp_not:n {#2} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_loop:} +% \begin{macro}{\@@_parse_loop_first:N} +% \begin{macro}{\@@_parse_loop_main:NNNNN} +% \begin{macro}{\@@_parse_loop_main_end:NN} +% \begin{macro}{\@@_parse_loop_main_digit:NNNNN} +% \begin{macro}{\@@_parse_loop_main_decimal:NN} +% \begin{macro}{\@@_parse_loop_main_uncert:NNN} +% \begin{macro}{\@@_parse_loop_main_sign:NNN} +% \begin{macro}{\@@_parse_loop_main_store:NNN} +% \begin{macro}{\@@_parse_loop_after_decimal:NNN} +% \begin{macro}{\@@_parse_loop_root_swap:NNwNN} +% \begin{macro}{\@@_parse_loop_break:wN} +% At this stage, the partial input \cs{l_@@_arg_tl} will contain any +% mantissa, which may contain an uncertainty or complex part. Parsing this +% and allowing for all of the different formats possible is best done using +% a token-by-token approach. However, as at each stage only a subset of +% tokens are valid, the approach take is to use a set of semi-dedicated +% functions to parse different components along with switches to allow a +% sensible amount of code sharing. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop: + { + \tl_clear:N \l_@@_partial_tl + \exp_after:wN \@@_parse_loop_first:NNN + \exp_after:wN \l_@@_parsed_tl \exp_after:wN \c_true_bool + \l_@@_arg_tl + \q_recursion_tail \q_recursion_stop + } +% \end{macrocode} +% The very first token of the input is handled with a dedicated function. +% Valid cases here are +% \begin{itemize} +% \item Entirely blank if the original input was for example |+e10|: +% simply clean up if in the integer part of issue an error if in +% a second part (complex number, \foreign{etc.}). +% \item An integer part digit: pass through to the main collection +% routine. +% \item A decimal marker: store an empty integer part and move to +% the main collection routine for a decimal part. +% \end{itemize} +% Anything else is invalid and sends the code to the abort function. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_first:NNN #1#2#3 + { + \quark_if_recursion_tail_stop_do:Nn #3 + { + \bool_if:NTF #2 + { \tl_put_right:Nn #1 { { 1 } { } { } } } + { \@@_parse_loop_break:wN \q_recursion_stop } + } + \tl_if_in:NnTF \l_@@_input_digit_tl {#3} + { + \@@_parse_loop_main:NNNNN + #1 \c_true_bool \c_false_bool #2 #3 + } + { + \tl_if_in:NnTF \l_siunitx_number_input_decimal_tl {#3} + { + \tl_put_right:Nn #1 { { 0 } } + \@@_parse_loop_after_decimal:NNN #1 #2 + } + { \@@_parse_loop_break:wN } + } + } +% \end{macrocode} +% A single function is used to cover the \enquote{main} part of numbers: +% finding real, complex or separated uncertainty parts and covering both +% the integer and decimal components. This works because these elements +% share a lot of concepts: a small number of switches can be used to +% differentiate between them. To keep the code at least somewhat readable, +% this main function deals with the validity testing but hands off other +% tasks to dedicated auxiliaries for each case. +% +% The possibilities are +% \begin{itemize} +% \item The number terminates, meaning that some digits were collected +% and everything is simply tidied up (as far as the loop is concerned). +% \item A digit is found: this is the common case and leads to a storage +% auxiliary (which handles non-significant zeros). +% \item A decimal marker is found: only valid in the integer part and +% there leading to a store-and-switch situation. +% \item An open-uncertainty token: switch to the dedicated collector +% for uncertainties. +% \item A sign token (if allowed): stop collecting this number and +% restart collection for the second part. +% \end{itemize} +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_main:NNNNN #1#2#3#4#5 + { + \quark_if_recursion_tail_stop_do:Nn #5 + { \@@_parse_loop_main_end:NN #1#2 } + \tl_if_in:NnTF \l_@@_input_digit_tl {#5} + { \@@_parse_loop_main_digit:NNNNN #1#2#3#4#5 } + { + \tl_if_in:NnTF \l_siunitx_number_input_decimal_tl {#5} + { + \bool_if:NTF #2 + { \@@_parse_loop_main_decimal:NN #1 #4 } + { \@@_parse_loop_break:wN } + } + { + \tl_if_in:NnTF \l_@@_input_uncert_open_tl {#5} + { \@@_parse_loop_main_uncert:NNN #1#2 #4 } + { + \bool_if:NTF #4 + { + \tl_if_in:NnTF \l_siunitx_number_input_sign_tl {#5} + { + \@@_parse_loop_main_sign:NNN + #1#2 #5 + } + { \@@_parse_loop_break:wN } + } + { \@@_parse_loop_break:wN } + } + } + } + } +% \end{macrocode} +% If the main loop finds the end marker then there is a tidy up phase. +% The current partial number is stored either as the integer or decimal, +% depending on the setting for the indicator switch. For the integer +% part, if no number has been collected then one or more non-significant +% zeros have been dropped. Exactly one zero is therefore needed to make +% sure the parsed result is correct. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_main_end:NN #1#2 + { + \bool_lazy_and:nnT + {#2} { \tl_if_empty_p:N \l_@@_partial_tl } + { \tl_set:Nn \l_@@_partial_tl { 0 } } + \tl_put_right:Nx #1 + { + { \exp_not:V \l_@@_partial_tl } + \bool_if:NT #2 { { } } + { } + } + } +% \end{macrocode} +% The most common case for the main loop collector is to find a digit. +% Here, in the integer part it is possible that zeros are non-significant: +% that is handled using a combination of a switch and a string test. Other +% than that, the situation here is simple: store the input and loop. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_main_digit:NNNNN #1#2#3#4#5 + { + \bool_lazy_or:nnTF + {#3} { ! \str_if_eq_p:nn {#5} { 0 } } + { + \tl_put_right:Nn \l_@@_partial_tl {#5} + \@@_parse_loop_main:NNNNN #1 #2 \c_true_bool #4 + } + { \@@_parse_loop_main:NNNNN #1 #2 \c_false_bool #4 } + } +% \end{macrocode} +% When a decimal marker was found, move the integer part to the +% store and then go back to the loop with the flags set correctly. +% There is the case of non-significant zeros to cover before that, of course. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_main_decimal:NN #1#2 + { + \@@_parse_loop_main_store:NNN #1 \c_false_bool \c_false_bool + \@@_parse_loop_after_decimal:NNN #1 #2 + } +% \end{macrocode} +% Starting an uncertainty part means storing the number to date as in other +% cases, with the possibility of a blank decimal part allowed for. The +% uncertainty itself is collected by a dedicated function as it is extremely +% restricted. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_main_uncert:NNN #1#2#3 + { + \@@_parse_loop_main_store:NNN #1 #2 \c_false_bool + \@@_parse_uncert:NN #1 + } +% \end{macrocode} +% If a sign is found, terminate the current number, store the sign as the +% first token of the second part and go back to do the dedicated first-token +% function. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_main_sign:NNN #1#2#3 + { + \@@_parse_loop_main_store:NNN #1 #2 \c_true_bool + \tl_set:Nn \l_@@_flex_tl { {#3} } + \@@_parse_loop_first:NNN + \l_@@_flex_tl \c_false_bool + } +% \end{macrocode} +% A common auxiliary for the various non-digit token functions: tidy up the +% integer and decimal parts of a number. Here, the two flags are used to +% indicate if empty decimal and uncertainty parts should be included in +% the storage cycle. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_main_store:NNN #1#2#3 + { + \tl_if_empty:NT \l_@@_partial_tl + { \tl_set:Nn \l_@@_partial_tl { 0 } } + \tl_put_right:Nx #1 + { + { \exp_not:V \l_@@_partial_tl } + \bool_if:NT #2 { { } } + \bool_if:NT #3 { { } } + } + \tl_clear:N \l_@@_partial_tl + } +% \end{macrocode} +% After a decimal marker there has to be a digit if there wasn't one before +% it. That is handled by using a dedicated function, which checks for +% an empty integer part first then either simply hands off or looks for +% a digit. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_after_decimal:NNN #1#2#3 + { + \tl_if_blank:fTF { \exp_after:wN \use_none:n #1 } + { + \quark_if_recursion_tail_stop_do:Nn #3 + { \@@_parse_loop_break:wN \q_recursion_stop } + \tl_if_in:NnTF \l_@@_input_digit_tl {#1} + { + \tl_put_right:Nn \l_@@_partial_tl {#3} + \@@_parse_loop_main:NNNNN + #1 \c_false_bool \c_true_bool #2 + } + { \@@_parse_loop_break:wN } + } + { + \@@_parse_loop_main:NNNNN + #1 \c_false_bool \c_true_bool #2 #3 + } + } +% \end{macrocode} +% Something is not right: remove all of the remaining tokens from the +% number and clear the storage areas as a signal for the next part of the +% code. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_loop_break:wN + #1 \q_recursion_stop + { + \tl_clear:N \l_@@_flex_tl + \tl_clear:N \l_@@_parsed_tl + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_sign:} +% \begin{macro}{\@@_parse_sign_aux:Nw} +% The first token of a number after a comparator could be a sign. A quick +% check is made and if found stored. For the number to be valid it has to be +% more than just a sign, so the next part of the chain is only called if that +% is the case. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_sign: + { + \exp_after:wN \@@_parse_sign_aux:Nw + \l_@@_arg_tl \q_stop + } +\cs_new_protected:Npn \@@_parse_sign_aux:Nw #1#2 \q_stop + { + \tl_if_in:NnTF \l_siunitx_number_input_sign_tl {#1} + { + \tl_set:Nn \l_@@_arg_tl {#2} + \bool_lazy_and:nnTF + { \token_if_eq_charcode_p:NN #1 + } + { ! \l_@@_explicit_plus_bool } + { \tl_set:Nn \l_@@_parsed_tl { { } } } + { \tl_set:Nn \l_@@_parsed_tl { {#1} } } + } + { \tl_set:Nn \l_@@_parsed_tl { { } } } + \tl_if_empty:NTF \l_@@_arg_tl + { \tl_clear:N \l_@@_parsed_tl } + { \@@_parse_exponent: } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_uncert:NN} +% \begin{macro}{\@@_parse_uncert:NNNN} +% \begin{macro}{\@@_parse_uncert_auxi:NN, \@@_parse_uncert_auxii:NN} +% \begin{macro} +% { +% \@@_parse_uncert_auxii:N , +% \@@_parse_uncert_marker:N , +% \@@_parse_uncert_after:N +% } +% Parsing a combined uncertainty has a very restricted range of allowed +% tokens. A closing uncertainty token in the first place is an error, +% so we filter that out explicitly. After that, we check for digits, +% which require checking for significant digits. The non-digit function +% is separate to make the flow clearer. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_uncert:NN #1#2 + { + \quark_if_recursion_tail_stop_do:Nn #2 + { \@@_parse_loop_break:wN \q_recursion_stop } + \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#2} + { \@@_parse_loop_break:wN } + { + \@@_parse_uncert:NNNN + #1 \c_false_bool \@@_parse_uncert_auxi:NN #2 + } + } +% \end{macrocode} +% Deal with digits: a simple question of whether they are significant. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_uncert:NNNN #1#2#3#4 + { + \quark_if_recursion_tail_stop_do:Nn #4 + { \@@_parse_loop_break:wN \q_recursion_stop } + \tl_if_in:NnTF \l_@@_input_digit_tl {#4} + { + \bool_lazy_or:nnTF + {#2} { ! \str_if_eq_p:nn {#4} { 0 } } + { + \tl_put_right:Nn \l_@@_partial_tl {#4} + \@@_parse_uncert:NNNN #1 \c_true_bool #3 + } + { \@@_parse_uncert:NNNN #1 \c_false_bool #3 } + } + { #3 #1#4 } + } +% \end{macrocode} +% For the two auxiliaries, the difference is the handling of a +% decimal marker: one may be present, but only exactly one. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_uncert_auxi:NN #1#2 + { + \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#2} + { + \@@_parse_uncert_auxiii:N #1 + \@@_parse_uncert_after:N + } + { + \tl_if_in:NnTF \l_siunitx_number_input_decimal_tl {#2} + { \@@_parse_uncert_marker:N #1 } + { \@@_parse_loop_break:wN } + } + } +\cs_new_protected:Npn \@@_parse_uncert_auxii:NN #1#2 + { + \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#2} + { + \@@_parse_uncert_auxiii:N #1 + \@@_parse_uncert_after:N + } + { \@@_parse_loop_break:wN } + } +% \end{macrocode} +% Deal with the closing bracket, which might leave us with nothing if there +% were no significant digits. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_uncert_auxiii:N #1 + { + \tl_if_empty:NTF \l_@@_partial_tl + { + \tl_put_right:Nx #1 + { + { + \bool_if:NT \l_@@_zero_uncert_bool + { { S } { 0 } } + } + } + } + { + \tl_set:Nx \l_@@_partial_tl + { { S } { \exp_not:V \l_@@_partial_tl } } + \@@_parse_loop_main_store:NNN #1 + \c_false_bool \c_false_bool + } + } +% \end{macrocode} +% Handling a decimal marker in the uncertainty is a bit tricky: we need to make +% sure it's valid. First, we need to be sure that the integer part of the captured +% uncertainty is not too long. Then we need to check that the decimal part is +% not too long. Both of these require data from the collected partial number, +% so we extract that first. Checking the decimal part needs the length of the +% not-yet-collected uncertainty. Handily, we know that it should be a set of +% digits then a closing marker. So we can use that as a length: if it's +% too long we can stop. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_uncert_marker:N #1 + { \exp_after:wN \@@_parse_uncert_marker:nnnN #1 #1 } +\cs_new_protected:Npn \@@_parse_uncert_marker:nnnN #1#2#3#4 + { + \int_compare:nNnTF + { \tl_count:N \l_@@_partial_tl } > { \tl_count:n {#2} } + { \@@_parse_loop_break:wN } + { \@@_parse_uncert_marker:nNw {#3} #4 } + } +\cs_new_protected:Npn \@@_parse_uncert_marker:nNw + #1#2#3 \q_recursion_tail \q_recursion_stop + { + \int_compare:nNnTF + { \tl_count:n {#3} - 1 } = { \tl_count:n {#1} } + { + \str_if_eq:eeTF + { \exp_not:V \l_@@_partial_tl } + { \prg_replicate:nn { \tl_count:N \l_@@_partial_tl } { 0 } } + { + \@@_parse_uncert:NNNN + #2 \c_false_bool + } + { + \@@_parse_uncert:NNNN + #2 \c_true_bool + } + \@@_parse_uncert_auxii:NN + } + { \@@_parse_loop_break:wN } + #3 \q_recursion_tail \q_recursion_stop + } +% \end{macrocode} +% No further tokens are allowed after an uncertainty in parenthesis. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_uncert_after:N #1 + { + \quark_if_recursion_tail_stop:N #1 + \@@_parse_loop_break:wN + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Processing numbers} +% +% \begin{variable} +% { +% \l_@@_drop_exponent_bool , +% \l_@@_drop_uncertainty_bool , +% \l_@@_drop_zero_decimal_bool , +% \l_@@_exponent_mode_tl , +% \l_@@_exponent_fixed_int , +% \l_@@_min_decimal_int , +% \l_@@_min_integer_int , +% \l_@@_round_half_even_bool , +% \l_@@_round_mode_tl , +% \l_@@_round_pad_bool , +% \l_@@_round_precision_int +% } +% \begin{macrocode} +\keys_define:nn { siunitx } + { + drop-exponent .bool_set:N = + \l_@@_drop_exponent_bool , + drop-uncertainty .bool_set:N = + \l_@@_drop_uncertainty_bool , + drop-zero-decimal .bool_set:N = + \l_@@_drop_zero_decimal_bool , + exponent-mode .choices:nn = + { engineering , fixed , input , scientific } + { \tl_set_eq:NN \l_@@_exponent_mode_tl \l_keys_choice_tl } , + fixed-exponent .int_set:N = + \l_@@_exponent_fixed_int , + minimum-decimal-digits .int_set:N = + \l_@@_min_decimal_int , + minimum-integer-digits .int_set:N = + \l_@@_min_integer_int , + round-half .choice: , + round-half / even .code:n = + { \bool_set_true:N \l_@@_round_half_even_bool } , + round-half / up .code:n = + { \bool_set_false:N \l_@@_round_half_even_bool } , + round-minimum .code:n = + { \@@_set_round_min:n {#1} } , + round-mode .choices:nn = + { figures , none , places, uncertainty } + { \tl_set_eq:NN \l_@@_round_mode_tl \l_keys_choice_tl } , + round-pad .bool_set:N = + \l_@@_round_pad_bool , + round-precision .int_set:N = + \l_@@_round_precision_int , + } +\bool_new:N \l_@@_round_half_even_bool +\tl_new:N \l_@@_exponent_mode_tl +\tl_new:N \l_@@_round_mode_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_round_min_tl} +% For storing the minimum for rounding. +% \begin{macrocode} +\tl_new:N \l_@@_round_min_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_set_round_min:n} +% \begin{macro}[EXP]{\@@_set_round_min:nnnnnnn} +% For setting the rounding minimum, the aim is to do as much of the work +% now as possible. That's mainly a question of checking if there are any +% significant digits in the mantissa given. +% \begin{macrocode} +\cs_new_protected:Npn \@@_set_round_min:n #1 + { + \siunitx_number_parse:nN {#1} \l_@@_tmp_tl + \exp_after:wN \@@_set_round_min:nnnnnnn \l_@@_tmp_tl + } +\cs_new:Npn \@@_set_round_min:nnnnnnn #1#2#3#4#5#6#7 + { + \tl_set:Nx \l_@@_round_min_tl + { + \bool_lazy_and:nnF + { \str_if_eq_p:nn {#3} { 0 } } + { + \str_if_eq_p:ee + { \exp_not:n {#4} } + { \prg_replicate:nn { \tl_count:n {#4} } { 0 } } + } + { \exp_not:n { {#3} {#4} } } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\siunitx_number_process:NN} +% \begin{macro}{\@@_process:nnnnnnnNN} +% A top-level interface for the processing tools. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_number_process:NN #1#2 + { + \tl_if_empty:NTF #1 + { \tl_clear:N #2 } + { + \@@_drop_uncertainty:NN #1 #2 + \exp_after:wN \@@_process:nnnnnnnNN #2 #2 #2 + \@@_drop_exponent:NN #2 #2 + \@@_zero_decimal:NN #2 #2 + \@@_digits:NN #2 #2 + } + } +\cs_new_protected:Npn \@@_process:nnnnnnnNN #1#2#3#4#5#6#7#8#9 + { + \bool_lazy_and:nnF + { \str_if_eq_p:nn {#3} { 0 } } + { + \str_if_eq_p:ee + { \exp_not:n {#4} } { \prg_replicate:nn { \tl_count:n {#4} } { 0 } } + } + { + \@@_exponent:NN #8 #9 + \@@_round:NN #9 #9 + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_exponent:NN} +% \begin{macro}[EXP] +% { +% \@@_exponent_engineering:nnnnnnn , +% \@@_exponent_fixed:nnnnnnn , +% \@@_exponent_input:nnnnnnn , +% \@@_exponent_scientific:nnnnnnn +% } +% \begin{macro}[EXP] +% { +% \@@_exponent_fixed:nnnnnnnn , +% \@@_exponent_scientific:nnnnnnnn +% } +% \begin{macro}[EXP]{\@@_exponent_scientific:nnnw} +% \begin{macro}[EXP]{\@@_exponent_shift:nnn,\@@_exponent_shift:nnf} +% \begin{macro}[EXP]{\@@_exponent_shift_down:nnnw} +% \begin{macro}[EXP]{\@@_exponent_shift_down:nnn} +% \begin{macro}[EXP]{\@@_exponent_shift_down:nw} +% \begin{macro}[EXP]{\@@_exponent_shift_up:nnn} +% \begin{macro}[EXP]{\@@_exponent_shift_up:nnw} +% \begin{macro}[EXP] +% { +% \@@_exponent_shift_up_aux:nnn , +% \@@_exponent_shift_up_aux:fnn , +% \@@_exponent_shift_up_aux:ffn +% } +% \begin{macro}[EXP]{\@@_exponent_shift_uncert:nw} +% \begin{macro}[EXP] +% {\@@_exponent_shift_uncert_S:nnnn, \@@_exponent_shift_uncert_S:fnnn} +% \begin{macro}[EXP]{\@@_exponent_uncert:n} +% \begin{macro}[EXP]{\@@_exponent_finalise:n} +% \begin{macro}[EXP]{\@@_exponent_engineering_aux:nnnnnnn} +% \begin{macro}[EXP] +% { +% \@@_exponent_engineering_0:nnnn , +% \@@_exponent_engineering_1:nnnn , +% \@@_exponent_engineering_2:nnnn +% } +% \begin{macro}[EXP]{\@@_exponent_engineering:nnNw} +% \begin{macro}[EXP]{\@@_exponent_engineering_uncert:nn} +% \begin{macro}[EXP]{\@@_exponent_engineering_uncert_S:nnn} +% Manipulating an exponent is done using a single expansion function +% \emph{unless} dealing with engineering-style output. The latter is easier +% to handle by first converting to scientific output, then post-processing. +% (Once \texttt{e}-type expansion is generally available, this will be +% handling using a single \cs{tl_set:Nx}.) +% \begin{macrocode} +\cs_new_protected:Npn \@@_exponent:NN #1#2 + { + \tl_set:Nx #2 + { + \cs:w + @@_exponent_ \l_@@_exponent_mode_tl :nnnnnnn + \exp_after:wN + \cs_end: #1 + } + \str_if_eq:VnT \l_@@_exponent_mode_tl { engineering } + { + \tl_set:Nx #2 + { \exp_after:wN \@@_exponent_engineering_aux:nnnnnnn #2 } + } + } +\cs_new:Npn \@@_exponent_fixed:nnnnnnn #1#2#3#4#5#6#7 + { + \exp_args:Nf \@@_exponent_fixed:nnnnnnnn + { \int_eval:n { \l_@@_exponent_fixed_int - (#6#7) } } + {#1} {#2} {#3} {#4} {#5} {#6} {#7} + } +\cs_new:Npn \@@_exponent_fixed:nnnnnnnn #1#2#3#4#5#6#7#8 + { + \exp_not:n { {#2} {#3} } + \@@_exponent_shift:nnn {#1} {#4} {#5} + \@@_exponent_uncert:n {#6} + \exp_not:n { {#7} } { \int_use:N \l_@@_exponent_fixed_int } + } +\cs_new:Npn \@@_exponent_input:nnnnnnn #1#2#3#4#5#6#7 + { \exp_not:n { {#1} {#2} {#3} {#4} {#5} {#6} {#7} } } +% \end{macrocode} +% To convert to scientific notation, the key question is to find the number +% of significant places. That is easy enough if the number has a non-zero +% integer component. For a pure decimal, we have to trim off leading +% zeros in a loop. +% \begin{macrocode} +\cs_new:Npn \@@_exponent_scientific:nnnnnnn #1#2#3#4#5#6#7 + { + \exp_args:Nf \@@_exponent_scientific:nnnnnnnn + { \int_eval:n { \tl_count:n {#3} } } + {#1} {#2} {#3} {#4} {#5} {#6} {#7} + } +\cs_new:Npn \@@_exponent_scientific:nnnnnnnn #1#2#3#4#5#6#7#8 + { + \exp_not:n { {#2} {#3} } + \int_compare:nNnTF {#1} = 1 + { + \str_if_eq:nnTF {#4} { 0 } + { + \@@_exponent_scientific:nnnw + { 0 } {#6} { #7#8 } #5 \q_stop + } + { \exp_not:n { {#4} {#5} {#6} {#7} {#8} } } + } + { + \@@_exponent_shift:nnn { #1 - 1 } {#4} {#5} + \@@_exponent_uncert:n {#6} + \@@_exponent_finalise:n { #1 + #7#8 - 1 } + } + } +\cs_new_eq:NN \@@_exponent_engineering:nnnnnnn + \@@_exponent_scientific:nnnnnnn +\cs_new:Npn \@@_exponent_scientific:nnnw #1#2#3#4#5 \q_stop + { + \str_if_eq:nnTF {#4} { 0 } + { + \@@_exponent_scientific:nnnw + { #1 - 1 } {#2} {#3} #5 \q_stop + } + { + \exp_not:n { {#4} {#5} {#2} } + \@@_exponent_finalise:n { #1 + #3 - 1 } + } + } +% \end{macrocode} +% When adjusting the exponent position, there are two paths depending on +% which way the shift takes place. +% \begin{macrocode} +\cs_new:Npn \@@_exponent_shift:nnn #1#2#3 + { + \int_compare:nNnTF {#1} > 0 + { \@@_exponent_shift_down:nnnw {#1} {#3} { } #2 \q_stop } + { + \int_compare:nNnTF {#1} < 0 + { \@@_exponent_shift_up:nnn {#1} {#2} {#3} } + { {#2} {#3} } + } + } +\cs_generate_variant:Nn \@@_exponent_shift:nnn { nnf } +% \end{macrocode} +% For shifting the exponent down, there is first a loop to reserve the +% integer part before doing the work: that of course has to be undone +% for any remainder at he end of the process. +% \begin{macrocode} +\cs_new:Npn \@@_exponent_shift_down:nnnw #1#2#3#4#5 \q_stop + { + \tl_if_blank:nTF {#5} + { \@@_exponent_shift_down:nnn {#1} { #4 #3 } {#2} } + { \@@_exponent_shift_down:nnnw {#1} {#2} { #4 #3 } #5 \q_stop } + } +\cs_new:Npn \@@_exponent_shift_down:nnn #1#2#3 + { + \int_compare:nNnTF {#1} = 0 + { { \tl_reverse:n {#2} } \exp_not:n { {#3} } } + { \@@_exponent_shift_down:nw {#1} #2 \q_stop {#3} } + } +\cs_new:Npn \@@_exponent_shift_down:nw #1#2#3 \q_stop #4 + { + \tl_if_blank:nTF {#3} + { \@@_exponent_shift_down:nnn { #1 - 1 } { 0 } { #2#4 } } + { \@@_exponent_shift_down:nnn { #1 - 1 } {#3} { #2#4 } } + } +% \end{macrocode} +% For shifting the exponent up, we can run out of decimal digits, at which +% point filling is easy. Other than that a simple loop as we are picking +% input off the front of the decimal part. We also need to deal with leading +% zeros: these cannot accumulate. +% \begin{macrocode} +\cs_new:Npn \@@_exponent_shift_up:nnn #1#2#3 + { + \tl_if_blank:nTF {#3} + { + \@@_exponent_shift_up_aux:ffn + { \int_eval:n { #1 + 1 } } + { \str_if_eq:nnF {#2} { 0 } {#2} 0 } + { } + \@@_exponent_shift_uncert:nw { 1 } + } + { \@@_exponent_shift_up:nnw {#1} {#2} #3 \q_stop } + } +\cs_new:Npn \@@_exponent_shift_up:nnw #1#2#3#4 \q_stop + { + \@@_exponent_shift_up_aux:ffn + { \int_eval:n { #1 + 1 } } + { \str_if_eq:nnF {#2} { 0 } {#2} #3 } + {#4} + } +\cs_new:Npn \@@_exponent_shift_up_aux:nnn #1#2#3 + { + \int_compare:nNnTF {#1} = 0 + { \exp_not:n { {#2} {#3} } } + { + \tl_if_blank:nTF {#3} + { + { + \exp_not:n {#2} + \prg_replicate:nn { \int_abs:n {#1} } { 0 } + } + { } + \@@_exponent_shift_uncert:nw { \int_abs:n {#1} } + } + { \@@_exponent_shift_up:nnn {#1} {#2} {#3} } + } + } +\cs_generate_variant:Nn \@@_exponent_shift_up_aux:nnn { f , ff } +% \end{macrocode} +% If the shift has put digits into the integer part, we have to adjust the +% uncertainty accordingly. First, we grab the data, then adjust by the +% number of places that have been transferred. +% \begin{macrocode} +\cs_new:Npn \@@_exponent_shift_uncert:nw + #1#2 \@@_exponent_uncert:n #3 + { + \tl_if_blank:nTF {#3} + { + #2 + \@@_exponent_uncert:n { } + } + { + \str_if_eq:nnTF {#3} { 0 } + { + #2 + \@@_exponent_uncert:n { { S } { 0 } } + } + { + \use:c { @@_exponent_shift_uncert_ \use_i:nn #3 :fnnn } + { \prg_replicate:nn {#1} { 0 } } + {#2} + #3 + } + } + } +\cs_new:Npn \@@_exponent_shift_uncert_S:nnnn #1#2#3#4 + { + #2 + \@@_exponent_uncert:n { { S } { #4#1 } } + } +\cs_generate_variant:Nn \@@_exponent_shift_uncert_S:nnnn { f } +\cs_new:Npn \@@_exponent_uncert:n #1 { { \exp_not:n {#1} } } +% \end{macrocode} +% Tidy up the exponent to put the sign in the right place. +% \begin{macrocode} +\cs_new:Npn \@@_exponent_finalise:n #1 + { + \int_compare:nNnTF {#1} < 0 + { { - } } + { { } } + { \int_abs:n {#1} } + } +% \end{macrocode} +% This could (and eventually will) be combined with the main function above: +% that will need \texttt{e}-type expansion. The input has already been +% normalised such that the integer part is in the range $1 \le n < 10$. +% Thus there are only three cases to deal with, depending on the required +% adjustment to the exponent. +% \begin{macrocode} +\cs_new:Npn \@@_exponent_engineering_aux:nnnnnnn #1#2#3#4#5#6#7 + { + \exp_not:n { {#1} {#2} } + \use:c + { + @@_exponent_engineering_ + \int_compare:nNnTF {#6#7} < 0 + { + \int_case:nnF { \int_mod:nn { #7 } { 3 } } + { + { 1 } { 2 } + { 2 } { 1 } + } + { 0 } + } + { \int_mod:nn {#7} { 3 } } + :nnnn + } + {#3} {#4} {#5} {#6#7} + } +\cs_new:cpn { @@_exponent_engineering_0:nnnn } #1#2#3#4 + { + \exp_not:n { {#1} {#2} {#3} } + \@@_exponent_finalise:n {#4} + } +\cs_new:cpn { @@_exponent_engineering_1:nnnn } #1#2#3#4 + { + \tl_if_blank:nTF {#2} + { + { \exp_not:n { #1 0 } } { } + { \@@_exponent_engineering_uncert:nn {#3} { 0 } } + } + { + { \exp_not:n {#1} \exp_not:o { \tl_head:w #2 \q_stop } } + { \exp_not:f { \tl_tail:n {#2} } } + { \exp_not:n {#3} } + } + \@@_exponent_finalise:n { #4 - 1 } + } +\cs_new:cpn { @@_exponent_engineering_2:nnnn } #1#2#3#4 + { + \tl_if_blank:nTF {#2} + { + { \exp_not:n { #1 00 } } { } + { \@@_exponent_engineering_uncert:nn {#3} { 00 } } + } + {\@@_exponent_engineering:nnNw {#1} {#3} #2 \q_stop } + \@@_exponent_finalise:n { #4 - 2 } + } +\cs_new:Npn \@@_exponent_engineering:nnNw #1#2#3#4 \q_stop + { + \tl_if_blank:nTF {#4} + { + { \exp_not:n { #1#3 0 } } { } + { { \@@_exponent_engineering_uncert:nn {#2} { 0 } } } + } + { + { \exp_not:n {#1#3} \exp_not:o { \tl_head:w #4 \q_stop } } + { \exp_not:f { \tl_tail:n {#4} } } + { \exp_not:n {#2} } + } + } +\cs_new:Npn \@@_exponent_engineering_uncert:nn #1#2 + { + \tl_if_blank:nF {#1} + { + \use:c { @@_exponent_engineering_uncert_ \use_i:nn #1 :nnn } + #1 {#2} + } + } +\cs_new:Npn \@@_exponent_engineering_uncert_S:nnn #1#2#3 + { + { S } + { + \exp_not:n {#2} + \str_if_eq:nnF {#2} { 0 } {#3} + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_digits:NN} +% \begin{macro}[EXP]{\@@_digits:nnnnnnn} +% \begin{macro}[EXP]{\@@_digits:Nn} +% \begin{macro}[EXP]{\@@_digits:nn} +% \begin{macro}[EXP]{\@@_digits_S:n} +% Forcing a minimum number of digits in each part is quite easy. As +% the common case is that we don't do anything here, there is no real need +% to optimise the calculation (normally also numbers have only a few digits). +% \begin{macrocode} +\cs_new_protected:Npn \@@_digits:NN #1#2 + { + \tl_set:Nx #2 + { \exp_after:wN \@@_digits:nnnnnnn #1 } + } +\cs_new:Npn \@@_digits:nnnnnnn #1#2#3#4#5#6#7 + { + \exp_not:n { {#1} {#2} } + { + \@@_digits:Nn \l_@@_min_integer_int {#3} + \exp_not:n {#3} + } + { + \exp_not:n {#4} + \@@_digits:Nn \l_@@_min_decimal_int {#4} + } + { \tl_if_blank:nF {#5} { \@@_digits_uncert:nn #5 } } + \exp_not:n { {#6} {#7} } + } +\cs_new:Npn \@@_digits:Nn #1#2 + { + \int_compare:nNnT + { #1 - \tl_count:n {#2} } > 0 + { \prg_replicate:nn { #1 - \tl_count:n {#2} } { 0 } } + } +\cs_new:Npn \@@_digits_uncert:nn #1#2 + { + { #1 } + { \use:c { @@_digits_uncert_ #1 :n } {#2} } + } +\cs_new:Npn \@@_digits_uncert_S:n #1 + { + \exp_not:n {#1} + \@@_digits:Nn \l_@@_min_decimal_int {#1} + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_drop_exponent:NN} +% \begin{macro}[EXP]{\@@_drop_exponent:nnnnnnn} +% Simple stripping of the exponent. +% \begin{macrocode} +\cs_new_protected:Npn \@@_drop_exponent:NN #1#2 + { + \bool_if:NT \l_@@_drop_exponent_bool + { + \tl_set:Nx #2 + { \exp_after:wN \@@_drop_exponent:nnnnnnn #1 } + } + } +\cs_new:Npn \@@_drop_exponent:nnnnnnn #1#2#3#4#5#6#7 + { \exp_not:n { {#1} {#2} {#3} {#4} {#5} { } { 0 } } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_drop_uncertainty:NN} +% \begin{macro}[EXP]{\@@_drop_uncertainty:nnnnnnn} +% Simple stripping of the uncertainty. +% \begin{macrocode} +\cs_new_protected:Npn \@@_drop_uncertainty:NN #1#2 + { + \bool_if:NTF \l_@@_drop_uncertainty_bool + { + \tl_set:Nx #2 + { \exp_after:wN \@@_drop_uncertainty:nnnnnnn #1 } + } + { \tl_set_eq:NN #2 #1 } + + } +\cs_new:Npn \@@_drop_uncertainty:nnnnnnn #1#2#3#4#5#6#7 + { \exp_not:n { {#1} {#2} {#3} {#4} { } {#6} {#7} } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_round:NN} +% \begin{macro}[EXP]{\@@_round_none:nnnnnnn} +% Rounding is at the top level simple enough: fire off the expandable +% set up which does the work. +% \begin{macrocode} +\cs_new_protected:Npn \@@_round:NN #1#2 + { + \tl_set:Nx #2 + { + \cs:w + @@_round_ \l_@@_round_mode_tl :nnnnnnn + \exp_after:wN + \cs_end: #1 + } + } +\cs_new:Npn \@@_round_none:nnnnnnn #1#2#3#4#5#6#7 + { \exp_not:n { {#1} {#2} {#3} {#4} {#5} {#6} {#7} } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_round:nnn, \@@_round:fnn} +% \begin{macro}[EXP] +% { +% \@@_round_auxi:nnnN , +% \@@_round_auxii:nnnN , +% \@@_round_auxiii:nnnN +% } +% \begin{macro}[EXP]{\@@_round_auxiv:nnN, \@@_round_auxv:nnN} +% \begin{macro}[EXP]{\@@_round_auxvi:nN} +% \begin{macro}[EXP]{\@@_round_auxvii:nnN, \@@_round_auxviii:nnN} +% \begin{macro}[EXP]{\@@_round_final_integer:nnw, \@@_round_final_decimal:nnw} +% \begin{macro}[EXP]{\@@_round_final_output:nn, \@@_round_final_output:ff} +% \begin{macro}[EXP]{\@@_round_final:nn, \@@_round_final:fn} +% \begin{macro}[EXP]{\@@_round_final_shift:nn, \@@_round_final_shift:ff} +% \begin{macro}[EXP]{\@@_round_final_shift:Nw} +% \begin{macro}[EXP] +% { +% \@@_round_engineering:nn , +% \@@_round_fixed:nn , +% \@@_round_input:nn , +% \@@_round_scientifitc:nn +% } +% \begin{macro}[EXP]{\@@_round_engineering:NNNNn} +% \begin{macro}[EXP]{\@@_round_engineering:nnN} +% \begin{macro}[EXP]{\@@_round_truncate:n, \@@_round_truncate_direct:n} +% \begin{macro}[EXP]{\@@_round_truncate:nnN} +% Actually doing the rounding needs us to work from the least significant +% digit, so we start by reversing the input. We \emph{could} also drop +% digits in this phase, but tracking everything would be horrible, so +% we go slightly slower but clearer and split the steps. First we reverse +% the decimal part, then the integer. +% \begin{macrocode} +\cs_new:Npn \@@_round:nnn #1#2#3 + { + \@@_round_auxi:nnnN {#1} {#2} { } + #3 \q_recursion_tail \q_recursion_stop + } +\cs_generate_variant:Nn \@@_round:nnn { f } +\cs_new:Npn \@@_round_auxi:nnnN #1#2#3#4 + { + \quark_if_recursion_tail_stop_do:Nn #4 + { + \@@_round_auxii:nnnN {#1} {#3} { } #2 + \q_recursion_tail \q_recursion_stop + } + \@@_round_auxi:nnnN {#1} {#2} {#4#3} + } +\cs_new:Npn \@@_round_auxii:nnnN #1#2#3#4 + { + \quark_if_recursion_tail_stop_do:Nn #4 + { + \tl_if_blank:nTF {#2} + { + \@@_round_auxiv:nnnN {#1} { } { } #3 + \q_recursion_tail \q_recursion_stop + } + { + \@@_round_auxiii:nnnN {#1} {#3} { } #2 + \q_recursion_tail \q_recursion_stop + } + } + \@@_round_auxii:nnnN {#1} {#2} {#4#3} + } +% \end{macrocode} +% We now have the input reversed plus how many digits we need to discard +% (|#1|). We have two functions, one which deals with the decimal part, +% one of which deals with the integer. In the latter, we should never hit +% the end before we've dropped all the digits: the fixed-zero is a +% fall-back in case something weird happens. For the integer case, we need +% to collect up zeros to pad the length back out correctly later. +% \begin{macrocode} +\cs_new:Npn \@@_round_auxiii:nnnN #1#2#3#4 + { + \quark_if_recursion_tail_stop_do:Nn #4 + { + \@@_round_auxiv:nnnN {#1} { } {#3} #2 + \q_recursion_tail \q_recursion_stop + } + \int_compare:nNnTF {#1} > 0 + { + \exp_args:Nf \@@_round_auxiii:nnnN + { \int_eval:n { #1 - 1 } } {#2} { #4#3 } + } + { \@@_round_auxv:nnN {#3} {#2} #4 } + } +\cs_new:Npn \@@_round_auxiv:nnnN #1#2#3#4 + { + \quark_if_recursion_tail_stop_do:Nn #4 + { { 0 } { } } + \int_compare:nNnTF {#1} > 0 + { + \exp_args:Nf \@@_round_auxiv:nnnN + { \int_eval:n { #1 - 1 } } { #2 0 } { #4#3 } + } + { \@@_round_auxvi:nnnN {#3} {#2} #4 } + } +% \end{macrocode} +% The lead off to rounding proper needs to deal with the half-even rule: +% it can only apply at this stage, when the \emph{discarded} value can +% be exactly half. +% \begin{macrocode} +\cs_new:Npn \@@_round_auxv:nnN #1#2#3 + { + \quark_if_recursion_tail_stop_do:Nn #3 + { + \@@_round_auxvi:nnN + {#1} { } #2 \q_recursion_tail \q_recursion_stop + } + \bool_lazy_or:nnTF + { \int_compare_p:nNn { 0 \tl_head:n {#1} } < 5 } + { + \bool_lazy_all_p:n + { + { \l_@@_round_half_even_bool } + { \int_if_odd_p:n {#3} } + { \@@_round_if_half_p:n {#1} } + } + } + { \@@_round_final_decimal:nnw } + { \@@_round_auxvii:nnN } + {#2} { } #3 + } +\cs_new:Npn \@@_round_auxvi:nnnN #1#2#3 + { + \quark_if_recursion_tail_stop_do:Nn #3 + { { 0 } { } } + \bool_lazy_or:nnTF + { \int_compare_p:nNn { 0 \tl_head:n {#1} } < 5 } + { + \bool_lazy_all_p:n + { + { \l_@@_round_half_even_bool } + { \int_if_odd_p:n {#3} } + { \@@_round_if_half_p:n {#1} } + } + } + { \@@_round_final_integer:nnw } + { \@@_round_auxviii:nnN } + { } {#2} #3 + } +% \end{macrocode} +% The main rounding routines. These are only every called when there is +% rounding to do, so there is no need to carry a flag forward. Thus the +% question to ask is simple: is the next value a $9$ or not (as that +% continues the sequence). There is a general need to handle the case +% where a zero is rounded up: that automatically means a need to trim +% the other end. +% \begin{macrocode} +\cs_new:Npn \@@_round_auxvii:nnN #1#2#3 + { + \quark_if_recursion_tail_stop_do:Nn #3 + { + \str_if_eq:nnTF {#1} { 0 } + { + \@@_round_final_output:ff + { 1 } + { \@@_round_truncate:n {#2} } + } + { + \@@_round_auxviii:nnN {#2} { } #1 + \q_recursion_tail \q_recursion_stop + } + } + \int_compare:nNnTF {#3} = 9 + { \@@_round_auxvii:nnN {#1} { 0 #2 } } + { + \int_compare:nNnTF {#3} = 0 + { + \@@_round_final_decimal:nnw + {#1} { 1 \@@_round_truncate:n {#2} } + } + { + \@@_round_final:fn + { \int_eval:n { #3 + 1 } } + { \@@_round_final_decimal:nnw {#1} {#2} } + } + } + } +\cs_new:Npn \@@_round_auxviii:nnN #1#2#3 + { + \quark_if_recursion_tail_stop_do:Nn #3 + { + \tl_if_blank:nTF {#1} + { + \@@_round_final_shift:ff + { + \exp_last_unbraced:Nf 1 + { \@@_round_truncate_direct:n {#2} } 0 + } + { } + } + { + \@@_round_final_shift:ff + { 1 #2 } + { \@@_round_truncate:n {#1} } + } + } + \int_compare:nNnTF {#3} = 9 + { \@@_round_auxviii:nnN {#1} { 0 #2 } } + { + \@@_round_final:fn + { \int_eval:n { #3 + 1 } } + { \@@_round_final_integer:nnw {#1} {#2} } + } + } +% \end{macrocode} +% Tidying up means grabbing the remaining digits and undoing the reversal. +% \begin{macrocode} +\cs_new:Npn \@@_round_final_decimal:nnw + #1#2#3 \q_recursion_tail \q_recursion_stop + { + \@@_round_final_output:ff + { \tl_reverse:n {#1} } + { \tl_reverse:n {#3} #2 } + } +\cs_new:Npn \@@_round_final_integer:nnw + #1#2#3 \q_recursion_tail \q_recursion_stop + { + \@@_round_final_output:ff + { \tl_reverse:n {#3} #2 } + {#1} + } +\cs_new:Npn \@@_round_final_output:nn #1#2 { {#1} {#2} } +\cs_generate_variant:Nn \@@_round_final_output:nn { ff } +\cs_new:Npn \@@_round_final:nn #1#2 + { #2 #1 } +\cs_generate_variant:Nn \@@_round_final:nn { f } +% \end{macrocode} +% Here we deal with the case where rounding applies along with an +% exponent set based on number of places. We can only get here if an +% additional integer digit has been added, so there is no need to test for +% that. There are two cases for action: when using |scientific| mode, where +% we always need to shift by one, and when using |engineering| mode if +% we now have four digits. The latter is a bit more work: we need to trim +% digits off as required. +% \begin{macrocode} +\cs_new:Npn \@@_round_final_shift:nn #1#2 + { + \str_if_eq:VnTF \l_@@_round_mode_tl { places } + { + \use:c + { @@_round_ \l_@@_exponent_mode_tl :nn } + {#1} {#2} + } + { {#1} {#2} } + } +\cs_generate_variant:Nn \@@_round_final_shift:nn { ff } +\cs_new:Npn \@@_round_engineering:nn #1#2 + { + \int_compare:nNnTF { \tl_count:n {#1} } = 4 + { + \@@_round_engineering:NNNNn #1 {#2} + { } + \@@_round_final_shift:Nw 3 + } + { {#1} {#2} } + } +\cs_new:Npn \@@_round_engineering:NNNNn #1#2#3#4#5 + { + {#1} + \exp_args:NV \@@_round_engineering:nnN + { \l_@@_round_precision_int } { } + #2#3#4#5 \q_recursion_tail \q_recursion_stop + } +\cs_new:Npn \@@_round_engineering:nnN #1#2#3 + { + \quark_if_recursion_tail_stop_do:Nn #3 { {#2} } + \int_compare:nNnTF {#1} = { 0 } + { \use_i_delimit_by_q_recursion_stop:nw { {#2} } } + { \@@_round_engineering:nnN { #1 - 1 } { #2#3 } } + } +\cs_new:Npn \@@_round_fixed:nn #1#2 { {#1} {#2} } +\cs_new:Npn \@@_round_input:nn #1#2 { {#1} {#2} } +\cs_new:Npn \@@_round_scientific:nn #1#2 + { + \@@_exponent_shift:nnf + { 1 } {#1} { \@@_round_truncate_direct:n {#2} } + { } + \@@_round_final_shift:Nw 1 + } +\cs_new:Npn \@@_round_final_shift:Nw #1#2 \@@_round_places_end:nn #3#4 + { \@@_exponent_finalise:n { #3#4 + #1 } } +% \end{macrocode} +% When we have rounded up to the next power of ten, we need to go back and +% remove one more digit. That only happens when rounding to a number of +% figures or when dealing with an integer part. +% \begin{macrocode} +\cs_new:Npn \@@_round_truncate:n #1 + { + \str_if_eq:VnTF \l_@@_round_mode_tl { figures } + { \@@_round_truncate_direct:n {#1} } + {#1} + } +\cs_new:Npn \@@_round_truncate_direct:n #1 + { + \@@_round_truncate:nnN { } { } + #1 \q_recursion_tail \q_recursion_stop + } +\cs_new:Npn \@@_round_truncate:nnN #1#2#3 + { + \quark_if_recursion_tail_stop_do:Nn #3 { #1 } + \@@_round_truncate:nnN {#1#2} {#3} + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_round_if_half_p:n} +% \begin{macro}[EXP]{\@@_round_if_half:N} +% A simple test for a valuing being exactly half: we can only test +% digit-by-digit as there is no limit on the size of the value given. +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_round_if_half:n #1 { p } + { + \int_compare:nNnTF { \tl_head:n { #1 0 } } = 5 + { + \exp_after:wN \@@_round_if_half:N \use_none:n #1 0 + \q_recursion_tail \q_recursion_stop + } + { \prg_return_false: } + } +\cs_new:Npn \@@_round_if_half:N #1 + { + \quark_if_recursion_tail_stop_do:Nn #1 + { \prg_return_true: } + \int_compare:nNnTF {#1} = 0 + { \@@_round_if_half:N } + { \use_i_delimit_by_q_recursion_stop:nw { \prg_return_false: } } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_round_pad:nnn} +% The case where we are short of digits is easy enough to handle: +% generate zeros to pad it out. +% \begin{macrocode} +\cs_new:Npn \@@_round_pad:nnn #1#2#3 + { + {#2} + { + #3 + \bool_if:NT \l_@@_round_pad_bool + { \prg_replicate:nn {#1} { 0 } } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_round_figures:nnnnnnn} +% \begin{macro}[EXP]{\@@_round_figures_count:nnN} +% \begin{macro}[EXP]{\@@_round_figures_count:nnnN} +% Rounding to a fixed number of significant figures starts by checking that +% there is no uncertainty, and that the number of figures requested is +% positive: if not, the result is always fixed at zero. +% \begin{macrocode} +\cs_new:Npn \@@_round_figures:nnnnnnn #1#2#3#4#5#6#7 + { + \tl_if_blank:nTF {#5} + { + \int_compare:nNnTF \l_@@_round_precision_int > 0 + { + \exp_not:n { {#1} {#2} } + \@@_round_figures_count:nnN {#3} {#4} #3#4 + \q_recursion_tail \q_recursion_stop + \exp_not:n { { } {#6} {#7} } + } + { { } { } { 0 } { } { } { } { 0 } } + } + { \exp_not:n { {#1} {#2} {#3} {#4} {#5} {#6} {#7} } } + } +% \end{macrocode} +% The first real step is to count up the number of significant figures. +% The only tricky issue here is dealing with leading zeros. +% \begin{macrocode} +\cs_new:Npn \@@_round_figures_count:nnN #1#2#3 + { + \quark_if_recursion_tail_stop_do:Nn #3 + { { } { } { 0 } { } { } { } { 0 } } + \int_compare:nNnTF {#3} = 0 + { \@@_round_figures_count:nnN {#1} {#2} } + { \@@_round_figures_count:nnnN { 1 } {#1} {#2} } + } +\cs_new:Npn \@@_round_figures_count:nnnN #1#2#3#4 + { + \quark_if_recursion_tail_stop_do:Nn #4 + { + \int_compare:nNnTF {#1} > \l_@@_round_precision_int + { + \@@_round:fnn + { \int_eval:n { #1 - \l_@@_round_precision_int } } + {#2} {#3} + } + { + \@@_round_pad:nnn + { \l_@@_round_precision_int - (#1) } {#2} {#3} + } + } + \exp_args:Nf \@@_round_figures_count:nnnN + { \int_eval:n { #1 + 1 } } {#2} {#3} + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_round_places:nnnnnnn} +% \begin{macro}[EXP]{\@@_round_places_end:nn} +% \begin{macro}[EXP]{\@@_round_places_decimal:nn, \@@_round_places_integer:nn} +% \begin{macro}[EXP]{\@@_round_places_finalise:n} +% \begin{macro}[EXP]{\@@_round_places_finalise:nnnnnnn} +% \begin{macro}[EXP]{\@@_round_places_finalise:nnnnn} +% The first step when rounding to a fixed number of places is to establish +% if this is in the decimal or integer parts. The two require different +% calculations for how many digits to drop from the input. The no-op end +% function here is to allow tidying up in some cases: see the finalisation +% of rounding. +% \begin{macrocode} +\cs_new:Npn \@@_round_places:nnnnnnn #1#2#3#4#5#6#7 + { + \tl_if_blank:nTF {#5} + { + \exp_args:Ne \@@_round_places_finalise:n + { + \exp_not:n { {#1} {#2} } + \int_compare:nNnTF \l_@@_round_precision_int > 0 + { \@@_round_places_decimal:nn } + { \@@_round_places_integer:nn } + {#3} {#4} + \@@_round_places_end:nn {#6} {#7} + } + } + { \exp_not:n { {#1} {#2} {#3} {#4} {#5} {#6} {#7} } } + } +\cs_new:Npn \@@_round_places_end:nn #1#2 { { } \exp_not:n { {#1} {#2} } } +\cs_new:Npn \@@_round_places_decimal:nn #1#2 + { + \int_compare:nNnTF + { \l_@@_round_precision_int - 0 \tl_count:n {#2} } > 0 + { + \@@_round_pad:nnn + { \l_@@_round_precision_int - 0 \tl_count:n {#2} } + {#1} {#2} + } + { + \@@_round:fnn + { + \int_eval:n + { 0 \tl_count:n {#2} - \l_@@_round_precision_int } + } + {#1} {#2} + } + } +\cs_new:Npn \@@_round_places_integer:nn #1#2 + { + \@@_round:fnn + { + \int_eval:n + { 0 \tl_count:n {#2} - \l_@@_round_precision_int } + } + {#1} {#2} + } +% \end{macrocode} +% To finalise rounding to places, we have to worry about a minimum value: +% that is basically a case of looking for value of zero and rearranging. We +% also need to worry about a \enquote{negative zero} arising. +% \begin{macrocode} +\cs_new:Npn \@@_round_places_finalise:n #1 + { \@@_round_places_finalise:nnnnnnn #1 } +\cs_new:Npn \@@_round_places_finalise:nnnnnnn #1#2#3#4#5#6#7 + { + \bool_lazy_and:nnTF + { \str_if_eq_p:nn {#3} { 0 } } + { + \str_if_eq_p:ee + { \exp_not:n {#4} } { \prg_replicate:nn { \tl_count:n {#4} } { 0 } } + } + { + \tl_if_empty:NTF \l_@@_round_min_tl + { + \exp_not:n { {#1} } + { \str_if_eq:nnF {#2} { - } { \exp_not:n {#2} } } + \exp_not:n { {#3} {#4} {#5} {#6} {#7} } + } + { + \exp_after:wN \@@_round_places_finalise:nnnnn + \l_@@_round_min_tl {#2} {#6} {#7} + } + } + { \exp_not:n { {#1} {#2} {#3} {#4} {#5} {#6} {#7} } } + } +\cs_new:Npn \@@_round_places_finalise:nnnnn #1#2#3#4#5 + { + { + \str_if_eq:nnTF {#3} { - } + { > } + { < } + } + \exp_not:n { {#3} {#1} {#2} { } {#4} {#5} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_round_uncertainty:nnnnnnn} +% \begin{macro}[EXP]{\@@_round_uncertainty:nnn} +% \begin{macro}[EXP]{\@@_round_uncertainty:nnnnn} +% Rounding to an uncertainty can only happen where the result will have some +% uncertainty left: otherwise we simply drop the uncertainty entirely. Only +% |S|-type uncertainties can be used for rounding. +% \begin{macrocode} +\cs_new:Npn \@@_round_uncertainty:nnnnnnn #1#2#3#4#5#6#7 + { + \bool_lazy_or:nnTF + { \tl_if_blank_p:n {#5} } + { ! \int_compare_p:nNn \l_@@_round_precision_int > 0 } + { \exp_not:n { {#1} #2 {#3} {#4} { } #6 {#7} } } + { + \str_if_eq:eeTF { \tl_head:n {#5} } { S } + { + \exp_not:n { {#1} {#2} } + \exp_args:Nnno \@@_round_uncertainty:nnn + {#3} {#4} { \use_ii:nn #5 } + \exp_not:n { {#6} {#7} } + } + { \exp_not:n { {#1} {#2} {#3} {#4} {#5} {#6} {#7} } } + } + } +% \end{macrocode} +% Round the uncertainty first: this is needed to get the number of places +% correct (for the case where the uncertainty rounds up to |1...|). Once that +% is done, it's just a question of working out the digits in the main part. +% \begin{macrocode} +\cs_new:Npn \@@_round_uncertainty:nnn #1#2#3 + { + \exp_last_unbraced:Nf \@@_round_uncertainty:nnnnn + { + \@@_round:fnn + { \tl_count:n {#3} - \l_@@_round_precision_int } { } {#3} + } + {#1} {#2} {#3} + } +\cs_new:Npn \@@_round_uncertainty:nnnnn #1#2#3#4#5 + { + \tl_if_blank:nTF {#1} + { + \@@_round:fnn + { \tl_count:n {#5} - \tl_count:n {#2} } {#3} {#4} + { { S } {#2} } + } + { + \@@_round:fnn + { \tl_count:n {#5} - \tl_count:n {#2} + 1 } {#3} {#4} + { { S } { #1 \@@_round_truncate_direct:n {#2} } } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_zero_decimal:NN} +% \begin{macro}[EXP]{\@@_zero_decimal:nnnnnnn} +% Simple stripping of the decimal part if zero. +% \begin{macrocode} +\cs_new_protected:Npn \@@_zero_decimal:NN #1#2 + { + \bool_if:NT \l_@@_drop_zero_decimal_bool + { + \tl_set:Nx #2 + { \exp_after:wN \@@_zero_decimal:nnnnnnn #1 } + } + } +\cs_new:Npn \@@_zero_decimal:nnnnnnn #1#2#3#4#5#6#7 + { + \exp_not:n { {#1} {#2} {#3} } + \str_if_eq:eeTF + { \exp_not:n {#4} } + { \prg_replicate:nn { \tl_count:n {#4} } { 0 } } + { { } } + { \exp_not:n { {#4} } } + \exp_not:n { {#5} {#6} {#7} } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Number modification} +% +% \begin{macro}[rEXP]{\siunitx_number_adjust_exponent:nn} +% \begin{macro}[rEXP]{\siunitx_number_adjust_exponent:Nn} +% \begin{macro}[rEXP]{\@@_adjust_exp:nnnnnnnn} +% \begin{macro}[rEXP]{\@@_adjust_exp:nn} +% \begin{macro}[rEXP]{\@@_adjust_exp:nNw} +% A simply case of breaking down and rebuilding the number. +% \begin{macrocode} +\cs_new:Npn \siunitx_number_adjust_exponent:nn #1#2 + { \@@_adjust_exp:nnnnnnnn #1 {#2} } +\cs_new:Npn \siunitx_number_adjust_exponent:Nn #1#2 + { + \tl_if_empty:NF #1 + { \exp_args:NV \siunitx_number_adjust_exponent:nn #1 {#2} } + } +\cs_new:Npn \@@_adjust_exp:nnnnnnnn #1#2#3#4#5#6#7#8 + { + \exp_not:n { {#1} {#2} {#3} {#4} {#5} } + \exp_args:Ne \@@_adjust_exp:nn { \fp_eval:n { #6#7 + #8 } } {#6} + } +\cs_new:Npn \@@_adjust_exp:nn #1#2 + { \@@_adjust_exp:nNw {#2} #1 \q_stop } +\cs_new:Npn \@@_adjust_exp:nNw #1#2#3 \q_stop + { + \token_if_eq_meaning:NNTF #2 - + { { - } { \exp_not:n {#3} } } + { { \str_if_eq:nnT {#1} { + } { + } } { \exp_not:n {#2#3} } } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Outputting parsed numbers} +% +% \begin{variable}{\l_@@_bracket_close_tl, \l_@@_bracket_open_tl} +% Purely internal for the present. +% \begin{macrocode} +\tl_new:N \l_@@_bracket_close_tl +\tl_new:N \l_@@_bracket_open_tl +\tl_set:Nn \l_@@_bracket_open_tl { ( } +\tl_set:Nn \l_@@_bracket_close_tl { ) } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_siunitx_number_bracket_ambiguous_bool} +% \begin{macrocode} +\bool_new:N \l_siunitx_number_bracket_ambiguous_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_siunitx_number_output_decimal_tl} +% \begin{macrocode} +\tl_new:N \l_siunitx_number_output_decimal_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% { +% \l_@@_bracket_negative_bool , +% \l_@@_implicit_plus_bool , +% \l_@@_exponent_base_tl , +% \l_@@_exponent_product_tl , +% \l_@@_group_decimal_bool , +% \l_@@_group_integer_bool , +% \l_@@_group_minimum_int , +% \l_@@_group_separator_tl , +% \l_@@_negative_color_tl , +% \l_@@_output_uncert_close_tl , +% \l_@@_output_uncert_open_tl , +% \l_@@_uncert_mode_tl , +% \l_@@_uncert_separator_tl , +% \l_@@_tight_bool , +% \l_@@_unity_mantissa_bool , +% \l_@@_zero_exponent_bool +% } +% Keys producing tokens in the output. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + bracket-ambiguous-numbers .bool_set:N = + \l_siunitx_number_bracket_ambiguous_bool , + bracket-negative-numbers .bool_set:N = + \l_@@_bracket_negative_bool , + exponent-base .tl_set:N = + \l_@@_exponent_base_tl , + exponent-product .tl_set:N = + \l_@@_exponent_product_tl , + group-digits .choice: , + group-digits / all .code:n = + { + \bool_set_true:N \l_@@_group_decimal_bool + \bool_set_true:N \l_@@_group_integer_bool + } , + group-digits / decimal .code:n = + { + \bool_set_true:N \l_@@_group_decimal_bool + \bool_set_false:N \l_@@_group_integer_bool + } , + group-digits / integer .code:n = + { + \bool_set_false:N \l_@@_group_decimal_bool + \bool_set_true:N \l_@@_group_integer_bool + } , + group-digits / none .code:n = + { + \bool_set_false:N \l_@@_group_decimal_bool + \bool_set_false:N \l_@@_group_integer_bool + } , + group-digits .default:n = all , + group-minimum-digits .int_set:N = + \l_@@_group_minimum_int , + group-separator .tl_set:N = + \l_@@_group_separator_tl , + negative-color .tl_set:N = + \l_@@_negative_color_tl , + output-close-uncertainty .tl_set:N = + \l_@@_output_uncert_close_tl , + output-decimal-marker .tl_set:N = + \l_siunitx_number_output_decimal_tl , + output-open-uncertainty .tl_set:N = + \l_@@_output_uncert_open_tl , + print-implicit-plus .bool_set:N = + \l_@@_implicit_plus_bool , + print-unity-mantissa .bool_set:N = + \l_@@_unity_mantissa_bool , + print-zero-exponent .bool_set:N = + \l_@@_zero_exponent_bool , + tight-spacing .bool_set:N = + \l_@@_tight_bool , + uncertainty-mode .choices:nn = + { compact , compact-marker , full , separate } + { \tl_set_eq:NN \l_@@_uncert_mode_tl \l_keys_choice_tl } , + uncertainty-separator .tl_set:N = + \l_@@_uncert_separator_tl + } +\bool_new:N \l_@@_group_decimal_bool +\bool_new:N \l_@@_group_integer_bool +\tl_new:N \l_@@_uncert_mode_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}[rEXP]{\siunitx_number_output:N} +% \begin{macro}[rEXP]{\siunitx_number_output:n} +% \begin{macro}[rEXP]{\siunitx_number_output:NN} +% \begin{macro}[rEXP]{\siunitx_number_output:nN} +% \begin{macro}[rEXP]{\@@_output:Nn} +% \begin{macro}[rEXP]{\@@_output:nn} +% \begin{macro}[rEXP]{\@@_output:nnnnnnn} +% \begin{macro}[rEXP]{\@@_output_bracket:nn} +% \begin{macro}[rEXP]{\@@_output_bracket:w} +% \begin{macro}[rEXP]{\@@_output_comparator:nn} +% \begin{macro}[rEXP]{\@@_output_sign:nnn} +% \begin{macro}[rEXP]{\@@_output_sign:nN} +% \begin{macro}[rEXP]{\@@_output_sign:N} +% \begin{macro}[rEXP] +% {\@@_output_sign_color:w, \@@_output_sign_brackets:w} +% \begin{macro}[rEXP]{\@@_output_integer:nnn} +% \begin{macro}[rEXP]{\@@_output_decimal:nn, \@@_output_decimal:fn} +% \begin{macro}[rEXP]{\@@_output_digits:nn} +% \begin{macro}[rEXP]{\@@_output_integer_aux:n} +% \begin{macro}[rEXP] +% { +% \@@_output_integer_aux_0:n, +% \@@_output_integer_aux_1:n, +% \@@_output_integer_aux_2:n +% } +% \begin{macro}[rEXP]{\@@_output_decimal_aux:n} +% \begin{macro}[rEXP]{\@@_output_decimal_loop:NNNN} +% \begin{macro}[rEXP]{\@@_output_integer_first:nnNN} +% \begin{macro}[rEXP]{\@@_output_integer_loop:NNNN} +% \begin{macro}[rEXP]{\@@_output_uncertainty:nnn} +% \begin{macro}[rEXP]{\@@_output_uncertainty_unaligned:n} +% \begin{macro}[rEXP]{\@@_output_uncert_S:nnnw} +% \begin{macro}[rEXP] +% {\@@_output_uncert_S_aux:nnn, \@@_output_uncert_S_aux:fnn} +% \begin{macro}[rEXP] +% {\@@_output_uncert_S:nnnw, \@@_output_uncert_S:fnw} +% \begin{macro}[rEXP]{\@@_output_uncert_S:nnw} +% \begin{macro}[rEXP] +% { +% \@@_output_uncert_S_compact:nn , +% \@@_output_uncert_S_compact-marker:nn , +% \@@_output_uncert_S_full:nn +% } +% \begin{macro}[rEXP]{\@@_output_exponent:nnnn} +% \begin{macro}[rEXP]{\@@_output_end:} +% The approach to formatting a single number is to split into +% the constituent parts. All of the parts are assembled including +% inserting tabular alignment markers (which may be empty) for each +% separate unit. +% \begin{macrocode} +\cs_new:Npn \siunitx_number_output:N #1 + { \@@_output:Nn #1 { } } +\cs_new:Npn \siunitx_number_output:n #1 + { \@@_output:nn #1 { } } +\cs_new:Npn \siunitx_number_output:NN #1#2 + { \@@_output:Nn #1 {#2} } +\cs_new:Npn \siunitx_number_output:nN #1#2 + { \@@_output:nn #1 {#2} } +\cs_new:Npn \@@_output:Nn #1#2 + { + \tl_if_empty:NF #1 + { \exp_after:wN \@@_output:nnnnnnn #1 {#2} } + } +\cs_new:Npn \@@_output:nn #1#2 + { + \tl_if_empty:nF {#1} + { \@@_output:nnnnnnn #1 {#2} } + } +\cs_new:Npn \@@_output:nnnnnnn #1#2#3#4#5#6#7#8 + { + \@@_output_comparator:nn {#1} {#8} + \@@_output_bracket:nn {#5} {#7} + \@@_output_sign:nnn {#1} {#2} {#8} + \@@_output_integer:nnn {#3} {#4} {#7} + \@@_output_decimal:nn {#4} {#8} + \@@_output_uncertainty:nnn {#5} {#4} {#8} + \@@_output_exponent:nnnn {#6} {#7} { #3 . #4 } {#8} + \@@_output_end: + } +% \end{macrocode} +% Adding brackets for the combination of a separate uncertainty with an +% exponent may need brackets. This needs testing up-front, so has to come +% before the main formatting routines. +% \begin{macrocode} +\cs_new:Npn \@@_output_bracket:nn #1#2 + { + \bool_lazy_all:nT + { + { \str_if_eq_p:Vn \l_@@_uncert_mode_tl { separate } } + { \l_siunitx_number_bracket_ambiguous_bool } + { ! \tl_if_blank_p:n {#1} } + { + \bool_lazy_or_p:nn + { \l_@@_zero_exponent_bool } + { ! \str_if_eq_p:nn {#2} { 0 } } + } + } + \@@_output_bracket:w + } +\cs_new:Npn \@@_output_bracket:w #1 \@@_output_exponent:nnnn + { + \exp_not:V \l_@@_bracket_open_tl + #1 + \exp_not:V \l_@@_bracket_close_tl + \@@_output_exponent:nnnn + } +% \end{macrocode} +% To get the spacing correct this needs to be an ordinary math character. +% \begin{macrocode} +\cs_new:Npn \@@_output_comparator:nn #1#2 + { + \tl_if_blank:nF {#1} + { \exp_not:n { \mathord {#1} } } + \exp_not:n {#2} + } +% \end{macrocode} +% Formatting signs has to deal with some additional formatting requirements +% for negative numbers. Both making such numbers a fixed color and bracketing +% them needs some rearrangement of the order of tokens, which is set up in +% the main formatting macro by the dedicated do-nothing end function. We +% also have the comparator passed here: if it is present, we need to deal +% with tighter spacing. +% \begin{macrocode} +\cs_new:Npn \@@_output_sign:nnn #1#2#3 + { + \tl_if_blank:nTF {#2} + { + \bool_if:NT \l_@@_implicit_plus_bool + { \@@_output_sign:nN {#1} + } + } + { + \str_if_eq:nnTF {#2} { - } + { + \tl_if_empty:NF \l_@@_negative_color_tl + { \@@_output_sign_color:w } + \bool_if:NTF \l_@@_bracket_negative_bool + { \@@_output_sign_brackets:w } + { \@@_output_sign:nN {#1} #2 } + } + { \@@_output_sign:nN {#1} #2 } + } + \exp_not:n {#3} + } +\cs_new:Npn \@@_output_sign:nN #1#2 + { + \tl_if_blank:nTF {#1} + { \@@_output_sign:N #2 } + { \exp_not:n { \mathord {#2} } } + } +\cs_new:Npn \@@_output_sign:N #1 + { + \bool_if:NTF \l_@@_tight_bool + { \exp_not:n { \mathord {#1} } } + { \exp_not:n {#1} } + } +\cs_new:Npn + \@@_output_sign_color:w #1 \@@_output_end: + { + \exp_not:N \textcolor { \exp_not:V \l_@@_negative_color_tl } + { + #1 + \@@_output_end: + } + } +\cs_new:Npn + \@@_output_sign_brackets:w #1 \@@_output_end: + { + \exp_not:V \l_@@_bracket_open_tl + #1 + \exp_not:V \l_@@_bracket_close_tl + \@@_output_end: + } +% \end{macrocode} +% Digit formatting leads off with separate functions to allow for a few +% \enquote{up front} items before using a common set of tests for some common +% cases. The code then splits again as the two types of grouping need +% different strategies. +% \begin{macrocode} +\cs_new:Npn \@@_output_integer:nnn #1#2#3 + { + \bool_lazy_all:nF + { + { \str_if_eq_p:nn {#1} { 1 } } + { \tl_if_blank_p:n {#2} } + { ! \str_if_eq_p:nn {#3} { 0 } } + { ! \l_@@_unity_mantissa_bool } + } + { \@@_output_digits:nn { integer } {#1} } + } +\cs_new:Npn \@@_output_decimal:nn #1#2 + { + \exp_not:n {#2} + \tl_if_blank:nF {#1} + { + \str_if_eq:VnTF \l_siunitx_number_output_decimal_tl { , } + { \exp_not:N \mathord } + { \use:n } + { \exp_not:V \l_siunitx_number_output_decimal_tl } + } + \exp_not:n {#2} + \@@_output_digits:nn { decimal } {#1} + } +\cs_generate_variant:Nn \@@_output_decimal:nn { f } +\cs_new:Npn \@@_output_digits:nn #1#2 + { + \bool_if:cTF { l_@@_group_ #1 _ bool } + { + \int_compare:nNnTF + { \tl_count:n {#2} } < \l_@@_group_minimum_int + { \exp_not:n {#2} } + { \use:c { @@_output_ #1 _aux:n } {#2} } + } + { \exp_not:n {#2} } + } +% \end{macrocode} +% For integers, we need to know how many digits there are to allow for the +% correct insertion of separators. That is done using a two-part set up such +% that there is no separator on the first pass. +% \begin{macrocode} +\cs_new:Npn \@@_output_integer_aux:n #1 + { + \use:c + { + @@_output_integer_aux_ + \int_eval:n { \int_mod:nn { \tl_count:n {#1} } { 3 } } + :n + } {#1} + } +\cs_new:cpn { @@_output_integer_aux_0:n } #1 + { \@@_output_integer_first:nnNN #1 \q_nil } +\cs_new:cpn { @@_output_integer_aux_1:n } #1 + { \@@_output_integer_first:nnNN { } { } #1 \q_nil } +\cs_new:cpn { @@_output_integer_aux_2:n } #1 + { \@@_output_integer_first:nnNN { } #1 \q_nil } +\cs_new:Npn \@@_output_integer_first:nnNN #1#2#3#4 + { + \exp_not:n {#1#2#3} + \quark_if_nil:NF #4 + { \@@_output_integer_loop:NNNN #4 } + } +\cs_new:Npn \@@_output_integer_loop:NNNN #1#2#3#4 + { + \str_if_eq:VnTF \l_@@_group_separator_tl { , } + { \exp_not:N \mathord } + { \use:n } + { \exp_not:V \l_@@_group_separator_tl } + \exp_not:n {#1#2#3} + \quark_if_nil:NF #4 + { \@@_output_integer_loop:NNNN #4 } + } +% \end{macrocode} +% For decimals, no need to do any counting, just loop using enough markers to +% find the end of the list. By passing the decimal marker, it is possible not +% to have to use a check on the content of the rest of the number. The +% |\use_none:n(n)| mop up the remaining |\q_nil| tokens. +% \begin{macrocode} +\cs_new:Npn \@@_output_decimal_aux:n #1 + { + \@@_output_decimal_loop:NNNN \c_empty_tl + #1 \q_nil \q_nil \q_nil + } +\cs_new:Npn \@@_output_decimal_loop:NNNN #1#2#3#4 + { + \quark_if_nil:NF #2 + { + \exp_not:V #1 + \exp_not:n {#2} + \quark_if_nil:NTF #3 + { \use_none:n } + { + \exp_not:n {#3} + \quark_if_nil:NTF #4 + { \use_none:nn } + { + \exp_not:n {#4} + \@@_output_decimal_loop:NNNN + \l_@@_group_separator_tl + } + } + } + } +% \end{macrocode} +% Uncertainties which are directly attached are easy to deal with. For those +% that are separated, the first step is to find if they are entirely +% contained within the decimal part, and to pad if they are. For the case +% where the boundary is crossed to the integer part, the correct number of +% digit tokens need to be removed from the start of the uncertainty and +% the split result sent to the appropriate auxiliaries. +% \begin{macrocode} +\cs_new:Npn \@@_output_uncertainty:nnn #1#2#3 + { + \tl_if_blank:nTF {#1} + { \@@_output_uncertainty_unaligned:n {#3} } + { + \use:c { @@_output_uncert_ \tl_head:n {#1} :nnnw } + {#2} {#3} #1 + } + } +\cs_new:Npn \@@_output_uncertainty_unaligned:n #1 + { \exp_not:n { #1 #1 #1 #1 } } +\cs_new:Npn \@@_output_uncert_S:nnnw #1#2#3#4 + { + \str_if_eq:VnTF \l_@@_uncert_mode_tl { separate } + { + \exp_not:n {#2} + \@@_output_sign:N \pm + \exp_not:n {#2} + \@@_output_uncert_S_aux:nnn + { \int_eval:n { \tl_count:n {#4} - \tl_count:n {#1} } } + {#4} {#2} + } + { + \exp_not:V \l_@@_uncert_separator_tl + \exp_not:V \l_@@_output_uncert_open_tl + \use:c { @@_output_uncert_S_ \l_@@_uncert_mode_tl :nn } {#1} {#4} + \exp_not:V \l_@@_output_uncert_close_tl + \@@_output_uncertainty_unaligned:n {#2} + } + } +\cs_new:Npn \@@_output_uncert_S_aux:nnn #1#2#3 + { + \int_compare:nNnTF {#1} > 0 + { + \@@_output_uncert_S_aux:fnnw + { \int_eval:n { #1 - 1 } } + {#3} + { } + #2 \q_nil + } + { + 0 + \@@_output_decimal:fn + { + \prg_replicate:nn { \int_abs:n {#1} } { 0 } + #2 + } + {#3} + } + } +\cs_generate_variant:Nn \@@_output_uncert_S_aux:nnn { f } +\cs_new:Npn \@@_output_uncert_S_aux:nnnw #1#2#3#4 + { + \quark_if_nil:NF #4 + { + \int_compare:nNnTF {#1} = 0 + { \@@_output_uncert_S_aux:nnw {#3#4} {#2} } + { + \@@_output_uncert_S_aux:fnnw + { \int_eval:n { #1 - 1 } } + {#2} + {#3#4} + } + } + } +\cs_generate_variant:Nn \@@_output_uncert_S_aux:nnnw { f } +\cs_new:Npn \@@_output_uncert_S_aux:nnw #1#2#3 \q_nil + { + \@@_output_digits:nn { integer } {#1} + \@@_output_decimal:nn {#3} {#2} + } +% \end{macrocode} +% Handle the content of brackets: the only complex case is the +% mixed situation. +% \begin{macrocode} +\cs_new:Npn \@@_output_uncert_S_compact:nn #1#2 + { \exp_not:n {#2} } +\cs_new:cpn { @@_output_uncert_S_compact-marker:nn } #1#2 + { + \bool_lazy_or:nnTF + { \tl_if_blank_p:n {#1} } + { ! \int_compare_p:nNn { \tl_count:n {#2} } > { \tl_count:n {#1} } } + { \@@_output_uncert_S_compact:nn } + { \@@_output_uncert_S_full:nn } + {#1} {#2} + } +\cs_new:Npn \@@_output_uncert_S_full:nn #1#2 + { + \@@_output_uncert_S_aux:fnn + { \int_eval:n { \tl_count:n {#2} - \tl_count:n {#1} } } + {#2} { } + } +% \end{macrocode} +% Setting the exponent part requires some information about the mantissa: +% was it there or not. This means that whilst only the sign and value for +% the exponent are typeset here, there is a need to also have access to the +% combined mantissa part (with a decimal marker). The rest of the work is +% about picking up the various options and getting the combinations right. +% For signs, the auxiliary from the main sign routine can be used, but not +% the main function: negative exponents don't have special handling. +% \begin{macrocode} +\cs_new:Npn \@@_output_exponent:nnnn #1#2#3#4 + { + \exp_not:n {#4} + \bool_lazy_or:nnTF + { \l_@@_zero_exponent_bool } + { ! \str_if_eq_p:nn {#2} { 0 } } + { + \bool_lazy_and:nnTF + { \str_if_eq_p:nn {#3} { 1. } } + { ! \l_@@_unity_mantissa_bool } + { \exp_not:n {#4} } + { + \bool_if:NTF \l_@@_tight_bool + { \exp_not:N \mathord } + { \use:n } + { \exp_not:V \l_@@_exponent_product_tl } + \exp_not:n {#4} + } + \exp_not:V \l_@@_exponent_base_tl + ^ + { + \tl_if_blank:nTF {#1} + { + \bool_if:NT \l_@@_implicit_plus_bool + { \@@_output_sign:N + } + } + { \@@_output_sign:N #1 } + \@@_output_digits:nn { integer } {#2} + } + } + { \exp_not:n {#4} } + } +% \end{macrocode} +% A do-nothing marker used to allow shuffling of the output and so expandable +% operations for formatting. +% \begin{macrocode} +\cs_new:Npn \@@_output_end: { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Miscellaneous tools} +% +% \begin{variable}{\l_@@_valid_tl} +% The list of valid tokens. +% \begin{macrocode} +\tl_new:N \l_@@_valid_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}[TF]{\siunitx_if_number:n} +% Test if an entire number is valid: this means parsing the number but not +% returning anything. +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \siunitx_if_number:n #1 + { T , F , TF } + { + \group_begin: + \bool_set_true:N \l_@@_validate_bool + \bool_set_true:N \l_siunitx_number_parse_bool + \siunitx_number_parse:nN {#1} \l_@@_parsed_tl + \tl_if_empty:NTF \l_@@_parsed_tl + { + \group_end: + \prg_return_false: + } + { + \group_end: + \prg_return_true: + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[pTF, EXP]{\siunitx_if_number_token:N} +% \begin{macro}[EXP] +% { +% \@@_if_token_auxi:NN , +% \@@_if_token_auxii:NN , +% \@@_if_token_auxiii:NN +% } +% A simple conditional to answer the question of whether a specific token is +% possibly valid in a number. +% \begin{macrocode} +\prg_new_conditional:Npnn \siunitx_if_number_token:N #1 + { p , T , F , TF } + { + \@@_token_auxi:NN #1 + \l_siunitx_number_input_decimal_tl + \l_@@_input_uncert_close_tl + \l_siunitx_number_input_comparator_tl + \l_@@_input_digit_tl + \l_siunitx_number_input_exponent_tl + \l_@@_input_ignore_tl + \l_@@_input_uncert_open_tl + \l_siunitx_number_input_sign_tl + \l_@@_input_uncert_sign_tl + \q_recursion_tail + \q_recursion_stop + } +\cs_new:Npn \@@_token_auxi:NN #1#2 + { + \quark_if_recursion_tail_stop_do:Nn #2 { \prg_return_false: } + \@@_token_auxii:NN #1 #2 + \@@_token_auxi:NN #1 + } +\cs_new:Npn \@@_token_auxii:NN #1#2 + { + \exp_after:wN \@@_token_auxiii:NN \exp_after:wN #1 + #2 \q_recursion_tail \q_recursion_stop + } +\cs_new:Npn \@@_token_auxiii:NN #1#2 + { + \quark_if_recursion_tail_stop:N #2 + \str_if_eq:nnT {#1} {#2} + { + \use_i_delimit_by_q_recursion_stop:nw + { + \use_i_delimit_by_q_recursion_stop:nw + { \prg_return_true: } + } + } + \@@_token_auxiii:NN #1 + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Messages} +% +% \begin{macrocode} +\msg_new:nnnn { siunitx } { invalid-number } + { Invalid~number~'#1'. } + { + The~input~'#1'~could~not~be~parsed~as~a~number~following~the~ + format~defined~in~module~documentation. + } +% \end{macrocode} +% +% \subsection{Standard settings for module options} +% +% Some of these follow naturally from the point of definition +% (\foreign{e.g.}~boolean variables are always |false| to begin with), +% but for clarity everything is set here. +% \begin{macrocode} +\keys_set:nn { siunitx } + { + bracket-ambiguous-numbers = true , + bracket-negative-numbers = false , + drop-exponent = false , + drop-uncertainty = false , + drop-zero-decimal = false , + evaluate-expression = false , + exponent-base = 10 , + exponent-mode = input , + exponent-product = \times , + expression = #1 , + fixed-exponent = 0 , + group-digits = all , + group-minimum-digits = 4 , + group-separator = \, , % ( + input-close-uncertainty = ) , + input-comparators = { <=>\approx\ge\geq\gg\le\leq\ll\sim } , + input-decimal-markers = { ., } , + input-digits = 0123456789 , + input-exponent-markers = dDeE , + input-ignore = \, , + input-open-uncertainty = ( , % ) + input-signs = +-\mp\pm , + input-uncertainty-signs = \pm , + minimum-decimal-digits = 0 , + minimum-integer-digits = 0 , + negative-color = , % ( + output-close-uncertainty = ) , + output-decimal-marker = . , + output-open-uncertainty = ( , % ) + parse-numbers = true , + print-implicit-plus = false , + print-unity-mantissa = true , + print-zero-exponent = false , + retain-explicit-plus = false , + retain-zero-uncertainty = false , + round-half = up , + round-minimum = 0 , + round-mode = none , + round-pad = true , + round-precision = 2 , + tight-spacing = false , + uncertainty-mode = compact , + uncertainty-separator = + } +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/siunitx/siunitx-print.dtx b/macros/latex/contrib/siunitx/siunitx-print.dtx new file mode 100644 index 0000000000..0885d4f1aa --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-print.dtx @@ -0,0 +1,975 @@ +% \iffalse meta-comment +% +% File: siunitx-print.dtx Copyright (C) 2016-2019,2021 Joseph Wright +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +\ProvideDocumentCommand\foreign{m}{\textit{#1}} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-print} -- Printing material with font control^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \section{Printing quantities} +% +% This submodule is focussed on providing controlled printing for numbers and +% units. Key to this is control of font: conventions for printing quantities +% mean that the exact nature of the output is important. At the same time, this +% module provides flexibility for the user in terms of which aspects of the font +% are responsive to the surrounding general text. Printing material may also +% take place in text or math mode. +% +% The printing routines assume that normal \LaTeXe{} font selection commands +% are available, in particular \cs{bfseries}, \cs{mathrm}, \cs{mathversion}, +% \cs{fontfamily}, \cs{fontseries} and \cs{fontshape}, \cs{familydefault}, +% \cs{seriesdefault}, \cs{shapedefault} and \cs{selectfont}. +% It also requires the standard +% \LaTeXe{} kernel commands \cs{ensuremath}, \cs{textsubscript} and +% \cs{textsuperscript} for printing in text mode. The following packages are +% also required to provide the functionality detailed. +% \begin{itemize} +% \item \pkg{color}: support for color using \cs{textcolor} +% \item \pkg{textcomp}: \cs{textminus} and \cs{textpm} for printing +% in text mode +% \item \pkg{amstext}: the \cs{text} command for printing in text mode +% \end{itemize} +% +% \begin{function} +% { +% \siunitx_print_number:n, \siunitx_print_number:V, +% \siunitx_print_number:x, +% \siunitx_print_unit:n, \siunitx_print_unit:V, +% \siunitx_print_unit:x +% } +% \begin{syntax} +% \cs{siunitx_print_number:n} \Arg{material} +% \cs{siunitx_print_unit:n} \Arg{material} +% \end{syntax} +% Prints the \meta{material} according the the prevailing settings for the +% submodule as applicable to the \meta{type} of content (|number| or |unit|). +% The \meta{material} should comprise normal +% \LaTeX{} mark-up for numbers or units. In particular, units will typically +% use |\mathrm| to indicate material to be printed in the current upright +% roman font, and |^| and |_| will typically be used to indicate super- and +% subscripts, respectively. These elements will be correctly handled when +% printing for example using |\mathsf| in math mode, or using only text +% fonts. +% \end{function} +% +% \begin{function} +% {\siunitx_print_match:n, \siunitx_print_math:n, \siunitx_print_text:n} +% \begin{syntax} +% \cs{siunitx_print_match:n} \Arg{material} +% \cs{siunitx_print_math:n} \Arg{material} +% \cs{siunitx_print_text:n} \Arg{material} +% \end{syntax} +% Prints the \meta{material} as described for \cs{siunitx_print_\dots:n} but +% with a fixed text or math mode output. The printing does \emph{not} set +% color (which is managed on a |unit|/|number| basis), but otherwise sets +% the font as described above. The |match| function uses either the prevailing +% math or text mode. +% \end{function} +% +% \subsection{Key--value options} +% +% The options defined by this submodule are available within the \pkg{l3keys} +% |siunitx| tree. +% +% \begin{function}{color} +% \begin{syntax} +% |color| = \meta{color} +% \end{syntax} +% Color to apply to printed output: the latter should be a named color +% defined for use with \cs{textcolor}. The standard setting is empty (no +% color). +% \end{function} +% +% \begin{function}{mode} +% \begin{syntax} +% |mode| = |match|\verb"|"|math|\verb"|"|text| +% \end{syntax} +% Selects which mode (math or text) the output is printed in: a choice +% from the options |match|, |math| or |text|. The option |match| matches +% the mode prevailing at the point \cs{siunitx_print_\dots:n} is called. The +% |math| and |text| options choose the relevant \TeX{} mode for printing. +% The standard setting is |math|. +% \end{function} +% +% \begin{function}{number-color} +% \begin{syntax} +% |number-color| = \meta{color} +% \end{syntax} +% Color to apply to numbers in output: the latter should be a named color +% defined for use with \cs{textcolor}. The standard setting is empty (no +% color). +% \end{function} +% +% \begin{function}{number-mode} +% \begin{syntax} +% |number-mode| = |match|\verb"|"|math|\verb"|"|text| +% \end{syntax} +% Selects which mode (math or text) the numbers are printed in: a choice +% from the options |match|, |math| or |text|. The option |match| matches +% the mode prevailing at the point \cs{siunitx_prin_number:n} is called. The +% |math| and |text| options choose the relevant \TeX{} mode for printing. +% The standard setting is |math|. +% \end{function} +% +% \begin{function}{propagate-math-font} +% \begin{syntax} +% |propagate-math-font| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine if the currently-active math font is applied within +% printed output. This is relevant only when \cs{siunitx_print_\dots:n} is +% called from within math mode: in text mode there is not active math +% font. When not active, math mode material will be typeset using +% standard math mode fonts without any changes being made to the +% supplied argument. The standard setting is |false|. +% \end{function} +% +% \begin{function}{reset-math-version} +% \begin{syntax} +% |reset-math-version| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine whether the active \cs{mathversion} is reset to +% |normal| when printing in math mode. Note that math version is typically +% used to select \cs{boldmath}, though it is also be used by +% \foreign{e.g.}~\pkg{sansmath}. The standard setting is |true|. +% \end{function} +% +% \begin{function}{reset-text-family} +% \begin{syntax} +% |reset-text-family| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine whether the active text family is reset to +% \cs{rmfamily} when printing in text mode. The standard setting is |true|. +% \end{function} +% +% \begin{function}{reset-text-series} +% \begin{syntax} +% |reset-text-series| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine whether the active text series is reset to +% \cs{mdseries} when printing in text mode. The standard setting is |true|. +% \end{function} +% +% \begin{function}{reset-text-shape} +% \begin{syntax} +% |reset-text-shape| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine whether the active text shape is reset to +% \cs{upshape} when printing in text mode. The standard setting is |true|. +% \end{function} +% +% \begin{function}{text-family-to-math} +% \begin{syntax} +% |text-family-to-math| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine if the family of the current text font should be +% applied (where possible) to printing in math mode. The standard setting is +% |false|. +% \end{function} +% +% \begin{function}{text-font-command} +% \begin{syntax} +% |text-font-command| = \meta{cmd} +% \end{syntax} +% Command applied to text during output, inserted after any reset of +% font set-up. This can therefore be used to apply non-standard font +% set up when printing in text mode. The standard setting is empty. +% \end{function} +% +% \begin{function}{text-series-to-math} +% \begin{syntax} +% |text-series-to-math| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine if the weight of the current text font should be +% applied (where possible) to printing in math mode. This is achieved by +% setting the \cs{mathversion}, and so will override |reset-math-version|. +% The mappings between text and math weight are set . The standard setting is |false|. +% \end{function} +% +% \begin{function}{unit-color} +% \begin{syntax} +% |unit-color| = \meta{color} +% \end{syntax} +% Color to apply to units in output: the latter should be a named color +% defined for use with \cs{textcolor}. The standard setting is empty (no +% color). +% \end{function} +% +% \begin{function}{unit-mode} +% \begin{syntax} +% |unit-mode| = |match|\verb"|"|math|\verb"|"|text| +% \end{syntax} +% Selects which mode (math or text) units are printed in: a choice +% from the options |match|, |math| or |text|. The option |match| matches +% the mode prevailing at the point \cs{siunitx_print_\dots:n} is called. The +% |math| and |text| options choose the relevant \TeX{} mode for printing. +% The standard setting is |math|. +% \end{function} +% +% \begin{function}{series-version-mapping} +% \begin{syntax} +% |series-version-mapping| |/| \meta{weight} = \meta{version} +% \end{syntax} +% Defines how \pkg{siunitx} maps from text font weight to math font +% version. The pre-defined weights are those used as-standard by +% \pkg{autoinst}: +% \begin{itemize} +% \item \texttt{ul} +% \item \texttt{el} +% \item \texttt{l} +% \item \texttt{sl} +% \item \texttt{m} +% \item \texttt{sb} +% \item \texttt{b} +% \item \texttt{eb} +% \item \texttt{ub} +% \end{itemize} +% As standard, the \texttt{m} weight maps to \texttt{normal} math version +% whilst all of the \texttt{b} weights map to \texttt{bold} and all of the +% \texttt{l} weights map to \texttt{light}. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-print} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_print> +% \end{macrocode} +% +% \subsection{Initial set up} +% +% The printing routines depend on \pkg{amstext} for text mode working. +% \begin{macrocode} +\RequirePackage { amstext } +% \end{macrocode} +% +% Color support is always required. +% \begin{macrocode} +\RequirePackage { color } +% \end{macrocode} +% +% \begin{macro}{\tl_replace_all:NVn} +% Required variants. +% \begin{macrocode} +\cs_generate_variant:Nn \tl_replace_all:Nnn { NV } +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\l_@@_tmp_box, \l_@@_tmp_tl} +% Scratch space. +% \begin{macrocode} +\box_new:N \l_@@_tmp_box +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\document} +% \begin{macro}{\@@_store_fam:n} +% \begin{variable}{\c_@@_mathrm_int, \c_@@_mathsf_int, \c_@@_mathtt_int} +% In order to test math fonts, we need information about the \cs{fam} used +% by the various options. As we are doing typesetting (if only in a box), we +% need to be right at the start of the document: this also avoids any issue +% with \pkg{fontspec}. With a sufficiently recent \LaTeXe{} this is easy; +% for older kernels, we have to do things manually. +% \begin{macrocode} +\IfFormatAtLeastTF { 2020-10-01 } + { \hook_gput_code:nnn { begindocument/end } { siunitx } } + { \tl_put_right:Nn \document } + { + \@@_store_fam:n { rm } + \@@_store_fam:n { sf } + \@@_store_fam:n { tt } + } +\IfFormatAtLeastTF { 2020-10-01 } + { } + { \tl_put_right:Nn \document { \ignorespaces } } +\cs_new_protected:Npn \@@_store_fam:n #1 + { + \group_begin: + \hbox_set:Nn \l_@@_tmp_box + { + \ensuremath + { + \use:c { math #1 } + { \int_const:cn { c_@@_math #1 _int } { \fam } } + } + } + \group_end: + } +% \end{macrocode} +% \end{variable} +% \end{macro} +% \end{macro} +% +% \subsection{Printing routines} +% +% \begin{variable} +% { +% \l_@@_number_color_tl , +% \l_@@_number_mode_tl , +% \l_@@_unit_color_tl , +% \l_@@_unit_mode_tl , +% \l_@@_math_font_bool , +% \l_@@_math_version_bool , +% \l_@@_math_family_bool , +% \l_@@_text_font_tl , +% \l_@@_math_weight_bool +% } +% Options which apply to the main formatting routine, and so are not tied +% to either symbolic or literal input. +% \begin{macrocode} +\tl_new:N \l_@@_number_mode_tl +\tl_new:N \l_@@_unit_mode_tl +\keys_define:nn { siunitx } + { + color .meta:n = + { number-color = #1 , unit-color = #1 } , + mode .meta:n = + { number-mode = #1 , unit-mode = #1 } , + number-color .tl_set:N = + \l_@@_number_color_tl , + number-mode .choices:nn = + { match , math , text } + { + \tl_set_eq:NN + \l_@@_number_mode_tl \l_keys_choice_tl + } , + propagate-math-font .bool_set:N = + \l_@@_math_font_bool , + reset-math-version .bool_set:N = + \l_@@_math_version_bool , + reset-text-family .bool_set:N = + \l_@@_text_family_bool , + reset-text-series .bool_set:N = + \l_@@_text_series_bool , + reset-text-shape .bool_set:N = + \l_@@_text_shape_bool , + text-family-to-math .bool_set:N = + \l_@@_math_family_bool , + text-font-command .tl_set:N = + \l_@@_text_font_tl , + text-series-to-math .bool_set:N = + \l_@@_math_weight_bool , + unit-color .tl_set:N = + \l_@@_unit_color_tl , + unit-mode .choices:nn = + { match , math , text } + { + \tl_set_eq:NN + \l_@@_unit_mode_tl \l_keys_choice_tl + } + } +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% { +% \l_@@_version_ul_tl , +% \l_@@_version_el_tl , +% \l_@@_version_l_tl , +% \l_@@_version_sl_tl , +% \l_@@_version_m_tl , +% \l_@@_version_sb_tl , +% \l_@@_version_b_tl , +% \l_@@_version_eb_tl , +% \l_@@_version_ub_tl +% } +% One set of \enquote{focussed} options. +% \begin{macrocode} +\keys_define:nn { siunitx / series-version-mapping } + { + ul . tl_set:N = \l_@@_version_ul_tl , + el . tl_set:N = \l_@@_version_el_tl , + l . tl_set:N = \l_@@_version_l_tl , + sl . tl_set:N = \l_@@_version_sl_tl , + m . tl_set:N = \l_@@_version_m_tl , + sb . tl_set:N = \l_@@_version_sb_tl , + b . tl_set:N = \l_@@_version_b_tl , + eb . tl_set:N = \l_@@_version_eb_tl , + ub . tl_set:N = \l_@@_version_ub_tl + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro} +% { +% \siunitx_print_number:n, \siunitx_print_number:V, +% \siunitx_print_number:x, +% \siunitx_print_unit:n, \siunitx_print_unit:V, +% \siunitx_print_unit:x +% } +% \begin{macro}{\@@_aux:nn} +% The main printing function doesn't actually need to do very much: just set +% the color and select the correct sub-function. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_print_number:n #1 + { \@@_aux:nn { number } {#1} } +\cs_generate_variant:Nn \siunitx_print_number:n { V , x } +\cs_new_protected:Npn \siunitx_print_unit:n #1 + { \@@_aux:nn { unit } {#1} } +\cs_generate_variant:Nn \siunitx_print_unit:n { V , x } +\cs_new_protected:Npn \@@_aux:nn #1#2 + { + \tl_if_empty:cTF { l_@@_ #1 _color_tl } + { \use:n } + { \exp_args:Nv \textcolor { l_@@_ #1 _color_tl } } + { + \use:c + { + siunitx_print_ + \tl_use:c { l_@@_ #1 _mode_tl } :n + } + {#2} + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\siunitx_print_match:n} +% When the \emph{output} mode should match the input, a simple selection of +% route can be made. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_print_match:n #1 + { + \mode_if_math:TF + { \siunitx_print_math:n {#1} } + { \siunitx_print_text:n {#1} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_replace_font:N} +% A simple auxiliary for \enquote{zapping} the unit font. +% \begin{macrocode} +\cs_new_protected:Npn \@@_replace_font:N #1 + { + \tl_if_empty:NF \l_siunitx_unit_font_tl + { + \tl_replace_all:NVn #1 + \l_siunitx_unit_font_tl + { \use:n } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{variable} +% { +% \c_@@_weight_uc_tl , +% \c_@@_weight_ecl_tl , +% \c_@@_weight_c_tl , +% \c_@@_weight_sc_tl , +% \c_@@_weight_sx_tl , +% \c_@@_weight_x_tl , +% \c_@@_weight_ex_tl , +% \c_@@_weight_ux_tl +% } +% Font widths where the |m| for weight is omitted. +% \begin{macrocode} +\clist_map_inline:nn { uc , ec , c , sc , sx , x , ex , ux } + { \tl_const:cn { c_@@_weight_ #1 _tl } { m } } +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% { +% \c_@@_weight_l_tl , +% \c_@@_weight_m_tl , +% \c_@@_weight_b_tl +% } +% Font widths with one letter. +% \begin{macrocode} +\clist_map_inline:nn { l , m , b } + { \tl_const:cn { c_@@_weight_ #1 _tl } { #1 } } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_print_math:n} +% \begin{macro}[EXP]{\@@_extract_series:Nw} +% \begin{macro}[EXP]{\@@_convert_series:n, \@@_convert_series:v} +% \begin{macro}{\@@_math_version:nn, \@@_math_version:Vn} +% \begin{macro} +% { +% \@@_math_auxi:n, +% \@@_math_auxii:n, +% \@@_math_auxiii:n, +% \@@_math_auxiv:n, +% \@@_math_auxv:n +% } +% \begin{macro}{\@@_math_aux:Nn, \@@_math_aux:cn} +% \begin{macro}{\@@_math_sub:n, \@@_math_super:n, \@@_math_script:n} +% \begin{macro}{\@@_math_text:n} +% The first step in setting in math mode is to check on the math version. +% The starting point is the question of whether text series needs to +% propagate to math mode: if so, check on the mapping, otherwise check on +% the current math version. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_print_math:n #1 + { + \bool_if:NTF \l_@@_math_weight_bool + { + \tl_set:Nx \l_@@_tmp_tl + { \exp_after:wN \@@_extract_series:Nw \f@series ? \q_stop } + \tl_if_empty:NTF \l_@@_tmp_tl + { \@@_math_auxi:n {#1} } + { \@@_math_version:Vn \l_@@_tmp_tl {#1} } + } + { \@@_math_auxi:n {#1} } + } +% \end{macrocode} +% Look up the math version from the text series. The weight is omitted +% if it is |m| plus there are either one or two letters, so we have a little +% work to do. To keep things fast, we use a hash table based lookup rather +% than a sequence or property list. +% \begin{macrocode} +\cs_new:Npn \@@_extract_series:Nw #1#2 ? #3 \q_stop + { + \cs_if_exist:cTF { c_@@_weight_ #1#2 _tl } + { \@@_convert_series:v { c_@@_weight_ #1#2 _tl } } + { + \cs_if_exist:cTF { c_@@_weight_ #1 _tl } + { \@@_convert_series:v { c_@@_weight_ #1 _tl } } + { \@@_convert_series:n {#1#2} } + } + } +\cs_new:Npn \@@_convert_series:n #1 + { \tl_use:c { l_@@_version_ #1 _tl } } +\cs_generate_variant:Nn \@@_convert_series:n { v } +\cs_new_protected:Npn \@@_math_auxi:n #1 + { + \bool_if:NTF \l_@@_math_version_bool + { \@@_math_version:nn { normal } {#1} } + { \@@_math_auxii:n {#1} } + } +% \end{macrocode} +% Any setting which changes the math version can only be set from text mode +% (as it applies at the level of a formula). As such, the first test is to +% see if that needs to be to check if the math version has to be set: if so, +% switch to text mode, sort it out and switch back. That of course means +% that in such cases, line breaking will not be possible. +% \begin{macrocode} +\cs_new_protected:Npn \@@_math_version:nn #1#2 + { + \str_if_eq:VnTF \math@version { #1 } + { \@@_math_auxii:n {#2} } + { + \mode_if_math:TF + { \text } + { \use:n } + { + \mathversion {#1} + \@@_math_auxii:n {#2} + } + } + } +\cs_generate_variant:Nn \@@_math_version:nn { V } +% \end{macrocode} +% At this point, force math mode then start dealing with setting math font +% based on text family. If the text family is roman, life is slightly +% different to if it is sanserif or monospaced. In all cases, the outcomes +% can be handled using the same routines as for normal math mode treatment. +% The test here is on a string basis as |\f@family| and the |\...default| +% commands have different |\long| status. +% \begin{macrocode} +\cs_new_protected:Npn \@@_math_auxii:n #1 + { \ensuremath { \@@_math_auxiii:n {#1} } } +\cs_new_protected:Npn \@@_math_auxiii:n #1 + { + \bool_if:NTF \l_@@_math_family_bool + { + \str_case_e:nnF { \f@family } + { + { \rmdefault } { \@@_math_auxv:n } + { \sfdefault } { \@@_math_aux:Nn \mathsf } + { \ttdefault } { \@@_math_aux:Nn \mathtt } + } + { \@@_math_auxiv:n } + } + { \@@_math_auxiv:n } + {#1} + } +% \end{macrocode} +% Now we deal with the font selection in math mode. There are two possible +% cases. First, we are retaining the current math font, and the active one is +% \cs{mathsf} or \cs{mathtt}: that needs to be applied to the argument. +% Alternatively, if the current font is not retained, ensure that +% normal math mode rules are active. The parts here are split up to allow +% reuse when picking up the text family. +% \begin{macrocode} +\cs_new_protected:Npn \@@_math_auxiv:n #1 + { + \bool_if:NTF \l_@@_math_font_bool + { + \int_case:nnF \fam + { + \c_@@_mathsf_int { \@@_math_aux:Nn \mathsf } + \c_@@_mathtt_int { \@@_math_aux:Nn \mathtt } + } + { \use:n } + } + { \@@_math_auxv:n } + {#1} + } +\cs_new_protected:Npn \@@_math_auxv:n #1 + { + \bool_lazy_or:nnTF + { \int_compare_p:nNn \fam = { -1 } } + { \int_compare_p:nNn \fam = \c_@@_mathrm_int } + { \use:n } + { \mathrm } + {#1} + } +% \end{macrocode} +% Search-and-replace fun: deal with any font commands in the argument and +% also inside sub/superscripts. +% \begin{macrocode} +\cs_new_protected:Npx \@@_math_aux:Nn #1#2 + { + \group_begin: + \tl_set:Nn \exp_not:N \l_@@_tmp_tl {#2} + \@@_replace_font:N \exp_not:N \l_@@_tmp_tl + \tl_replace_all:Nnn \exp_not:N \l_@@_tmp_tl + { \char_generate:nn { `\_ } { 8 } } + { \exp_not:N \@@_math_sub:n } + \tl_replace_all:Nnn \exp_not:N \l_@@_tmp_tl + { ^ } + { \exp_not:N \@@_math_super:n } + #1 { \exp_not:N \tl_use:N \exp_not:N \l_@@_tmp_tl } + \group_end: + } +\cs_generate_variant:Nn \@@_math_aux:Nn { c } +\cs_new_protected:Npx \@@_math_sub:n #1 + { + \char_generate:nn { `\_ } { 8 } + { \exp_not:N \@@_math_script:n {#1} } + } +\cs_new_protected:Npn \@@_math_super:n #1 + { ^ { \@@_math_script:n {#1} } } +\cs_new_protected:Npn \@@_math_script:n #1 + { + \group_begin: + \tl_set:Nn \l_@@_tmp_tl {#1} + \@@_replace_font:N \l_@@_tmp_tl + \tl_use:N \l_@@_tmp_tl + \group_end: + } +% \end{macrocode} +% For \pkg{tex4ht}, we need to have category code $12$ |^| tokens in math +% mode. We handle that by intercepting at the first auxiliary that makes +% sense. +% \begin{macrocode} +\AtBeginDocument + { + \@ifpackageloaded { tex4ht } + { + \cs_set_protected:Npn \@@_math_auxii:n #1 + { + \tl_set:Nn \l_@@_tmp_tl {#1} + \exp_args:NNnx \tl_replace_all:Nnn \l_@@_tmp_tl + { ^ } { \token_to_str:N ^ } + \ensuremath { \exp_args:NV \@@_math_auxiii:n \l_@@_tmp_tl } + } + } + { } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\siunitx_print_text:n} +% \begin{macro}{\@@_text_replace:n} +% \begin{macro}{\@@_text_replace:N} +% \begin{macro}{\@@_text_replace:NNn} +% \begin{macro}{\@@_text_sub:n, \@@_text_super:n} +% \begin{macro}{\@@_text_scripts:NnN} +% \begin{macro}{\@@_text_scripts:} +% \begin{macro}{\@@_text_scripts_one:NnN} +% \begin{macro}{\@@_text_scripts_two:NnNn} +% \begin{macro}{\@@_text_scripts_two:nn} +% \begin{macro}{\@@_text_scripts_two:n} +% Typesetting in text mode is easy in font control terms but more tricky +% in the manipulation of the input. The easy part comes first. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_print_text:n #1 + { + \text + { + \bool_if:NT \l_@@_text_family_bool + { \fontfamily { \familydefault } } + \bool_if:NT \l_@@_text_series_bool + { \fontseries { \seriesdefault } } + \bool_if:NT \l_@@_text_shape_bool + { \fontshape { \shapedefault } } + \bool_lazy_any:nT + { + { \l_@@_text_family_bool } + { \l_@@_text_series_bool } + { \l_@@_text_shape_bool } + } + { \selectfont } + \tl_use:N \l_@@_text_font_tl + \@@_text_replace:n {#1} + } + } +% \end{macrocode} +% To get math mode material to print in text mode, various search-and-replace +% steps are needed. +% \begin{macrocode} +\cs_new_protected:Npn \@@_text_replace:n #1 + { + \group_begin: + \tl_set:Nn \l_@@_tmp_tl {#1} + \@@_text_replace:N \l_@@_tmp_tl + \tl_use:N \l_@@_tmp_tl + \group_end: + } +\cs_new_protected:Npx \@@_text_replace:N #1 + { + \@@_replace_font:N #1 + \exp_not:N \@@_text_replace:NNn #1 + \exp_not:N \mathord { } + \exp_not:N \pm + { \exp_not:N \textpm } + \exp_not:N \mp + { \exp_not:n { \ensuremath { \mp } } } + - + { \exp_not:N \textminus } + \char_generate:nn { `\_ } { 8 } + { \exp_not:N \@@_text_sub:n } + ^ + { \exp_not:N \@@_text_super:n } + \exp_not:N \q_recursion_tail + { ? } + \exp_not:N \q_recursion_stop + } +\cs_new_protected:Npn \@@_text_replace:NNn #1#2#3 + { + \quark_if_recursion_tail_stop:N #2 + \tl_replace_all:Nnn #1 {#2} {#3} + \@@_text_replace:NNn #1 + } +% \end{macrocode} +% When the \pkg{bidi} package is loaded, we need to make sure +% that \cs{text} is doing the correct thing. +% \begin{macrocode} +\sys_if_engine_xetex:T + { + \AtBeginDocument + { + \@ifpackageloaded { bidi } + { + \cs_set_protected:Npn \@@_text_replace:n #1 + { + \group_begin: + \tl_set:Nn \l_@@_tmp_tl {#1} + \@@_text_replace:N \l_@@_tmp_tl + \LRE { \tl_use:N \l_@@_tmp_tl } + \group_end: + } + } + { } + } + } +% \end{macrocode} +% Sub- and superscripts can be in any order in the source. The first step +% of handling them is therefore to do a look-ahead to work out whether +% only one or both are present. +% \begin{macrocode} +\cs_new_protected:Npn \@@_text_sub:n #1 + { + \@@_text_scripts:NnN + \textsubscript {#1} \@@_text_super:n + } +\cs_new_protected:Npn \@@_text_super:n #1 + { + \@@_text_scripts:NnN + \textsuperscript {#1} \@@_text_sub:n + } +\cs_new_protected:Npn \@@_text_scripts:NnN #1#2#3 + { + \cs_set_protected:Npn \@@_text_scripts: + { + \if_meaning:w \l_peek_token #3 + \exp_after:wN \@@_text_scripts_two:NnNn + \else: + \exp_after:wN \@@_text_scripts_one:Nn + \fi: + #1 {#2} + } + \peek_after:Nw \@@_text_scripts: + } +\cs_new_protected:Npn \@@_text_scripts: { } +% \end{macrocode} +% In the simple case of one script item, we have to do a search-and-replace +% to deal with anything inside the argument. +% \begin{macrocode} +\cs_new_protected:Npn \@@_text_scripts_one:Nn #1#2 + { + \group_begin: + \tl_set:Nn \l_@@_tmp_tl {#2} + \@@_text_replace:N \l_@@_tmp_tl + \exp_args:NNV \group_end: + #1 \l_@@_tmp_tl + } +% \end{macrocode} +% For the two scripts case, we cannot use |\textsubscript|/|\textsuperscript| +% as they don't stack directly. Instead, we sort out the ordering then use +% an implementation for both parts that is the same as the kernel text +% scripts. +% \begin{macrocode} +\cs_new_protected:Npn \@@_text_scripts_two:NnNn #1#2#3#4 + { + \cs_if_eq:NNTF #1 \textsubscript + { \@@_text_scripts_two:nn {#4} {#2} } + { \@@_text_scripts_two:nn {#2} {#4} } + } +\cs_new_protected:Npx \@@_text_scripts_two:nn #1#2 + { + \group_begin: + \exp_not:N \m@th + \exp_not:N \ensuremath + { + ^ { \exp_not:N \@@_text_scripts_two:n {#1} } + \char_generate:nn { `\_ } { 8 } + { \exp_not:N \@@_text_scripts_two:n {#2} } + } + \group_end: + } +\cs_new_protected:Npn \@@_text_scripts_two:n #1 + { + \mbox + { + \fontsize \sf@size \z@ \selectfont + \@@_text_scripts_one:Nn \use:n {#1} + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Standard settings for module options} +% +% Some of these follow naturally from the point of definition +% (\foreign{e.g.}~boolean variables are always |false| to begin with), +% but for clarity everything is set here. +% \begin{macrocode} +\keys_set:nn { siunitx } + { + color = , + mode = math , + number-color = , + number-mode = math , + propagate-math-font = false , + reset-math-version = true , + reset-text-shape = true , + reset-text-series = true , + reset-text-family = true , + text-family-to-math = false , + text-font-command = , + text-series-to-math = false , + unit-color = , + unit-mode = math + } +% \end{macrocode} +% +% These are separate as they all fall inside the same key. +% \begin{macrocode} +\keys_set:nn { siunitx / series-version-mapping } + { + ul = light , + el = light , + l = light , + sl = light , + m = normal , + sb = bold , + b = bold , + eb = bold , + ub = bold + } +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/siunitx/siunitx-quantity.dtx b/macros/latex/contrib/siunitx/siunitx-quantity.dtx new file mode 100644 index 0000000000..930f75c5fc --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-quantity.dtx @@ -0,0 +1,445 @@ +% \iffalse meta-comment +% +% File: siunitx-quantity.dtx Copyright (C) 2018-2021 Joseph Wright +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +\ProvideDocumentCommand\foreign{m}{\textit{#1}} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-quantity} -- Quantities^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% This submodule is focussed on providing controlled printing for quantities: +% the combination of a number and a unit. It largely builds on the submodules +% \pkg{siunitx-number} and \pkg{siunitx-unit}. A small number of adjustments +% are made to standard set up in the latter to reflect additional functionality +% added here. +% +% \begin{function}{\siunitx_quantity:nn} +% \begin{syntax} +% \cs{siunitx_quantity:nn} \Arg{number} \Arg{unit} +% \end{syntax} +% Parses the \meta{number} and the \meta{unit} as detailed for +% \cs{siunitx_number_parse:nN} and \cs{siunitx_unit_format:nN}, +% the prints the results using \cs{siunitx_print_unit:n}. +% \end{function} +% +% \begin{function} +% { +% \siunitx_quantity_print:nn, \siunitx_quantity_print:nV, +% \siunitx_quantity_print:VV, \siunitx_quantity_print:xV +% } +% \begin{syntax} +% \cs{siunitx_quantity_print:nn} \Arg{number} \Arg{unit} +% \end{syntax} +% A low-level function which prints the quantity directly: there is +% no processing applied to either the \meta{number} or \meta{unit}. The +% two parts are printed using \cs{siunitx_print_unit:n} and appropriate +% spacing and break-prevention is applied. +% \end{function} +% +% \begin{function}{allow-quantity-breaks} +% \begin{syntax} +% |allow-quantity-breaks| = |true|\verb"|"|false| +% \end{syntax} +% Specifies whether breaks are permitted between units. The standard setting +% is |false|. +% \end{function} +% +% \begin{function}{prefix-mode} +% \begin{syntax} +% |prefix-mode| = |combine-exponent|\verb"|"|extract-exponent|\verb"|"|input| +% \end{syntax} +% Selects the method used for producing prefixes: a choice from the options +% |combine-exponent|, |extract-exponent| and |input|. The option +% |combine-exponent| combines any exponent from the number with the prefix +% of the first unit, and prints the updated prefix. The option +% |extract-exponent| removes all prefixes from the unit, and combines them +% with the exponent of number. The option |input| prints prefixes and +% exponent as given in the source. The standard setting is |input|. +% \end{function} +% +% \begin{function}{quantity-product} +% \begin{syntax} +% |quantity-product| = \meta{tokens} +% \end{syntax} +% The product marker used between a number and the unit. The standard setting +% is~\cs{,}. +% \end{function} +% +% \begin{function}{separate-uncertainty-units} +% \begin{syntax} +% |separate-uncertainty-units| = |bracket|\verb"|"|repeat|\verb"|"|single| +% \end{syntax} +% Specifies how units are applied when a separated uncertainty is present: +% a choice from |bracket|, |repeat| and |single|. The option |bracket| places +% brackets around the number, with the unit given after these. The option +% |repeat| means that the unit it printed with the main value and with the +% uncertainty. When |single| is set, the unit is printed only once and no +% brackets are applied. The standard setting is |bracket|. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-quantity} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_quantity> +% \end{macrocode} +% +% \subsection{Initial set-up} +% +% \begin{variable}{\l_@@_tmp_fp, \l_@@_tmp_tl} +% Scratch space. +% \begin{macrocode} +\tl_new:N \l_@@_tmp_fp +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{variable} +% +% \subsection{Main formatting routine} +% +% \begin{variable}{\l_@@_bracket_close_tl, \l_@@_bracket_open_tl} +% Purely internal for the present. +% \begin{macrocode} +\tl_new:N \l_@@_bracket_close_tl +\tl_new:N \l_@@_bracket_open_tl +\tl_set:Nn \l_@@_bracket_open_tl { ( } +\tl_set:Nn \l_@@_bracket_close_tl { ) } +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% { +% \l_siunitx_quantity_prefix_mode_tl , +% \l_@@_break_bool , +% \l_@@_product_tl , +% \l_@@_uncert_bracket_bool , +% \l_@@_uncert_repeat_bool +% } +% \begin{macrocode} +\tl_new:N \l_siunitx_quantity_prefix_mode_tl +\bool_new:N \l_@@_uncert_bracket_bool +\bool_new:N \l_@@_uncert_repeat_bool +\keys_define:nn { siunitx } + { + allow-quantity-breaks .bool_set:N = + \l_@@_break_bool , + prefix-mode .choices:nn = + { combine-exponent , extract-exponent , input } + { \tl_set_eq:NN \l_siunitx_quantity_prefix_mode_tl \l_keys_choice_tl } , + quantity-product .tl_set:N = + \l_@@_product_tl , + separate-uncertainty-units .choice: , + separate-uncertainty-units / bracket .code:n = + { + \bool_set_true:N \l_@@_uncert_bracket_bool + \bool_set_false:N \l_@@_uncert_repeat_bool + } , + separate-uncertainty-units / repeat .code:n = + { + \bool_set_false:N \l_@@_uncert_bracket_bool + \bool_set_true:N \l_@@_uncert_repeat_bool + } , + separate-uncertainty-units / single .code:n = + { + \bool_set_false:N \l_@@_uncert_bracket_bool + \bool_set_false:N \l_@@_uncert_repeat_bool + } + } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_number_tl, \l_@@_unit_tl} +% \begin{macrocode} +\tl_new:N \l_@@_number_tl +\tl_new:N \l_@@_unit_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_quantity:nn, \@@_parsed:nn} +% \begin{macro}{\@@_parsed_combine-exponent:n, \@@_parsed_combine-exponent:n, \@@_parsed_input:n} +% \begin{macro}{\@@_parsed_aux:w} +% \begin{macro}{\@@_parsed_aux:nnnw} +% \begin{macro}{\@@_parsed_aux:nnnn} +% For quantities, there is bit to do to combine things. The first question is +% whether we are parsing at all: if not, things are quite short. Notice that +% within this group we turn off bracketing in the number formatter: we +% have to deal with quantity-based brackets instead. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_quantity:nn #1#2 + { + \group_begin: + \siunitx_unit_options_apply:n {#2} + \tl_if_blank:nTF {#1} + { + \siunitx_unit_format:nN {#2} \l_@@_unit_tl + \siunitx_print_unit:V \l_@@_unit_tl + } + { + \bool_if:NTF \l_siunitx_number_parse_bool + { \@@_parsed:nn {#1} {#2} } + { + \tl_set:Nn \l_@@_number_tl { \ensuremath {#1} } + \siunitx_unit_format:nN {#2} \l_@@_unit_tl + \siunitx_quantity_print:VV + \l_@@_number_tl \l_@@_unit_tl + } + } + \group_end: + } +% \end{macrocode} +% For parsed numbers, we have two major questions to think about: whether we +% are combining prefixes, and whether we have a multi-part numbers to handle. +% Number processing has to be delayed it needs to come after any extracted +% exponent is combined. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parsed:nn #1#2 + { + \bool_set_false:N \l_siunitx_number_bracket_ambiguous_bool + \siunitx_number_parse:nN {#1} \l_@@_number_tl + \use:c { @@_parsed_ \l_siunitx_quantity_prefix_mode_tl :n } {#2} + \tl_set:Nx \l_@@_number_tl + { \siunitx_number_output:NN \l_@@_number_tl \q_nil } + \exp_after:wN \@@_parsed_aux:w \l_@@_number_tl \q_stop + } +\cs_new_protected:cpn { @@_parsed_combine-exponent:n } #1 + { + \siunitx_number_process:NN \l_@@_number_tl \l_@@_number_tl + \exp_args:NV \@@_extract_exp:nNN + \l_@@_number_tl \l_@@_tmp_fp \l_@@_number_tl + \siunitx_unit_format_combine_exponent:nnN {#1} + \l_@@_tmp_fp \l_@@_unit_tl + } +\cs_new_protected:cpn { @@_parsed_extract-exponent:n } #1 + { + \siunitx_unit_format_extract_prefixes:nNN {#1} + \l_@@_unit_tl \l_@@_tmp_fp + \tl_set:Nx \l_@@_number_tl + { + \siunitx_number_adjust_exponent:Nn + \l_@@_number_tl \l_@@_tmp_fp + } + \siunitx_number_process:NN \l_@@_number_tl \l_@@_number_tl + } +\cs_new_protected:Npn \@@_parsed_input:n #1 + { + \siunitx_number_process:NN \l_@@_number_tl \l_@@_number_tl + \siunitx_unit_format:nN {#1} \l_@@_unit_tl + } +% \end{macrocode} +% To find out if we need to work harder, we first need to split the formatted +% number into the constituent parts. That is done using the table-like +% approach: that avoids needing to both check the settings and break down +% the input separately. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parsed_aux:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil + #8 \q_nil #9 \q_stop + { \@@_parsed_aux:nnnw {#1} {#2#3#4#5} {#6#7#8} #9 \q_stop } +\cs_new_protected:Npn \@@_parsed_aux:nnnw + #1#2#3 #4 \q_nil #5 \q_nil #6 \q_stop + { \@@_parsed_aux:nnnn {#1} {#2} {#3#4} {#5#6} } +\cs_new_protected:Npn \@@_parsed_aux:nnnn #1#2#3#4 + { + \tl_if_blank:nTF {#3} + { \siunitx_quantity_print:nV {#1#2#4} \l_@@_unit_tl } + { + \bool_if:NTF \l_@@_uncert_bracket_bool + { + \siunitx_quantity_print:xV + { + \exp_not:n {#1} + \exp_not:V \l_@@_bracket_open_tl + \exp_not:n {#2#3} + \exp_not:V \l_@@_bracket_close_tl + \exp_not:n {#4} + } + \l_@@_unit_tl + } + { + \bool_if:NTF \l_@@_uncert_repeat_bool + { + \siunitx_quantity_print:nV {#1#2} + \l_@@_unit_tl + \siunitx_quantity_print:nV { { } #3 } + \l_@@_unit_tl + \siunitx_print_number:n { { } #4 } + } + { \siunitx_quantity_print:nV {#1#2#3#4} \l_@@_unit_tl } + } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_extract_exp:nNN} +% \begin{macro}{\@@_extract_exp:nnnnnnnNN} +% To extract the exponent part for a combined prefix, we decompose the value +% and remove it. +% \begin{macrocode} +\cs_new_protected:Npn \@@_extract_exp:nNN #1#2#3 + { \@@_extract_exp:nnnnnnnNN #1 #2 #3 } +\cs_new_protected:Npn \@@_extract_exp:nnnnnnnNN #1#2#3#4#5#6#7#8#9 + { + \fp_set:Nn #8 {#6#7} + \tl_set:Nx #9 + { {#1} {#2} {#3} {#4} {#5} { } { 0 } } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro} +% { +% \siunitx_quanity_print:nn, \siunitx_quanity_print:nV, +% \siunitx_quanity_print:VV, \siunitx_quanity_print:xV +% } +% For printing a single part of a quantity. This is needed for compound +% quantities and so is public: that's also the reason for passing both +% argument explicitly. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_quantity_print:nn #1#2 + { + \siunitx_print_number:n {#1} + \tl_if_blank:nF {#2} + { + \tl_use:N \l_@@_product_tl + \bool_if:NTF \l_@@_break_bool + { \penalty \binoppenalty } + { \nobreak } + \siunitx_print_unit:n {#2} + } + } +\cs_generate_variant:Nn \siunitx_quantity_print:nn { nV , VV , xV } +% \end{macrocode} +% \end{macro} +% +% \subsection{Standard settings for module options} +% +% Some of these follow naturally from the point of definition +% (\foreign{e.g.}~boolean variables are always |false| to begin with), +% but for clarity everything is set here. +% \begin{macrocode} +\keys_set:nn { siunitx } + { + allow-quantity-breaks = false , + prefix-mode = input , + quantity-product = \, , + separate-uncertainty-units = bracket + } +% \end{macrocode} +% +% \subsection{Adjustments to units} +% +% \begin{macro}{\@@_non_latin:n} +% \begin{macro}{\@@_non_latin:nnnn} +% As in \pkg{siunitx-unit}, but internal in both cases as it's rather +% specialised. +% \begin{macrocode} +\bool_lazy_or:nnTF + { \sys_if_engine_luatex_p: } + { \sys_if_engine_xetex_p: } + { + \cs_new:Npn \@@_non_latin:n #1 + { \char_generate:nn {#1} { \char_value_catcode:n {#1} } } + } + { + \cs_new:Npn \@@_non_latin:n #1 + { + \exp_last_unbraced:Nf \@@_non_latin:nnnn + { \char_to_utfviii_bytes:n {#1} } + } + \cs_new:Npn \@@_non_latin:nnnn #1#2#3#4 + { + \exp_after:wN \exp_after:wN \exp_after:wN + \exp_not:N \char_generate:nn {#1} { 13 } + \exp_after:wN \exp_after:wN \exp_after:wN + \exp_not:N \char_generate:nn {#2} { 13 } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\degree} +% The \cs{degree} unit is re-declared here: this is needed for using it +% in quantities. This is done here as it avoids a dependency in +% \pkg{siunitx-unit} on options it does not contain. +% \begin{macrocode} +\siunitx_declare_unit:Nxn \degree + { \@@_non_latin:n { "00B0 } } + { quantity-product = { } } +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/siunitx/siunitx-symbol.dtx b/macros/latex/contrib/siunitx/siunitx-symbol.dtx new file mode 100644 index 0000000000..6d67c5a29d --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-symbol.dtx @@ -0,0 +1,313 @@ +% \iffalse meta-comment +% +% File: siunitx-symbol.dtx Copyright (C) 2018-2021 Joseph Wright +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-symbol} -- Symbol-related settings^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-symbol} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_symbol> +% \end{macrocode} +% +% \begin{variable}{\l_@@_tmpa_tl, \l_@@_tmpb_tl} +% Scratch space. +% \begin{macrocode} +\tl_new:N \l_@@_tmpa_tl +\tl_new:N \l_@@_tmpb_tl +% \end{macrocode} +% \end{variable} +% +% A small number of commands are needed from the companion fonts when working +% with $8$-bit engines. These are loaded by modern \LaTeXe{} kernel, so for +% older ones, force loading them using \pkg{textcomp}. +% \begin{macrocode} +\AtBeginDocument + { + \cs_if_free:cT { T@TS1 } + { \RequirePackage { textcomp } } + } +% \end{macrocode} +% +% \begin{macro}{\@@_non_latin:n} +% \begin{macro}{\@@_non_latin:nnnn} +% As in \pkg{siunitx-unit}, but internal in both cases as it's rather +% specialised. +% \begin{macrocode} +\bool_lazy_or:nnTF + { \sys_if_engine_luatex_p: } + { \sys_if_engine_xetex_p: } + { + \cs_new:Npn \@@_non_latin:n #1 + { \char_generate:nn {#1} { \char_value_catcode:n {#1} } } + } + { + \cs_new:Npn \@@_non_latin:n #1 + { + \exp_last_unbraced:Nf \@@_non_latin:nnnn + { \char_to_utfviii_bytes:n {#1} } + } + \cs_new:Npn \@@_non_latin:nnnn #1#2#3#4 + { + \exp_after:wN \exp_after:wN \exp_after:wN + \exp_not:N \char_generate:nn {#1} { 13 } + \exp_after:wN \exp_after:wN \exp_after:wN + \exp_not:N \char_generate:nn {#2} { 13 } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_if_replace:NnT} +% A test to see if the unit definition which applies is still one we expect: +% here that means it is just using a (Unicode) codepoint. The comparison +% is string-based as \pkg{unicode-math} (at least) can alter some of them. +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \@@_if_replace:Nn #1#2 { T , TF } + { + \group_begin: + \tl_set:Nx \l_@@_tmpa_tl { \@@_non_latin:n {#2} } + \protected@edef \l_@@_tmpa_tl + { \exp_not:N \mathrm { \l_@@_tmpa_tl } } + \keys_set:nn { siunitx } { parse-units = false } + \siunitx_unit_format:nN {#1} \l_@@_tmpb_tl + \str_if_eq:VVTF \l_@@_tmpa_tl \l_@@_tmpb_tl + { + \group_end: + \prg_return_true: + } + { + \group_end: + \prg_return_false: + } + } +% \end{macrocode} +% \end{macro} +% +% At the start of the document, fonts are fixed and the user may have +% altered unit set up. If things are unchanged, we can alter the settings +% such that they use something \enquote{more sensible}. +% \begin{macrocode} +\AtBeginDocument + { + \@@_if_replace:NnT \arcminute { "02B9 } + { + \siunitx_declare_unit:Nn \arcminute + { \exp_not:N \ensuremath { { } ' } } + } + \@@_if_replace:NnT \arcsecond { "02BA } + { + \siunitx_declare_unit:Nn \arcsecond + { \exp_not:N \ensuremath { { } '' } } + } +% \end{macrocode} +% For |\degree|, direct input works in text mode so there is +% only a need to tidy up for math mode. If \pkg{fontspec} is loaded then that +% problem goes away, so nothing needs to be done. +% \begin{macrocode} + \@@_if_replace:NnT \degree { "00B0 } + { + \@ifpackageloaded { fontspec } + { } + { + \siunitx_declare_unit:Nxn \degree + { + \siunitx_print_text:n + { \@@_non_latin:n { "00B0 } } + } + { quantity-product = { } } + } + } +% \end{macrocode} +% For |\degreeCelsius|, much the same to think about but the comparison +% must be done by hand. +% \begin{macrocode} + \group_begin: + \tl_set:Nx \l_@@_tmpa_tl { \@@_non_latin:n { "00B0 } C } + \protected@edef \l_@@_tmpa_tl + { \exp_not:N \mathrm { \l_@@_tmpa_tl } } + \keys_set:nn { siunitx } { parse-units = false } + \siunitx_unit_format:nN { \degreeCelsius } \l_@@_tmpb_tl + \str_if_eq:VVTF \l_@@_tmpa_tl \l_@@_tmpb_tl + { + \group_end: + \@ifpackageloaded { fontspec } + { } + { + \siunitx_declare_unit:Nx \degreeCelsius + { + \siunitx_print_text:n + { \@@_non_latin:n { "00B0 } } C + } + } + } + { \group_end: } +% \end{macrocode} +% For |\ohm|, there is a math mode symbol we can use, so there has to be +% a mode-dependent definition. +% \begin{macrocode} + \@@_if_replace:NnT \ohm { "03A9 } + { + \siunitx_declare_unit:Nx \ohm + { + \exp_not:N \ifmmode + \cs_if_exist:NTF \upOmega + { \exp_not:N \upOmega } + { \exp_not:N \Omega } + \exp_not:N \else + \siunitx_print_text:n + { + \bool_lazy_or:nnTF + { \sys_if_engine_luatex_p: } + { \sys_if_engine_xetex_p: } + { \@@_non_latin:n { "03A9 } } + { \exp_not:N \textohm } + } + \exp_not:N \fi + } + } +% \end{macrocode} +% Only a text mode command is available for |\micro| in the standard +% set up. +% \begin{macrocode} + \@@_if_replace:NnT \micro { "03BC } + { + \siunitx_declare_prefix:Nnx \micro { -6 } + { + \siunitx_print_text:n + { + \bool_lazy_or:nnTF + { \sys_if_engine_luatex_p: } + { \sys_if_engine_xetex_p: } + { \@@_non_latin:n { "00B5 } } + { \exp_not:N \textmu } + } + } + } + } +% \end{macrocode} +% +% For the times symbol, only \LuaTeX{} allows us to use the math mode symbol +% directly. However, that likely won't follow the surrounding font appearance, +% so in all cases we use the |TS1| version for text. Otherwise much the +% same as |\textmu| support. It's hard to check for the product symbol, so +% we just go with it an hope for the best! +% \begin{macrocode} +\AtBeginDocument + { + \group_begin: + \tl_set:Nn \l_@@_tmpa_tl + { { } { } { 2 } { } { } { } { 1 } } + \tl_set:Nx \l_@@_tmpa_tl + { \siunitx_number_output:N \l_@@_tmpa_tl } + \tl_set:Nn \l_@@_tmpb_tl { 2 \times 10 ^ { 1 } } + \tl_if_eq:NNTF \l_@@_tmpa_tl \l_@@_tmpb_tl + { + \group_end: + \keys_set:nn { siunitx } + { + exponent-product = + \ifmmode \times \else \texttimes \fi , + product-symbol = + \ifmmode \times \else \texttimes \fi + } + } + { \group_end: } + } +% \end{macrocode} +% +% \subsection{Bookmark definitions} +% +% Inside PDF strings we disable the text printing function. The definition of +% |\ohm| is also reset as otherwise engine-dependent strings are generated +% (\XeTeX{} and \LuaTeX{} give different outcomes using for example +% |\textohm|). +% \begin{macrocode} +\AtBeginDocument + { + \@ifpackageloaded { hyperref } + { + \exp_args:Nx \pdfstringdefDisableCommands + { + \cs_set_eq:NN \siunitx_print_text:n \exp_not:N \use:n + \siunitx_declare_unit:Nn \exp_not:N \ohm + { \@@_non_latin:n { "03A9 } } + } + } + { } + } +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/siunitx/siunitx-table.dtx b/macros/latex/contrib/siunitx/siunitx-table.dtx new file mode 100644 index 0000000000..d16d2d7780 --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-table.dtx @@ -0,0 +1,1445 @@ +% \iffalse meta-comment +% +% File: siunitx-table.dtx Copyright (C) 2016-2019,2021 Joseph Wright +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +\ProvideDocumentCommand\foreign{m}{\textit{#1}} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-table} -- Formatting numbers in tables^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% \section{Numbers in tables} +% +% This submodule is concerned with formatting numbers in table cells or +% similar fixed-width contexts. The main function, \cs{siunitx_cell_begin:w}, +% is designed to work with the normal \LaTeXe{} tablular cell construct +% featuring \cs{ignorespaces}. Therefore, if used outside of a \LaTeXe{} +% tabular, it is necessary to provide this token. +% +% \begin{function}{\siunitx_cell_begin:w, \siunitx_cell_end:} +% \begin{syntax} +% \cs{siunitx_cell_begin:w} \meta{preamble} \cs{ignorespaces} +% \meta{content} +% \cs{siunitx_cell_end:} +% \end{syntax} +% Collects the \meta{preamble} and \meta{content} tokens, and determines +% if it is text or a number (as parsed by \cs{siunitx_number_parse:nN}). +% It produces output of a fixed width suitable for alignment in a table, +% although it is not \emph{required} that the code is used within a cell. +% Note that |\ignorespaces| must occur in the \enquote{cell}: it marks +% the end of the \TeX{} |\halign| template. +% \end{function} +% +% \subsection{Key--value options} +% +% The options defined by this submodule are available within the \pkg{l3keys} +% |siunitx| tree. +% +% \begin{function}{table-align-comparator} +% \begin{syntax} +% |table-align-comparator| = |true|\verb"|"|false| +% \end{syntax} +% Switch which determines whether alignment of comparators is attempted +% within table cells. The standard setting is |true|. +% \end{function} +% +% \begin{function}{table-align-exponent} +% \begin{syntax} +% |table-align-exponent| = |true|\verb"|"|false| +% \end{syntax} +% Switch which determines whether alignment of exponents is attempted +% within table cells. The standard setting is |true|. +% \end{function} +% +% \begin{function}{table-align-text-after} +% \begin{syntax} +% |table-align-text-after| = |true|\verb"|"|false| +% \end{syntax} +% Switch which determines whether alignment of text falling after a number +% is attempted within table cells. The standard setting is |true|. +% \end{function} +% +% \begin{function}{table-align-text-before} +% \begin{syntax} +% |table-align-text-before| = |true|\verb"|"|false| +% \end{syntax} +% Switch which determines whether alignment of text falling before a number +% is attempted within table cells. The standard setting is |true|. +% \end{function} +% +% \begin{function}{table-align-uncertainty} +% \begin{syntax} +% |table-align-uncertainty| = |true|\verb"|"|false| +% \end{syntax} +% Switch which determines whether alignment of separated uncertainty values +% is attempted within table cells. The standard setting is |true|. +% \end{function} +% +% \begin{function}{table-alignment} +% \begin{syntax} +% |table-alignment| = |center|\verb"|"|left|\verb"|"|right| +% \end{syntax} +% Selects the alignment of all tabular content with the margins of the table +% cell (or other boundary). See also |table-number-alignment| and +% |table-text-alignment|. The standard setting is |center|. +% \end{function} +% +% \begin{function}{table-alignment-mode} +% \begin{syntax} +% |table-alignment-mode| = |format|\verb"|"|marker|\verb"|"|none| +% \end{syntax} +% Selects the method used to align numbers with the desired position in the +% cell (set by |table-alignment|). When set to |format|, a dedicated +% amount of space is calculated from the |table-format|. When |marker| +% is selected, alignment is carried out symmetrically around the decimal +% marker. Finally, |none| switches off all alignment: numbers are parsed +% and formatted but with no attempt at placement within the cell. The +% standard setting is |marker|. +% \end{function} +% +% \begin{function}{table-auto-round} +% \begin{syntax} +% |table-auto-round| = |true|\verb"|"|false| +% \end{syntax} +% Switch which determines whether numbers are rounded to fit within +% the |table-format| specification (if possible). The standard +% setting is |false|. +% \end{function} +% +% \begin{function}{table-column-width} +% \begin{syntax} +% |table-column-width| = \meta{width} +% \end{syntax} +% Sets the width of the table column used for numbers. This is only used +% when |table-fixed-width| is |true|. +% \end{function} +% +% \begin{function}{table-fixed-width} +% \begin{syntax} +% |table-fixed-width| = |true|\verb"|"|false| +% \end{syntax} +% Switch which determines whether a fixed-width column is used for numbers +% in tables. When |true|, the width is taken from |table-column-width|. The +% standard setting is |false|. +% \end{function} +% +% \begin{function}{table-format} +% \begin{syntax} +% |table-format| = \meta{format} +% \end{syntax} +% Describes the amount of space that should be reserved when +% |table-alignment-mode| is set to |format|. The \meta{format} takes the +% same general form as input for a table cell, with the numerical parts +% describing how many digits to reserve space for. For example, |1.2e3| +% would allow space for one digit in the integer part, two in the decimal +% part and three in the exponent part. Signs can be allowed for using any +% valid input sign, so for example |+1.2 \pm 1.2| would allow for a sign, +% a number with one integer and two decimal digits and a uncertainty of +% the same size. +% \end{function} +% +% \begin{function}{table-number-alignment} +% \begin{syntax} +% |table-number-alignment| = |center|\verb"|"|left|\verb"|"|right| +% \end{syntax} +% Selects the alignment of numerical content with the margins of the table +% cell (or other boundary). See also |table-alignment| and +% |table-text-alignment|. The standard setting is |center|. +% \end{function} +% +% \begin{function}{table-text-alignment} +% \begin{syntax} +% |table-text-alignment| = |center|\verb"|"|left|\verb"|"|right| +% \end{syntax} +% Selects the alignment of non-numerical content with the margins of the +% table cell (or other boundary). See also |table-alignment| and +% |table-number-alignment|. The standard setting is |center|. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-table} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_table> +% \end{macrocode} +% +% \begin{variable}{\l_@@_tmp_box, \l_@@_tmp_dim, \l_@@_tmp_tl} +% Scratch space. +% \begin{macrocode} +\box_new:N \l_@@_tmp_box +\dim_new:N \l_@@_tmp_dim +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{variable} +% +% \subsection{Interface functions} +% +% \begin{variable}{\l_@@_text_bool} +% Used to track that a cell is purely text. +% \begin{macrocode} +\bool_new:N \l_@@_text_bool +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_cell_begin:w} +% \begin{macro}{\siunitx_cell_end:} +% The start and end of the cell need to deal with the possibility of +% a cell containing only text. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_cell_begin:w + { + \bool_set_false:N \l_@@_text_bool + \bool_if:NTF \l_siunitx_number_parse_bool + { \@@_collect_begin: } + { \@@_direct_begin: } + } +\cs_new_protected:Npn \siunitx_cell_end: + { + \bool_if:NF \l_@@_text_bool + { + \bool_if:NTF \l_siunitx_number_parse_bool + { \@@_collect_end: } + { \@@_direct_end: } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Collecting tokens} +% +% \begin{variable}{\l_@@_collect_tl} +% Space for tokens. +% \begin{macrocode} +\tl_new:N \l_@@_collect_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_collect_begin:} +% \begin{macro}{\@@_collect_begin:w} +% Collecting a tabular cell means doing a token-by-token collection. +% In previous versions of \pkg{siunitx} that was done along with picking +% out the numerical part, but the code flow ends up very tricky. Here, +% therefore, we just collect up the unchanged tokens first. The definition of +% \cs{cr} is used to allow collection of any tokens +% inserted after the main content when dealing with the last cell of a row: +% the \enquote{group} around it is needed to avoid issues with the underlying +% |\halign|. (The approach is based on that in \pkg{collcell}.) Whilst the +% group formed by a cell will normally tidy up |\cr|, we add an extra one as +% the collected material could be a tabular in itself. We use an auxiliary to +% fish out the |\ignorespaces| from the template: that has to go to avoid +% issues with the peek-ahead code (everything before the |#| needs to be +% read \emph{before} the Appendix~D trick gets applied). Some packages +% add additional tokens before the |\ignorespaces|, which are dealt with by +% the delimited argument. +% \begin{macrocode} +\cs_new_protected:Npn \@@_collect_begin: + { + \group_begin: + \tl_clear:N \l_@@_collect_tl + \if_false: { \fi: + \cs_set_protected:Npn \cr + { + \@@_collect_loop: + \tex_cr:D + } + \if_false: } \fi: + \@@_collect_begin:w + } +\cs_new_protected:Npn \@@_collect_begin:w #1 \ignorespaces + { \@@_collect_loop: #1 } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_collect_loop:} +% \begin{macro}{\@@_collect_group:n} +% \begin{macro}{\@@_collect_token:N} +% \begin{macro}{\@@_collect_search:NnF} +% \begin{macro}{\@@_collect_search_aux:NNn} +% Collecting up the cell content needs a loop: this is done using +% a |peek| approach as it's most natural. (A slower approach is possible +% using something like the |\text_lowercase:n| loop code.) The set of +% possible tokens is somewhat limited compared to an arbitrary cell +% (\foreign{cf.}~the approach in \pkg{collcell}): the special cases are +% pulled out for manual handling. The flexible lookup approach is more-or-less +% the same idea as in the kernel |case| functions. The |\relax| special case +% covers the case where |\\| has been expanded in an empty cell. +% \begin{macrocode} +\cs_new_protected:Npn \@@_collect_loop: + { + \peek_catcode_ignore_spaces:NTF \c_group_begin_token + { \@@_collect_group:n } + { \@@_collect_token:N } + } +\cs_new_protected:Npn \@@_collect_group:n #1 + { + \tl_put_right:Nn \l_@@_collect_tl { {#1} } + \@@_collect_loop: + } +\cs_new_protected:Npn \@@_collect_token:N #1 + { + \@@_collect_search:NnF #1 + { + \unskip { \@@_collect_loop: } + \end { \tabularnewline \end } + \relax { \relax } + \tabularnewline { \tabularnewline } + \siunitx_cell_end: { \siunitx_cell_end: } + } + { + \tl_put_right:Nn \l_@@_collect_tl {#1} + \@@_collect_loop: + } + } +\AtBeginDocument + { + \@ifpackageloaded { mdwtab } + { + \cs_set_protected:Npn \@@_collect_token:N #1 + { + \@@_collect_search:NnF #1 + { + \@maybe@unskip { \@@_collect_loop: } + \tab@setcr { \@@_collect_loop: } + \unskip { \@@_collect_loop: } + \end { \tabularnewline \end } + \relax { \relax } + \tabularnewline { \tabularnewline } + \siunitx_cell_end: { \siunitx_cell_end: } + } + { + \tl_put_right:Nn \l_@@_collect_tl {#1} + \@@_collect_loop: + } + } + } + { } + } +\cs_new_protected:Npn \@@_collect_search:NnF #1#2#3 + { + \@@_collect_search_aux:NNn #1 + #2 + #1 {#3} + \q_stop + } +\cs_new_protected:Npn \@@_collect_search_aux:NNn #1#2#3 + { + \token_if_eq_meaning:NNTF #1 #2 + { \use_i_delimit_by_q_stop:nw {#3} } + { \@@_collect_search_aux:NNn #1 } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Separating collected material} +% +% The input needs to be divided into numerical tokens and those which appear +% before and after them. This needs a second loop and validation. +% +% \begin{variable}{\l_@@_before_tl, \l_@@_number_tl, \l_@@_after_tl} +% Space for tokens. +% \begin{macrocode} +\tl_new:N \l_@@_before_tl +\tl_new:N \l_@@_number_tl +\tl_new:N \l_@@_after_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_collect_end:} +% \begin{macro}{\@@_collect_end:n} +% \begin{macro}[EXP]{\@@_collect_end_aux:n} +% \begin{macro}[EXP]{\@@_collect_end:w} +% At the end of the cell, escape the group and check for expansion. We +% only do that if the entire content is not a brace group: there is more +% likely to be problematic content in the case of a header. +% \begin{macrocode} +\cs_new_protected:Npn \@@_collect_end: + { + \exp_args:NNV \group_end: + \@@_collect_end:n \l_@@_collect_tl + \exp_args:NV \@@_split:nNNN + \l_@@_collect_tl + \l_@@_before_tl + \l_@@_number_tl + \l_@@_after_tl + \tl_if_empty:NTF \l_@@_number_tl + { \@@_print_text:V \l_@@_before_tl } + { + \@@_print:VVV + \l_@@_before_tl + \l_@@_number_tl + \l_@@_after_tl + } + } +\cs_new_protected:Npn \@@_collect_end:n #1 + { + \str_if_eq:eeTF { \exp_not:n {#1} } + { { \@@_collect_end_aux:n {#1} } } + { \tl_set:Nn } + { \protected@edef } + \l_@@_collect_tl {#1} + } +\cs_new:Npn \@@_collect_end_aux:n #1 + { \exp_after:wN \@@_collect_end:w #1 \q_stop } +\cs_new:Npn \@@_collect_end:w #1 \q_stop + { \exp_not:n {#1} } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_split:nNNN} +% \begin{macro}{\@@_split_loop:NNN} +% \begin{macro}{\@@_split_group:NNNn} +% \begin{macro}{\@@_split_token:NNNN} +% Splitting into parts uses the fact that numbers cannot contain groups +% and that we can track where we are up to based on the content of the +% token lists. +% \begin{macrocode} +\cs_new_protected:Npn \@@_split:nNNN #1#2#3#4 + { + \tl_clear:N #2 + \tl_clear:N #3 + \tl_clear:N #4 + \@@_split_loop:NNN #2#3#4 #1 \q_recursion_tail \q_recursion_stop + \@@_split_tidy:N #2 + \@@_split_tidy:N #4 + } +\cs_new_protected:Npn \@@_split_loop:NNN #1#2#3 + { + \peek_catcode_ignore_spaces:NTF \c_group_begin_token + { \@@_split_group:NNNn #1#2#3 } + { \@@_split_token:NNNN #1#2#3 } + } +\cs_new_protected:Npn \@@_split_group:NNNn #1#2#3#4 + { + \tl_if_empty:NTF #2 + { \tl_put_right:Nn #1 { {#4} } } + { \tl_put_right:Nn #3 { {#4} } } + \@@_split_loop:NNN #1#2#3 + } +\cs_new_protected:Npn \@@_split_token:NNNN #1#2#3#4 + { + \quark_if_recursion_tail_stop:N #4 + \tl_if_empty:NTF \l_@@_after_tl + { + \siunitx_if_number_token:NTF #4 + { \tl_put_right:Nn #2 {#4} } + { + \tl_if_empty:NTF #2 + { \tl_put_right:Nn #1 {#4} } + { \tl_put_right:Nn #3 {#4} } + } + } + { \tl_put_right:Nn #3 {#4} } + \@@_split_loop:NNN #1#2#3 + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_split_tidy:N} +% \begin{macro}{\@@_split_tidy:Nn, \@@_split_tidy:NV} +% A quick test for the entire content being surrounded by a set of braces: +% rather than look explicitly, use the fact that a string comparison can +% detect the same thing. The auxiliary is needed to avoid having to go +% \foreign{via} a |:D| function (for the expansion behaviour). +% \begin{macrocode} +\cs_new_protected:Npn \@@_split_tidy:N #1 + { + \tl_if_empty:NF #1 + { \@@_split_tidy:NV #1 #1 } + } +\cs_new_protected:Npn \@@_split_tidy:Nn #1#2 + { + \str_if_eq:onT { \exp_after:wN { \use:n #2 } } {#2} + { \tl_set:No #1 { \use:n #2 } } + } +\cs_generate_variant:Nn \@@_split_tidy:Nn { NV } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Printing numbers in cells: spacing} +% +% Getting the general alignment correct in tables is made more complex than one +% would like by the \pkg{colortbl} package. In the original \LaTeXe{} +% definition, cell material is centred by a construction of the (primitive) +% form +% \begin{verbatim} +% \hfil +% # +% \hfil +% \end{verbatim} +% which only uses \texttt{fil} stretch. That is altered by \pkg{colortbl} to +% broadly +% \begin{verbatim} +% \hskip 0pt plus 0.5fill +% \kern 0pt +% # +% \hskip 0pt plus 0.5fill +% \end{verbatim} +% which means there is \texttt{fill} stretch to worry about and the kern as +% well. +% +% \begin{macro}{\@@_skip:n} +% To prevent combination of skips, a kern is inserted after each one. +% This is best handled as a short auxiliary. +% \begin{macrocode} +\cs_new_protected:Npn \@@_skip:n #1 + { + \skip_horizontal:n {#1} + \tex_kern:D \c_zero_skip + } +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\l_@@_column_width_dim, \l_@@_fixed_width_bool} +% Settings which apply to aligned columns in general. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + table-column-width .dim_set:N = + \l_@@_column_width_dim , + table-fixed-width .bool_set:N = + \l_@@_fixed_width_bool + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_align_center:n, \@@_align_left:n, \@@_align_right:n} +% \begin{macro}{\@@_align_auxi:nn, \@@_align_auxii:nn} +% The beginning and end of each table cell have to adjust the position of +% the content using glue. When \pkg{colortbl} is loaded the glue is done in +% two parts: one for our positioning and one to explicitly override that from +% the package. Using a two-step auxiliary chain avoids needing to repeat any +% code and the impact of the extra expansion should be trivial. +% \begin{macrocode} +\cs_new_protected:Npn \@@_align_center:n #1 + { \@@_align_auxi:nn {#1} { 0pt~plus~0.5fill } } +\cs_new_protected:Npn \@@_align_left:n #1 + { \@@_align_auxi:nn {#1} { 0pt } } +\cs_new_protected:Npn \@@_align_right:n #1 + { \@@_align_auxi:nn {#1} { 0pt~plus~1fill } } +\cs_new_protected:Npn \@@_align_auxi:nn #1#2 + { + \bool_if:NTF \l_@@_fixed_width_bool + { \hbox_to_wd:nn \l_@@_column_width_dim } + { \use:n } + { + \@@_skip:n {#2} + #1 + \@@_skip:n { 0pt~plus~1fill - #2 } + } + } +\AtBeginDocument + { + \@ifpackageloaded { colortbl } + { + \cs_new_eq:NN + \@@_align_auxii:nn + \@@_align_auxi:nn + \cs_set_protected:Npn \@@_align_auxi:nn #1#2 + { + \@@_skip:n{ 0pt~plus~-0.5fill } + \@@_align_auxii:nn {#1} {#2} + \@@_skip:n { 0pt~plus~-0.5fill } + } + } + { } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Printing just text} +% +% In cases where there is no numerical part, \pkg{siunitx} allows alignment +% of the \enquote{escaped} text independent of the underlying column type. +% +% \begin{variable}{\l_@@_align_text_tl} +% Alignment is handled using a |tl| as this allows a fast lookup at the +% point of use. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + table-text-alignment .choices:nn = + { center , left , right } + { \tl_set:Nn \l_@@_align_text_tl {#1} } , + } +\tl_new:N \l_@@_align_text_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_print_text:n, \@@_print_text:V} +% Printing escaped text is easy: just place it in correctly in the +% column. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_text:n #1 + { + \bool_set_true:N \l_@@_text_bool + \use:c { @@_align_ \l_@@_align_text_tl :n } {#1} + } +\cs_generate_variant:Nn \@@_print_text:n { V } +% \end{macrocode} +% \end{macro} +% +% \subsection{Number alignment: core ideas} +% +% \begin{variable}{\l_@@_integer_box, \l_@@_decimal_box} +% Boxes for the content before and after the decimal marker. +% \begin{macrocode} +\box_new:N \l_@@_integer_box +\box_new:N \l_@@_decimal_box +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_fil:} +% A primitive renamed. +% \begin{macrocode} +\cs_new_eq:NN \@@_fil: \tex_hfil:D +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_cleanup_decimal:w} +% To remove the excess marker tokens in a decimal part. +% \begin{macrocode} +\cs_new:Npn \@@_cleanup_decimal:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil + { #1#2#3#4#5#6#7 } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_center_marker:} +% When centering on the decimal marker, the easiest approach is to simply +% re-box the two parts. That is needed whether or not we are parsing numbers, +% so is best as a short auxiliary. +% \begin{macrocode} +\cs_new_protected:Npn \@@_center_marker: + { + \dim_compare:nNnTF + { \box_wd:N \l_@@_integer_box } + > { \box_wd:N \l_@@_decimal_box } + { + \hbox_set_to_wd:Nnn \l_@@_decimal_box + { \box_wd:N \l_@@_integer_box } + { + \hbox_unpack:N \l_@@_decimal_box + \@@_fil: + } + } + { + \hbox_set_to_wd:Nnn \l_@@_integer_box + { \box_wd:N \l_@@_decimal_box } + { + \@@_fil: + \hbox_unpack:N \l_@@_integer_box + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{variable} +% {\l_@@_auto_round_bool, \l_@@_align_mode_tl, \l_@@_align_number_tl} +% Options for tables with defined space. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + table-alignment .meta:n = + { table-number-alignment = #1 , table-text-alignment = #1 }, + table-alignment-mode .choices:nn = + { none , format , marker } + { \tl_set_eq:NN \l_@@_align_mode_tl \l_keys_choice_tl } , + table-auto-round .bool_set:N = + \l_@@_auto_round_bool , + table-format .code:n = + { + \@@_split:nNNN {#1} + \l_@@_before_model_tl + \l_@@_model_tl + \l_@@_after_model_tl + \exp_args:NV \@@_generate_model:n \l_@@_model_tl + \tl_set:Nn \l_@@_align_mode_tl { format } + } , + table-number-alignment .choices:nn = + { center , left , right } + { \tl_set_eq:NN \l_@@_align_number_tl \l_keys_choice_tl } + } +\tl_new:N \l_@@_align_mode_tl +\tl_new:N \l_@@_align_number_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_format_tl, \l_@@_model_tl} +% The input and output versions of the model entry in a table. +% \begin{macrocode} +\tl_new:N \l_@@_format_tl +\tl_new:N \l_@@_before_model_tl +\tl_new:N \l_@@_model_tl +\tl_new:N \l_@@_after_model_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_generate_model:n} +% \begin{macro}{\@@_generate_model:nnnnnnn} +% \begin{macro}[EXP]{\@@_generate_model_S:nnw} +% \begin{macro}[EXP]{\@@_generate_model_S:nnn} +% Creating a model for a table at this stage means parsing the format and +% converting that to an appropriate model. Things are quite straight-forward +% other than the uncertainty part. At this stage there is no point in +% formatting the model: that has to happen at point-of-use. Notice that +% the uncertainty part needs to allow for the case where we cross the +% decimal. +% \begin{macrocode} +\cs_new_protected:Npn \@@_generate_model:n #1 + { + \group_begin: + \bool_set_true:N \l_siunitx_number_parse_bool + \keys_set:nn { siunitx } { retain-explicit-plus = true } + \siunitx_number_parse:nN {#1} \l_@@_format_tl + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_format_tl \l_@@_format_tl + \tl_if_empty:NF \l_@@_format_tl + { + \exp_after:wN \@@_generate_model:nnnnnnn + \l_@@_format_tl + } + } +\cs_new_protected:Npn \@@_generate_model:nnnnnnn #1#2#3#4#5#6#7 + { + \tl_set:Nx \l_@@_model_tl + { + \exp_not:n { {#1} {#2} } + { \prg_replicate:nn {#3} { 8 } } + { \prg_replicate:nn { 0 #4 } { 8 } } + { + \tl_if_blank:nF {#5} + { + \use:c { @@_generate_model_ \tl_head:n {#5} :nnw } + {#4} #5 + } + } + \exp_not:n { {#6} } + { + \int_compare:nNnTF {#7} = 0 + { 0 } + { \prg_replicate:nn {#7} { 8 } } + } + } + } +\cs_new:Npn \@@_generate_model_S:nnw #1#2#3 + { + { S } + { + \exp_args:Nff \@@_generate_model_S:nnn + { \tl_count:n {#1} } { \tl_count:n {#3} } + {#3} + } + } +\cs_new:Npn \@@_generate_model_S:nnn #1#2#3 + { + \prg_replicate:nn + { + \int_compare:nNnTF {#2} > {#1} + { + \str_range:nnn {#3} { 1 } {#1} + + + \str_range:nnn {#3} { 1 + #1 } {#2} + } + {#3} + } + { 8 } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Directly printing without collection} +% +% Collecting the number allows for various effects but is not as fast +% as simply aligning on the first token that is a decimal marker. The +% strategy here is that used by \pkg{dcolumn}. +% +% \begin{macro}{\@@_direct_begin:} +% \begin{macro}{\@@_direct_begin:w} +% \begin{macro}{\@@_direct_end:} +% \begin{macro} +% { +% \@@_direct_marker: , +% \@@_direct_marker_switch: , +% \@@_direct_marker_end: +% } +% \begin{macro}{\@@_direct_format:} +% \begin{macro}[EXP]{\@@_direct_format:nnnnnnn} +% \begin{macro}{\@@_direct_format:w} +% \begin{macro} +% { +% \@@_direct_format_switch: , +% \@@_direct_format_end: +% } +% \begin{macro}{\@@_direct_none:, \@@_direct_none_end:} +% After removing the |\ignorespaces| at the start of the cell (see comments +% for \cs{@@_collect_begin:N}), check to see if there is a |{| and branch +% as appropriate. +% \begin{macrocode} +\cs_new_protected:Npn \@@_direct_begin: + { \@@_direct_begin:w } +\cs_new_protected:Npn \@@_direct_begin:w #1 \ignorespaces + { + #1 + \peek_catcode_ignore_spaces:NTF \c_group_begin_token + { \@@_print_text:n } + { + \m@th + \use:c { @@_direct_ \l_@@_align_mode_tl : } + } + } +\cs_new_protected:Npn \@@_direct_end: + { \use:c { @@_direct_ \l_@@_align_mode_tl _end: } } +% \end{macrocode} +% When centring the content about a decimal marker, the trick is +% to collect everything into two boxes and then compare the sizes. +% As we are always in math mode, we can use a math active token +% to make the switch. The up-front setting of the |decimal| box deals +% with the case where there is no decimal part. +% \begin{macrocode} +\cs_new_protected:Npn \@@_direct_marker: + { + \hbox_set:Nn \l_@@_tmp_box + { \ensuremath { \mathord { \l_siunitx_number_output_decimal_tl } } } + \hbox_set_to_wd:Nnn \l_@@_decimal_box + { \box_wd:N \l_@@_tmp_box } + { \@@_fil: } + \hbox_set:Nw \l_@@_integer_box + \c_math_toggle_token + \tl_map_inline:Nn \l_siunitx_number_input_decimal_tl + { + \char_set_active_eq:NN ##1 \@@_direct_marker_switch: + \char_set_mathcode:nn { `##1 } { "8000 } + } + } +\cs_new_protected:Npn \@@_direct_marker_switch: + { + \c_math_toggle_token + \hbox_set_end: + \hbox_set:Nw \l_@@_decimal_box + \c_math_toggle_token + \l_siunitx_number_output_decimal_tl + } +\cs_new_protected:Npn \@@_direct_marker_end: + { + \c_math_toggle_token + \hbox_set_end: + \@@_center_marker: + \box_use_drop:N \l_@@_integer_box + \box_use_drop:N \l_@@_decimal_box + } +% \end{macrocode} +% For the version where there is space reserved, first format and decompose +% that, then create appropriately-sized boxes. +% \begin{macrocode} +\cs_new_protected:Npn \@@_direct_format: + { + \tl_set:Nx \l_@@_tmp_tl + { \siunitx_number_output:NN \l_@@_model_tl \q_nil } + \exp_after:wN \@@_direct_format_aux:w + \l_@@_tmp_tl \q_stop + } +\cs_new_protected:Npn \@@_direct_format_aux:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_stop + { + \hbox_set:Nn \l_@@_tmp_box + { \ensuremath { \@@_cleanup_decimal:w #4 } } + \hbox_set_to_wd:Nnn \l_@@_decimal_box + { \box_wd:N \l_@@_tmp_box } + { \@@_fil: } + \hbox_set:Nn \l_@@_tmp_box { \ensuremath { #1#2#3 } } + \hbox_set_to_wd:Nnw \l_@@_integer_box + { \box_wd:N \l_@@_tmp_box } + \c_math_toggle_token + \tl_map_inline:Nn \l_siunitx_number_input_decimal_tl + { + \char_set_active_eq:NN ##1 \@@_direct_format_switch: + \char_set_mathcode:nn { `##1 } { "8000 } + } + \@@_fil: + } +\cs_new_protected:Npn \@@_direct_format_switch: + { + \c_math_toggle_token + \hbox_set_end: + \hbox_set_to_wd:Nnw \l_@@_decimal_box + { \box_wd:N \l_@@_decimal_box } + \c_math_toggle_token + \mathord { \l_siunitx_number_output_decimal_tl } + } +\cs_new_protected:Npn \@@_direct_format_end: + { + \c_math_toggle_token + \@@_fil: + \hbox_set_end: + \use:c { @@_align_ \l_@@_align_number_tl :n } + { + \box_use_drop:N \l_@@_integer_box + \box_use_drop:N \l_@@_decimal_box + } + } +% \end{macrocode} +% No parsing and no alignment is easy. +% \begin{macrocode} +\cs_new_protected:Npn \@@_direct_none: { \c_math_toggle_token } +\cs_new_protected:Npn \@@_direct_none_end: { \c_math_toggle_token } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Printing numbers in cells: main functions} +% +% \begin{variable}{\l_@@_before_box, \l_@@_after_box} +% For alignment of text outside of a number. +% \begin{macrocode} +\box_new:N \l_@@_before_box +\box_new:N \l_@@_after_box +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_carry_dim} +% Used to \enquote{carry forward} the amount of white space which needs to +% be inserted after the decimal marker. +% \begin{macrocode} +\dim_new:N \l_@@_carry_dim +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% { +% \l_@@_align_comparator_bool , +% \l_@@_align_exponent_bool , +% \l_@@_align_after_bool , +% \l_@@_align_before_bool , +% \l_@@_align_uncertainty_bool +% } +% Alignment is handled using a |tl| as this allows a fast lookup at the +% point of use. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + table-align-comparator .bool_set:N = + \l_@@_align_comparator_bool , + table-align-exponent .bool_set:N = + \l_@@_align_exponent_bool , + table-align-text-after .bool_set:N = + \l_@@_align_after_bool , + table-align-text-before .bool_set:N = + \l_@@_align_before_bool , + table-align-uncertainty .bool_set:N = + \l_@@_align_uncertainty_bool + } +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_print:nnn, \@@_print:VVV} +% \begin{macro}{\@@_print_marker:nnn} +% \begin{macro}{\@@_print_marker:w} +% \begin{macro}[EXP]{\@@_print_marker_aux:w} +% \begin{macro}{\@@_print_format:nnn} +% \begin{macro} +% { +% \@@_print_marker_auxi:w, +% \@@_print_marker_auxii:w, +% \@@_print_marker_auxiii:w +% } +% \begin{macro}{\@@_print_format_after:N} +% \begin{macro}{\@@_print_format_box:Nn} +% \begin{macro}{\@@_print_none:nnn} +% \begin{macrocode} +\cs_new_protected:Npn \@@_print:nnn #1#2#3 + { \use:c { @@_print_ \l_@@_align_mode_tl :nnn } {#1} {#2} {#3} } +\cs_generate_variant:Nn \@@_print:nnn { VVV } +% \end{macrocode} +% When centering on the decimal marker, alignment is relatively simple, and +% close in concept to that used without parsing. First we need to deal with any +% text before or after the number. For text \emph{before}, there's the case +% where is has no width and might be a font or color change: that has to be +% filtered out first. Then we can adjust the size of this material and that +% after the number such that they are equal. The number itself can then be +% formatted, splitting at he decimal marker. A bit more size adjustment, then +% the number itself and any text at the end can be inserted. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_marker:nnn #1#2#3 + { + \hbox_set:Nn \l_@@_before_box {#1} + \dim_compare:nNnT { \box_wd:N \l_@@_before_box } = { 0pt } + { + \box_clear:N \l_@@_before_box + #1 + } + \hbox_set:Nn \l_@@_after_box {#3} + \dim_compare:nNnTF + { \box_wd:N \l_@@_after_box } + > { \box_wd:N \l_@@_before_box } + { + \hbox_set_to_wd:Nnn \l_@@_before_box + { \box_wd:N \l_@@_after_box } + { + \@@_fil: + \hbox_unpack:N \l_@@_before_box + } + } + { + \hbox_set_to_wd:Nnn \l_@@_after_box + { \box_wd:N \l_@@_before_box } + { + \hbox_unpack:N \l_@@_after_box + \@@_fil: + } + } + \box_use_drop:N \l_@@_before_box + \siunitx_number_parse:nN {#2} \l_@@_tmp_tl + \siunitx_number_process:NN \l_@@_tmp_tl \l_@@_tmp_tl + \tl_set:Nx \l_@@_tmp_tl + { \siunitx_number_output:NN \l_@@_tmp_tl \q_nil } + \exp_after:wN \@@_print_marker:w + \l_@@_tmp_tl \q_stop + \box_use_drop:N \l_@@_after_box + } +\cs_new_protected:Npn \@@_print_marker:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_stop + { + \hbox_set:Nn \l_@@_integer_box + { \siunitx_print_number:n { #1#2#3 } } + \hbox_set:Nn \l_@@_decimal_box + { + \siunitx_print_number:x + { \@@_print_marker_aux:w #4 } + } + \@@_center_marker: + \box_use_drop:N \l_@@_integer_box + \box_use_drop:N \l_@@_decimal_box + } +\cs_new:Npn \@@_print_marker_aux:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil + { + \exp_not:n {#1#2#3#4#5} + \tl_if_blank:nT {#1#2#3#4#5} { { } } + \exp_not:n {#6#7} + } +% \end{macrocode} +% For positioning based on a format, we have to work part-by-part as there +% are a number of alignment points to get right. As for the |marker| approach, +% first we check if the material before the numerical content is of zero +% width. Next we need to format the model and content numbers, before +% starting an auxiliary chain to pick out the various parts in order. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format:nnn #1#2#3 + { + \hbox_set:Nn \l_@@_tmp_box { \l_@@_before_model_tl } + \hbox_set:Nn \l_@@_before_box {#1} + \dim_compare:nNnT { \box_wd:N \l_@@_before_box } = { 0pt } + { + \box_clear:N \l_@@_before_box + #1 + } + \hbox_set_to_wd:Nnn \l_@@_before_box + { \box_wd:N \l_@@_tmp_box } + { + \@@_fil: + \hbox_unpack:N \l_@@_before_box + } + \siunitx_number_parse:nN {#2} \l_@@_tmp_tl + \group_begin: + \bool_if:NT \l_@@_auto_round_bool + { + \exp_args:Nx \keys_set:nn { siunitx } + { + round-mode = places , + round-pad = true , + round-precision = + \exp_after:wN \@@_print_format:nnnnnn + \l_@@_format_tl + } + } + \siunitx_number_process:NN \l_@@_tmp_tl \l_@@_tmp_tl + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_tmp_tl \l_@@_tmp_tl + \tl_set:Nx \l_@@_tmp_tl + { + \siunitx_number_output:NN \l_@@_model_tl \q_nil + \exp_not:N \q_mark + \siunitx_number_output:NN \l_@@_tmp_tl \q_nil + } + \exp_after:wN \@@_print_format_auxi:w + \l_@@_tmp_tl \q_stop + \hbox_set:Nn \l_@@_tmp_box { \l_@@_after_model_tl } + \hbox_set_to_wd:Nnn \l_@@_after_box + { \box_wd:N \l_@@_tmp_box + \l_@@_carry_dim } + { + \bool_if:NT \l_@@_align_after_bool + { \skip_horizontal:n { \l_@@_carry_dim } } + #3 + \@@_fil: + } + \use:c { @@_align_ \l_@@_align_number_tl :n } + { + \box_use_drop:N \l_@@_before_box + \box_use_drop:N \l_@@_integer_box + \box_use_drop:N \l_@@_decimal_box + \box_use_drop:N \l_@@_after_box + } + } +\cs_new:Npn \@@_print_format:nnnnnn #1#2#3#4#5#6#7 + { 0 #4 } +% \end{macrocode} +% The first numerical part to handle is the comparator. Any white space we +% need to add goes into the text part \emph{if} alignment is not active +% (\foreign{i.e.}~we are looking \enquote{backwards} to place this filler). +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_auxi:w + #1 \q_nil #2 \q_mark #3 \q_nil #4 \q_stop + { + \@@_print_format_box:Nn \l_@@_tmp_box {#1} + \bool_if:NTF \l_@@_align_before_bool + { + \hbox_set_to_wd:Nnn \l_@@_integer_box + { \box_wd:N \l_@@_tmp_box } + { + \@@_fil: + \tl_if_blank:nF {#3} + { \siunitx_print_number:n {#3} } + } + } + { + \@@_print_format_box:Nn \l_@@_integer_box {#3} + \hbox_set_to_wd:Nnn \l_@@_before_box + { + \box_wd:N \l_@@_before_box + + \box_wd:N \l_@@_tmp_box + - \box_wd:N \l_@@_integer_box + } + { + \@@_fil: + \hbox_unpack:N \l_@@_before_box + } + } + \@@_print_format_auxii:w #2 \q_mark #4 \q_stop + } +% \end{macrocode} +% The integer part follows much the same pattern, except now it is control +% of the comparator alignment that determines where the white space goes. +% As we already have content in the |integer| box, we need to measure how +% much \emph{extra} material has been added. To avoid using more boxes +% or re-setting, we do that by recording sizes before and after the change. +% (In effect, \cs{l_@@_tmp_dim} is here \enquote{l_@@_comparator_dim}.) +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_auxii:w + #1 \q_nil #2 \q_nil #3 \q_mark #4 \q_nil #5 \q_nil #6 \q_stop + { + \@@_print_format_box:Nn \l_@@_tmp_box {#1#2} + \bool_lazy_and:nnTF + { \l_@@_align_comparator_bool } + { \dim_compare_p:nNn { \box_wd:N \l_@@_integer_box } > { 0pt } } + { + \hbox_set_to_wd:Nnn \l_@@_integer_box + { + \box_wd:N \l_@@_integer_box + + \box_wd:N \l_@@_tmp_box + } + { + \hbox_unpack:N \l_@@_integer_box + \@@_fil: + \siunitx_print_number:n {#4#5} + } + } + { + \bool_if:NTF \l_@@_align_before_bool + { + \hbox_set_to_wd:Nnn \l_@@_integer_box + { + \box_wd:N \l_@@_integer_box + + \box_wd:N \l_@@_tmp_box + } + { + \@@_fil: + \hbox_unpack:N \l_@@_integer_box + \siunitx_print_number:n {#4#5} + } + } + { + \dim_set:Nn \l_@@_tmp_dim + { \box_wd:N \l_@@_integer_box } + \hbox_set:Nn \l_@@_integer_box + { + \hbox_unpack:N \l_@@_integer_box + \siunitx_print_number:n {#4#5} + } + \hbox_set_to_wd:Nnn \l_@@_before_box + { + \box_wd:N \l_@@_before_box + + \box_wd:N \l_@@_tmp_box + + \l_@@_tmp_dim + - \box_wd:N \l_@@_integer_box + } + { + \@@_fil: + \hbox_unpack:N \l_@@_before_box + } + } + } + \@@_print_format_auxiii:w #3 \q_mark #6 \q_stop + } +% \end{macrocode} +% We now deal with the decimal part: there is nothing already in the +% |decimal| box, so the basics are easy. We need to \enquote{carry forward} +% any white space, as where it gets inserted depends on the options for +% subsequent parts. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_auxiii:w + #1 \q_nil #2 \q_nil #3 \q_mark #4 \q_nil #5 \q_nil #6 \q_stop + { + \@@_print_format_box:Nn \l_@@_tmp_box {#1#2} + \@@_print_format_box:Nn \l_@@_decimal_box {#4#5} + \dim_set:Nn \l_@@_carry_dim + { + \box_wd:N \l_@@_tmp_box + - \box_wd:N \l_@@_decimal_box + } + \@@_print_format_auxiv:w #3 \q_mark #6 \q_stop + } +% \end{macrocode} +% Any separated uncertainty is now picked up. That has a number of parts, so +% the first step is to look for a sign (which will be |#1|). We then split, +% either simply tidying up the markers if there is no uncertainty, or +% setting it. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_auxiv:w + #1 \q_nil #2 \q_mark #3 \q_nil #4 \q_stop + { + \tl_if_blank:nTF {#1} + { \@@_print_format_auxv:w } + { \@@_print_format_auxvi:w } + #1#2 \q_mark #3#4 \q_stop + } +\cs_new_protected:Npn \@@_print_format_auxv:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_mark + #5 \q_nil #6 \q_nil #7 \q_nil #8 \q_stop + { \@@_print_format_auxvii:w #4 \q_mark #8 \q_stop } +% \end{macrocode} +% Sorting out the placement of the uncertainty requires both the model and +% real data widths, so we store the former to avoiding needing more boxes. +% It's then just a case of putting the carry-over white space in the right +% place. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_auxvi:w + #1 \q_nil #2 \q_nil #3 \q_nil #4 \q_mark + #5 \q_nil #6 \q_nil #7 \q_nil #8 \q_stop + { + \@@_print_format_box:Nn \l_@@_tmp_box { { } #1#2#3 } + \dim_set:Nn \l_@@_tmp_dim { \box_wd:N \l_@@_tmp_box } + \@@_print_format_box:Nn \l_@@_tmp_box { { } #5#6#7 } + \@@_print_format_after:N \l_@@_align_uncertainty_bool + \@@_print_format_auxvii:w #4 \q_mark #8 \q_stop + } +% \end{macrocode} +% Finally, we get to the exponent part: the multiplication symbol is +% |#1| and the number itself is |#2|. The code is almost the same as for +% uncertainties, which allows a shared auxiliary to be used. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_auxvii:w + #1 \q_nil #2 \q_mark #3 \q_nil #4 \q_stop + { + \tl_if_blank:nF {#2} + { + \@@_print_format_box:Nn \l_@@_tmp_box { { } #1#2 } + \dim_set:Nn \l_@@_tmp_dim { \box_wd:N \l_@@_tmp_box } + \@@_print_format_box:Nn \l_@@_tmp_box { { } #3#4 } + \@@_print_format_after:N \l_@@_align_exponent_bool + } + } +% \end{macrocode} +% A simple auxiliary to avoid relatively expensive use of the print routine +% for empty parts. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_box:Nn #1#2 + { + \hbox_set:Nn #1 + { + \tl_if_blank:nF {#2} + { \siunitx_print_number:n {#2} } + } + } +% \end{macrocode} +% A common routine for placing material after the decimal marker and +% \enquote{shuffling}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_format_after:N #1 + { + \bool_if:NTF #1 + { + \hbox_set_to_wd:Nnn \l_@@_decimal_box + { + \box_wd:N \l_@@_decimal_box + + \l_@@_carry_dim + + \box_wd:N \l_@@_tmp_box + } + { + \hbox_unpack:N \l_@@_decimal_box + \@@_fil: + \hbox_unpack:N \l_@@_tmp_box + } + \dim_set:Nn \l_@@_carry_dim + { + \l_@@_tmp_dim + - \box_wd:N \l_@@_tmp_box + } + } + { + \hbox_set:Nn \l_@@_decimal_box + { + \hbox_unpack:N \l_@@_decimal_box + \hbox_unpack:N \l_@@_tmp_box + } + \dim_add:Nn \l_@@_carry_dim + { + \l_@@_tmp_dim + - \box_wd:N \l_@@_tmp_box + } + } + } +% \end{macrocode} +% With no alignment, everything supplied is treated more-or-less the +% same as \cs{num} (but without the \pkg{xparse} wrapper). +% \begin{macrocode} +\cs_new_protected:Npn \@@_print_none:nnn #1#2#3 + { + \use:c { @@_align_ \l_@@_align_number_tl :n } + { + #1 + \siunitx_number_format:nN {#2} \l_@@_tmp_tl + \siunitx_print_number:V \l_@@_tmp_tl + #3 + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Standard settings for module options} +% +% Some of these follow naturally from the point of definition +% (\foreign{e.g.}~boolean variables are always |false| to begin with), +% but for clarity everything is set here. +% \begin{macrocode} +\keys_set:nn { siunitx } + { + table-align-comparator = true , + table-align-exponent = true , + table-align-text-after = true , + table-align-text-before = true , + table-align-uncertainty = true , + table-alignment = center , + table-auto-round = false , + table-column-width = 0pt , + table-fixed-width = false , + table-format = 2.2 , + table-number-alignment = center , + table-text-alignment = center , +% \end{macrocode} +% Out of order as |table-format| sets this implicitly too. +% \begin{macrocode} + table-alignment-mode = marker + } +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/siunitx/siunitx-unit.dtx b/macros/latex/contrib/siunitx/siunitx-unit.dtx new file mode 100644 index 0000000000..8eaf45c5ac --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-unit.dtx @@ -0,0 +1,2795 @@ +% \iffalse meta-comment +% +% File: siunitx-unit.dtx Copyright (C) 2014-2021 Joseph Wright +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% https://www.latex-project.org/lppl.txt +% +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% The released version of this bundle is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/josephwright/siunitx +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +%<*driver> +\documentclass{l3doc} +\ExplSyntaxOn +\makeatletter +\NewDocumentCommand \acro { m } + { + \textsc + { + \exp_args:NV \tl_if_head_eq_charcode:nNTF \f@series { m } + { \tl_lower_case:n } + { \use:n } + {#1} + } + } +\makeatother +\ExplSyntaxOff +\ProvideDocumentCommand\foreign{m}{\textit{#1}} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{siunitx.sty} +% +% \title{^^A +% \pkg{siunitx-unit} -- Parsing and formatting units^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } +% +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } +% +% \date{Released \filedate} +% +% \maketitle +% +% \begin{documentation} +% +% This submodule is dedicated to formatting physical units. The main function, +% \cs{siunitx_unit_format:nN}, takes user input specify physical units and +% converts it into a formatted token list suitable for typesetting in math +% mode. While the formatter will deal correctly with \enquote{literal} user +% input, the key strength of the module is providing a method to describe +% physical units in a \enquote{symbolic} manner. The output format of these +% symbolic units can then be controlled by a number of key--value options +% made available by the module. +% +% A small number of \LaTeXe{} math mode commands are assumed to be available +% as part of the formatted output. The \cs{mathchoice} command +% (normally the \TeX{} primitive) is needed when using +% |per-mode = symbol-or-fraction|. The commands \cs{frac}, \cs{mathrm}, +% \cs{mbox}, \verb*|\ | and \cs{,} are used by the standard module settings. +% For the display of colored (highlighted) and cancelled units, the commands +% \cs{textcolor} and \cs{cancel} are assumed to be available. +% +% \section{Formatting units} +% +% \begin{function}{\siunitx_unit_format:nN, \siunitx_unit_format:xN} +% \begin{syntax} +% \cs{siunitx_unit_format:nN} \Arg{units} \meta{tl~var} +% \end{syntax} +% This function converts the input \meta{units} into a processed +% \meta{tl~var} which can then be inserted in math mode to typeset the +% material. Where the \meta{units} are given in symbolic form, described +% elsewhere, this formatting process takes place in two stages: the +% \meta{units} are parsed into a structured form before the generation +% of the appropriate output form based on the active settings. When the +% \meta{units} are given as literals, processing is minimal: the +% characters |.| and |~| are converted to unit products (boundaries). +% In both cases, the result is a series of tokens intended to be typeset +% in math mode with appropriate choice of font for typesetting of the +% textual parts. +% +% For example, +% \begin{verbatim} +% \siunitx_unit_format:nN { \kilo \metre \per \second } \l_tmpa_tl +% \end{verbatim} +% will, with standard settings, result in \cs{l_tmpa_tl} being set to +% \begin{verbatim} +% \mathrm{km}\,\mathrm{s}^{-1} +% \end{verbatim} +% \end{function} +% +% \begin{function}{\siunitx_unit_format_extract_prefixes:nNN} +% \begin{syntax} +% \cs{siunitx_unit_format_extract_prefixes:nNN} \Arg{units} \meta{tl~var} \meta{fp~var} +% \end{syntax} +% This function formats the \meta{units} in the same way as described for +% \cs{siunitx_unit_format:nN}. When the input is given in symbolic form, +% any decimal unit prefixes will be extracted and the overall power of +% ten that these represent will be stored in the \meta{fp~var}. +% +% For example, +% \begin{verbatim} +% \siunitx_unit_format_extract_prefixes:nNN { \kilo \metre \per \second } +% \l_tmpa_tl \l_tmpa_fp +% \end{verbatim} +% will, with standard settings, result in \cs{l_tmpa_tl} being set to +% \begin{verbatim} +% \mathrm{m}\,\mathrm{s}^{-1} +% \end{verbatim} +% with \cs{l_tmpa_fp} taking value~$3$. Note that the latter is a floating +% point variable: it is possible for non-integer values to be obtained here. +% \end{function} +% +% \begin{function}{\siunitx_unit_format_combine_exponent:nnN} +% \begin{syntax} +% \cs{siunitx_unit_format_combine_exponent:nnN} \Arg{units} \Arg{exponent} \meta{tl~var} +% \end{syntax} +% This function formats the \meta{units} in the same way as described for +% \cs{siunitx_unit_format:nN}. The \meta{exponent} is combined with any +% prefix for the \emph{first} unit of the \meta{units}, and an updated +% prefix is introduced. +% +% For example, +% \begin{verbatim} +% \siunitx_unit_format_combine_exponent:nnN { \metre \per \second } +% { 3 } \l_tmpa_tl +% \end{verbatim} +% will, with standard settings, result in \cs{l_tmpa_tl} being set to +% \begin{verbatim} +% \mathrm{km}\,\mathrm{s}^{-1} +% \end{verbatim} +% \end{function} +% +% \begin{function} +% { +% \siunitx_unit_format_multiply:nnN , +% \siunitx_unit_format_multiply_extract_prefixes:nnNN , +% \siunitx_unit_format_multiply_combine_exponent:nnnN +% } +% \begin{syntax} +% \cs{siunitx_unit_format_multiply:nnN} \Arg{units} \Arg{factor} \meta{tl~var} +% \cs{siunitx_unit_format_multiply_extract_prefixes:nnNN} +% \Arg{units} \Arg{factor} \meta{tl~var} \meta{fp~var} +% \cs{siunitx_unit_format_multiply_combine_exponent:nnnN} +% \Arg{units} \Arg{factor} \Arg{exponent} \meta{tl~var} +% \end{syntax} +% These function formats the \meta{units} in the same way as described for +% \cs{siunitx_unit_format:nN}. The units are multiplied by the \meta{factor}, +% and further processing takes place as previously described. +% +% For example, +% \begin{verbatim} +% \siunitx_unit_format_multiply:nnN { \metre \per \second } +% { 3 } \l_tmpa_tl +% \end{verbatim} +% will, with standard settings, result in \cs{l_tmpa_tl} being set to +% \begin{verbatim} +% \mathrm{km}^{3}\,\mathrm{s}^{-3} +% \end{verbatim} +% \end{function} +% +% \section{Defining symbolic units} +% +% \begin{function}{\siunitx_declare_prefix:Nnn, \siunitx_declare_prefix:Nnx} +% \begin{syntax} +% \cs{siunitx_declare_prefix:Nnn} \meta{prefix} \Arg{power} \Arg{symbol} +% \end{syntax} +% Defines a symbolic \meta{prefix} (which should be a control sequence +% such as |\kilo|) to be converted by the parser to the \meta{symbol}. +% The latter should consist of literal content (\foreign{e.g.}~|k|). +% In literal mode the \meta{symbol} will be typeset directly. The prefix +% should represent an integer \meta{power} of $10$, and this information +% may be used to convert from one or more \meta{prefix} symbols to an +% overall power applying to a unit. See also +% \cs{siunitx_declare_prefix:Nn}. +% \end{function} +% +% \begin{function}{\siunitx_declare_prefix:Nn} +% \begin{syntax} +% \cs{siunitx_declare_prefix:Nn} \meta{prefix} \Arg{symbol} +% \end{syntax} +% Defines a symbolic \meta{prefix} (which should be a control sequence +% such as |\kilo|) to be converted by the parser to the \meta{symbol}. +% The latter should consist of literal content (\foreign{e.g.}~|k|). +% In literal mode the \meta{symbol} will be typeset directly. In contrast +% to \cs{siunitx_declare_prefix:Nnn}, there is no assumption about the +% mathematical nature of the \meta{prefix}, \foreign{i.e.}~the prefix may +% represent a power of any base. As a result, no conversion of the +% \meta{prefix} to a numerical power will be possible. +% \end{function} +% +% \begin{function}{\siunitx_declare_power:NNn} +% \begin{syntax} +% \cs{siunitx_declare_power:NnN} \meta{pre-power} \meta{post-power} \Arg{value} +% \end{syntax} +% Defines \emph{two} symbolic \meta{powers} (which should be control +% sequences such as |\squared|) to be converted by the parser to the +% \meta{value}. The latter should be an integer or floating point number in +% the format defined for \pkg{l3fp}. Powers may precede a unit or be give +% after it: both forms are declared at once, as indicated by the argument +% naming. In literal mode, the \meta{value} will be applied as +% a superscript to either the next token in the input (for the +% \meta{pre-power}) or appended to the previously-typeset material +% (for the \meta{post-power}). +% \end{function} +% +% \begin{function}{\siunitx_declare_qualifier:Nn} +% \begin{syntax} +% \cs{siunitx_declare_qualifier:Nn} \meta{qualifier} \Arg{meaning} +% \end{syntax} +% Defines a symbolic \meta{qualifier} (which should be a control sequence +% such as |\catalyst|) to be converted by the parser to the \meta{meaning}. +% The latter should consist of literal content (\foreign{e.g.}~|cat|). In +% literal mode the \meta{meaning} will be typeset following a space after +% the unit to which it applies. +% \end{function} +% +% \begin{function} +% { +% \siunitx_declare_unit:Nn, +% \siunitx_declare_unit:Nx, +% \siunitx_declare_unit:Nnn, +% \siunitx_declare_unit:Nxn +% } +% \begin{syntax} +% \cs{siunitx_declare_unit:Nn} \meta{unit} \Arg{meaning} +% \cs{siunitx_declare_unit:Nnn} \meta{unit} \Arg{meaning} \Arg{options} +% \end{syntax} +% Defines a symbolic \meta{unit} (which should be a control sequence +% such as |\kilogram|) to be converted by the parser to the \meta{meaning}. +% The latter may consist of literal content (\foreign{e.g.}~|kg|), other +% symbolic unit commands (\foreign{e.g.}~|\kilo\gram|) or a mixture of the two. +% In literal mode the \meta{meaning} will be typeset directly. The version +% taking an \meta{options} argument may be used to support per-unit +% options: these are applied at the top level or using +% \cs{siunitx_unit_options_apply:n}. +% \end{function} +% +% \begin{variable}{\l_siunitx_unit_font_tl} +% The font function which is applied to the text of units when constructing +% formatted units: set by |font-command|. +% \end{variable} +% +% \begin{variable}{\l_siunitx_unit_symbolic_seq} +% This sequence contains all of the symbolic names defined: +% these will be in the form of control sequences such as |\kilogram|. +% The order of the sequence is unimportant. This includes prefixes and +% powers as well as units themselves. +% \end{variable} +% +% \begin{variable}{\l_siunitx_unit_seq} +% This sequence contains all of the symbolic \emph{unit} names defined: +% these will be in the form of control sequences such as |\kilogram|. +% In contrast to \cs{l_siunitx_unit_symbolic_seq}, it \emph{only} holds +% units themselves +% \end{variable} +% +% \section{Per-unit options} +% +% \begin{function}{\siunitx_unit_options_apply:n} +% \begin{syntax} +% \cs{siunitx_unit_options_apply:n} \meta{unit(s)} +% \end{syntax} +% Applies any unit-specific options set up using +% \cs{siunitx_declare_unit:Nnn}. This allows there use outside of unit +% formatting, for example to influence spacing in quantities. The options +% are applied only once at a given group level, which allows for user +% over-ride \foreign{via} |\keys_set:nn { siunitx } { ... }|. +% \end{function} +% +% \section{Units in (PDF) strings} +% +% \begin{function}{\siunitx_unit_pdfstring_context:} +% \begin{syntax} +% \cs{group_begin:} +% \cs{siunitx_unit_pdfstring_context:} +% \meta{Expansion context} \meta{units} +% \cs{group_end:} +% \end{syntax} +% Sets symbol unit macros to generate text directly. This is needed in +% expansion contexts where units must be converted to simple text. This +% function is itself not expandable, so must be using within a +% surrounding group as show in the example. +% \end{function} +% +% \section{Pre-defined symbolic unit components} +% +% The unit parser is defined to recognise a number of pre-defined units, +% prefixes and powers, and also interpret a small selection of +% \enquote{generic} symbolic parts. +% +% Broadly, the pre-defined units are those defined by the \textsc{bipm} in the +% documentation for the \emph{International System of Units} +% (\acro{SI})~\cite{BIPM}. As far as possible, the names given to the command +% names for units are those used by the \acro{bipm}, omitting spaces and using +% only \acro{ASCII} characters. The standard symbols are also taken from the +% same documentation. In the following documentation, the order of the +% description of units broadly follows the \acro{SI}~Brochure. +% +% \begin{function} +% { +% \kilogram , +% \metre , +% \meter , +% \mole , +% \kelvin , +% \candela , +% \second , +% \ampere +% } +% The base units as defined in the \acro{SI} Brochure~\cite{base-units}. +% Notice that \cs{meter} is defined as an alias for \cs{metre} as the former +% spelling is common in the US (although the latter is the official spelling). +% \end{function} +% +% \begin{function}{\gram} +% The base unit \cs{kilogram} is defined using an \acro{SI} prefix: as such +% the (derived) unit \cs{gram} is required by the module to correctly produce +% output for the \cs{kilogram}. +% \end{function} +% +% \begin{function} +% { +% \yocto , +% \zepto , +% \atto , +% \femto , +% \pico , +% \nano , +% \micro , +% \milli , +% \centi , +% \deci , +% \deca , +% \deka , +% \hecto , +% \kilo , +% \mega , +% \giga , +% \tera , +% \peta , +% \exa , +% \zetta , +% \yotta +% } +% Prefixes, all of which are integer powers of $10$: the powers are stored +% internally by the module and can be used for conversion from prefixes to +% their numerical equivalent. These prefixes are documented in Section~3.1 +% of the \acro{SI}~Brochure. +% +% Note that the \cs{kilo} prefix is required to +% define the base \cs{kilogram} unit. Also note the two spellings available +% for \cs{deca}/\cs{deka}. +% \end{function} +% +% \begin{function} +% { +% \becquerel , +% \degreeCelsius , +% \coulomb , +% \farad , +% \gray , +% \hertz , +% \henry , +% \joule , +% \katal , +% \lumen , +% \lux , +% \newton , +% \ohm , +% \pascal , +% \radian , +% \siemens , +% \sievert , +% \steradian , +% \tesla , +% \volt , +% \watt , +% \weber +% } +% The defined \acro{SI}~units with defined names and symbols, as given in +% Table~4 of the \acro{SI}~Brochure. Notice that the names +% of the units are lower case with the exception of \cs{degreeCelsius}, and +% that this unit name includes \enquote{degree}. +% \end{function} +% +% \begin{function} +% { +% \astronomicalunit , +% \bel , +% \dalton , +% \day , +% \decibel , +% \electronvolt , +% \hectare , +% \hour , +% \litre , +% \liter , +% \neper , +% \minute , +% \tonne +% } +% Units accepted for use with the \acro{SI}: here \cs{minute} is a unit of +% time not of plane angle. These units are taken from Table~8 of the +% \acro{SI}~Brochure. +% +% For the unit \cs{litre}, both |l| and |L| are listed +% as acceptable symbols: the latter is the standard setting of the module. +% The alternative spelling \cs{liter} is also given for this unit for US +% users (as with \cs{metre}, the official spelling is \enquote{re}). +% \end{function} +% +% \begin{function} +% { +% \arcminute , +% \arcsecond , +% \degree +% } +% Units for plane angles accepted for use with the \acro{SI}: to avoid a +% clash with units for time, here \cs{arcminute} and \cs{arcsecond} are +% used in place of \cs{minute} and \cs{second}. These units are taken from +% Table~8 of the \acro{SI}~Brochure. +% \end{function} +% +% \begin{function}{\percent} +% The mathematical concept of percent, usable with the \acro{SI} as detailed +% in Section~5.4.7 of the \acro{SI}~Brochure. +% \end{function} +% +% \begin{function}{\square, \cubic} +% \begin{syntax} +% \cs{square} \meta{prefix} \meta{unit} +% \cs{cubic} \meta{prefix} \meta{unit} +% \end{syntax} +% Pre-defined unit powers which apply to the next \meta{prefix}/\meta{unit} +% combination. +% \end{function} +% +% \begin{function}{\squared, \cubed} +% \begin{syntax} +% \meta{prefix} \meta{unit} \cs{squared} +% \meta{prefix} \meta{unit} \cs{cubed} +% \end{syntax} +% Pre-defined unit powers which apply to the preceding +% \meta{prefix}/\meta{unit} combination. +% \end{function} +% +% \begin{function}{\per} +% \begin{syntax} +% \cs{per} \meta{prefix} \meta{unit} \meta{power} +% \end{syntax} +% Indicates that the next \meta{prefix}/\meta{unit}/\meta{power} combination +% is reciprocal, \foreign{i.e.}~raises it to the power $-1$. This symbolic +% representation may be applied in addition to a \cs{power}, and will work +% correctly if the \cs{power} itself is negative. In literal mode \cs{per} +% will print a slash (\enquote{$/$}). +% \end{function} +% +% \begin{function}{\cancel} +% \begin{syntax} +% \cs{cancel} \meta{prefix} \meta{unit} \meta{power} +% \end{syntax} +% Indicates that the next \meta{prefix}/\meta{unit}/\meta{power} combination +% should be \enquote{cancelled out}. In the parsed output, the entire unit +% combination will be given as the argument to a function \cs{cancel}, which +% is assumed to be available at a higher level. In literal mode, the same +% higher-level \cs{cancel} will be applied to the next token. It is the +% responsibility of the calling code to provide an appropriate definition +% for \cs{cancel} outside of the scope of the unit parser. +% \end{function} +% +% \begin{function}{\highlight} +% \begin{syntax} +% \cs{highlight} \Arg{color} \meta{prefix} \meta{unit} \meta{power} +% \end{syntax} +% Indicates that the next \meta{prefix}/\meta{unit}/\meta{power} combination +% should be highlighted in the specified \meta{color}. In the parsed output, +% the entire unit combination will be given as the argument to a function +% \cs{textcolor}, which is assumed to be available at a higher level. In +% literal mode, the same higher-level \cs{textcolor} will be applied to the +% next token. It is the responsibility of the calling code to provide an +% appropriate definition for \cs{textcolor} outside of the scope of the unit +% parser. +% \end{function} +% +% \begin{function}{\of} +% \begin{syntax} +% \meta{prefix} \meta{unit} \meta{power} \cs{of} \Arg{qualifier} +% \end{syntax} +% Indicates that the \meta{qualifier} applies to the current +% \meta{prefix}/\meta{unit}/\meta{power} combination. In parsed mode, the +% display of the result will depend upon module options. In literal mode, +% the \meta{qualifier} will be printed in parentheses following the preceding +% \meta{unit} and a full-width space. +% \end{function} +% +% \begin{function}{\raiseto, \tothe} +% \begin{syntax} +% \cs{raiseto} \Arg{power} \meta{prefix} \meta{unit} +% \meta{prefix} \meta{unit} \cs{tothe} \Arg{power} +% \end{syntax} +% Indicates that the \meta{power} applies to the current +% \meta{prefix}/\meta{unit} combination. As shown, \cs{raiseto} applies to +% the next \meta{unit} whereas \cs{tothe} applies to the preceding unit. In +% literal mode the \cs{power} will be printed as a superscript attached to +% the next token (\cs{raiseto}) or preceding token (\cs{tothe}) as +% appropriate. +% \end{function} +% +% \subsection{Key--value options} +% +% The options defined by this submodule are available within the \pkg{l3keys} +% |siunitx| tree. +% +% \begin{function}{bracket-unit-denominator} +% \begin{syntax} +% |bracket-unit-denominator| = |true|\verb"|"|false| +% \end{syntax} +% Switch to determine whether brackets are added to the denominator part of +% a unit when printed using inline fractional form (with |per-mode| as +% |repeated-symbol|, |symbol| or |symbol-or-fraction|). The standard setting +% is |true|. +% \end{function} +% +% \begin{function}{extract-mass-in-kilograms} +% \begin{syntax} +% |extract-mass-in-kilograms| = |true|\verb"|"|false| +% \end{syntax} +% Determines whether prefix extraction treats kilograms as a base unit; when +% set |false|, grams are used. The standard setting is |true|. +% \end{function} +% +% \begin{function}{forbid-literal-units} +% \begin{syntax} +% |forbid-literal-units| = |true|\verb"|"|false| +% \end{syntax} +% Switch which determines if literal units are allowed when parsing is +% active; does not apply when |parse-units| is |false|. +% \end{function} +% +% \begin{function}{fraction-command} +% \begin{syntax} +% |fraction-command| = \meta{command} +% \end{syntax} +% Command used to create fractional output when |per-mode| is set to +% |fraction|. The standard setting is |\frac|. +% \end{function} +% +% \begin{function}{inter-unit-product} +% \begin{syntax} +% |inter-unit-product| = \meta{separator} +% \end{syntax} +% Inserted between unit combinations in parsed mode, and used to replace +% |.| and |~| in literal mode. The standard setting is |\,|. +% \end{function} +% +% \begin{function}{parse-units} +% \begin{syntax} +% |parse-units| = |true|\verb"|"|false| +% \end{syntax} +% Determines whether parsing of unit symbols is attempted or literal +% mode is used directly. The standard setting is |true|. +% \end{function} +% +% \begin{function}{per-mode} +% \begin{syntax} +% |per-mode| = |fraction|\verb"|"|power|\verb"|"|power-positive-first|\verb"|"|repeated-symbol|\verb"|"|symbol|\verb"|"|symbol-or-fraction| +% \end{syntax} +% Selects how the negative powers (\cs{per}) are formatted: a choice from +% the options |fraction|, |power|, |power-positive-first|, |repeated-symbol|, +% |symbol| and |symbol-or-fraction|. The option |fraction| generates +% fractional output when appropriate using the command specified by +% the |fraction-command| option. The setting |power| uses reciprocal powers +% leaving the units in the order of input, while |power-positive-first| uses +% the same display format but sorts units such that the positive powers +% come before negative ones. The |symbol| setting uses a symbol (specified +% by |per-symbol|) between positive and negative powers, while +% |repeated-symbol| uses the same symbol but places it before \emph{every} +% unit with a negative power (this is mathematically \enquote{wrong} but +% often seen in real work). Finally, |symbol-or-fraction| acts like +% |symbol| for inline output and like |fraction| when the output is used +% in a display math environment. The standard setting is |power|. +% \end{function} +% +% \begin{function}{per-symbol} +% \begin{syntax} +% |per-symbol| = \meta{symbol} +% \end{syntax} +% Specifies the symbol to be used to denote negative powers when the option +% |per-mode| is set to |repeated-symbol|, |symbol| or |symbol-or-fraction|. +% The standard setting is |/|. +% \end{function} +% +% \begin{function}{qualifier-mode} +% \begin{syntax} +% |qualifier-mode| = |bracket|\verb"|"|combine|\verb"|"|phrase|\verb"|"|subscript| +% \end{syntax} +% Selects how qualifiers are formatted: a choice from the options |bracket|, +% |combine|, |phrase| and |subscript|. The option |bracket| wraps the qualifier +% in parenthesis, |combine| joins the qualifier with the unit directly, |phrase| +% joins the material using |qualifier-phrase| as a link, and +% |subscript| formats the qualifier as a subscript. The standard setting is +% |subscript|. +% \end{function} +% +% \begin{function}{qualifier-phrase} +% \begin{syntax} +% |qualifier-phrase| = \meta{phrase} +% \end{syntax} +% Defines the \meta{phrase} used when |qualifier-mode| is set to |phrase|. +% \end{function} +% +% \begin{function}{sticky-per} +% \begin{syntax} +% |sticky-per| = |true|\verb"|"|false| +% \end{syntax} +% Used to determine whether \cs{per} should be applied one a unit-by-unit +% basis (when |false|) or should apply to all following units +% (when |true|). The latter mode is somewhat akin conceptually to the +% \TeX{} \cs{over} primitive. The standard setting is |false|. +% \end{function} +% +% \begin{function}{unit-font-command} +% \begin{syntax} +% |unit-font-command| = \meta{command} +% \end{syntax} +% Command applied to text during output of units: should be command usable +% in math mode for font selection. Notice that in a typical unit this does +% not (necessarily) apply to all output, for example powers or brackets. +% The standard setting is |\mathrm|. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{siunitx-unit} implementation} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention): only +% internal material in this \emph{submodule} should be used directly. +% \begin{macrocode} +%<@@=siunitx_unit> +% \end{macrocode} +% +% \subsection{Initial set up} +% +% The mechanisms defined here need a few variables to exist and to be +% correctly set: these don't belong to one subsection and so are created +% in a small general block. +% +% Variants not provided by \pkg{expl3}. +% \begin{macrocode} +\cs_generate_variant:Nn \tl_replace_all:Nnn { NnV } +% \end{macrocode} +% +% \begin{variable}{\l_@@_tmp_fp} +% \begin{variable}{\l_@@_tmp_int} +% \begin{variable}{\l_@@_tmp_tl} +% Scratch space. +% \begin{macrocode} +\fp_new:N \l_@@_tmp_fp +\int_new:N \l_@@_tmp_int +\tl_new:N \l_@@_tmp_tl +% \end{macrocode} +% \end{variable} +% \end{variable} +% \end{variable} +% +% \begin{variable}{\c_@@_math_subscript_tl} +% Useful tokens with awkward category codes. +% \begin{macrocode} +\tl_const:Nx \c_@@_math_subscript_tl + { \char_generate:nn { `\_ } { 8 } } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_parsing_bool} +% A boolean is used to indicate when the symbolic unit functions should +% produce symbolic or literal output. This is used when the symbolic names +% are used along with literal input, and ensures that there is a sensible +% fall-back for these cases. +% \begin{macrocode} +\bool_new:N \l_@@_parsing_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_test_bool} +% A switch used to indicate that the code is testing the input to find +% if there is any typeset output from individual unit macros. This is needed +% to allow the \enquote{base} macros to be found, and also to pick up the +% difference between symbolic and literal unit input. +% \begin{macrocode} +\bool_new:N \l_@@_test_bool +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_if_symbolic:nTF} +% The test for symbolic units is needed in two places. First, there is the +% case of \enquote{pre-parsing} input to check if it can be parsed. Second, +% when parsing there is a need to check if the current unit is built up +% from others (symbolic) or is defined in terms of some literals. To do this, +% the approach used is to set all of the symbolic unit commands expandable +% and to do nothing, with the few special cases handled manually. +% \begin{macrocode} +\prg_new_protected_conditional:Npnn \@@_if_symbolic:n #1 { TF } + { + \group_begin: + \bool_set_true:N \l_@@_test_bool + \protected@edef \l_@@_tmp_tl {#1} + \exp_args:NNV \group_end: + \tl_if_blank:nTF \l_@@_tmp_tl + { \prg_return_true: } + { \prg_return_false: } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Defining symbolic unit} +% +% Unit macros and related support are created here. These exist only within +% the scope of the unit processor code, thus not polluting document-level +% namespace and allowing overlap with other areas in the case of useful short +% names (for example \cs{pm}). Setting up the mechanisms to allow this requires +% a few additional steps on top of simply saving the data given by the user +% in creating the unit. +% +% \begin{variable}{\l_siunitx_unit_symbolic_seq} +% A list of all of the symbolic units, \foreign{etc.}, set up. This is needed +% to allow the symbolic names to be defined within the scope of the unit +% parser but not elsewhere using simple mappings. +% \begin{macrocode} +\seq_new:N \l_siunitx_unit_symbolic_seq +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_siunitx_unit_seq} +% A second list featuring only the units themselves. +% \begin{macrocode} +\seq_new:N \l_siunitx_unit_seq +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_set_symbolic:Nnn} +% \begin{macro}{\@@_set_symbolic:Npnn} +% \begin{macro}{\@@_set_symbolic:Nnnn} +% The majority of the work for saving each symbolic definition is the same +% irrespective of the item being defined (unit, prefix, power, qualifier). +% This is therefore all carried out in a single internal function which +% does the common tasks. The three arguments here are the symbolic macro +% name, the literal output and the code to insert when doing full unit +% parsing. To allow for the \enquote{special cases} (where arguments are +% required) the entire mechanism is set up in a two-part fashion allowing +% for flexibility at the slight cost of additional functions. +% +% Importantly, notice that the unit macros are declared as expandable. This +% is required so that literals can be correctly converted into a token list +% of material which does not depend on local redefinitions for the unit +% macros. That is required so that the unit formatting system can be grouped. +% \begin{macrocode} +\cs_new_protected:Npn \@@_set_symbolic:Nnn #1 + { \@@_set_symbolic:Nnnn #1 { } } +\cs_new_protected:Npn \@@_set_symbolic:Npnn #1#2# + { \@@_set_symbolic:Nnnn #1 {#2} } +\cs_new_protected:Npn \@@_set_symbolic:Nnnn #1#2#3#4 + { + \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} + \cs_set:cpn { @@_ \token_to_str:N #1 :w } #2 + { + \bool_if:NF \l_@@_test_bool + { + \bool_if:NTF \l_@@_parsing_bool + {#4} + {#3} + } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\siunitx_declare_power:NNn} +% Powers can come either before or after the unit. As they always come +% (logically) in matching, we handle this by declaring two commands, +% and setting each up separately. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_declare_power:NNn #1#2#3 + { + \@@_set_symbolic:Nnn #1 + { \@@_literal_power:nn {#3} } + { \@@_parse_power:nnN {#1} {#3} \c_true_bool } + \@@_set_symbolic:Nnn #2 + { ^ {#3} } + { \@@_parse_power:nnN {#2} {#3} \c_false_bool } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\siunitx_declare_prefix:Nn} +% \begin{macro}{\siunitx_declare_prefix:Nnn, \siunitx_declare_prefix:Nnx} +% \begin{variable} +% {\l_@@_prefixes_forward_prop, \l_@@_prefixes_reverse_prop} +% For prefixes there are a couple of options. In all cases, the basic +% requirement is to set up to parse the prefix using the appropriate +% internal function. For prefixes which are powers of $10$, there is also +% the need to be able to do conversion to/from the numerical equivalent. +% That is handled using two properly lists which can be used to supply +% the conversion data later. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_declare_prefix:Nn #1#2 + { + \@@_set_symbolic:Nnn #1 + {#2} + { \@@_parse_prefix:Nn #1 {#2} } + } +\cs_new_protected:Npn \siunitx_declare_prefix:Nnn #1#2#3 + { + \siunitx_declare_prefix:Nn #1 {#3} + \prop_put:Nnn \l_@@_prefixes_forward_prop {#3} {#2} + \prop_put:Nnn \l_@@_prefixes_reverse_prop {#2} {#3} + } +\cs_generate_variant:Nn \siunitx_declare_prefix:Nnn { Nnx } +\prop_new:N \l_@@_prefixes_forward_prop +\prop_new:N \l_@@_prefixes_reverse_prop +% \end{macrocode} +% \end{variable} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\siunitx_declare_qualifier:Nn} +% Qualifiers are relatively easy to handle: nothing to do other than save +% the input appropriately. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_declare_qualifier:Nn #1#2 + { + \@@_set_symbolic:Nnn #1 + { ~ ( #2 ) } + { \@@_parse_qualifier:nn {#1} {#2} } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\siunitx_declare_unit:Nn, \siunitx_declare_unit:Nx} +% \begin{macro}{\siunitx_declare_unit:Nnn, \siunitx_declare_unit:Nxn} +% For the unit parsing, allowing for variations in definition order requires +% that a test is made for the output of each unit at point of use. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_declare_unit:Nn #1#2 + { \siunitx_declare_unit:Nnn #1 {#2} { } } +\cs_generate_variant:Nn \siunitx_declare_unit:Nn { Nx } +\cs_new_protected:Npn \siunitx_declare_unit:Nnn #1#2#3 + { + \seq_put_right:Nn \l_siunitx_unit_seq {#1} + \@@_set_symbolic:Nnn #1 + {#2} + { + \@@_if_symbolic:nTF {#2} + {#2} + { \@@_parse_unit:Nn #1 {#2} } + } + \tl_clear_new:c { l_@@_options_ \token_to_str:N #1 _tl } + \tl_if_empty:nF {#3} + { \tl_set:cn { l_@@_options_ \token_to_str:N #1 _tl } {#3} } + } +\cs_generate_variant:Nn \siunitx_declare_unit:Nnn { Nx } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Applying unit options} +% +% \begin{variable}{\l_@@_options_bool} +% \begin{macrocode} +\bool_new:N \l_@@_options_bool +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_unit_options_apply:n} +% Options apply only if they have not already been set at this group +% level. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_unit_options_apply:n #1 + { + \bool_if:NF \l_@@_options_bool + { + \tl_if_single_token:nT {#1} + { + \tl_if_exist:cT { l_@@_options_ \token_to_str:N #1 _tl } + { + \keys_set:nv { siunitx } + { l_@@_options_ \token_to_str:N #1 _tl } + } + } + } + \bool_set_true:N \l_@@_options_bool + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Non-standard symbolic units} +% +% A few of the symbolic units require non-standard definitions: these are +% created here. They all use parts of the more general code but have particular +% requirements which can only be addressed by hand. Some of these could in +% principle be used in place of the dedicated definitions above, but at point +% of use that would then require additional expansions for each unit parsed: +% as the macro names would still be needed, this does not offer any real +% benefits. +% +% \begin{macro}{\per} +% The \cs{per} symbolic unit is a bit special: it has a mechanism entirely +% different from everything else, so has to be set up by hand. In literal +% mode it is represented by a very simple symbol! +% \begin{macrocode} +\@@_set_symbolic:Nnn \per + { / } + { \@@_parse_per: } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\cancel} +% \begin{macro}{\highlight} +% The two special cases, \cs{cancel} and \cs{highlight}, are easy to deal +% with when parsing. When not parsing, a precaution is taken to ensure that +% the user level equivalents always get a braced argument. +% \begin{macrocode} +\@@_set_symbolic:Npnn \cancel + { } + { \@@_parse_special:n { \cancel } } +\@@_set_symbolic:Npnn \highlight #1 + { \@@_literal_special:nN { \textcolor {#1} } } + { \@@_parse_special:n { \textcolor {#1} } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\of} +% The generic qualifier is simply the same as the dedicated ones except for +% needing to grab an argument. +% \begin{macrocode} +\@@_set_symbolic:Npnn \of #1 + { \ ( #1 ) } + { \@@_parse_qualifier:nn { \of {#1} } {#1} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\raiseto, \tothe} +% Generic versions of the pre-defined power macros. These require an +% argument and so cannot be handled using the general approach. Other than +% that, the code here is very similar to that in +% \cs{siunitx_unit_power_set:NnN}. +% \begin{macrocode} +\@@_set_symbolic:Npnn \raiseto #1 + { \@@_literal_power:nn {#1} } + { \@@_parse_power:nnN { \raiseto {#1} } {#1} \c_true_bool } +\@@_set_symbolic:Npnn \tothe #1 + { ^ {#1} } + { \@@_parse_power:nnN { \tothe {#1} } {#1} \c_false_bool } +% \end{macrocode} +% \end{macro} +% +% \subsection{Main formatting routine} +% +% Unit input can take two forms, \enquote{literal} units (material to be +% typeset directly) or \enquote{symbolic} units (macro-based). Before any +% parsing or typesetting is carried out, a small amount of pre-parsing has to +% be carried out to decide which of these cases applies. +% +% \begin{variable} +% {\l_siunitx_unit_font_tl, \l_@@_product_tl, \l_@@_mass_kilogram_bool} +% Options which apply to the main formatting routine, and so are not tied +% to either symbolic or literal input. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + extract-mass-in-kilograms .bool_set:N = + \l_@@_mass_kilogram_bool , + inter-unit-product .tl_set:N = + \l_@@_product_tl , + unit-font-command .tl_set:N = + \l_siunitx_unit_font_tl + } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_formatted_tl} +% A token list for the final formatted result: may or may not be generated +% by the parser, depending on the nature of the input. +% \begin{macrocode} +\tl_new:N \l_@@_formatted_tl +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\siunitx_unit_format:nN} +% \begin{macro}{\siunitx_unit_format_extract_prefixes:nNN} +% \begin{macro}{\siunitx_unit_format_combine_exponent:nnN} +% \begin{macro}{\siunitx_unit_format_multiply:nnN} +% \begin{macro}{\siunitx_unit_format_multiply_extract_prefixes:nnNN} +% \begin{macro}{\siunitx_unit_format_multiply_combine_exponent:nnnN} +% \begin{macro}{\@@_format:nNN} +% \begin{macro}{\@@_format_aux:} +% Formatting parsed units can take place either with the prefixes printed or +% separated out into a power of ten. This variation is handled using two +% separate functions: as this submodule does not really deal with numbers, +% formatting the numeral part here would be tricky and it is better therefore +% to have a mechanism to return a simple numerical power. At the same time, +% most uses will no want this more complex return format and so a version of +% the code which does not do this is also provided. +% +% The main unit formatting routine groups all of the parsing/formatting, so +% that the only value altered will be the return token list. As definitions +% for the various unit macros are not globally created, the first step is to +% map over the list of names and active the unit definitions: these do +% different things depending on the switches set. There is then a decision to +% be made: is the unit input one that can be parsed (\enquote{symbolic}), or +% is is one containing one or more literals. In the latter case, there is a +% still the need to convert the input into an expanded token list as some +% parts of the input could still be using unit macros. +% +% Notice that for \cs{siunitx_unit_format:nN} a second return value from the +% auxiliary has to be allowed for, but is simply discarded. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_unit_format:nN #1#2 + { + \bool_set_false:N \l_@@_prefix_exp_bool + \fp_zero:N \l_@@_combine_exp_fp + \fp_set:Nn \l_@@_multiple_fp { \c_one_fp } + \@@_format:nNN {#1} #2 \l_@@_tmp_fp + } +\cs_new_protected:Npn \siunitx_unit_format_extract_prefixes:nNN #1#2#3 + { + \bool_set_true:N \l_@@_prefix_exp_bool + \fp_zero:N \l_@@_combine_exp_fp + \fp_set:Nn \l_@@_multiple_fp { \c_one_fp } + \@@_format:nNN {#1} #2 #3 + } +\cs_new_protected:Npn \siunitx_unit_format_combine_exponent:nnN #1#2#3 + { + \bool_set_false:N \l_@@_prefix_exp_bool + \fp_set:Nn \l_@@_combine_exp_fp {#2} + \fp_set:Nn \l_@@_multiple_fp { \c_one_fp } + \@@_format:nNN {#1} #3 \l_@@_tmp_fp + } +\cs_new_protected:Npn \siunitx_unit_format_multiply:nnN #1#2#3 + { + \bool_set_false:N \l_@@_prefix_exp_bool + \fp_zero:N \l_@@_combine_exp_fp + \fp_set:Nn \l_@@_multiple_fp {#2} + \@@_format:nNN {#1} #3 \l_@@_tmp_fp + } +\cs_new_protected:Npn \siunitx_unit_format_multiply_extract_prefixes:nnNN + #1#2#3#4 + { + \bool_set_true:N \l_@@_prefix_exp_bool + \fp_zero:N \l_@@_combine_exp_fp + \fp_set:Nn \l_@@_multiple_fp {#2} + \@@_format:nNN {#1} #3 #4 + } +\cs_new_protected:Npn \siunitx_unit_format_multiply_combine_exponent:nnnN + #1#2#3#4 + { + \bool_set_false:N \l_@@_prefix_exp_bool + \fp_set:Nn \l_@@_combine_exp_fp {#3} + \fp_set:Nn \l_@@_multiple_fp {#2} + \@@_format:nNN {#1} #4 \l_@@_tmp_fp + } +\cs_new_protected:Npn \@@_format:nNN #1#2#3 + { + \group_begin: + \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq + { \cs_set_eq:Nc ##1 { @@_ \token_to_str:N ##1 :w } } + \tl_clear:N \l_@@_formatted_tl + \fp_zero:N \l_@@_prefix_fp + \bool_if:NTF \l_@@_parse_bool + { + \@@_if_symbolic:nTF {#1} + { + \@@_parse:n {#1} + \prop_if_empty:NF \l_@@_parsed_prop + { \@@_format_parsed: } + } + { + \bool_if:NTF \l_@@_forbid_literal_bool + { \msg_error:nnn { siunitx } { unit / literal } {#1} } + { \@@_format_literal:n {#1} } + } + } + { \@@_format_literal:n {#1} } + \cs_set_protected:Npx \@@_format_aux: + { + \tl_set:Nn \exp_not:N #2 + { \exp_not:V \l_@@_formatted_tl } + \fp_set:Nn \exp_not:N #3 + { \fp_use:N \l_@@_prefix_fp } + } + \exp_after:wN \group_end: + \@@_format_aux: + } +\cs_new_protected:Npn \@@_format_aux: { } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Formatting literal units} +% +% While in literal mode no parsing occurs, there is a need to provide a few +% auxiliary functions to handle one or two special cases. +% +% \begin{macro}[EXP]{\@@_literal_power:nn} +% For printing literal units which are given before the unit they apply to, +% there is a slight rearrangement. This is ex[EXP]pandable to cover the case of +% creation of a PDF string. +% \begin{macrocode} +\cs_new:Npn \@@_literal_power:nn #1#2 { #2 ^ {#1} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_literal_special:nN} +% When dealing with the special cases, there is an argument to absorb. This +% should be braced to be passed up to the user level, which is dealt with +% here. +% \begin{macrocode} +\cs_new:Npn \@@_literal_special:nN #1#2 { #1 {#2} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_format_literal:n} +% \begin{macro} +% { +% \@@_format_literal_tilde: , +% \@@_format_literal_subscript: , +% \@@_format_literal_superscript: +% } +% \begin{macro}{\@@_format_literal_auxi:w} +% \begin{macro}{\@@_format_literal_auxii:w} +% \begin{macro}{\@@_format_literal_auxiii:w} +% \begin{macro}{\@@_format_literal_auxiv:w} +% \begin{macro}{\@@_format_literal_auxv:w} +% \begin{variable}{\l_@@_separator_tl} +% To format literal units, there are two tasks to do. The input is +% \texttt{x}-type expanded to force any symbolic units to be converted into +% their literal representation: this requires setting the appropriate +% switch. In the resulting token list, all |.| and |~| tokens are then +% replaced by the current unit product token list. To enable this to happen +% correctly with a normal (active) |~|, a small amount of +% \enquote{protection} is needed first. To cover active sub- and superscript +% tokens, appropriate definitions are provided at this stage. Those have +% to be expandable macros rather than implicit character tokens. +% +% As with other code dealing with user input, \cs{protected@edef} is used +% here rather than \cs{tl_set:Nx} as \LaTeXe{} robust commands may be +% present. +% \begin{macrocode} +\group_begin: + \char_set_catcode_active:n { `\~ } + \cs_new_protected:Npx \@@_format_literal:n #1 + { + \group_begin: + \exp_not:n { \bool_set_false:N \l_@@_parsing_bool } + \tl_set:Nn \exp_not:N \l_@@_tmp_tl {#1} + \tl_replace_all:Nnn \exp_not:N \l_@@_tmp_tl + { \token_to_str:N ^ } { ^ } + \tl_replace_all:Nnn \exp_not:N \l_@@_tmp_tl + { \token_to_str:N _ } { \c_@@_math_subscript_tl } + \char_set_active_eq:NN ^ + \exp_not:N \@@_format_literal_superscript: + \char_set_active_eq:NN _ + \exp_not:N \@@_format_literal_subscript: + \char_set_active_eq:NN \exp_not:N ~ + \exp_not:N \@@_format_literal_tilde: + \exp_not:n + { + \protected@edef \l_@@_tmp_tl + { \l_@@_tmp_tl } + \tl_clear:N \l_@@_formatted_tl + \tl_if_empty:NF \l_@@_tmp_tl + { + \exp_after:wN \@@_format_literal_auxi:w + \l_@@_tmp_tl . + \q_recursion_tail . \q_recursion_stop + } + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_formatted_tl + \l_@@_formatted_tl + } + } +\group_end: +\cs_new:Npx \@@_format_literal_subscript: { \c_@@_math_subscript_tl } +\cs_new:Npn \@@_format_literal_superscript: { ^ } +\cs_new:Npn \@@_format_literal_tilde: { . } +% \end{macrocode} +% To introduce the font changing commands while still allowing for line +% breaks in literal units, a loop is needed to replace one |.| at a time. +% To also allow for division, a second loop is used within that to handle +% |/|: as a result, the separator between parts has to be tracked. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_literal_auxi:w #1 . + { + \quark_if_recursion_tail_stop:n {#1} + \@@_format_literal_auxii:n {#1} + \tl_set_eq:NN \l_@@_separator_tl \l_@@_product_tl + \@@_format_literal_auxi:w + } +\cs_set_protected:Npn \@@_format_literal_auxii:n #1 + { + \@@_format_literal_auxiii:w + #1 / \q_recursion_tail / \q_recursion_stop + } +\cs_new_protected:Npn \@@_format_literal_auxiii:w #1 / + { + \quark_if_recursion_tail_stop:n {#1} + \@@_format_literal_auxiv:w #1 ^ ^ \q_stop + \tl_set:Nn \l_@@_separator_tl { / } + \@@_format_literal_auxiii:w + } +% \end{macrocode} +% Within each unit any sub- and superscript parts need to be separated out: +% wrapping everything in the font command is incorrect. The superscript part +% is relatively easy as there is no catcode issue or font command to add, +% while the subscript part needs a bit more work. As the user might have the +% two parts in either order, picking up the subscript needs to look in two +% places. We assume that only one is given: odd input here is simply accepted. +% \begin{macrocode} +\use:x + { + \cs_new_protected:Npn \exp_not:N \@@_format_literal_auxiv:w + ##1 ^ ##2 ^ ##3 \exp_not:N \q_stop + { + \exp_not:N \@@_format_literal_auxv:w + ##1 + \c_@@_math_subscript_tl + \c_@@_math_subscript_tl + \exp_not:N \q_mark + ##2 + \c_@@_math_subscript_tl + \c_@@_math_subscript_tl + \exp_not:N \q_stop + } + \cs_new_protected:Npn \exp_not:N \@@_format_literal_auxv:w + ##1 \c_@@_math_subscript_tl + ##2 \c_@@_math_subscript_tl ##3 + \exp_not:N \q_mark + ##4 \c_@@_math_subscript_tl + ##5 \c_@@_math_subscript_tl ##6 + \exp_not:N \q_stop + { + \tl_set:Nx \exp_not:N \l_@@_formatted_tl + { + \exp_not:N \exp_not:V + \exp_not:N \l_@@_formatted_tl + \exp_not:N \tl_if_empty:NF + \exp_not:N \l_@@_formatted_tl + { + \exp_not:N \exp_not:V + \exp_not:N \l_@@_separator_tl + } + \exp_not:N \tl_if_blank:nF {##1} + { + \exp_not:N \exp_not:V + \exp_not:N \l_siunitx_unit_font_tl + { \exp_not:N \exp_not:n {##1} } + } + \exp_not:N \tl_if_blank:nF {##4} + { ^ { \exp_not:N \exp_not:n {##4} } } + \exp_not:N \tl_if_blank:nF {##2##5} + { + \c_@@_math_subscript_tl + { + \exp_not:N \exp_not:V + \exp_not:N \l_siunitx_unit_font_tl + { \exp_not:N \exp_not:n {##2##5} } + } + } + } + } + } +\tl_new:N \l_@@_separator_tl +% \end{macrocode} +% \end{variable} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{(PDF) String creation} +% +% \begin{macro}{\siunitx_unit_pdfstring_context:} +% A simple function that sets up to make units equal to their text +% representation. +% \begin{macrocode} +\cs_new_protected:Npn \siunitx_unit_pdfstring_context: + { + \bool_set_false:N \l_@@_parsing_bool + \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq + { \cs_set_eq:Nc ##1 { @@_ \token_to_str:N ##1 :w } } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Parsing symbolic units} +% +% Parsing units takes place by storing information about each unit in a +% \texttt{prop}. As well as the unit itself, there are various other optional +% data points, for example a prefix or a power. Some of these can come before +% the unit, others only after. The parser therefore tracks the number of units +% read and uses the current position to allocate data to individual units. +% +% The result of parsing is a property list (\cs{l_@@_parsed_prop}) which +% contains one or more entries for each unit: +% \begin{itemize} +% \item \texttt{prefix-$n$} The symbol for the prefix which applies to this +% unit, \foreign{e.g.} for \cs{kilo} with (almost certainly) would be +% |k|. +% \item \texttt{unit-$n$} The symbol for the unit itself, \foreign{e.g.}~for +% \cs{metre} with (almost certainly) would be |m|. +% \item \texttt{power-$n$} The power which a unit is raised to. During +% initial parsing this will (almost certainly) be positive, but is combined +% with \texttt{per-$n$} to give a \enquote{fully qualified} power before +% any formatting takes place +% \item \texttt{per-$n$} Indicates that \texttt{per} applies to the current +% unit: stored during initial parsing then combined with \texttt{power-$n$} +% (and removed from the list) before further work. +% \item \texttt{qualifier-$n$} Any qualifier which applies to the current +% unit. +% \item \texttt{special-$n$} Any \enquote{special effect} to apply to the +% current unit. +% \item \texttt{command-$1$} The command corresponding to \texttt{unit-$n$}: +% needed to track base units; used for \cs{gram} only. +% \end{itemize} +% +% \begin{variable}{\l_@@_sticky_per_bool} +% There is one option when \emph{parsing} the input (as opposed to +% \emph{formatting} for output): how to deal with \cs{per}. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + sticky-per .bool_set:N = \l_@@_sticky_per_bool + } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_parsed_prop} +% \begin{variable}{\l_@@_per_bool} +% \begin{variable}{\l_@@_position_int} +% Parsing units requires a small number of variables are available: a +% \texttt{prop} for the parsed units themselves, a \texttt{bool} to +% indicate if \cs{per} is active and an \texttt{int} to track how many units +% have be parsed. +% \begin{macrocode} +\prop_new:N \l_@@_parsed_prop +\bool_new:N \l_@@_per_bool +\int_new:N \l_@@_position_int +% \end{macrocode} +% \end{variable} +% \end{variable} +% \end{variable} +% +% \begin{macro}{\@@_parse:n} +% The main parsing function is quite simple. After initialising the variables, +% each symbolic unit is set up. The input is then simply inserted into the +% input stream: the symbolic units themselves then do the real work of +% placing data into the parsing system. There is then a bit of tidying up to +% ensure that later stages can rely on the nature of the data here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse:n #1 + { + \prop_clear:N \l_@@_parsed_prop + \bool_set_true:N \l_@@_parsing_bool + \bool_set_false:N \l_@@_per_bool + \bool_set_false:N \l_@@_test_bool + \int_zero:N \l_@@_position_int + \siunitx_unit_options_apply:n {#1} + #1 + \int_step_inline:nn \l_@@_position_int + { \@@_parse_finalise:n {##1} } + \@@_parse_finalise: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_parse_add:nnnn} +% In all cases, storing a data item requires setting a temporary \texttt{tl} +% which will be used as the key, then using this to store the value. The +% \texttt{tl} is set using \texttt{x}-type expansion as this will expand the +% unit index and any additional calculations made for this. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_add:nnnn #1#2#3#4 + { + \tl_set:Nx \l_@@_tmp_tl { #1 - #2 } + \prop_if_in:NVTF \l_@@_parsed_prop + \l_@@_tmp_tl + { + \msg_error:nnxx { siunitx } { unit / duplicate-part } + { \exp_not:n {#1} } { \token_to_str:N #3 } + } + { + \prop_put:NVn \l_@@_parsed_prop + \l_@@_tmp_tl {#4} + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_parse_prefix:Nn} +% \begin{macro}{\@@_parse_power:nnN} +% \begin{macro}{\@@_parse_qualifier:nn} +% \begin{macro}{\@@_parse_special:n} +% Storage of the various optional items follows broadly the same pattern +% in each case. The data to be stored is passed along with an appropriate +% key name to the underlying storage system. The details for each type of +% item should be relatively clear. For example, prefixes have to come before +% their \enquote{parent} unit and so there is some adjustment to do to add +% them to the correct unit. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_prefix:Nn #1#2 + { + \int_set:Nn \l_@@_tmp_int { \l_@@_position_int + 1 } + \@@_parse_add:nnnn { prefix } + { \int_use:N \l_@@_tmp_int } {#1} {#2} + } +\cs_new_protected:Npn \@@_parse_power:nnN #1#2#3 + { + \tl_set:Nx \l_@@_tmp_tl + { unit- \int_use:N \l_@@_position_int } + \bool_lazy_or:nnTF + {#3} + { + \prop_if_in_p:NV + \l_@@_parsed_prop \l_@@_tmp_tl + } + { + \@@_parse_add:nnnn { power } + { + \int_eval:n + { \l_@@_position_int \bool_if:NT #3 { + 1 } } + } + {#1} {#2} + } + { + \msg_error:nnxx { siunitx } + { unit / part-before-unit } { power } { \token_to_str:N #1 } + } + } +\cs_new_protected:Npn \@@_parse_qualifier:nn #1#2 + { + \tl_set:Nx \l_@@_tmp_tl + { unit- \int_use:N \l_@@_position_int } + \prop_if_in:NVTF \l_@@_parsed_prop \l_@@_tmp_tl + { + \@@_parse_add:nnnn { qualifier } + { \int_use:N \l_@@_position_int } {#1} {#2} + } + { + \msg_error:nnnn { siunitx } + { unit / part-before-unit } { qualifier } { \token_to_str:N #1 } + } + } +% \end{macrocode} +% Special (exceptional) items should always come before the relevant units. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_special:n #1 + { + \@@_parse_add:nnnn { special } + { \int_eval:n { \l_@@_position_int + 1 } } + {#1} {#1} + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_parse_unit:Nn} +% Parsing units is slightly more involved than the other cases: this is the +% one place where the tracking value is incremented. If the switch +% \cs{l_@@_per_bool} is set true then the current unit is also +% reciprocal: this can only happen if \cs{l_@@_sticky_per_bool} is also +% true, so only one test is required. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_unit:Nn #1#2 + { + \int_incr:N \l_@@_position_int + \tl_if_eq:nnT {#1} { \gram } + { + \@@_parse_add:nnnn { command } + { \int_use:N \l_@@_position_int } + {#1} {#1} + } + \@@_parse_add:nnnn { unit } + { \int_use:N \l_@@_position_int } + {#1} {#2} + \bool_if:NT \l_@@_per_bool + { + \@@_parse_add:nnnn { per } + { \int_use:N \l_@@_position_int } + { \per } { true } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_parse_per:} +% Storing the \cs{per} command requires adding a data item separate from +% the power which applies: this makes later formatting much more +% straight-forward. This data could in principle be combined with the +% \texttt{power}, but depending on the output format required that may make +% life more complex. Thus this information is stored separately for later +% retrieval. If \cs{per} is set to be \enquote{sticky} then after parsing +% the first occurrence, any further uses are in error. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_per: + { + \bool_if:NTF \l_@@_sticky_per_bool + { + \bool_set_true:N \l_@@_per_bool + \cs_set_protected:Npn \per + { \msg_error:nn { siunitx } { unit / duplicate-sticky-per } } + } + { + \@@_parse_add:nnnn + { per } { \int_eval:n { \l_@@_position_int + 1 } } + { \per } { true } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_parse_finalise:n} +% If \cs{per} applies to the current unit, the power needs to be multiplied +% by $-1$. That is done using an \texttt{fp} operation so that non-integer +% powers are supported. The flag for \cs{per} is also removed as this means +% we don't have to check that the original power was positive. To be on +% the safe side, there is a check for a trivial power at this stage. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_finalise:n #1 + { + \tl_set:Nx \l_@@_tmp_tl { per- #1 } + \prop_if_in:NVT \l_@@_parsed_prop \l_@@_tmp_tl + { + \prop_remove:NV \l_@@_parsed_prop + \l_@@_tmp_tl + \tl_set:Nx \l_@@_tmp_tl { power- #1 } + \prop_get:NVNTF + \l_@@_parsed_prop + \l_@@_tmp_tl + \l_@@_part_tl + { + \tl_set:Nx \l_@@_part_tl + { \fp_eval:n { \l_@@_part_tl * -1 } } + \fp_compare:nNnTF \l_@@_part_tl = 1 + { + \prop_remove:NV \l_@@_parsed_prop + \l_@@_tmp_tl + } + { + \prop_put:NVV \l_@@_parsed_prop + \l_@@_tmp_tl \l_@@_part_tl + } + } + { + \prop_put:NVn \l_@@_parsed_prop + \l_@@_tmp_tl { -1 } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_parse_finalise:} +% The final task is to check that there is not a \enquote{dangling} power +% or prefix: these are added to the \enquote{next} unit so are easy to +% test for. +% \begin{macrocode} +\cs_new_protected:Npn \@@_parse_finalise: + { + \clist_map_inline:nn { per , power , prefix } + { + \tl_set:Nx \l_@@_tmp_tl + { ##1 - \int_eval:n { \l_@@_position_int + 1 } } + \prop_if_in:NVT \l_@@_parsed_prop \l_@@_tmp_tl + { \msg_error:nnn { siunitx } { unit / dangling-part } { ##1 } } + } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Formatting parsed units} +% +% \begin{variable} +% { +% \l_@@_denominator_bracket_bool , +% \l_@@_forbid_literal_bool , +% \l_@@_fraction_function_tl , +% \l_@@_parse_bool , +% \l_@@_per_symbol_tl , +% \l_@@_qualifier_mode_tl , +% \l_@@_qualifier_phrase_tl +% } +% Set up the options which apply to formatting. +% \begin{macrocode} +\keys_define:nn { siunitx } + { + bracket-unit-denominator .bool_set:N = + \l_@@_denominator_bracket_bool , + forbid-literal-units .bool_set:N = + \l_@@_forbid_literal_bool , + fraction-command .tl_set:N = + \l_@@_fraction_function_tl , + parse-units .bool_set:N = + \l_@@_parse_bool , + per-mode .choice: , + per-mode / fraction .code:n = + { + \bool_set_false:N \l_@@_autofrac_bool + \bool_set_false:N \l_@@_per_symbol_bool + \bool_set_true:N \l_@@_powers_positive_bool + \bool_set_true:N \l_@@_two_part_bool + } , + per-mode / power .code:n = + { + \bool_set_false:N \l_@@_autofrac_bool + \bool_set_false:N \l_@@_per_symbol_bool + \bool_set_false:N \l_@@_powers_positive_bool + \bool_set_false:N \l_@@_two_part_bool + } , + per-mode / power-positive-first .code:n = + { + \bool_set_false:N \l_@@_autofrac_bool + \bool_set_false:N \l_@@_per_symbol_bool + \bool_set_false:N \l_@@_powers_positive_bool + \bool_set_true:N \l_@@_two_part_bool + } , + per-mode / repeated-symbol .code:n = + { + \bool_set_false:N \l_@@_autofrac_bool + \bool_set_true:N \l_@@_per_symbol_bool + \bool_set_true:N \l_@@_powers_positive_bool + \bool_set_false:N \l_@@_two_part_bool + } , + per-mode / symbol .code:n = + { + \bool_set_false:N \l_@@_autofrac_bool + \bool_set_true:N \l_@@_per_symbol_bool + \bool_set_true:N \l_@@_powers_positive_bool + \bool_set_true:N \l_@@_two_part_bool + } , + per-mode / symbol-or-fraction .code:n = + { + \bool_set_true:N \l_@@_autofrac_bool + \bool_set_true:N \l_@@_per_symbol_bool + \bool_set_true:N \l_@@_powers_positive_bool + \bool_set_true:N \l_@@_two_part_bool + } , + per-symbol .tl_set:N = + \l_@@_per_symbol_tl , + qualifier-mode .choices:nn = + { bracket , combine , phrase , subscript } + { \tl_set_eq:NN \l_@@_qualifier_mode_tl \l_keys_choice_tl } , + qualifier-phrase .tl_set:N = + \l_@@_qualifier_phrase_tl + } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_bracket_bool} +% A flag to indicate that the unit currently under construction will require +% brackets if a power is added. +% \begin{macrocode} +\bool_new:N \l_@@_bracket_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_bracket_open_tl, \l_@@_bracket_close_tl} +% Abstracted out but currently purely internal. +% \begin{macrocode} +\tl_new:N \l_@@_bracket_open_tl +\tl_new:N \l_@@_bracket_close_tl +\tl_set:Nn \l_@@_bracket_open_tl { ( } +\tl_set:Nn \l_@@_bracket_close_tl { ) } +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_font_bool} +% A flag to control when font wrapping is applied to the output. +% \begin{macrocode} +\bool_new:N \l_@@_font_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable} +% { +% \l_@@_autofrac_bool , +% \l_@@_powers_positive_bool , +% \l_@@_per_symbol_bool , +% \l_@@_two_part_bool +% } +% Dealing with the various ways that reciprocal (\cs{per}) can be handled +% requires a few different switches. +% \begin{macrocode} +\bool_new:N \l_@@_autofrac_bool +\bool_new:N \l_@@_per_symbol_bool +\bool_new:N \l_@@_powers_positive_bool +\bool_new:N \l_@@_two_part_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_numerator_bool} +% Indicates that the current unit should go into the numerator when splitting +% into two parts (fractions or other \enquote{sorted} styles). +% \begin{macrocode} +\bool_new:N \l_@@_numerator_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_qualifier_mode_tl} +% For storing the text of options which are best handled by picking +% function names. +% \begin{macrocode} +\tl_new:N \l_@@_qualifier_mode_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_combine_exp_fp} +% For combining an exponent with the first unit. +% \begin{macrocode} +\fp_new:N \l_@@_combine_exp_fp +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_prefix_exp_bool} +% Used to determine if prefixes are converted into powers. Note that +% while this may be set as an option \enquote{higher up}, at this point it +% is handled as an internal switch (see the two formatting interfaces for +% reasons). +% \begin{macrocode} +\bool_new:N \l_@@_prefix_exp_bool +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_prefix_fp} +% When converting prefixes to powers, the calculations are done as an +% \texttt{fp}. +% \begin{macrocode} +\fp_new:N \l_@@_prefix_fp +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_multiple_fp} +% For multiplying units. +% \begin{macrocode} +\fp_new:N \l_@@_multiple_fp +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_current_tl, \l_@@_part_tl} +% Building up the (partial) formatted unit requires some token list storage. +% Each part of the unit combination that is recovered also has to be +% placed in a token list: this is a dedicated one to leave the scratch +% variables available. +% \begin{macrocode} +\tl_new:N \l_@@_current_tl +\tl_new:N \l_@@_part_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_denominator_tl} +% For fraction-like units, space is needed for the denominator as well as +% the numerator (which is handled using \cs{l_@@_formatted_tl}). +% \begin{macrocode} +\tl_new:N \l_@@_denominator_tl +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_total_int} +% The formatting routine needs to know both the total number of units and +% the current unit. Thus an \texttt{int} is required in addition to +% \cs{l_@@_position_int}. +% \begin{macrocode} +\int_new:N \l_@@_total_int +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\@@_format_parsed:} +% \begin{macro}{\@@_format_parsed_aux:n} +% The main formatting routine is essentially a loop over each position, +% reading the various parts of the unit to build up complete unit +% combination. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_parsed: + { + \int_set_eq:NN \l_@@_total_int \l_@@_position_int + \tl_clear:N \l_@@_denominator_tl + \tl_clear:N \l_@@_formatted_tl + \fp_zero:N \l_@@_prefix_fp + \int_zero:N \l_@@_position_int + \fp_compare:nNnF \l_@@_combine_exp_fp = \c_zero_fp + { \@@_format_combine_exp: } + \fp_compare:nNnF \l_@@_multiple_fp = \c_one_fp + { \@@_format_multiply: } + \bool_lazy_and:nnT + { \l_@@_prefix_exp_bool } + { \l_@@_mass_kilogram_bool } + { \@@_format_mass_to_kilogram: } + \int_do_while:nNnn + \l_@@_position_int < \l_@@_total_int + { + \bool_set_false:N \l_@@_bracket_bool + \tl_clear:N \l_@@_current_tl + \bool_set_false:N \l_@@_font_bool + \bool_set_true:N \l_@@_numerator_bool + \int_incr:N \l_@@_position_int + \clist_map_inline:nn { prefix , unit , qualifier , power , special } + { \@@_format_parsed_aux:n {##1} } + \@@_format_output: + } + \@@_format_finalise: + } +\cs_new_protected:Npn \@@_format_parsed_aux:n #1 + { + \tl_set:Nx \l_@@_tmp_tl + { #1 - \int_use:N \l_@@_position_int } + \prop_get:NVNT \l_@@_parsed_prop + \l_@@_tmp_tl \l_@@_part_tl + { \use:c { @@_format_ #1 : } } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_format_combine_exp:} +% To combine an exponent into the first prefix, we first adjust for any +% power, then deal with any existing prefix, before looking up the +% final result. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_combine_exp: + { + \prop_get:NnNF \l_@@_parsed_prop { power-1 } \l_@@_tmp_tl + { \tl_set:Nn \l_@@_tmp_tl { 1 } } + \fp_set:Nn \l_@@_tmp_fp + { \l_@@_combine_exp_fp / \l_@@_tmp_tl } + \prop_get:NnNTF \l_@@_parsed_prop { prefix-1 } \l_@@_tmp_tl + { + \prop_get:NVNF \l_@@_prefixes_forward_prop + \l_@@_tmp_tl \l_@@_tmp_tl + { + \prop_get:NnN \l_@@_parsed_prop { prefix-1 } \l_@@_tmp_tl + \msg_error:nnx { siunitx } { unit / non-numeric-exponent } + { \l_@@_tmp_tl } + \tl_set:Nn \l_@@_tmp_tl { 0 } + } + } + { \tl_set:Nn \l_@@_tmp_tl { 0 } } + \tl_set:Nx \l_@@_tmp_tl + { \fp_eval:n { \l_@@_tmp_fp + \l_@@_tmp_tl } } + \fp_compare:nNnTF \l_@@_tmp_tl = \c_zero_fp + { \prop_remove:Nn \l_@@_parsed_prop { prefix-1 } } + { + \prop_get:NVNTF \l_@@_prefixes_reverse_prop + \l_@@_tmp_tl \l_@@_tmp_tl + { \prop_put:NnV \l_@@_parsed_prop { prefix-1 } \l_@@_tmp_tl } + { + \msg_error:nnx { siunitx } { unit / non-convertible-exponent } + { \l_@@_tmp_tl } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_format_multiply:} +% A simple mapping. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_multiply: + { + \int_step_inline:nn { \prop_count:N \l_@@_parsed_prop } + { + \prop_get:NnNF \l_@@_parsed_prop { power- ##1 } \l_@@_tmp_tl + { \tl_set:Nn \l_@@_tmp_tl { 1 } } + \fp_set:Nn \l_@@_tmp_fp + { \l_@@_tmp_tl * \l_@@_multiple_fp } + \fp_compare:nNnTF \l_@@_tmp_fp = \c_one_fp + { \prop_remove:N \l_@@_parsed_prop { power- ##1 } } + { + \prop_put:Nnx \l_@@_parsed_prop { power- ##1 } + { \fp_use:N \l_@@_tmp_fp } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_format_mass_to_kilogram:} +% To deal correctly with prefix extraction in combination with kilograms, we +% need to coerce the prefix for grams. Currently, only this one special case +% is recorded in the property list, so we do not actually need to check the +% value. If there is then no prefix we do a bit of gymnastics to create one +% and then shift the starting point for the prefix extraction. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_mass_to_kilogram: + { + \int_step_inline:nn \l_@@_total_int + { + \prop_if_in:NnT \l_@@_parsed_prop { command- ##1 } + { + \prop_if_in:NnF \l_@@_parsed_prop { prefix- ##1 } + { + \group_begin: + \bool_set_false:N \l_@@_parsing_bool + \tl_set:Nx \l_@@_tmp_tl { \kilo } + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_tmp_tl \l_@@_tmp_tl + \prop_put:NnV \l_@@_parsed_prop { prefix- ##1 } + \l_@@_tmp_tl + \prop_get:NnNF \l_@@_parsed_prop { power- ##1 } + \l_@@_tmp_tl + { \tl_set:Nn \l_@@_tmp_tl { 1 } } + \fp_set:Nn \l_@@_prefix_fp + { \l_@@_prefix_fp - 3 * \l_@@_tmp_tl } + } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[EXP]{\@@_format_bracket:N} +% A quick utility function which wraps up a token list variable in brackets +% if they are required. +% \begin{macrocode} +\cs_new:Npn \@@_format_bracket:N #1 + { + \bool_if:NTF \l_@@_bracket_bool + { + \exp_not:V \l_@@_bracket_open_tl + \exp_not:V #1 + \exp_not:V \l_@@_bracket_close_tl + } + { \exp_not:V #1 } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_format_power:} +% \begin{macro}[EXP]{\@@_format_power_aux:wTF} +% \begin{macro} +% { +% \@@_format_power_positive: , +% \@@_format_power_negative: +% } +% \begin{macro}[EXP]{\@@_format_power_negative_aux:w} +% \begin{macro}{\@@_format_power_superscript:} +% Formatting powers requires a test for negative numbers and depending on +% output format requests some adjustment to the stored value. This could be +% done using an \texttt{fp} function, but that would be slow compared to +% a dedicated if lower-level approach based on delimited arguments. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_power: + { + \@@_format_font: + \exp_after:wN \@@_format_power_aux:wTF + \l_@@_part_tl - \q_stop + { \@@_format_power_negative: } + { \@@_format_power_positive: } + } +\cs_new:Npn \@@_format_power_aux:wTF #1 - #2 \q_stop + { \tl_if_empty:nTF {#1} } +% \end{macrocode} +% In the case of positive powers, there is little to do: add the power +% as a subscript (must be required as the parser ensures it's $\neq 1$). +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_power_positive: + { \@@_format_power_superscript: } +% \end{macrocode} +% Dealing with negative powers starts by flipping the switch used to track +% where in the final output the current part should get added to. For the +% case where the output is fraction-like, strip off the |~| then ensure that +% the result is not the trivial power~$1$. Assuming all is well, addition +% to the current unit combination goes ahead. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_power_negative: + { + \bool_set_false:N \l_@@_numerator_bool + \bool_if:NTF \l_@@_powers_positive_bool + { + \tl_set:Nx \l_@@_part_tl + { + \exp_after:wN \@@_format_power_negative_aux:w + \l_@@_part_tl \q_stop + } + \str_if_eq:VnF \l_@@_part_tl { 1 } + { \@@_format_power_superscript: } + } + { \@@_format_power_superscript: } + } +\cs_new:Npn \@@_format_power_negative_aux:w - #1 \q_stop + { \exp_not:n {#1} } +% \end{macrocode} +% Adding the power as a superscript has the slight complication that there +% is the possibility of needing some brackets. The superscript itself uses +% \cs{sp} as that avoids any category code issues and also allows redirection +% at a higher level more readily. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_power_superscript: + { + \exp_after:wN \@@_format_power_superscipt:w + \l_@@_part_tl . . \q_stop + } +\cs_new_protected:Npn \@@_format_power_superscipt:w #1 . #2 . #3 \q_stop + { + \tl_if_blank:nTF {#2} + { + \tl_set:Nx \l_@@_current_tl + { + \@@_format_bracket:N \l_@@_current_tl + ^ { \exp_not:n {#1} } + } + } + { + \tl_set:Nx \l_@@_tmp_tl + { + { } + \tl_if_head_eq_charcode:nNTF {#1} - + { { - } { \exp_not:o { \use_none:n #1 } } } + { { } { \exp_not:n {#1} } } + {#2} + { } + { } + { 0 } + } + \tl_set:Nx \l_@@_current_tl + { + \@@_format_bracket:N \l_@@_current_tl + ^ { \siunitx_number_output:N \l_@@_tmp_tl } + } + } + \bool_set_false:N \l_@@_bracket_bool + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_format_prefix:} +% \begin{macro} +% { +% \@@_format_prefix_exp: , +% \@@_format_prefix_gram: , +% \@@_format_prefix_symbol: +% } +% Formatting for prefixes depends on whether they are to be expressed as +% symbols or collected up to be returned as a power of $10$. The latter +% case requires a bit of processing, which includes checking that the +% conversion is possible and allowing for any power that applies to the +% current unit. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_prefix: + { + \bool_if:NTF \l_@@_prefix_exp_bool + { \@@_format_prefix_exp: } + { \@@_format_prefix_symbol: } + } +\cs_new_protected:Npn \@@_format_prefix_exp: + { + \prop_get:NVNTF \l_@@_prefixes_forward_prop + \l_@@_part_tl \l_@@_part_tl + { + \bool_if:NT \l_@@_mass_kilogram_bool + { + \tl_set:Nx \l_@@_tmp_tl + { command- \int_use:N \l_@@_position_int } + \prop_if_in:NVT \l_@@_parsed_prop \l_@@_tmp_tl + { \@@_format_prefix_gram: } + } + \tl_set:Nx \l_@@_tmp_tl + { power- \int_use:N \l_@@_position_int } + \prop_get:NVNF \l_@@_parsed_prop + \l_@@_tmp_tl \l_@@_tmp_tl + { \tl_set:Nn \l_@@_tmp_tl { 1 } } + \fp_add:Nn \l_@@_prefix_fp + { \l_@@_tmp_tl * \l_@@_part_tl } + } + { \@@_format_prefix_symbol: } + } +% \end{macrocode} +% When the units in use are grams, we may need to deal with conversion to +% kilograms. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_prefix_gram: + { + \tl_set:Nx \l_@@_part_tl + { \int_eval:n { \l_@@_part_tl - 3 } } + \group_begin: + \bool_set_false:N \l_@@_parsing_bool + \tl_set:Nx \l_@@_current_tl { \kilo } + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_current_tl \l_@@_current_tl + } +\cs_new_protected:Npn \@@_format_prefix_symbol: + { \tl_set_eq:NN \l_@@_current_tl \l_@@_part_tl } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_format_qualifier:} +% \begin{macro} +% { +% \@@_format_qualifier_bracket: , +% \@@_format_qualifier_combine: , +% \@@_format_qualifier_phrase: , +% \@@_format_qualifier_subscript: +% } +% There are various ways that a qualifier can be added to the output. The +% idea here is to modify the \enquote{base} text appropriately and then add +% to the current unit. Notice that when the qualifier is just treated as +% \enquote{text}, the auxiliary is actually a no-op. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_qualifier: + { + \use:c + { + @@_format_qualifier_ + \l_@@_qualifier_mode_tl : + } + \tl_put_right:NV \l_@@_current_tl \l_@@_part_tl + } +\cs_new_protected:Npn \@@_format_qualifier_bracket: + { + \@@_format_font: + \tl_set:Nx \l_@@_part_tl + { + \exp_not:V \l_@@_bracket_open_tl + \exp_not:V \l_siunitx_unit_font_tl + { \exp_not:V \l_@@_part_tl } + \exp_not:V \l_@@_bracket_close_tl + } + } +\cs_new_protected:Npn \@@_format_qualifier_combine: { } +\cs_new_protected:Npn \@@_format_qualifier_phrase: + { + \@@_format_font: + \tl_set:Nx \l_@@_part_tl + { + \exp_not:V \l_@@_qualifier_phrase_tl + \exp_not:V \l_siunitx_unit_font_tl + { \exp_not:V \l_@@_part_tl } + } + } +\cs_new_protected:Npn \@@_format_qualifier_subscript: + { + \@@_format_font: + \tl_set:Nx \l_@@_part_tl + { + \c_@@_math_subscript_tl + { + \exp_not:V \l_siunitx_unit_font_tl + { \exp_not:V \l_@@_part_tl } + } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_format_special:} +% Any special odds and ends are handled by simply making the current +% combination into an argument for the recovered code. Font control +% needs to be \emph{inside} the special formatting here. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_special: + { + \tl_set:Nx \l_@@_current_tl + { + \exp_not:V \l_@@_part_tl + { + \bool_if:NTF \l_@@_font_bool + { \use:n } + { \exp_not:V \l_siunitx_unit_font_tl } + { \exp_not:V \l_@@_current_tl } + } + } + \bool_set_true:N \l_@@_font_bool + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_format_unit:} +% A very simple task: add the unit to the output currently being +% constructed. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_unit: + { + \tl_put_right:NV + \l_@@_current_tl \l_@@_part_tl + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_format_output:} +% \begin{macro} +% {\@@_format_output_aux:, \@@_format_output_denominator:} +% \begin{macro} +% { +% \@@_format_output_aux:nn , +% \@@_format_output_aux:nV , +% \@@_format_output_aux:nv +% } +% The first step here is to make a choice based on whether the current +% part should be stored as part of the numerator or denominator of a +% fraction. In all cases, if the switch \cs{l_@@_numerator_bool} is +% true then life is simple: add the current part to the numerator with +% a standard separator +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_output: + { + \@@_format_font: + \bool_set_false:N \l_@@_bracket_bool + \use:c + { + @@_format_output_ + \bool_if:NTF \l_@@_numerator_bool + { aux: } + { denominator: } + } + } +\cs_new_protected:Npn \@@_format_output_aux: + { + \@@_format_output_aux:nV { formatted } + \l_@@_product_tl + } +% \end{macrocode} +% There are a few things to worry about at this stage if the current part +% is in the denominator. Powers have already been dealt with and some +% formatting outcomes only need a branch at the final point of building +% the entire unit. That means that there are three possible outcomes here: +% if collecting two separate parts, add to the denominator with a product +% separator, or if only building one token list there may be a need to use +% a symbol separator. When the |repeated-symbol| option is in use there may +% be a need to add a leading |1| to the output in the case where the +% first unit is in the denominator: that can be picked up by looking for +% empty output in combination with the flag for using a symbol in the output +% but not a two-part strategy. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_output_denominator: + { + \bool_if:NTF \l_@@_two_part_bool + { + \bool_lazy_and:nnT + { \l_@@_denominator_bracket_bool } + { ! \tl_if_empty_p:N \l_@@_denominator_tl } + { \bool_set_true:N \l_@@_bracket_bool } + \@@_format_output_aux:nV { denominator } + \l_@@_product_tl + } + { + \bool_lazy_and:nnT + { \l_@@_per_symbol_bool } + { \tl_if_empty_p:N \l_@@_formatted_tl } + { \tl_set:Nn \l_@@_formatted_tl { 1 } } + \@@_format_output_aux:nv { formatted } + { + l_@@_ + \bool_if:NTF \l_@@_per_symbol_bool + { per_symbol } + { product } + _tl + } + } + } +\cs_new_protected:Npn \@@_format_output_aux:nn #1#2 + { + \tl_set:cx { l_@@_ #1 _tl } + { + \exp_not:v { l_@@_ #1 _tl } + \tl_if_empty:cF { l_@@_ #1 _tl } + { \exp_not:n {#2} } + \exp_not:V \l_@@_current_tl + } + } +\cs_generate_variant:Nn \@@_format_output_aux:nn { nV , nv } +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@@_format_font:} +% A short auxiliary which checks if the font has been applied to the +% main part of the output: if not, add it and set the flag. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_font: + { + \bool_if:NF \l_@@_font_bool + { + \tl_set:Nx \l_@@_current_tl + { + \exp_not:V \l_siunitx_unit_font_tl + { \exp_not:V \l_@@_current_tl } + } + \bool_set_true:N \l_@@_font_bool + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_format_finalise:} +% \begin{macro} +% { +% \@@_format_finalise_autofrac: , +% \@@_format_finalise_fractional: , +% \@@_format_finalise_power: +% } +% Finalising the unit format is really about picking up the cases involving +% fractions: these require assembly of the parts with the need to add +% additional material in some cases +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_finalise: + { + \tl_if_empty:NF \l_@@_denominator_tl + { + \bool_if:NTF \l_@@_powers_positive_bool + { \@@_format_finalise_fractional: } + { \@@_format_finalise_power: } + } + } +% \end{macrocode} +% For fraction-like output, there are three possible choices and two +% actual styles. In all cases, if the numerator is empty then it is set +% here to |1|. To deal with the \enquote{auto-format} case, the two +% styles (fraction and symbol) are handled in auxiliaries: this allows both +% to be used at the same time! Beyond that, the key here is to use a +% single \cs{tl_set:Nx} to keep down the number of assignments. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_finalise_fractional: + { + \tl_if_empty:NT \l_@@_formatted_tl + { \tl_set:Nn \l_@@_formatted_tl { 1 } } + \bool_if:NTF \l_@@_autofrac_bool + { \@@_format_finalise_autofrac: } + { + \bool_if:NTF \l_@@_per_symbol_bool + { \@@_format_finalise_symbol: } + { \@@_format_finalise_fraction: } + } + } +% \end{macrocode} +% For the \enquote{auto-selected} fraction method, the two other auxiliary +% functions are used to do both forms of formatting. So that everything +% required is available, this needs one group so that the second auxiliary +% receives the correct input. After that it is just a case of applying +% \cs{mathchoice} to the formatted output. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_finalise_autofrac: + { + \group_begin: + \@@_format_finalise_fraction: + \exp_args:NNNV \group_end: + \tl_set:Nn \l_@@_tmp_tl \l_@@_formatted_tl + \@@_format_finalise_symbol: + \tl_set:Nx \l_@@_formatted_tl + { + \mathchoice + { \exp_not:V \l_@@_tmp_tl } + { \exp_not:V \l_@@_formatted_tl } + { \exp_not:V \l_@@_formatted_tl } + { \exp_not:V \l_@@_formatted_tl } + } + } +% \end{macrocode} +% When using a fraction function the two parts are now assembled. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_finalise_fraction: + { + \tl_set:Nx \l_@@_formatted_tl + { + \exp_not:V \l_@@_fraction_function_tl + { \exp_not:V \l_@@_formatted_tl } + { \exp_not:V \l_@@_denominator_tl } + } + } +\cs_new_protected:Npn \@@_format_finalise_symbol: + { + \tl_set:Nx \l_@@_formatted_tl + { + \exp_not:V \l_@@_formatted_tl + \exp_not:V \l_@@_per_symbol_tl + \@@_format_bracket:N \l_@@_denominator_tl + } + } +% \end{macrocode} +% In the case of sorted powers, there is a test to make sure there was +% at least one positive power, and if so a simple join of the two parts +% with the appropriate product. +% \begin{macrocode} +\cs_new_protected:Npn \@@_format_finalise_power: + { + \tl_if_empty:NTF \l_@@_formatted_tl + { + \tl_set_eq:NN + \l_@@_formatted_tl + \l_@@_denominator_tl + } + { + \tl_set:Nx \l_@@_formatted_tl + { + \exp_not:V \l_@@_formatted_tl + \exp_not:V \l_@@_product_tl + \exp_not:V \l_@@_denominator_tl + } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Non-Latin character support} +% +% \begin{macro}{\@@_non_latin:n} +% \begin{macro}{\@@_non_latin:nnnn} +% A small amount of code to make it convenient to include non-Latin +% characters in units without having to directly include them in the +% sources directly. +% \begin{macrocode} +\bool_lazy_or:nnTF + { \sys_if_engine_luatex_p: } + { \sys_if_engine_xetex_p: } + { + \cs_new:Npn \@@_non_latin:n #1 + { \char_generate:nn {#1} { \char_value_catcode:n {#1} } } + } + { + \cs_new:Npn \@@_non_latin:n #1 + { + \exp_last_unbraced:Nf \@@_non_latin:nnnn + { \char_to_utfviii_bytes:n {#1} } + } + \cs_new:Npn \@@_non_latin:nnnn #1#2#3#4 + { + \exp_after:wN \exp_after:wN \exp_after:wN + \exp_not:N \char_generate:nn {#1} { 13 } + \exp_after:wN \exp_after:wN \exp_after:wN + \exp_not:N \char_generate:nn {#2} { 13 } + } + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Pre-defined unit components} +% +% Quite a number of units can be predefined: while this is a code-level module, +% there is little point having a unit parser which does not start off able to +% parse any units! +% +% \begin{macro} +% { +% \kilogram , +% \metre , +% \meter , +% \mole , +% \kelvin , +% \candela , +% \second , +% \ampere +% } +% The basic \acro{SI} units: technically the correct spelling is \cs{metre} +% but US users tend to use \cs{meter}. +% \begin{macrocode} +\siunitx_declare_unit:Nn \kilogram { \kilo \gram } +\siunitx_declare_unit:Nn \metre { m } +\siunitx_declare_unit:Nn \meter { \metre } +\siunitx_declare_unit:Nn \mole { mol } +\siunitx_declare_unit:Nn \second { s } +\siunitx_declare_unit:Nn \ampere { A } +\siunitx_declare_unit:Nn \kelvin { K } +\siunitx_declare_unit:Nn \candela { cd } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\gram} +% The gram is an odd unit as it is needed for the base unit kilogram. +% \begin{macrocode} +\siunitx_declare_unit:Nn \gram { g } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \yocto , +% \zepto , +% \atto , +% \femto , +% \pico , +% \nano , +% \micro , +% \milli , +% \centi , +% \deci +% } +% The various \acro{SI} multiple prefixes are defined here: first the small +% ones. +% \begin{macrocode} +\siunitx_declare_prefix:Nnn \yocto { -24 } { y } +\siunitx_declare_prefix:Nnn \zepto { -21 } { z } +\siunitx_declare_prefix:Nnn \atto { -18 } { a } +\siunitx_declare_prefix:Nnn \femto { -15 } { f } +\siunitx_declare_prefix:Nnn \pico { -12 } { p } +\siunitx_declare_prefix:Nnn \nano { -9 } { n } +\siunitx_declare_prefix:Nnx \micro { -6 } { \@@_non_latin:n { "03BC } } +\siunitx_declare_prefix:Nnn \milli { -3 } { m } +\siunitx_declare_prefix:Nnn \centi { -2 } { c } +\siunitx_declare_prefix:Nnn \deci { -1 } { d } +% \end{macrocode} +% \end{macro} +% \begin{macro} +% { +% \deca , +% \deka , +% \hecto , +% \kilo , +% \mega , +% \giga , +% \tera , +% \peta , +% \exa , +% \zetta , +% \yotta +% } +% Now the large ones. +% \begin{macrocode} +\siunitx_declare_prefix:Nnn \deca { 1 } { da } +\siunitx_declare_prefix:Nnn \deka { 1 } { da } +\siunitx_declare_prefix:Nnn \hecto { 2 } { h } +\siunitx_declare_prefix:Nnn \kilo { 3 } { k } +\siunitx_declare_prefix:Nnn \mega { 6 } { M } +\siunitx_declare_prefix:Nnn \giga { 9 } { G } +\siunitx_declare_prefix:Nnn \tera { 12 } { T } +\siunitx_declare_prefix:Nnn \peta { 15 } { P } +\siunitx_declare_prefix:Nnn \exa { 18 } { E } +\siunitx_declare_prefix:Nnn \zetta { 21 } { Z } +\siunitx_declare_prefix:Nnn \yotta { 24 } { Y } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \becquerel , +% \degreeCelsius , +% \coulomb , +% \farad , +% \gray , +% \hertz , +% \henry , +% \joule , +% \katal , +% \lumen , +% \lux +% } +% Named derived units: first half of alphabet. +% \begin{macrocode} +\siunitx_declare_unit:Nn \becquerel { Bq } +\siunitx_declare_unit:Nx \degreeCelsius { \@@_non_latin:n { "00B0 } C } +\siunitx_declare_unit:Nn \coulomb { C } +\siunitx_declare_unit:Nn \farad { F } +\siunitx_declare_unit:Nn \gray { Gy } +\siunitx_declare_unit:Nn \hertz { Hz } +\siunitx_declare_unit:Nn \henry { H } +\siunitx_declare_unit:Nn \joule { J } +\siunitx_declare_unit:Nn \katal { kat } +\siunitx_declare_unit:Nn \lumen { lm } +\siunitx_declare_unit:Nn \lux { lx } +% \end{macrocode} +% \end{macro} +% \begin{macro} +% { +% \newton , +% \ohm , +% \pascal , +% \radian , +% \siemens , +% \sievert , +% \steradian , +% \tesla , +% \volt , +% \watt , +% \weber +% } +% Named derived units: second half of alphabet. +% \begin{macrocode} +\siunitx_declare_unit:Nn \newton { N } +\siunitx_declare_unit:Nx \ohm { \@@_non_latin:n { "03A9 } } +\siunitx_declare_unit:Nn \pascal { Pa } +\siunitx_declare_unit:Nn \radian { rad } +\siunitx_declare_unit:Nn \siemens { S } +\siunitx_declare_unit:Nn \sievert { Sv } +\siunitx_declare_unit:Nn \steradian { sr } +\siunitx_declare_unit:Nn \tesla { T } +\siunitx_declare_unit:Nn \volt { V } +\siunitx_declare_unit:Nn \watt { W } +\siunitx_declare_unit:Nn \weber { Wb } +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \astronomicalunit , +% \bel , +% \dalton , +% \day , +% \decibel , +% \electronvolt , +% \hectare , +% \hour , +% \litre , +% \liter , +% \minute , +% \neper , +% \tonne +% } +% Non-\acro{SI}, but accepted for general use. Once again there are two +% spellings, here for litre and with different output in this case. +% \begin{macrocode} +\siunitx_declare_unit:Nn \astronomicalunit { au } +\siunitx_declare_unit:Nn \bel { B } +\siunitx_declare_unit:Nn \decibel { \deci \bel } +\siunitx_declare_unit:Nn \dalton { Da } +\siunitx_declare_unit:Nn \day { d } +\siunitx_declare_unit:Nn \electronvolt { eV } +\siunitx_declare_unit:Nn \hectare { ha } +\siunitx_declare_unit:Nn \hour { h } +\siunitx_declare_unit:Nn \litre { L } +\siunitx_declare_unit:Nn \liter { \litre } +\siunitx_declare_unit:Nn \minute { min } +\siunitx_declare_unit:Nn \neper { Np } +\siunitx_declare_unit:Nn \tonne { t } +% \end{macrocode} +% \end{macro} +% \begin{macro} +% { +% \arcminute , +% \arcsecond , +% \degree +% } +% Arc units: again, non-\acro{SI}, but accepted for general use. +% \begin{macrocode} +\siunitx_declare_unit:Nx \arcminute { \@@_non_latin:n { "02B9 } } +\siunitx_declare_unit:Nx \arcsecond { \@@_non_latin:n { "02BA } } +\siunitx_declare_unit:Nx \degree { \@@_non_latin:n { "00B0 } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\percent} +% For percent, the raw character is the most flexible way of handling output. +% \begin{macrocode} +\siunitx_declare_unit:Nx \percent { \cs_to_str:N \% } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\square, \squared, \cubic, \cubed} +% Basic powers. +% \begin{macrocode} +\siunitx_declare_power:NNn \square \squared { 2 } +\siunitx_declare_power:NNn \cubic \cubed { 3 } +% \end{macrocode} +% \end{macro} +% +% \subsection{Messages} +% +% \begin{macrocode} +\msg_new:nnnn { siunitx } { unit / dangling-part } + { Found~#1~part~with~no~unit. } + { + Each~#1~part~must~be~associated~with~a~unit:~a~#1~part~was~found~ + but~no~following~unit~was~given. + } +\msg_new:nnnn { siunitx } { unit / duplicate-part } + { Duplicate~#1~part:~#2. } + { + Each~unit~may~have~only~one~#1:\\ + the~additional~#1~part~'#2'~will~be~ignored. + } +\msg_new:nnnn { siunitx } { unit / duplicate-sticky-per } + { Duplicate~\token_to_str:N \per. } + { + When~the~'sticky-per'~option~is~active,~only~one~ + \token_to_str:N \per \ may~appear~in~a~unit. + } +\msg_new:nnnn { siunitx } { unit / literal } + { Literal~units~disabled. } + { + You~gave~the~literal~input~'#1'~ + but~literal~unit~output~is~disabled. + } +\msg_new:nnnn { siunitx } { unit / non-convertible-exponent } + { Exponent~'#1'~cannot~be~converted~into~a~symbolic~prefix. } + { + The~exponent~'#1'~does~not~match~with~any~of~the~symbolic~prefixes~ + set~up. + } +\msg_new:nnnn { siunitx } { unit / non-numeric-exponent } + { Prefix~'#1'~does~not~have~a~numerical~value. } + { + The~prefix~'#1'~needs~to~be~combined~with~a~number,~but~it~has~no + numerical~value. + } +\msg_new:nnnn { siunitx } { unit / part-before-unit } + { Found~#1~part~before~first~unit:~#2. } + { + The~#1~part~'#2'~must~follow~after~a~unit:~ + it~cannot~appear~before~any~units~and~will~therefore~be~ignored. + } +% \end{macrocode} +% +% \subsection{Standard settings for module options} +% +% Some of these follow naturally from the point of definition +% (\foreign{e.g.}~boolean variables are always |false| to begin with), +% but for clarity everything is set here. +% \begin{macrocode} +\keys_set:nn { siunitx } + { + bracket-unit-denominator = true , + forbid-literal-units = false , + fraction-command = \frac , + inter-unit-product = \, , + extract-mass-in-kilograms = true , + parse-units = true , + per-mode = power , + per-symbol = / , + qualifier-mode = subscript , + qualifier-phrase = , + sticky-per = false , + unit-font-command = \mathrm + } +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \begin{thebibliography}{1} +% \bibitem{BIPM} +% \emph{The International System of Units (\acro{SI})}, +% \url{https://www.bipm.org/en/measurement-units/}. +% \bibitem{base-units} +% \emph{SI base units}, +% \url{https://www.bipm.org/en/measurement-units/si-base-units}. +% \end{thebibliography} +% +% \PrintIndex diff --git a/macros/latex/contrib/siunitx/siunitx-v2.sty b/macros/latex/contrib/siunitx/siunitx-v2.sty new file mode 100644 index 0000000000..260971dfcb --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-v2.sty @@ -0,0 +1,7652 @@ +%% +%% This is file `siunitx-v2.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% siunitx-v2.dtx (with options: `package') +%% --------------------------------------------------------------- +%% The siunitx package --- A comprehensive (SI) units package +%% Maintained by Joseph Wright +%% E-mail: joseph.wright@morningstar2.co.uk +%% Released under the LaTeX Project Public License v1.3c or later +%% See http://www.latex-project.org/lppl.txt +%% --------------------------------------------------------------- +%% +\RequirePackage{expl3}[2020/01/12] +\RequirePackage{xparse} +\ProvidesExplPackage {siunitx} {2021-04-17} {2.8e} + {A comprehensive (SI) units package} +\@ifpackagelater { expl3 } { 2020/01/12 } + { } + { + \PackageError { siunitx } { Support~package~expl3~too~old } + { + You~need~to~update~your~installation~of~the~bundles~'l3kernel'~and~ + 'l3packages'.\MessageBreak + Loading~siunitx~will~abort! + } + \tex_endinput:D + } +\msg_new:nnnn { siunitx } { incompatible-package } + { Package~'#1'~incompatible. } + { The~#1~package~and~siunitx~are~incompatible. } +\cs_new_protected:Npn \__siunitx_load_check:n #1 { + \group_begin: + \@ifpackageloaded {#1} + { \msg_error:nnx { siunitx } { incompatible-package } {#1} } + { } + \group_end: +} +\clist_map_function:nN + { SIunits , sistyle , siunits , SIstyle , unitsdef , fancyunits } + \__siunitx_load_check:n +\AtBeginDocument { + \clist_map_function:nN { SIunits , sistyle , siunits , SIstyle } + \__siunitx_load_check:n +} +\RequirePackage{ amstext , array , l3keys2e } +\@ifl@t@r \fmtversion { 2020-10-01 } + { \cs_new_eq:NN \__siunitx_if_hooks:TF \use_i:nn } + { \cs_new_eq:NN \__siunitx_if_hooks:TF \use_ii:nn } +\cs_new:Npn \__siunitx_tmp:w { } +\cs_generate_variant:Nn \clist_map_function:nN { nc } +\cs_generate_variant:Nn \tl_if_blank:nTF { V } +\cs_generate_variant:Nn \tl_replace_all:Nnn { No, NV , Nx } +\bool_new:N \l__siunitx_tmp_bool +\box_new:N \l__siunitx_tmp_box +\dim_new:N \l__siunitx_tmp_dim +\int_new:N \l__siunitx_tmp_int +\tl_new:N \l__siunitx_tmpa_tl +\tl_new:N \l__siunitx_tmpb_tl +\cs_new_protected:Npn \__siunitx_error:nxx #1#2#3 { + \bool_set_true:N \l__siunitx_error_bool + \msg_error:nnxx { siunitx } {#1} {#2} {#3} +} +\cs_new_protected:Npn \__siunitx_error:nx #1#2 { + \__siunitx_error:nxx {#1} {#2} { } +} +\cs_new_protected:Npn \__siunitx_error:n #1 { + \__siunitx_error:nxx {#1} { } { } +} +\bool_new:N \l__siunitx_error_bool +\AtBeginDocument { + \cs_if_free:cT { T@TS1 } + { \RequirePackage { textcomp } } +} +\cs_new_protected:Npn \__siunitx_tl_put_left_math:Nn #1#2 + { \tl_put_left:Nn #1 { \ensuremath {#2} } } +\cs_generate_variant:Nn \__siunitx_tl_put_left_math:Nn { NV } +\exp_args:NNx \seq_const_from_clist:Nn \c__siunitx_old_options_seq + { + \tl_to_str:n + { + addsign , + allowlitunits , + allowoptarg , + allowzeroexp , + alsoload , + angformat , + anglesep , + astroang , + closeerr , + closrfrac , + closerange , + colour , + colorall , + colourall , + colorneg , + colourneg , + colourunits , + colourunits , + colorvalues , + colourvalues , + decimalsymbol , + debug , + detectdisplay , + digitsep , + dp , + emulate , + errspace , + eVcorra , + eVcorrb , + expbase , + expproduct , + fixdp , + fixsf , + fraction , + inlinebold , + loctolang , + log , + load , + mathOmega , + mathcelsius , + mathdegree , + mathminute , + mathmu , + mathringA , + mathrm , + mathsOmega , + mathscelsius , + mathsdegree , + mathsecond , + mathsf , + mathsminute , + mathsmu , + mathsringA , + mathsrm , + mathssecond , + mathssf , + mathstt , + mathtt , + negcolor , + negcolour , + noload , + numaddn , + numcloseerr , + numdecimal , + numdigits , + numdiv , + numexp , + numgobble , + numopenerr , + numprod , + numsign , + obeyall , + obeybold , + obeyfamily , + obeymode , + obeyitalic , + openerr , + openfrac , + openrange , + padangle , + padnumber , + per , + prefixbase , + prefixproduct , + prefixsymbolic , + prespace , + redefsymbols , + repeatunits , + retainplus , + seperr , + sepfour , + sf , + sign , + slash , + stickyper , + strictarc , + tabalign , + tabalignexp , + tabautofit , + tabexpalign , + tabformat , + tabnumalign , + tabparseonly , + tabtextalign , + textOmega , + textcelsius , + textdegree , + textminute , + textmode , + textmu , + textringA , + textrm , + textsecond , + textsf , + texttt , + tightpm , + tophrase , + trapamigerr , + trapambigfrac , + trapambigrange , + unitcolor , + unitcolour , + unitmathrm , + unitmathsf , + unitmathsrm , + unitmathssf , + unitmathstt , + unitmathtt , + unitmode , + unitsep , + unitspace , + valuecolor , + valuecolour , + valuemathrm , + valuemathsf , + valuemathsrm , + valuemathssf , + valuemathstt , + valuemathtt , + valuemode , + valuesep , + xspace + } + } +\tl_new:N \l__siunitx_key_tl +\keys_define:nn { siunitx } { + unknown .code:n = + { + \seq_if_in:NVTF \c__siunitx_old_options_seq \l_keys_key_tl + { + \msg_warning:nnx { siunitx } { version-1-option } + { \exp_not:V \l_keys_key_tl } + \tl_set:Nx \l__siunitx_key_tl + { + \keys_set:nn { siunitx } + { + \exp_not:V \l_keys_key_tl + \tl_if_blank:nF {#1} { = \exp_not:n {#1} } + } + } + \keys_set:nn { siunitx } { version-1-compatibility } + \tl_use:N \l__siunitx_key_tl + } + { + \msg_error:nnx { siunitx } { unknown-option } + { \exp_not:V \l_keys_key_tl } + } + } +} +\AtBeginDocument { + \keys_define:nn { siunitx } { + unknown .code:n = + { + \seq_if_in:NVTF \c__siunitx_old_options_seq \l_keys_key_tl + { + \msg_error:nnx { siunitx } { version-1-option } + { \exp_not:V \l_keys_key_tl } + } + { + \msg_error:nnx { siunitx } { unknown-option } + { \exp_not:V \l_keys_key_tl } + } + } +} +} +\cs_new_protected:Npn \__siunitx_option_deactivate:n #1 { + \clist_put_right:Nn \l__siunitx_option_deactivate_clist {#1} +} +\cs_new_protected:Npn \__siunitx_option_deactivate_aux:n #1 { + \keys_define:nn { siunitx } + { + #1 .code:n = + { \msg_warning:nnx { siunitx } { option-preamble-only } {#1} } + } +} +\AtBeginDocument { + \clist_map_function:NN \l__siunitx_option_deactivate_clist + \__siunitx_option_deactivate_aux:n +} +\clist_new:N \l__siunitx_option_deactivate_clist +\cs_new_protected:Npn \__siunitx_option_unchanged:Nnn #1#2#3 + { + \str_if_eq:VnT #1 {#2} + { \tl_set:Nn #1 {#3} } + } +\cs_generate_variant:Nn \tl_if_empty_p:n { f } +\cs_generate_variant:Nn \tl_if_empty:nT { f } +\cs_generate_variant:Nn \tl_if_in:NnTF { NV } +\cs_generate_variant:Nn \tl_replace_all:Nnn { NnV } +\prg_new_conditional:Npnn \__siunitx_cs_if_tl:N #1 { T, F , TF , p } + { + \bool_lazy_and:nnTF + { + \tl_if_empty_p:f + { + \cs_prefix_spec:N #1 + \cs_argument_spec:N #1 + } + } + { \bool_not_p:n { \cs_if_exist_p:c { \cs_to_str:N #1 ~ } } } + { \prg_return_true: } + { \prg_return_false: } + } +\prg_new_conditional:Npnn \__siunitx_number_if_zero:n #1 { p , TF } + { + \tl_map_function:nN {#1} \__siunitx_number_if_zero_aux:n + \prg_return_true: + } +\cs_generate_variant:Nn \__siunitx_number_if_zero_p:n { V } +\cs_new:Npn \__siunitx_number_if_zero_aux:n #1 + { + \token_if_eq_charcode:NNF #1 0 + { \tl_map_break:n { \prg_return_false: \use_none:n } } + } +\AtBeginDocument + { + \@ifpackageloaded { tex4ht } + { + \cs_set_eq:NN \__siunitx_print_text_super:n \textsuperscript + \__siunitx_option_unchanged:Nnn \l__siunitx_qualifier_mode_tl + { subscript } { brackets } + \keys_set:nn { siunitx } { mode = text } + } + { } + } +\cs_new_eq:NN \__siunitx_ensure_ltr:n \use:n +\AtBeginDocument + { + \@ifpackageloaded { bidi } + { + \sys_if_engine_xetex:T + { \cs_set_protected:Npn \__siunitx_ensure_ltr:n #1 { \LRE {#1} } } + } + { } + } +\cs_new_protected:Npn \__siunitx_textsuperscript:n #1 + { + \m@th + \ensuremath { ^ { \mbox { \fontsize \sf@size \z@ \selectfont #1 } } } + } +\bool_new:N \l__siunitx_display_math_bool +\tex_everydisplay:D \exp_after:wN + { + \tex_the:D \tex_everydisplay:D + \bool_set_true:N \l__siunitx_display_math_bool + } +\cs_generate_variant:Nn \prop_get:NnNT { NV } +\cs_generate_variant:Nn \prop_get:NnNF { NV } +\cs_generate_variant:Nn \prop_get:NnNTF { NV } +\cs_new_protected:Npn \__siunitx_set_math_fam:n #1 { + \group_begin: + \hbox_set:Nn \l__siunitx_tmp_box + { + \ensuremath + { + \use:c { math #1 } + { + \int_const:cn { c__siunitx_math #1 _int } { \fam } + } + } + } + \group_end: +} +\__siunitx_if_hooks:TF + { + \AddToHook { begindocument / end } [ siunitx ] + { + \__siunitx_set_math_fam:n { sf } + \__siunitx_set_math_fam:n { tt } + } + } + { + \tl_put_right:Nn \document + { + \__siunitx_set_math_fam:n { sf } + \__siunitx_set_math_fam:n { tt } + \ignorespaces + } + } +\cs_new_protected:Npn \__siunitx_set_text_fam:n #1 { + \tl_const:cx { c__siunitx_text #1 _tl } { \use:c { #1 default } } +} +\AtBeginDocument { + \__siunitx_set_text_fam:n { sf } + \__siunitx_set_text_fam:n { tt } +} +\tl_new:N \l__siunitx_detect_inline_weight_tl +\tl_new:N \l__siunitx_detect_inline_family_tl +\keys_define:nn { siunitx } { + detect-all .choice:, + detect-all .default:n = true, + detect-all / false .meta:n = + { + detect-family = false , + detect-mode = false , + detect-shape = false , + detect-weight = false , + }, + detect-all / true .meta:n = + { + detect-family = true , + detect-mode = true , + detect-shape = true , + detect-weight = true , + }, + detect-display-math .bool_set:N = + \l__siunitx_detect_display_math_bool, + detect-family .bool_set:N = \l__siunitx_detect_family_bool, + detect-inline-family .choice:, + detect-inline-family .value_required:n = true, + detect-inline-family / + math .code:n = + { \tl_set:Nn \l__siunitx_detect_inline_family_tl { math } }, + detect-inline-family / + text .code:n = + { \tl_set:Nn \l__siunitx_detect_inline_family_tl { text } }, + detect-inline-weight .choice:, + detect-inline-weight .value_required:n = true, + detect-inline-weight / + math .code:n = + { \tl_set:Nn \l__siunitx_detect_inline_weight_tl { math } }, + detect-inline-weight / + text .code:n = + { \tl_set:Nn \l__siunitx_detect_inline_weight_tl { text } }, + detect-italic .bool_set:N = \l__siunitx_detect_shape_bool, + detect-mode .bool_set:N = \l__siunitx_detect_mode_bool, + detect-none .choice:, + detect-none .default:n = true, + detect-none / false .meta:n = + { + detect-family = true, + detect-mode = true, + detect-shape = true, + detect-weight = true + }, + detect-none / true .meta:n = + { + detect-family = false, + detect-mode = false, + detect-shape = false, + detect-weight = false + }, + detect-shape .bool_set:N = \l__siunitx_detect_shape_bool, + detect-weight .bool_set:N = \l__siunitx_detect_weight_bool +} +\keys_set:nn { siunitx } { + detect-inline-family = text , + detect-inline-weight = text , +} +\bool_new:N \l__siunitx_font_set_bool +\bool_new:N \l__siunitx_font_math_mode_bool +\tl_new:N \l__siunitx_font_family_tl +\cs_new:Npn \__siunitx_font_shape: { } +\cs_new:Npn \__siunitx_font_weight: { } +\cs_new_protected:Npn \__siunitx_detect_font: { + \bool_if:NF \l__siunitx_font_set_bool + { + \__siunitx_detect_font_init: + \bool_if:NT \l__siunitx_detect_weight_bool + { \__siunitx_detect_font_weight: } + \bool_if:NT \l__siunitx_detect_family_bool + { \__siunitx_detect_font_family: } + \bool_if:NT \l__siunitx_detect_shape_bool + { \__siunitx_detect_font_shape: } + \bool_if:NT \l__siunitx_detect_mode_bool + { \__siunitx_detect_font_mode: } + } +} +\cs_new_protected:Npn \__siunitx_detect_font_init: { + \bool_set_true:N \l__siunitx_font_set_bool + \cs_set:Npn \__siunitx_font_weight: + { + \unboldmath + \mdseries + } + \cs_set:Npn \__siunitx_font_shape: { \upshape } + \tl_set:Nn \l__siunitx_font_family_tl { rm } + \bool_set_true:N \l__siunitx_font_math_mode_bool +} +\cs_new_protected:Npn \__siunitx_detect_font_weight: { + \mode_if_math:TF + { + \bool_if:NTF \l__siunitx_display_math_bool + { + \bool_if:NTF \l__siunitx_detect_display_math_bool + { \__siunitx_detect_font_weight_math: } + { \__siunitx_detect_font_weight_text: } + } + { + \use:c + { + __siunitx_detect_font_weight_ + \l__siunitx_detect_inline_weight_tl + : + } + } + } + { \__siunitx_detect_font_weight_text: } +} +\cs_new_protected:Npn \__siunitx_detect_font_weight_math: { + \str_if_eq:VnT \math@version { bold } + { + \cs_set:Npn \__siunitx_font_weight: + { + \boldmath + \bfseries + } + } + \str_if_eq:VnT \math@version { light } + { \cs_set:Npn \__siunitx_font_weight: { \lseries } } +} +\cs_new_protected:Npn \__siunitx_detect_font_weight_text: { + \tl_set:Nx \l__siunitx_tmpa_tl { \tl_head:N \f@series } + \str_if_eq:VnT \l__siunitx_tmpa_tl { b } + { + \cs_set:Npn \__siunitx_font_weight: + { + \boldmath + \bfseries + } + } + \str_if_eq:VnT \l__siunitx_tmpa_tl { l } + { \cs_set:Npn \__siunitx_font_weight: { \lseries } } +} +\cs_new_protected:Npn \__siunitx_detect_font_family: { + \mode_if_math:TF + { + \bool_if:NTF \l__siunitx_display_math_bool + { + \bool_if:NTF \l__siunitx_detect_display_math_bool + { \__siunitx_detect_font_family_math: } + { \__siunitx_detect_font_family_text: } + } + { + \use:c + { + __siunitx_detect_font_family_ + \l__siunitx_detect_inline_family_tl + : + } + } + } + { \__siunitx_detect_font_family_text: } +} +\cs_new_protected:Npn \__siunitx_detect_font_family_math: { + \tl_set:Nn \l__siunitx_font_family_tl { rm } + \int_compare:nNnT { \fam } = { \c__siunitx_mathsf_int } + { \tl_set:Nn \l__siunitx_font_family_tl { sf } } + \int_compare:nNnT { \fam } = { \c__siunitx_mathtt_int } + { \tl_set:Nn \l__siunitx_font_family_tl { tt } } +} +\cs_new_protected:Npn \__siunitx_detect_font_family_text: { + \tl_if_eq:NNT \f@family \c__siunitx_textsf_tl + { \tl_set:Nn \l__siunitx_font_family_tl { sf } } + \tl_if_eq:NNT \f@family \c__siunitx_texttt_tl + { \tl_set:Nn \l__siunitx_font_family_tl { tt } } +} +\cs_new_protected:Npn \__siunitx_detect_font_shape: + { + \cs_if_exist:cT { \f@shape shape } + { + \cs_set:Npx \__siunitx_font_shape: { \exp_not:c { \f@shape shape } } + } + } +\cs_new_protected:Npn \__siunitx_detect_font_mode: { + \mode_if_math:F + { + \bool_set_false:N \l__siunitx_font_math_mode_bool + \bool_set_false:N \l__siunitx_number_math_mode_bool + \bool_set_false:N \l__siunitx_unit_math_mode_bool + } +} +\bool_new:N \l__siunitx_number_math_mode_bool +\bool_new:N \l__siunitx_unit_math_mode_bool +\cs_new:Npn \__siunitx_number_mathrm:n #1 { } +\cs_new:Npn \__siunitx_number_mathsf:n #1 { } +\cs_new:Npn \__siunitx_number_mathtt:n #1 { } +\cs_new:Npn \__siunitx_number_textrm: { } +\cs_new:Npn \__siunitx_number_textsf: { } +\cs_new:Npn \__siunitx_number_texttt: { } +\keys_define:nn { siunitx } { + number-color .tl_set:N = \l__siunitx_number_color_tl, + number-math-rm .code:n = + { \cs_set:Npn \__siunitx_number_mathrm:n ##1 { #1 {##1} } }, + number-math-sf .code:n = + { \cs_set:Npn \__siunitx_number_mathsf:n ##1 { #1 {##1} } }, + number-math-tt .code:n = + { \cs_set:Npn \__siunitx_number_mathtt:n ##1 { #1 {##1} } }, + number-mode .choice:, + number-mode / math .code:n = + { \bool_set_true:N \l__siunitx_number_math_mode_bool }, + number-mode / text .code:n = + { \bool_set_false:N \l__siunitx_number_math_mode_bool }, + number-text-rm .code:n = + { \cs_set:Npn \__siunitx_number_textrm: {#1} }, + number-text-sf .code:n = + { \cs_set:Npn \__siunitx_number_textsf: {#1} }, + number-text-tt .code:n = + { \cs_set:Npn \__siunitx_number_texttt: {#1} } +} +\cs_new:Npn \__siunitx_unit_mathrm: { } +\cs_new:Npn \__siunitx_unit_mathsf: { } +\cs_new:Npn \__siunitx_unit_mathtt: { } +\cs_new:Npn \__siunitx_unit_textrm: { } +\cs_new:Npn \__siunitx_unit_textsf: { } +\cs_new:Npn \__siunitx_unit_texttt: { } +\keys_define:nn { siunitx } { + unit-color .tl_set:N = \l__siunitx_unit_color_tl, + unit-math-rm .code:n = + { \cs_set:Npn \__siunitx_unit_mathrm:n ##1 { #1 {##1} } }, + unit-math-sf .code:n = + { \cs_set:Npn \__siunitx_unit_mathsf:n ##1 { #1 {##1} } }, + unit-math-tt .code:n = + { \cs_set:Npn \__siunitx_unit_mathtt:n ##1 { #1 {##1} } }, + unit-mode .choice:, + unit-mode / math .code:n = + { \bool_set_true:N \l__siunitx_unit_math_mode_bool }, + unit-mode / text .code:n = + { \bool_set_false:N \l__siunitx_unit_math_mode_bool }, + unit-text-rm .code:n = + { \cs_set:Npn \__siunitx_unit_textrm: {#1} }, + unit-text-sf .code:n = + { \cs_set:Npn \__siunitx_unit_textsf: {#1} }, + unit-text-tt .code:n = + { \cs_set:Npn \__siunitx_unit_texttt: {#1} } +} +\keys_define:nn { siunitx } { + color .meta:n = + { + number-color = #1, + unit-color = #1 + }, + math-rm .meta:n = + { + number-math-rm = #1, + unit-math-rm = #1 + }, + math-sf .meta:n = + { + number-math-sf = #1, + unit-math-sf = #1 + }, + math-tt .meta:n = + { + number-math-tt = #1, + unit-math-tt = #1 + }, + mode .choice:, + mode / math .meta:n = + { + number-mode = math, + unit-mode = math + }, + mode / text .meta:n = + { + number-mode = text, + unit-mode = text + }, + text-rm .meta:n = + { + number-text-rm = #1, + unit-text-rm = #1 + }, + text-sf .meta:n = + { + number-text-sf = #1, + unit-text-sf = #1 + }, + text-tt .meta:n = + { + number-text-tt = #1, + unit-text-tt = #1 + } +} +\keys_set:nn { siunitx } { + math-rm = \mathrm, + math-sf = \mathsf, + math-tt = \mathtt, + mode = math, + text-rm = \rmfamily, + text-sf = \sffamily, + text-tt = \ttfamily, +} +\AtBeginDocument { + \tl_set:Nx \l__siunitx_tmpa_tl { \familydefault } + \@ifpackageloaded { eulervm } + { + \cs_set:Npn \__siunitx_tmp:w #1 { \mathrm {#1} } + \cs_if_eq:NNT \__siunitx_number_mathrm:n \__siunitx_tmp:w + { \keys_set:nn { siunitx } { number-math-rm = \mathnormal } } + \cs_if_eq:NNT \__siunitx_unit_mathrm:n \__siunitx_tmp:w + { \keys_set:nn { siunitx } { unit-math-rm = \mathnormal } } + } + { } + \tl_if_eq:NNT \l__siunitx_tmpa_tl \c__siunitx_textsf_tl + { + \@ifpackageloaded { arev } + { } + { + \@ifpackageloaded { cmbright } + { } + { + \cs_set:Npn \__siunitx_tmp:w #1 { \mathrm {#1} } + \cs_if_eq:NNT \__siunitx_number_mathrm:n \__siunitx_tmp:w + { \keys_set:nn { siunitx } { number-math-rm = \mathsf } } + \cs_if_eq:NNT \__siunitx_unit_mathrm:n \__siunitx_tmp:w + { \keys_set:nn { siunitx } { unit-math-rm = \mathsf } } + } + } + \cs_set:Npn \__siunitx_tmp:w { \rmfamily } + \cs_if_eq:NNT \__siunitx_number_textrm: \__siunitx_tmp:w + { \keys_set:nn { siunitx } { number-text-rm = \sffamily } } + \cs_if_eq:NNT \__siunitx_unit_textrm: \__siunitx_tmp:w + { \keys_set:nn { siunitx } { unit-text-rm = \sffamily } } + } + \tl_if_eq:NNT \l__siunitx_tmpa_tl \c__siunitx_texttt_tl + { + \cs_set:Npn \__siunitx_tmp:w #1 { \mathrm {#1} } + \cs_if_eq:NNT \__siunitx_number_mathrm:n \__siunitx_tmp:w + { \keys_set:nn { siunitx } { number-math-rm = \mathtt } } + \cs_if_eq:NNT \__siunitx_unit_mathrm:n \__siunitx_tmp:w + { \keys_set:nn { siunitx } { unit-math-rm = \mathtt } } + \cs_set:Npn \__siunitx_tmp:w { \rmfamily } + \cs_if_eq:NNT \__siunitx_number_textrm: \__siunitx_tmp:w + { \keys_set:nn { siunitx } { number-text-rm = \ttfamily } } + \cs_if_eq:NNT \__siunitx_unit_textrm: \__siunitx_tmp:w + { \keys_set:nn { siunitx } { unit-text-rm = \ttfamily } } + } +} +\tl_new:N \l__siunitx_print_arg_tl +\tl_new:N \l__siunitx_print_type_tl +\cs_new_protected:Npn \__siunitx_print:nn #1#2 { + \group_begin: + \tl_set:Nn \l__siunitx_print_type_tl {#1} + \tl_set:Nn \l__siunitx_print_arg_tl {#2} + \__siunitx_detect_font: + \bool_if:NF \l__siunitx_detect_mode_bool + { + \bool_if:cTF { l__siunitx_ #1 _math_mode_bool } + { \bool_set_true:N \l__siunitx_font_math_mode_bool } + { \bool_set_false:N \l__siunitx_font_math_mode_bool } + } + \__siunitx_print_aux: + \group_end: +} +\cs_generate_variant:Nn \__siunitx_print:nn { nV } +\cs_new_protected:Npn \__siunitx_print_aux: + { + \text + { + \__siunitx_ensure_ltr:n + { + \color@begingroup + \__siunitx_print_color: + \__siunitx_font_shape: + \__siunitx_font_weight: + \use:c + { + __siunitx_ \l__siunitx_print_type_tl _ + text \l__siunitx_font_family_tl : + } + \bool_if:NTF \l__siunitx_font_math_mode_bool + { \__siunitx_print_math: } + { \__siunitx_print_text: } + \color@endgroup + } + } + } +\cs_new_protected:Npn \__siunitx_print_color: { + \tl_if_empty:cF { l__siunitx_ \l__siunitx_print_type_tl _color_tl } + { + \color + { + \tl_use:c { l__siunitx_ \l__siunitx_print_type_tl _color_tl } + } + } +} +\AtBeginDocument { + \@ifpackageloaded { color } + { \cs_new_eq:NN \__siunitx_textcolor:n \textcolor } + { + \cs_set_protected:Npn \__siunitx_print_color: + { + \tl_if_empty:cF { l__siunitx_ \l__siunitx_print_type_tl _color_tl } + { + \cs_gset_eq:NN \__siunitx_print_color: \scan_stop: + \msg_warning:nn { siunitx } { color-not-loaded } + } + } + \cs_new_protected:Npn \__siunitx_textcolor:n #1 + { + \cs_gset_eq:NN \__siunitx_textcolor:n \use_none:n + \msg_warning:nn { siunitx } { color-not-loaded } + } + } +} +\cs_new_protected:Npn \__siunitx_print_math: + { + \cs_set_eq:NN \PrintSubscript \sb + \cs_set_eq:NN \PrintSuperscript \sp + \ensuremath + { + \use:c + { + __siunitx_ \l__siunitx_print_type_tl _ + math \l__siunitx_font_family_tl :n + } + { \l__siunitx_print_arg_tl } + } + } +\cs_new_protected:Npn \__siunitx_print_text: + { + \tl_replace_all:Nnn \l__siunitx_print_arg_tl { - } + { \textminus } + \__siunitx_print_text_aux: + \tl_replace_all:Nnn \l__siunitx_print_arg_tl { \mp } + { \ensuremath { \mp } } + \tl_remove_all:Nn \l__siunitx_print_arg_tl { \mathord } + \cs_set_eq:NN \PrintSubscript \__siunitx_print_text_sub:n + \cs_set_eq:NN \PrintSuperscript \__siunitx_print_text_super:n + \__siunitx_print_text_aux:NnN + _ { math_subscript } \__siunitx_print_text_sub:n + _ { active } \__siunitx_print_text_sub:n + ^ { math_superscript } \__siunitx_print_text_super:n + ^ { active } \__siunitx_print_text_super:n + \q_recursion_tail ? ? + \q_recursion_stop + \l__siunitx_print_arg_tl + } +\cs_new_protected:Npn \__siunitx_print_text_aux: + { + \tl_replace_all:Nnn \l__siunitx_print_arg_tl { \pm } + { \ensuremath { \pm } } + } +\cs_new_protected:Npn \__siunitx_print_text_aux:NnN #1#2#3 + { + \quark_if_recursion_tail_stop:N #1 + \tl_set_rescan:Nnn \l__siunitx_tmpa_tl + { \use:c { char_set_catcode_ #2 :N } #1 } + {#1} + \tl_replace_all:NVn \l__siunitx_print_arg_tl \l__siunitx_tmpa_tl {#3} + \__siunitx_print_text_aux:NnN + } +\AtBeginDocument + { + \@ifpackageloaded { textcomp } + { + \cs_set_protected:Npn \__siunitx_print_text_aux: + { + \tl_replace_all:Nnn \l__siunitx_print_arg_tl { \pm } + { \textpm } + } + } + { } + } +\cs_new_protected:Npn \__siunitx_print_text_sub:n #1 + { + \cs_set:Npn \__siunitx_print_text_sub_super:n ##1 + { + \ensuremath + { + \sb { \text {#1} } + \sp { \text {##1} } + } + } + \cs_set_protected:Npn \__siunitx_peek_true: + { + \tex_afterassignment:D \__siunitx_print_text_sub_super:n + \cs_set_eq:NN \__siunitx_tmp:w + } + \cs_set_protected:Npn \__siunitx_peek_false: + { \ensuremath { \sb { \text {#1} } } } + \peek_after:Nw \__siunitx_print_text_sub_peek: + } +\cs_new_protected:Npn \__siunitx_print_text_sub_peek: + { + \if_meaning:w \l_peek_token \__siunitx_print_text_super:n + \exp_after:wN \__siunitx_peek_true: + \else: + \exp_after:wN \__siunitx_peek_false: + \fi: + } +\cs_new_protected:Npn \__siunitx_peek_true: { } +\cs_new_protected:Npn \__siunitx_peek_false: { } +\cs_new_protected:Npn \__siunitx_print_text_sub_super:n { } +\cs_new_protected:Npn \__siunitx_print_text_super:n #1 { + \tl_set:Nn \l__siunitx_tmpa_tl {#1} + \tl_replace_all:Nnn \l__siunitx_tmpa_tl { - } + { \textminus } + \tl_set:Nx \l__siunitx_tmpa_tl + { + \exp_not:N \ensuremath + { \sp { \exp_not:N \text { \exp_not:V \l__siunitx_tmpa_tl } } } + } + \l__siunitx_tmpa_tl +} +\keys_define:nn { siunitx } { + input-product .tl_set:N = \l__siunitx_input_product_tl, + input-quotient .tl_set:N = \l__siunitx_input_quotient_tl, +} +\keys_set:nn { siunitx } { + input-product = x, + input-quotient = / +} +\tl_new:N \l__siunitx_number_arg_tl +\tl_new:N \l__siunitx_number_next_tl +\tl_new:N \l__siunitx_number_multi_tl +\tl_new:N \l__siunitx_number_denominator_tl +\tl_new:N \l__siunitx_number_numerator_tl +\cs_new_protected:Npn \__siunitx_number_preprocess:n #1 { + \__siunitx_number_preprocess_init: + \tl_set:Nn \l__siunitx_number_arg_tl {#1} + \__siunitx_number_preprocess_product: + \tl_if_empty:NT \l__siunitx_number_multi_tl + { \__siunitx_number_preprocess_quotient: } +} +\cs_generate_variant:Nn \__siunitx_number_preprocess:n { V } +\cs_new_protected:Npn \__siunitx_number_preprocess_init: { + \bool_set_false:N \l__siunitx_error_bool + \tl_clear:N \l__siunitx_number_multi_tl +} +\cs_new_protected:Npn \__siunitx_number_preprocess_product: { + \tl_map_function:NN \l__siunitx_input_product_tl + \__siunitx_number_preprocess_product_aux:N +} +\cs_new_protected:Npn \__siunitx_number_preprocess_product_aux:N #1 { + \tl_if_in:NnT \l__siunitx_number_arg_tl {#1} + { + \cs_set:Npn \__siunitx_tmp:w ##1 #1 ##2 \q_stop + { + \tl_set:Nn \l__siunitx_number_arg_tl {##1} + \tl_set:Nn \l__siunitx_number_next_tl {##2} + \tl_set:Nn \l__siunitx_number_multi_tl { product } + } + \exp_after:wN \__siunitx_tmp:w \l__siunitx_number_arg_tl \q_stop + \tl_if_empty:NT \l__siunitx_number_arg_tl + { \__siunitx_error:n { starting-product-token } } + \tl_if_empty:NT \l__siunitx_number_next_tl + { \__siunitx_error:n { ending-product-token } } + \tl_map_break: + } +} +\cs_new_protected:Npn \__siunitx_number_preprocess_quotient: { + \tl_map_function:NN \l__siunitx_input_quotient_tl + \__siunitx_number_preprocess_quotient_aux:N +} +\cs_new_protected:Npn \__siunitx_number_preprocess_quotient_aux:N #1 { + \tl_if_in:NnT \l__siunitx_number_arg_tl {#1} + { + \cs_set:Npn \__siunitx_tmp:w ##1 #1 ##2 \q_stop + { + \tl_set:Nn \l__siunitx_number_numerator_tl {##1} + \tl_set:Nn \l__siunitx_number_denominator_tl {##2} + \tl_set:Nn \l__siunitx_number_multi_tl { quotient } + } + \exp_after:wN \__siunitx_tmp:w \l__siunitx_number_arg_tl \q_stop + \tl_if_empty:NT \l__siunitx_number_numerator_tl + { \__siunitx_error:n { starting-quotient-token } } + \tl_if_empty:NT \l__siunitx_number_denominator_tl + { \__siunitx_error:n { ending-quotient-token } } + \tl_if_in:NnT \l__siunitx_number_denominator_tl {#1} + { \__siunitx_error:n { duplicate-quotient-token } } + \tl_map_break: + } +} +\tl_const:Nn \c__siunitx_number_part_complex_tl { complex } +\bool_new:N \l__siunitx_number_in_complex_bool +\bool_new:N \l__siunitx_number_in_complex_root_bool +\bool_new:N \l__siunitx_number_in_decimal_bool +\bool_new:N \l__siunitx_number_in_exponent_bool +\bool_new:N \l__siunitx_number_in_first_bool +\bool_new:N \l__siunitx_number_in_sign_bool +\bool_new:N \l__siunitx_number_in_uncert_bool +\bool_new:N \l__siunitx_number_in_value_bool +\prop_new:N \l__siunitx_number_in_prop +\tl_new:N \l__siunitx_number_parsed_tl +\tl_new:N \l__siunitx_number_part_tl +\tl_new:N \l__siunitx_number_part_decimal_tl +\tl_new:N \l__siunitx_number_part_decimal_marker_tl +\tl_new:N \l__siunitx_number_part_integer_tl +\tl_new:N \l__siunitx_number_part_sign_tl +\tl_new:N \l__siunitx_number_part_uncert_tl +\int_new:N \l__siunitx_number_mantissa_length_int +\tl_new:N \l__siunitx_number_uncert_tl +\int_new:N \l__siunitx_number_uncert_length_int +\tl_new:N \l__siunitx_input_uncert_sign_tl +\keys_define:nn { siunitx } { + input-close-uncertainty .tl_set:N = \l__siunitx_input_uncert_close_tl , + input-complex-roots .tl_set:N = \l__siunitx_input_complex_tl , + input-comparators .tl_set:N = \l__siunitx_input_comparator_tl , + input-decimal-markers .tl_set:N = \l__siunitx_input_decimal_tl , + input-digits .tl_set:N = \l__siunitx_input_digit_tl , + input-exponent-markers .tl_set:N = \l__siunitx_input_exponent_tl , + input-ignore .tl_set:N = \l__siunitx_input_ignore_tl , + input-open-uncertainty .tl_set:N = \l__siunitx_input_uncert_open_tl , + input-protect-tokens .tl_set:N = \l__siunitx_input_protect_tl , + input-signs .tl_set:N = \l__siunitx_input_sign_tl , + input-symbols .tl_set:N = \l__siunitx_input_symbol_tl , + input-uncertainty-signs .code:n = + { + \tl_set:Nn \l__siunitx_input_uncert_sign_tl {#1} + \tl_map_inline:nn {#1} + { + \tl_if_in:NnF \l__siunitx_input_sign_tl {##1} + { \tl_put_right:Nn \l__siunitx_input_sign_tl {##1} } + } + } , +} +\keys_set:nn { siunitx } { % ( + input-close-uncertainty = ), + input-complex-roots = ij, + input-comparators = {<=>\approx\ge\geq\gg\le\leq\ll\sim}, + input-decimal-markers = {.,}, + input-digits = 0123456789, + input-exponent-markers = dDeE, + input-open-uncertainty = (, % ) + input-protect-tokens = \approx\dots\ge\geq\gg\le\leq\ll\mp\pi\pm\sim, + input-signs = +-\mp\pm, + input-symbols = \dots\pi, + input-uncertainty-signs = \pm, +} +\cs_new_protected:Npn \__siunitx_number_in_parse:n #1 { + \tl_if_empty:nF {#1} + { + \__siunitx_number_in_init: + \cs_set_eq:NN \__siunitx_number_in_parse_more:N + \__siunitx_number_in_parse_mantissa_aux:N + \__siunitx_number_in_parse_aux:n {#1} + } +} +\cs_generate_variant:Nn \__siunitx_number_in_parse:n { V } +\group_begin: + \char_set_catcode_active:N \~ + \char_set_catcode_space:N \ % + \cs_new_protected:Npn \__siunitx_number_in_parse_aux:n#1% + {% + \group_begin: + \__siunitx_number_in_protect: + \cs_set_eq:NN\,\prg_do_nothing: + \cs_set_eq:NN~\prg_do_nothing: + \tl_set_rescan:Nnx\l__siunitx_number_arg_tl + {% + \char_set_catcode_ignore:N\ % + \char_set_catcode_other:N\,% + \char_set_catcode_other:N\.% + }% + {#1}% + \exp_args:NNNV\group_end: + \tl_set:Nn\l__siunitx_number_arg_tl\l__siunitx_number_arg_tl + \__siunitx_number_in_sign_replace:N\l__siunitx_number_arg_tl + \__siunitx_number_in_parse_relation:N\l__siunitx_number_arg_tl + \tl_map_function:NN\l__siunitx_number_arg_tl + \__siunitx_number_in_parse_loop:N + \tl_if_empty:NF\l__siunitx_number_parsed_tl + {% + \bool_if:NTF\l__siunitx_number_in_uncert_bool + {\__siunitx_error:nx{invalid-number}{#1}}% + {% + \prop_put:NVn \l__siunitx_number_in_prop + \l__siunitx_number_part_tl {true}% + \bool_if:NTF\l__siunitx_number_in_decimal_bool + {% + \prop_put:NVV\l__siunitx_number_in_prop + \l__siunitx_number_part_decimal_tl + \l__siunitx_number_parsed_tl + }% + {% + \prop_put:NVV\l__siunitx_number_in_prop + \l__siunitx_number_part_integer_tl + \l__siunitx_number_parsed_tl + }% + }% + }% + \__siunitx_number_in_check:n {#1}% + } +\group_end: +\cs_new_protected:Npn \__siunitx_number_in_init: { + \cs_set_eq:NN \__siunitx_number_in_parse_loop:N + \__siunitx_number_in_parse_mantissa:N + \cs_set_eq:NN \__siunitx_number_in_check:n + \__siunitx_number_in_check_short:n + \tl_clear:N \l__siunitx_number_parsed_tl + \prop_clear:N \l__siunitx_number_in_prop + \bool_set_false:N \l__siunitx_error_bool + \bool_set_false:N \l__siunitx_number_in_complex_bool + \bool_set_false:N \l__siunitx_number_in_complex_root_bool + \bool_set_false:N \l__siunitx_number_in_exponent_bool + \bool_set_false:N \l__siunitx_number_in_uncert_bool + \__siunitx_number_in_init_part:n { mantissa } +} +\cs_new_protected:Npn \__siunitx_number_in_init_part:n #1 { + \bool_set_false:N \l__siunitx_number_in_decimal_bool + \bool_set_true:N \l__siunitx_number_in_first_bool + \bool_set_false:N \l__siunitx_number_in_sign_bool + \bool_set_false:N \l__siunitx_number_in_value_bool + \tl_set:Nn \l__siunitx_number_part_tl {#1} + \tl_set:Nn \l__siunitx_number_part_decimal_tl { #1 -decimal } + \tl_set:Nn \l__siunitx_number_part_decimal_marker_tl + { #1 -decimal-marker } + \tl_set:Nn \l__siunitx_number_part_integer_tl { #1 -integer } + \tl_set:Nn \l__siunitx_number_part_sign_tl { #1 -sign } + \tl_set:Nn \l__siunitx_number_part_uncert_tl { #1 -uncertainty } +} +\cs_new_protected:Npn \__siunitx_number_in_protect: { + \tl_map_function:NN \l__siunitx_input_protect_tl + \__siunitx_number_in_protect_aux:N +} +\cs_new_protected:Npn \__siunitx_number_in_protect_aux:N #1 { + \cs_set_eq:NN #1 \scan_stop: +} +\cs_new_protected:Npn \__siunitx_number_in_sign_replace:N #1 + { + \__siunitx_number_in_sign_replace_aux:N #1 + \__siunitx_number_in_sign_replace_aux:NnN #1 + { -+ } \mp + { +- } \pm + { << } \ll + { <= } \le + { >> } \gg + { >= } \ge + { ?? } \q_recursion_tail + \q_recursion_stop + } +\group_begin: + \char_set_catcode_active:N - + \cs_new_protected:Npx \__siunitx_number_in_sign_replace_aux:N #1 + { \tl_replace_all:Nnn #1 { \exp_not:N - } { \token_to_str:N - } } +\group_end: +\cs_new_protected:Npn \__siunitx_number_in_sign_replace_aux:NnN #1#2#3 + { + \quark_if_recursion_tail_stop:N #3 + \tl_replace_all:Nnn #1 {#2} {#3} + \__siunitx_number_in_sign_replace_aux:NnN #1 + } +\cs_new_protected:Npn \__siunitx_number_in_parse_error:nn #1#2 { + \__siunitx_error:nx {#1} { \exp_not:n {#2} } + \tl_map_break: +} +\cs_generate_variant:Nn \__siunitx_number_in_parse_error:nn { nV } +\cs_new_protected:Npn \__siunitx_number_in_parse_loop:N #1 { } +\cs_new_protected:Npn \__siunitx_number_in_parse_more:N #1 { } +\cs_new_protected:Npn \__siunitx_number_in_parse_relation:N #1 { + \exp_after:wN \__siunitx_number_in_parse_relation:w #1 \q_stop #1 +} +\cs_new_protected:Npn \__siunitx_number_in_parse_relation:w + #1#2 \q_stop #3 { + \tl_if_in:NnT \l__siunitx_input_comparator_tl {#1} + { + \prop_put:Nnn \l__siunitx_number_in_prop { comparator } {#1} + \tl_set:Nn #3 {#2} + } +} +\cs_new_protected:Npn \__siunitx_number_in_parse_restricted:N #1 { + \tl_if_in:NnTF \l__siunitx_input_exponent_tl {#1} + { + \__siunitx_number_in_parse_error:nn + { restricted-number } {#1} + } + { + \tl_if_in:NnTF \l__siunitx_input_uncert_open_tl {#1} + { + \__siunitx_number_in_parse_error:nV + { restricted-number } \l__siunitx_number_arg_tl + } + { + \tl_if_in:NnTF \l__siunitx_input_uncert_close_tl {#1} + { + \__siunitx_number_in_parse_error:nV + { restricted-number } \l__siunitx_number_arg_tl + } + { + \tl_if_in:NnTF \l__siunitx_input_complex_tl {#1} + { + \__siunitx_number_in_parse_error:nV + { restricted-number } \l__siunitx_number_arg_tl + } + { + \__siunitx_number_in_parse_error:nn + { restricted-number } {#1} + } + } + } + } +} +\cs_new_protected:Npn \__siunitx_number_in_parse_complex:N #1 { + \tl_if_in:NnTF \l__siunitx_input_exponent_tl {#1} + { + \cs_set_eq:NN \__siunitx_number_in_parse_loop:N + \__siunitx_number_in_parse_mantissa:N + \__siunitx_number_in_exponent:N #1 + } + { + \tl_if_in:NnF \l__siunitx_input_ignore_tl {#1} + { + \__siunitx_number_in_parse_error:nV + { misplaced-complex-root-token } + \l__siunitx_number_arg_tl + } + } +} +\cs_new_protected:Npn \__siunitx_number_in_parse_exponent:N #1 { + \tl_if_in:NnTF \l__siunitx_input_exponent_tl {#1} + { + \__siunitx_number_in_parse_error:nn + { duplicate-exponent-token } { \token_to_str:N #1 } + } + { + \tl_if_in:NnTF \l__siunitx_input_uncert_open_tl {#1} + { + \__siunitx_number_in_parse_error:nV + { invalid-token-in-exponent } \l__siunitx_number_arg_tl + } + { + \tl_if_in:NnTF \l__siunitx_input_uncert_close_tl {#1} + { + \__siunitx_number_in_parse_error:nV + { invalid-token-in-exponent } \l__siunitx_number_arg_tl + } + { + \tl_if_in:NnTF \l__siunitx_input_complex_tl {#1} + { + \__siunitx_number_in_parse_error:nV + { invalid-token-in-exponent } + \l__siunitx_number_arg_tl + } + { + \__siunitx_number_in_parse_error:nn + { invalid-token-in-number } {#1} + } + } + } + } +} +\cs_new_protected:Npn \__siunitx_number_in_parse_mantissa:N #1 { + \tl_if_in:NnTF \l__siunitx_input_digit_tl {#1} + { \__siunitx_number_in_digit:n {#1} } + { + \tl_if_in:NnTF \l__siunitx_input_decimal_tl {#1} + { \__siunitx_number_in_decimal:N #1 } + { + \tl_if_in:NnTF \l__siunitx_input_sign_tl {#1} + { \__siunitx_number_in_sign:N #1 } + { + \tl_if_in:NnTF \l__siunitx_input_symbol_tl {#1} + { + \prop_put:Nnn \l__siunitx_number_in_prop { symbolic } + { true } + \__siunitx_number_in_digit:n {#1} + } + { + \tl_if_in:NnF \l__siunitx_input_ignore_tl {#1} + { \__siunitx_number_in_parse_more:N #1 } + } + } + } + } +} +\cs_new_protected:Npn \__siunitx_number_in_parse_mantissa_aux:N #1 { + \tl_if_in:NnTF \l__siunitx_input_exponent_tl {#1} + { \__siunitx_number_in_exponent:N #1 } + { + \tl_if_in:NnTF \l__siunitx_input_uncert_open_tl {#1} + { \__siunitx_number_in_uncert_open:N #1 } + { + \tl_if_in:NnTF \l__siunitx_input_uncert_close_tl {#1} + { + \__siunitx_number_in_parse_error:nn + { misplaced-uncertainty-token } {#1} + } + { + \tl_if_in:NnTF \l__siunitx_input_complex_tl {#1} + { \__siunitx_number_in_complex:N #1 } + { + \__siunitx_number_in_parse_error:nn + { invalid-token-in-number } {#1} + } + } + } + } +} +\cs_new_protected:Npn \__siunitx_number_in_parse_uncert:N #1 { + \tl_if_in:NnTF \l__siunitx_input_digit_tl {#1} + { \__siunitx_number_in_digit:n {#1} } + { + \tl_if_in:NnTF \l__siunitx_input_decimal_tl {#1} + { + \__siunitx_number_in_parse_error:nV + { invalid-token-in-uncertainty } + \l__siunitx_number_arg_tl + } + { + \tl_if_in:NnTF \l__siunitx_input_sign_tl {#1} + { + \__siunitx_number_in_parse_error:nV + { invalid-token-in-uncertainty } + \l__siunitx_number_arg_tl + } + { + \tl_if_in:NnTF \l__siunitx_input_symbol_tl {#1} + { + \prop_put:Nnn \l__siunitx_number_in_prop { symbolic } + { true } + \__siunitx_number_in_digit:n {#1} + } + { + \tl_if_in:NnF \l__siunitx_input_ignore_tl {#1} + { + \tl_if_in:NnTF \l__siunitx_input_uncert_close_tl + {#1} + { \__siunitx_number_in_uncert_close:N #1 } + { + \__siunitx_number_in_parse_error:nV + { invalid-token-in-uncertainty } + \l__siunitx_number_arg_tl + } + } + } + } + } + } +} +\cs_new_protected:Npn \__siunitx_number_in_parse_uncert_after:N #1 { + \tl_if_in:NnTF \l__siunitx_input_exponent_tl {#1} + { + \cs_set_eq:NN \__siunitx_number_in_parse_loop:N + \__siunitx_number_in_parse_mantissa:N + \__siunitx_number_in_exponent:N #1 + } + { + \tl_if_in:NnTF \l__siunitx_input_sign_tl {#1} + { + \cs_set_eq:NN \__siunitx_number_in_parse_loop:N + \__siunitx_number_in_parse_mantissa:N + \__siunitx_number_in_sign:N #1 + } + { + \tl_if_in:NnF \l__siunitx_input_ignore_tl {#1} + { + \tl_if_in:NnTF \l__siunitx_input_complex_tl {#1} + { + \cs_set_eq:NN \__siunitx_number_in_parse_loop:N + \__siunitx_number_in_parse_mantissa:N + \__siunitx_number_in_complex:N #1 + } + { + \__siunitx_number_in_parse_error:nV { invalid-number } + \l__siunitx_number_arg_tl + } + } + } + } +} +\cs_new_protected:Npn \__siunitx_number_in_complex:N #1 { + \bool_set_false:N \l__siunitx_number_in_first_bool + \bool_if:NTF \l__siunitx_number_in_complex_root_bool + { + \__siunitx_number_in_parse_error:nn + { duplicate-complex-root-token } { \token_to_str:N #1 } + } + { + \cs_set_eq:NN \__siunitx_number_in_check:n + \__siunitx_number_in_check_full:n + \bool_set_true:N \l__siunitx_number_in_complex_root_bool + \prop_put:Nnn \l__siunitx_number_in_prop { complex-root } {#1} + \tl_if_empty:NF \l__siunitx_number_parsed_tl + { + \cs_set_eq:NN \__siunitx_number_in_parse_loop:N + \__siunitx_number_in_parse_complex:N + } + \bool_if:NT \l__siunitx_number_in_decimal_bool + { + \bool_if:NF \l__siunitx_number_in_complex_bool + { + \prop_if_in:NnT \l__siunitx_number_in_prop + { mantissa-uncertainty } + { + \__siunitx_number_in_complex_aux:nn + { mantissa-decimal } { complex-decimal } + \__siunitx_number_in_complex_aux:nn + { mantissa-uncertainty } { complex-uncertainty } + } + \__siunitx_number_in_complex_aux:nn { mantissa-integer } + { complex-integer } + \__siunitx_number_in_complex_aux:nn + { mantissa-decimal-marker } { complex-decimal-marker } + \prop_remove:Nn \l__siunitx_number_in_prop { mantissa } + \prop_put:Nnn \l__siunitx_number_in_prop { complex } + { true } + } + } + \prop_if_in:NnF \l__siunitx_number_in_prop { mantissa } + { + \prop_if_in:NnT \l__siunitx_number_in_prop { mantissa-sign } + { + \__siunitx_number_in_complex_aux:nn { mantissa-sign } + { complex-sign } + } + } + \bool_set_true:N \l__siunitx_number_in_complex_bool + \bool_set_false:N \l__siunitx_number_in_first_bool + \__siunitx_number_in_init_part:n { complex } + \prop_if_in:NnT \l__siunitx_number_in_prop + { complex-decimal-marker } + { \bool_set_true:N \l__siunitx_number_in_decimal_bool } + \prop_if_in:NnTF \l__siunitx_number_in_prop + { complex-sign } + { \bool_set_true:N \l__siunitx_number_in_sign_bool } + { \prop_remove:Nn \l__siunitx_number_in_prop { mantissa } } + } +} +\cs_new_protected:Npn \__siunitx_number_in_complex_aux:nn #1#2 { + \prop_get:NnNT \l__siunitx_number_in_prop {#1} \l__siunitx_tmpa_tl + { + \prop_remove:Nn \l__siunitx_number_in_prop {#1} + \prop_put:NnV \l__siunitx_number_in_prop {#2} \l__siunitx_tmpa_tl + } +} +\cs_new_protected:Npn \__siunitx_number_in_decimal:N #1 { + \bool_set_false:N \l__siunitx_number_in_first_bool + \bool_if:NTF \l__siunitx_number_in_decimal_bool + { + \__siunitx_number_in_parse_error:nn { duplicate-decimal-token } + {#1} + } + { + \bool_set_true:N \l__siunitx_number_in_decimal_bool + \tl_if_empty:NF \l__siunitx_number_parsed_tl + { + \prop_put:NVn \l__siunitx_number_in_prop + \l__siunitx_number_part_tl { true } + \prop_put:NVV \l__siunitx_number_in_prop + \l__siunitx_number_part_integer_tl + \l__siunitx_number_parsed_tl + \tl_clear:N \l__siunitx_number_parsed_tl + } + \prop_put:NVn \l__siunitx_number_in_prop + \l__siunitx_number_part_decimal_marker_tl {#1} + } +} +\cs_new_protected:Npn \__siunitx_number_in_digit:n #1 { + \bool_set_false:N \l__siunitx_number_in_first_bool + \bool_if:NTF \l__siunitx_number_in_uncert_bool + { \tl_put_right:Nn \l__siunitx_number_parsed_tl {#1} } + { + \bool_if:NTF \l__siunitx_number_in_decimal_bool + { + \tl_put_right:Nn \l__siunitx_number_parsed_tl {#1} + \str_if_eq:nnF {#1} { 0 } + { \bool_set_true:N \l__siunitx_number_in_value_bool } + } + { + \str_if_eq:nnTF {#1} { 0 } + { + \prop_put:NVn \l__siunitx_number_in_prop + \l__siunitx_number_part_tl { true } + \prop_put:NVn \l__siunitx_number_in_prop + \l__siunitx_number_part_integer_tl { 0 } + } + { \bool_set_true:N \l__siunitx_number_in_value_bool } + \bool_if:NT \l__siunitx_number_in_value_bool + { \tl_put_right:Nn \l__siunitx_number_parsed_tl {#1} } + } + } +} +\cs_new_protected:Npn \__siunitx_number_in_exponent:N #1 { + \bool_if:NTF \l__siunitx_number_in_exponent_bool + { + \__siunitx_number_in_parse_error:nn { duplicate-exponent-token } + { \token_to_str:N #1 } + } + { + \cs_set_eq:NN \__siunitx_number_in_parse_more:N + \__siunitx_number_in_parse_exponent:N + \tl_if_empty:NF \l__siunitx_number_parsed_tl + { \__siunitx_number_in_store: } + \bool_set_true:N \l__siunitx_number_in_exponent_bool + \__siunitx_number_in_init_part:n { exponent } + } +} +\cs_new_protected:Npn \__siunitx_number_in_sign:N #1 { + \bool_if:NTF \l__siunitx_number_in_first_bool + { + \bool_set_false:N \l__siunitx_number_in_first_bool + \bool_set_true:N \l__siunitx_number_in_sign_bool + \prop_put:NVn \l__siunitx_number_in_prop + \l__siunitx_number_part_sign_tl {#1} + } + { + \bool_if:NTF \l__siunitx_number_in_exponent_bool + { + \__siunitx_number_in_parse_error:nn { misplaced-sign-token } + {#1} + } + { + \bool_if:NTF \l__siunitx_number_in_complex_bool + { + \__siunitx_number_in_parse_error:nn + { misplaced-sign-token } {#1} + } + { + \tl_if_empty:NF \l__siunitx_number_parsed_tl + { \__siunitx_number_in_store: } + \cs_set_eq:NN \__siunitx_number_in_check:n + \__siunitx_number_in_check_full:n + \__siunitx_number_in_init_part:n { complex } + \prop_put:Nnn \l__siunitx_number_in_prop + { complex-sign } {#1} + \bool_set_true:N \l__siunitx_number_in_complex_bool + } + } + } +} +\cs_new_protected:Npn \__siunitx_number_in_uncert_open:N #1 { + \bool_set_false:N \l__siunitx_number_in_first_bool + \cs_set_eq:NN \__siunitx_number_in_parse_loop:N + \__siunitx_number_in_parse_uncert:N + \bool_set_true:N \l__siunitx_number_in_uncert_bool + \tl_if_empty:NTF \l__siunitx_number_parsed_tl + { + \prop_if_in:NVF \l__siunitx_number_in_prop + \l__siunitx_number_part_integer_tl + { + \__siunitx_number_in_parse_error:nV { invalid-number } + \l__siunitx_number_arg_tl + } + } + { \__siunitx_number_in_store: } +} +\cs_new_protected:Npn \__siunitx_number_in_uncert_close:N #1 { + \bool_set_false:N \l__siunitx_number_in_uncert_bool + \tl_if_empty:NTF \l__siunitx_number_parsed_tl + { + \__siunitx_number_in_parse_error:nV { empty-uncertainty } + \l__siunitx_number_arg_tl + } + { + \prop_put:NVV \l__siunitx_number_in_prop + \l__siunitx_number_part_uncert_tl \l__siunitx_number_parsed_tl + \prop_put:Nnn \l__siunitx_number_in_prop + { uncertainty } { true } + \tl_clear:N \l__siunitx_number_parsed_tl + \cs_set_eq:NN \__siunitx_number_in_parse_loop:N + \__siunitx_number_in_parse_uncert_after:N + } +} +\cs_new_protected:Npn \__siunitx_number_in_store: { + \prop_put:NVn \l__siunitx_number_in_prop \l__siunitx_number_part_tl + { true } + \bool_if:NTF \l__siunitx_number_in_decimal_bool + { + \prop_put:NVV \l__siunitx_number_in_prop + \l__siunitx_number_part_decimal_tl \l__siunitx_number_parsed_tl + } + { + \prop_put:NVV \l__siunitx_number_in_prop + \l__siunitx_number_part_integer_tl \l__siunitx_number_parsed_tl + } + \tl_clear:N \l__siunitx_number_parsed_tl +} +\cs_new_protected:Npn \__siunitx_number_in_check:n #1 { } +\cs_new_protected:Npn \__siunitx_number_in_check_short:n #1 { + \prop_if_in:NVF \l__siunitx_number_in_prop + \l__siunitx_number_part_integer_tl + { + \prop_if_in:NVF \l__siunitx_number_in_prop + \l__siunitx_number_part_decimal_tl + { \__siunitx_error:nx { invalid-number } {#1} } + } + \bool_if:NF \l__siunitx_number_in_value_bool + { + \tl_if_eq:NNF \l__siunitx_number_part_tl + \c__siunitx_number_part_complex_tl + { + \prop_get:NVNT \l__siunitx_number_in_prop + \l__siunitx_number_part_sign_tl \l__siunitx_tmpa_tl + { + \tl_set:Nx \l__siunitx_tmpb_tl + { \l__siunitx_number_part_sign_tl -deleted } + \prop_put:NVV \l__siunitx_number_in_prop + \l__siunitx_tmpb_tl \l__siunitx_tmpa_tl + } + \prop_remove:NV \l__siunitx_number_in_prop + \l__siunitx_number_part_sign_tl + } + } +} +\cs_new_protected:Npn \__siunitx_number_in_check_full:n #1 { + \tl_if_eq:NNF \l__siunitx_number_part_tl + \c__siunitx_number_part_complex_tl + { \__siunitx_number_in_check_short:n {#1} } + \bool_if:NF \l__siunitx_number_in_complex_root_bool + { + \prop_get:NnN \l__siunitx_number_in_prop { complex-sign } + \l__siunitx_tmpa_tl + \tl_if_in:NVTF \l__siunitx_input_uncert_sign_tl \l__siunitx_tmpa_tl + { + \prop_if_in:NnTF \l__siunitx_number_in_prop { uncertainty } + { + \__siunitx_error:nx { misplaced-sign-token } + { \exp_not:n {#1} } + } + { \__siunitx_number_in_complex_to_uncert:n {#1} } + } + { + \__siunitx_error:nx { misplaced-sign-token } + { \exp_not:n {#1} } + } + } + \prop_get:NnNT \l__siunitx_number_in_prop { mantissa-sign } + \l__siunitx_tmpa_tl + { + \prop_if_in:NnF \l__siunitx_number_in_prop { mantissa } + { + \prop_remove:Nn \l__siunitx_number_in_prop { mantissa-sign } + \prop_put:NnV \l__siunitx_number_in_prop { complex-sign } + \l__siunitx_tmpa_tl + } + } +} +\cs_new_protected:Npn \__siunitx_number_in_complex_to_uncert:n #1 { + \prop_remove:Nn \l__siunitx_number_in_prop { complex } + \prop_remove:Nn \l__siunitx_number_in_prop { complex-decimal-marker } + \prop_remove:Nn \l__siunitx_number_in_prop { complex-sign } + \prop_put:Nnn \l__siunitx_number_in_prop { uncertainty } { true } + \prop_get:NnNTF \l__siunitx_number_in_prop { complex-integer } + \l__siunitx_number_uncert_tl + { + \tl_if_single:NTF \l__siunitx_number_uncert_tl + { + \int_compare:nNnTF \l__siunitx_number_uncert_tl = 0 + { \__siunitx_number_in_complex_to_uncert_dec:n {#1} } + { \__siunitx_number_in_complex_to_uncert_int: } + } + { \__siunitx_number_in_complex_to_uncert_int: } + } + { \__siunitx_number_in_complex_to_uncert_dec:n {#1} } + \prop_remove:Nn \l__siunitx_number_in_prop { complex-integer } + \prop_remove:Nn \l__siunitx_number_in_prop { complex-decimal } +} +\cs_new_protected:Npn \__siunitx_number_in_complex_to_uncert_int: { + \prop_get:NnNF \l__siunitx_number_in_prop { complex-decimal } + \l__siunitx_tmpa_tl + { \tl_clear:N \l__siunitx_tmpa_tl } + \prop_get:NnNF \l__siunitx_number_in_prop { mantissa-decimal } + \l__siunitx_tmpb_tl + { \tl_clear:N \l__siunitx_tmpb_tl } + \__siunitx_number_in_complex_to_uncert_pad: +} +\cs_new_protected:Npn \__siunitx_number_in_complex_to_uncert_dec:n + #1 + { + \tl_clear:N \l__siunitx_number_uncert_tl + \prop_get:NnNTF \l__siunitx_number_in_prop { complex-decimal } + \l__siunitx_tmpa_tl + { + \prop_get:NnN \l__siunitx_number_in_prop { mantissa-decimal } + \l__siunitx_tmpb_tl + \quark_if_no_value:NT \l__siunitx_tmpb_tl + { \tl_clear:N \l__siunitx_tmpb_tl } + \tl_map_function:NN + \l__siunitx_tmpa_tl + \__siunitx_number_in_complex_to_uncert_dec_loop:N + \__siunitx_number_in_complex_to_uncert_pad: + } + { \__siunitx_error:nx { misplaced-sign-token } { \exp_not:n {#1} } } + } +\cs_new_protected:Npn + \__siunitx_number_in_complex_to_uncert_dec_loop:N #1 + { + \str_if_eq:nnTF {#1} { 0 } + { + \tl_set:Nx \l__siunitx_tmpa_tl + { \tl_tail:N \l__siunitx_tmpa_tl } + \tl_if_empty:NF \l__siunitx_tmpb_tl + { + \tl_set:Nx \l__siunitx_tmpb_tl + { \tl_tail:N \l__siunitx_tmpb_tl } + } + } + { \tl_map_break: } + } +\cs_new_protected:Npn \__siunitx_number_in_complex_to_uncert_pad: + { + \int_set:Nn \l__siunitx_number_uncert_length_int + { \tl_count:N \l__siunitx_tmpa_tl } + \int_set:Nn \l__siunitx_number_mantissa_length_int + { \tl_count:N \l__siunitx_tmpb_tl } + \int_compare:nNnTF + { \l__siunitx_number_mantissa_length_int } + > { \l__siunitx_number_uncert_length_int } + { + \tl_set:Nx \l__siunitx_tmpa_tl + { + \exp_not:V \l__siunitx_tmpa_tl + \prg_replicate:nn + { + \l__siunitx_number_mantissa_length_int + - \l__siunitx_number_uncert_length_int + } + { 0 } + } + } + { + \prop_get:NnNF \l__siunitx_number_in_prop { mantissa-decimal } + \l__siunitx_tmpb_tl + { \tl_clear:N \l__siunitx_tmpb_tl } + \tl_set:Nx \l__siunitx_tmpb_tl + { + \exp_not:V \l__siunitx_tmpb_tl + \prg_replicate:nn + { + \l__siunitx_number_uncert_length_int + - \l__siunitx_number_mantissa_length_int + } + { 0 } + } + \tl_if_empty:NF \l__siunitx_tmpb_tl + { + \prop_put:NnV \l__siunitx_number_in_prop { mantissa-decimal } + \l__siunitx_tmpb_tl + \prop_if_in:NnF \l__siunitx_number_in_prop + { mantissa-decimal-marker } + { + \prop_put:Nnn \l__siunitx_number_in_prop + { mantissa-decimal-marker } { . } + } + } + } + \tl_put_right:NV \l__siunitx_number_uncert_tl \l__siunitx_tmpa_tl + \prop_put:NnV \l__siunitx_number_in_prop { mantissa-uncertainty } + \l__siunitx_number_uncert_tl + } +\int_new:N \l__siunitx_round_int +\tl_new:N \l__siunitx_round_tl +\bool_new:N \l__siunitx_round_bool +\tl_new:N \l__siunitx_round_decimal_in_tl +\tl_new:N \l__siunitx_round_decimal_out_tl +\tl_new:N \l__siunitx_round_discard_tl +\tl_new:N \l__siunitx_round_even_bool +\tl_new:N \l__siunitx_round_integer_in_tl +\tl_new:N \l__siunitx_round_integer_out_tl +\bool_new:N \l__siunitx_round_half_up_bool +\int_new:N \l__siunitx_process_decimal_int +\int_new:N \l__siunitx_process_uncertainty_int +\tl_new:N \l__siunitx_uncertainty_decimal_tl +\tl_new:N \l__siunitx_uncertainty_integer_tl +\bool_new:N \l__siunitx_process_fixed_bool +\bool_new:N \l__siunitx_process_engineering_bool +\bool_new:N \l__siunitx_process_scientific_bool +\bool_new:N \l__siunitx_process_drop_exponent_bool +\keys_define:nn { siunitx } + { + add-decimal-zero .bool_set:N = \l__siunitx_process_decimal_zero_bool, + add-integer-zero .bool_set:N = \l__siunitx_process_integer_zero_bool, + explicit-sign .tl_set:N = \l__siunitx_process_sign_tl, + fixed-exponent .int_set:N = \l__siunitx_process_fixed_int, + minimum-integer-digits .int_set:N = + \l__siunitx_process_integer_min_int, + retain-explicit-plus .bool_set:N = \l__siunitx_process_plus_bool, + omit-uncertainty .bool_set:N = \l__siunitx_omit_uncert_bool, + retain-unity-mantissa .bool_set:N = + \l__siunitx_process_unity_mantissa_bool, + retain-zero-exponent .bool_set:N = + \l__siunitx_process_zero_exponent_bool, + round-half .choice:, + round-half / even .code:n = + { \bool_set_false:N \l__siunitx_round_half_up_bool }, + round-half / up .code:n = + { \bool_set_true:N \l__siunitx_round_half_up_bool }, + round-integer-to-decimal .bool_set:N = + \l__siunitx_process_int_to_dec_bool, + round-minimum .tl_set:N = \l__siunitx_process_round_min_tl, + round-mode .choice: , + round-mode / figures .code:n = + { \tl_set:Nn \l__siunitx_round_tl { figures } }, + round-mode / off .code:n = { \tl_clear:N \l__siunitx_round_tl }, + round-mode / places .code:n = + { \tl_set:Nn \l__siunitx_round_tl { places } }, + round-precision .int_set:N = \l__siunitx_process_precision_int, + scientific-notation .choice: , + scientific-notation + / false .code:n = + { + \bool_set_false:N \l__siunitx_process_fixed_bool + \bool_set_false:N \l__siunitx_process_engineering_bool + \bool_set_false:N \l__siunitx_process_scientific_bool + }, + scientific-notation + / engineering .code:n = + { + \bool_set_false:N \l__siunitx_process_fixed_bool + \bool_set_true:N \l__siunitx_process_engineering_bool + \bool_set_true:N \l__siunitx_process_scientific_bool + }, + scientific-notation + / fixed .code:n = + { + \bool_set_true:N \l__siunitx_process_fixed_bool + \bool_set_false:N \l__siunitx_process_engineering_bool + \bool_set_false:N \l__siunitx_process_scientific_bool + }, + scientific-notation + / true .code:n = + { + \bool_set_false:N \l__siunitx_process_fixed_bool + \bool_set_false:N \l__siunitx_process_engineering_bool + \bool_set_true:N \l__siunitx_process_scientific_bool + }, + zero-decimal-to-integer .bool_set:N = + \l__siunitx_zero_decimal_to_integer_bool + } +\keys_set:nn { siunitx } + { + add-decimal-zero = true, + add-integer-zero = true, + retain-unity-mantissa = true, + round-half = up, + round-minimum = 0, + round-precision = 2 + } +\cs_new_protected:Npn \__siunitx_number_process: + { + \__siunitx_number_process_sign: + \__siunitx_number_process_zero_fill: + \__siunitx_number_process_mantissa: + \prop_if_in:NnF \l__siunitx_number_in_prop { symbolic } + { + \bool_if:NTF \l__siunitx_process_fixed_bool + { \__siunitx_number_process_fixed: } + { + \bool_if:NT \l__siunitx_process_scientific_bool + { \__siunitx_number_process_scientific: } + } + \__siunitx_number_process_exponent: + \__siunitx_number_process_uncertainty: + \bool_if:NT \l__siunitx_exp_to_prefix_bool + { + \tl_if_empty:NF \l__siunitx_unit_tl + { \__siunitx_number_exp_to_prefix: } + } + \prop_if_in:NnTF \l__siunitx_number_in_prop { uncertainty } + { + \bool_if:NT \l__siunitx_omit_uncert_bool + { + \prop_remove:Nn \l__siunitx_number_in_prop { uncertainty } + \prop_remove:Nn \l__siunitx_number_in_prop { mantissa-uncertainty } + } + } + { \__siunitx_number_process_round: } + } + \__siunitx_number_process_zero_to_integer: + \__siunitx_number_process_integer_digits: + \bool_if:NT \l__siunitx_process_drop_exponent_bool + { + \prop_remove:Nn \l__siunitx_number_in_prop { exponent } + \prop_remove:Nn \l__siunitx_number_in_prop { exponent-integer } + } + } +\cs_new_protected:Npn \__siunitx_number_process_exponent: { + \bool_if:NF \l__siunitx_process_zero_exponent_bool + { + \prop_if_in:NnT \l__siunitx_number_in_prop { exponent } + { + \bool_set_false:N \l__siunitx_tmp_bool + \__siunitx_number_process_exponent_aux:n { integer } + \bool_if:NF \l__siunitx_tmp_bool + { \__siunitx_number_process_exponent_aux:n { decimal } } + \bool_if:NF \l__siunitx_tmp_bool + { + \prop_remove:Nn \l__siunitx_number_in_prop { exponent } + \prop_remove:Nn \l__siunitx_number_in_prop + { exponent-integer } + \prop_remove:Nn \l__siunitx_number_in_prop + { exponent-decimal } + \prop_if_in:NnF \l__siunitx_number_in_prop { mantissa } + { + \prop_put:Nnn \l__siunitx_number_in_prop { mantissa } { true } + \prop_put:Nnn \l__siunitx_number_in_prop { mantissa-integer } { 1 } + } + } + } + } +} +\cs_new_protected:Npn \__siunitx_number_process_exponent_aux:n #1 { + \prop_get:NnNT \l__siunitx_number_in_prop { exponent- #1 } + \l__siunitx_tmpa_tl + { + \int_compare:nNnF { \l__siunitx_tmpa_tl } = { 0 } + { \bool_set_true:N \l__siunitx_tmp_bool } + } +} +\cs_new_protected:Npn \__siunitx_number_process_figures:n #1 + { + \int_compare:nNnTF \l__siunitx_process_precision_int > 0 + { + \prop_if_in:NnT \l__siunitx_number_in_prop {#1} + { \__siunitx_number_process_figures_aux:n {#1} } + } + { + \prop_remove:Nn \l__siunitx_number_in_prop { #1 -sign } + \prop_put:Nnn \l__siunitx_number_in_prop { #1 -integer } { 0 } + \prop_remove:Nn \l__siunitx_number_in_prop { #1 -decimal } + \bool_if:NF \l__siunitx_process_int_to_dec_bool + { \prop_remove:Nn \l__siunitx_number_in_prop { #1 -decimal-marker } } + } + } +\cs_new_protected:Npn \__siunitx_number_process_figures_aux:n #1 + { + \__siunitx_number_process_figures_init:n {#1} + \__siunitx_number_process_figures_count:n { integer } + \__siunitx_number_process_figures_count:n { decimal } + \bool_if:NTF \l__siunitx_round_bool + { + \bool_set_false:N \l__siunitx_round_bool + \int_compare:nNnTF + \l__siunitx_round_int > \l__siunitx_process_precision_int + { + \__siunitx_number_process_figures_round: + \__siunitx_number_process_round_tidy:n {#1} + } + { \__siunitx_number_process_figures_pad:n {#1} } + } + { + \prop_put:Nnn \l__siunitx_number_in_prop { #1 -integer } { 0 } + \prop_remove:Nn \l__siunitx_number_in_prop { #1 -decimal } + } + } +\cs_new_protected:Npn \__siunitx_number_process_figures_init:n #1 + { + \int_zero:N \l__siunitx_round_int + \bool_set_false:N \l__siunitx_round_bool + \bool_set_false:N \l__siunitx_round_even_bool + \prop_get:NnNF \l__siunitx_number_in_prop { #1 -decimal } + \l__siunitx_round_decimal_in_tl + { \tl_clear:N \l__siunitx_round_decimal_in_tl } + \prop_get:NnNF \l__siunitx_number_in_prop { #1 -integer } + \l__siunitx_round_integer_in_tl + { \tl_clear:N \l__siunitx_round_integer_in_tl } + \tl_clear:N \l__siunitx_round_decimal_out_tl + \tl_clear:N \l__siunitx_round_integer_out_tl + \tl_clear:N \l__siunitx_round_discard_tl + } +\cs_new_protected:Npn \__siunitx_number_process_figures_count:n #1 + { + \tl_if_empty:cF { l__siunitx_round_ #1 _in_tl } + { + \prop_if_in:NnF \l__siunitx_number_in_prop { #1 -uncertainty } + { \__siunitx_number_process_figures_count_aux:n {#1} } + } + } +\cs_new_protected:Npn \__siunitx_number_process_figures_count_aux:n #1 + { + \int_set:Nn \l__siunitx_tmp_int + { \tl_head:v { l__siunitx_round_ #1 _in_tl } } + \tl_set:cx { l__siunitx_round_ #1 _in_tl } + { \tl_tail:v { l__siunitx_round_ #1 _in_tl } } + \tl_put_left:cV { l__siunitx_round_ #1 _out_tl } \l__siunitx_tmp_int + \bool_if:NF \l__siunitx_round_bool + { + \int_compare:nNnF \l__siunitx_tmp_int = 0 + { \bool_set_true:N \l__siunitx_round_bool } + } + \bool_if:NT \l__siunitx_round_bool + { \int_incr:N \l__siunitx_round_int } + \tl_if_empty:cTF { l__siunitx_round_ #1 _in_tl } + { + \tl_set_eq:cc { l__siunitx_round_ #1 _in_tl } + { l__siunitx_round_ #1 _out_tl } + \tl_clear:c { l__siunitx_round_ #1 _out_tl } + } + { \__siunitx_number_process_figures_count_aux:n {#1} } + } +\cs_new_protected:Npn \__siunitx_number_process_figures_round: + { + \int_set:Nn \l__siunitx_round_int + { \l__siunitx_round_int - \l__siunitx_process_precision_int } + \tl_if_empty:NF \l__siunitx_round_decimal_in_tl + { \__siunitx_number_process_figures_round_loop: } + \tl_if_empty:NF \l__siunitx_round_integer_in_tl + { \__siunitx_number_process_figures_integer: } + \bool_if:NT \l__siunitx_round_bool + { \tl_put_left:Nn \l__siunitx_round_integer_out_tl { 1 } } + } +\cs_new_protected:Npn \__siunitx_number_process_figures_round_loop: + { + \__siunitx_number_process_round_decimal: + \tl_if_empty:NF \l__siunitx_round_decimal_in_tl + { \__siunitx_number_process_figures_round_loop: } + } +\cs_new_protected:Npn \__siunitx_number_process_figures_integer: + { + \int_compare:nNnT \l__siunitx_round_int > 0 + { \tl_put_left:Nn \l__siunitx_round_integer_out_tl { 0 } } + \int_compare:nNnF \l__siunitx_round_int > 1 + { + \int_set:Nn \l__siunitx_tmp_int + { \tl_head:N \l__siunitx_round_integer_in_tl } + \__siunitx_number_process_round_up: + \int_compare:nNnTF \l__siunitx_round_int = 1 + { + \int_compare:nNnT \l__siunitx_tmp_int > 4 + { \bool_set_true:N \l__siunitx_round_bool } + } + { + \int_compare:nNnT \l__siunitx_tmp_int = { 10 } + { + \bool_set_true:N \l__siunitx_round_bool + \int_zero:N \l__siunitx_tmp_int + } + \tl_put_left:NV \l__siunitx_round_integer_out_tl + \l__siunitx_tmp_int + } + } + \int_decr:N \l__siunitx_round_int + \tl_set:Nx \l__siunitx_round_integer_in_tl + { \tl_tail:N \l__siunitx_round_integer_in_tl } + \tl_if_empty:NF \l__siunitx_round_integer_in_tl + { \__siunitx_number_process_figures_integer: } + } +\cs_new_protected:Npn \__siunitx_number_process_figures_pad:n #1 { + \prop_get:NnN \l__siunitx_number_in_prop { #1 -integer } + \l__siunitx_round_integer_in_tl + \prop_get:NnN \l__siunitx_number_in_prop { #1 -decimal } + \l__siunitx_round_decimal_in_tl + \int_set:Nn \l__siunitx_round_int + { \l__siunitx_process_precision_int - \l__siunitx_round_int } + \__siunitx_number_process_pad:n {#1} +} +\cs_new_protected:Npn \__siunitx_number_process_fixed: { + \prop_if_in:NnF \l__siunitx_number_in_prop { complex } + { + \prop_get:NnNF \l__siunitx_number_in_prop { mantissa-integer } + \l__siunitx_tmpa_tl + { \tl_set:Nn \l__siunitx_tmpa_tl { 0 } } + \prop_get:NnNF \l__siunitx_number_in_prop { mantissa-decimal } + \l__siunitx_tmpb_tl + { \tl_clear:N \l__siunitx_tmpb_tl } + \tl_set:Nx \l__siunitx_tmpa_tl + { { \l__siunitx_tmpa_tl } { \l__siunitx_tmpb_tl } } + \prop_get:NnNF \l__siunitx_number_in_prop { exponent-integer } + \l__siunitx_tmpb_tl + { \tl_set:Nn \l__siunitx_tmpb_tl { 0 } } + \group_begin: + \prop_get:NnNT \l__siunitx_number_in_prop { exponent-sign } + \l__siunitx_tmpa_tl + { + \tl_put_left:NV \l__siunitx_tmpb_tl \l__siunitx_tmpa_tl + } + \exp_args:NNNV \group_end: + \tl_set:Nn \l__siunitx_tmpb_tl \l__siunitx_tmpb_tl + \tl_set:Nx \l__siunitx_tmpa_tl + { \l__siunitx_tmpa_tl { \l__siunitx_tmpb_tl } } + \exp_after:wN \__siunitx_number_process_fixed_aux_i:nnn + \l__siunitx_tmpa_tl + } +} +\cs_new_protected:Npn \__siunitx_number_process_fixed_aux_i:nnn #1#2#3 + { + \prop_put:Nnn \l__siunitx_number_in_prop { exponent } { true } + \int_compare:nNnTF \l__siunitx_process_fixed_int > 0 + { + \prop_put:NnV \l__siunitx_number_in_prop { exponent-integer } + \l__siunitx_process_fixed_int + \prop_remove:Nn \l__siunitx_number_in_prop { exponent-sign } + } + { + \prop_put:Nnx \l__siunitx_number_in_prop { exponent-integer } + { \int_eval:n { - \l__siunitx_process_fixed_int } } + \prop_put:Nnn \l__siunitx_number_in_prop { exponent-sign } { - } + } + \__siunitx_number_process_fixed_aux_ii:nnn {#1} {#2} {#3} + } +\cs_new_protected:Npn \__siunitx_number_process_fixed_aux_ii:nnn #1#2#3 + { + \bool_set_true:N \l__siunitx_tmp_bool + \tl_map_inline:nn {#1#2} + { + \str_if_eq:nnF {##1} { 0 } + { + \bool_set_false:N \l__siunitx_tmp_bool + \tl_map_break: + } + } + \bool_if:NF \l__siunitx_tmp_bool + { \__siunitx_number_process_fixed_aux_iii:nnn {#1} {#2} {#3} } + } +\cs_new_protected:Npn + \__siunitx_number_process_fixed_aux_iii:nnn #1#2#3 { + \int_compare:nNnTF {#3} > { \l__siunitx_process_fixed_int } + { \__siunitx_number_process_fixed_large:nnn {#1} {#2} {#3} } + { + \int_compare:nNnTF {#3} < { \l__siunitx_process_fixed_int } + { \__siunitx_number_process_fixed_small:nnn {#1} {#2} {#3} } + { + \prop_put:Nnn \l__siunitx_number_in_prop + { mantissa-integer } {#1} + \tl_if_empty:nTF {#2} + { + \prop_remove:Nn \l__siunitx_number_in_prop + { mantissa-decimal } + \prop_remove:Nn \l__siunitx_number_in_prop + { mantissa-decimal-marker } + } + { + \prop_put:Nnn \l__siunitx_number_in_prop + { mantissa-decimal } {#2} + \prop_if_in:NnF \l__siunitx_number_in_prop + { mantissa-decimal-marker } + { + \prop_put:Nnn \l__siunitx_number_in_prop + { mantissa-decimal-marker } { . } + } + } + } + } +} +\cs_new_protected:Npn \__siunitx_number_process_fixed_large:nnn #1 + { + \__siunitx_number_if_zero:nTF {#1} + { \__siunitx_number_process_fixed_large_aux:nnn { } } + { \__siunitx_number_process_fixed_large_aux:nnn {#1} } + } +\cs_new_protected:Npn \__siunitx_number_process_fixed_large_aux:nnn #1#2#3 + { + \cs_set_protected:Npn + \__siunitx_number_process_fixed_large_aux:w ##1##2 \q_stop + { + \tl_if_empty:nTF {##2} + { + \int_compare:nNnTF + { #3 - 1 } = { \l__siunitx_process_fixed_int } + { + \__siunitx_number_process_fixed_aux_ii:nnn { #1 ##1 } + { } { #3 - 1 } + } + { + \__siunitx_number_process_fixed_aux_ii:nnn { #1 ##1 } + { 0 } { #3 - 1 } + } + } + { + \__siunitx_number_if_zero:nTF {#1} + { + \__siunitx_number_process_fixed_aux_ii:nnn {##1} {##2} + { #3 - 1 } + } + { + \__siunitx_number_process_fixed_aux_ii:nnn { #1 ##1 } + {##2} { #3 - 1 } + } + } + } + \tl_if_empty:nTF {#2} + { \__siunitx_number_process_fixed_aux_ii:nnn { #1 0 } { } { #3 - 1 } } + { \__siunitx_number_process_fixed_large_aux:w #2 \q_stop } +} +\cs_new_protected:Npn \__siunitx_number_process_fixed_large_aux:w + { } +\cs_new_protected:Npn + \__siunitx_number_process_fixed_small:nnn #1#2#3 { + \cs_set_protected:Npn + \__siunitx_number_process_fixed_small_aux:w ##1##2 \q_stop ##3 + { + \tl_if_empty:nTF {##2} + { + \tl_if_empty:nTF {##3} + { + \__siunitx_number_process_fixed_aux_ii:nnn { 0 } + { ##1 #2 } { #3 + 1 } + } + { + \__siunitx_number_process_fixed_aux_ii:nnn {##3} + { ##1 #2 } { #3 + 1 } + } + } + { + \__siunitx_number_process_fixed_small_aux:w ##2 \q_stop + { ##3 ##1 } + } + } + \__siunitx_number_process_fixed_small_aux:w #1 \q_stop { } +} +\cs_new_protected:Npn \__siunitx_number_process_fixed_small_aux:w + { } +\cs_new_protected:Npn \__siunitx_number_process_integer_digits: { + \int_compare:nNnT \l__siunitx_process_integer_min_int > 0 + { + \prop_get:NnNT \l__siunitx_number_in_prop { mantissa-integer } + \l__siunitx_tmpa_tl + { + \int_set:Nn \l__siunitx_tmp_int + { + \l__siunitx_process_integer_min_int + - \tl_count:N \l__siunitx_tmpa_tl + } + \int_compare:nNnT \l__siunitx_tmp_int > 0 + { + \tl_set:Nx \l__siunitx_tmpa_tl + { + \prg_replicate:nn { \l__siunitx_tmp_int } { 0 } + \exp_not:V \l__siunitx_tmpa_tl + } + \prop_put:NnV \l__siunitx_number_in_prop + { mantissa-integer } \l__siunitx_tmpa_tl + } + } + } +} +\cs_new_protected:Npn \__siunitx_number_process_mantissa: { + \bool_if:NF \l__siunitx_process_unity_mantissa_bool + { + \prop_if_in:NnT \l__siunitx_number_in_prop { exponent } + { + \prop_get:NnNT \l__siunitx_number_in_prop { mantissa-integer } + \l__siunitx_tmpa_tl + { + \tl_if_eq:NNT \c__siunitx_unity_tl \l__siunitx_tmpa_tl + { + \prop_if_in:NnF \l__siunitx_number_in_prop + { mantissa-decimal-marker } + { + \prop_remove:Nn \l__siunitx_number_in_prop + { mantissa } + \prop_remove:Nn \l__siunitx_number_in_prop + { mantissa-integer } + } + } + } + } + } +} +\tl_const:Nn \c__siunitx_unity_tl { 1 } +\cs_new_protected:Npn \__siunitx_number_process_pad:n #1 { + \prop_get:NnNT \l__siunitx_number_in_prop { #1 -decimal } + \l__siunitx_tmpa_tl + { + \int_while_do:nNnn { \l__siunitx_round_int } > { 0 } + { + \tl_put_right:Nn \l__siunitx_tmpa_tl { 0 } + \int_decr:N \l__siunitx_round_int + } + \prop_put:NnV \l__siunitx_number_in_prop { #1 -decimal } + \l__siunitx_tmpa_tl + } +} +\cs_new_protected:Npn \__siunitx_number_process_places:n #1 + { + \prop_if_in:NnT \l__siunitx_number_in_prop {#1} + { + \prop_if_in:NnF \l__siunitx_number_in_prop { #1 -uncertainty } + { \__siunitx_number_process_places_aux_i:n {#1} } + } + } +\cs_new_protected:Npn \__siunitx_number_process_places_aux_i:n #1 + { + \int_compare:nNnTF \l__siunitx_process_precision_int = 0 + { \__siunitx_number_process_places_none:n {#1} } + { + \prop_get:NnNT \l__siunitx_number_in_prop { #1 -decimal } + \l__siunitx_tmpa_tl + { + \tl_if_empty:NT \l__siunitx_tmpa_tl + { \tl_set:Nn \l__siunitx_tmpa_tl { 0 } } + \__siunitx_number_process_places_aux_i:TF + { + \prop_put:Nnn \l__siunitx_number_in_prop { #1 -decimal } { } + \int_set:Nn \l__siunitx_round_int + { \l__siunitx_process_precision_int } + \__siunitx_number_process_pad:n {#1} + } + { + \int_set:Nn \l__siunitx_round_int + { \tl_count:N \l__siunitx_tmpa_tl } + \__siunitx_number_process_places_aux_ii:n {#1} + } + } + } + } +\cs_new_protected:Npn \__siunitx_number_process_places_aux_i:TF + { + \bool_set_true:N \l__siunitx_tmp_bool + \tl_map_inline:Nn \l__siunitx_tmpa_tl + { + \int_compare:nNnF {##1} = 0 + { + \bool_set_false:N \l__siunitx_tmp_bool + \tl_map_break: + } + } + \bool_if:NTF \l__siunitx_tmp_bool + } +\cs_new_protected:Npn \__siunitx_number_process_places_none:n #1 + { + \prop_get:NnNT \l__siunitx_number_in_prop { #1 -decimal } \l__siunitx_tmpa_tl + { + \int_compare:nNnTF { \tl_head:N \l__siunitx_tmpa_tl } > 4 + { + \prop_get:NnNTF \l__siunitx_number_in_prop { #1 -integer } + \l__siunitx_tmpb_tl + { + \tl_set:Nx \l__siunitx_tmpb_tl + { \int_eval:n { \l__siunitx_tmpb_tl + 1 } } + \bool_if:NF \l__siunitx_round_half_up_bool + { + \bool_lazy_and:nnT + { + \int_compare_p:nNn + { 0 \tl_head:N \l__siunitx_tmpa_tl } = 5 + } + { + \int_compare_p:nNn + { 0 \tl_tail:N \l__siunitx_tmpa_tl } = 0 + } + { + \int_if_odd:nT \l__siunitx_tmpb_tl + { + \tl_set:Nx \l__siunitx_tmpb_tl + { \int_eval:n { \l__siunitx_tmpb_tl - 1 } } + } + } + } + } + { \tl_set:Nn \l__siunitx_tmpb_tl { 1 } } + \prop_put:NnV \l__siunitx_number_in_prop + { #1 -integer } \l__siunitx_tmpb_tl + } + { + \prop_if_in:NnF \l__siunitx_number_in_prop { #1 -integer } + { + \prop_put:Nnn \l__siunitx_number_in_prop + { #1 -integer } { 0 } + } + } + } + \prop_remove:Nn \l__siunitx_number_in_prop { #1 -decimal } + \bool_if:NF \l__siunitx_process_int_to_dec_bool + { \prop_remove:Nn \l__siunitx_number_in_prop { #1 -decimal-marker } } + } +\cs_new_protected:Npn \__siunitx_number_process_places_aux_ii:n #1 + { + \int_sub:Nn \l__siunitx_round_int + { \l__siunitx_process_precision_int } + \int_compare:nNnTF \l__siunitx_round_int < 0 + { + \int_set:Nn \l__siunitx_round_int { - \l__siunitx_round_int } + \__siunitx_number_process_pad:n {#1} + } + { + \__siunitx_number_process_places_init:n {#1} + \__siunitx_number_process_places_loop:n {#1} + \__siunitx_number_process_round_tidy:n {#1} + } + } +\cs_new_protected:Npn \__siunitx_number_process_places_init:n #1 + { + \prop_get:NnNF \l__siunitx_number_in_prop { #1 -integer } + \l__siunitx_round_integer_in_tl + { \tl_clear:N \l__siunitx_round_integer_in_tl } + \prop_get:NnN \l__siunitx_number_in_prop { #1 -decimal } + \l__siunitx_round_decimal_in_tl + \tl_reverse:N \l__siunitx_round_integer_in_tl + \tl_reverse:N \l__siunitx_round_decimal_in_tl + \tl_clear:N \l__siunitx_round_integer_out_tl + \tl_clear:N \l__siunitx_round_decimal_out_tl + \tl_clear:N \l__siunitx_round_discard_tl + \bool_set_false:N \l__siunitx_round_bool + \bool_set_false:N \l__siunitx_round_even_bool + } +\cs_new_protected:Npn \__siunitx_number_process_places_loop:n #1 + { + \tl_if_empty:NTF \l__siunitx_round_decimal_in_tl + { + \tl_if_empty:NF \l__siunitx_round_integer_in_tl + { + \__siunitx_number_process_places_integer:n {#1} + \__siunitx_number_process_places_loop:n {#1} + } + \bool_if:NT \l__siunitx_round_bool + { + \tl_put_left:Nn \l__siunitx_round_integer_out_tl { 1 } + \bool_set_false:N \l__siunitx_round_bool + } + } + { + \__siunitx_number_process_round_decimal: + \__siunitx_number_process_places_loop:n {#1} + } + } +\cs_new_protected:Npn \__siunitx_number_process_places_integer:n #1 + { + \int_set:Nn \l__siunitx_tmp_int + { \tl_head:N \l__siunitx_round_integer_in_tl } + \tl_set:Nx \l__siunitx_round_integer_in_tl + { \tl_tail:N \l__siunitx_round_integer_in_tl } + \__siunitx_number_process_round_up: + \bool_set_false:N \l__siunitx_round_bool + \int_compare:nNnT \l__siunitx_tmp_int = { 10 } + { + \int_zero:N \l__siunitx_tmp_int + \bool_set_true:N \l__siunitx_round_bool + } + \tl_put_left:NV \l__siunitx_round_integer_out_tl \l__siunitx_tmp_int + } +\cs_new_protected:Npn \__siunitx_number_process_round: + { + \tl_if_empty:NF \l__siunitx_round_tl + { + \bool_if:NT \l__siunitx_process_int_to_dec_bool + { + \prop_if_in:NnF \l__siunitx_number_in_prop { mantissa-decimal } + { + \prop_put:Nnn \l__siunitx_number_in_prop { mantissa-decimal } + { 0 } + } + \prop_if_in:NnF \l__siunitx_number_in_prop + { mantissa-decimal-marker } + { + \prop_put:Nnn \l__siunitx_number_in_prop + { mantissa-decimal-marker } { . } + } + } + \clist_map_function:nc { mantissa , complex } + { __siunitx_number_process_ \l__siunitx_round_tl :n } + } + } +\cs_new_protected:Npn \__siunitx_number_process_round_decimal: + { + \int_compare:nNnF \l__siunitx_round_int > 1 + { \__siunitx_number_process_round_decimal_aux: } + \tl_put_right:Nx \l__siunitx_round_discard_tl + { \tl_head:N \l__siunitx_round_decimal_in_tl } + \tl_set:Nx \l__siunitx_round_decimal_in_tl + { \tl_tail:N \l__siunitx_round_decimal_in_tl } + \int_decr:N \l__siunitx_round_int + } +\cs_new_protected:Npn \__siunitx_number_process_round_decimal_aux: + { + \int_set:Nn \l__siunitx_tmp_int + { \tl_head:N \l__siunitx_round_decimal_in_tl } + \__siunitx_number_process_round_up: + \int_compare:nNnTF \l__siunitx_round_int = 1 + { + \int_compare:nNnT \l__siunitx_tmp_int > 4 + { + \bool_set_true:N \l__siunitx_round_bool + \bool_if:NF \l__siunitx_round_half_up_bool + { + \int_compare:nNnT + { \l__siunitx_round_discard_tl \int_use:N \l__siunitx_tmp_int } = 5 + { \bool_set_true:N \l__siunitx_round_even_bool } + } + } + } + { + \int_compare:nNnT \l__siunitx_tmp_int = { 10 } + { + \bool_set_true:N \l__siunitx_round_bool + \int_zero:N \l__siunitx_tmp_int + } + \tl_put_left:NV \l__siunitx_round_decimal_out_tl + \l__siunitx_tmp_int + } + } +\cs_new_protected:Npn \__siunitx_number_process_round_up: + { + \bool_if:NT \l__siunitx_round_bool + { + \bool_if:NTF \l__siunitx_round_even_bool + { + \bool_set_false:N \l__siunitx_round_even_bool + \int_if_even:nF \l__siunitx_tmp_int + { \int_incr:N \l__siunitx_tmp_int } + } + { \int_incr:N \l__siunitx_tmp_int } + } + \bool_set_false:N \l__siunitx_round_bool + } +\cs_new_protected:Npn \__siunitx_number_process_round_tidy:n #1 + { + \bool_lazy_and:nnTF + { \__siunitx_number_if_zero_p:V \l__siunitx_round_integer_out_tl } + { \__siunitx_number_if_zero_p:V \l__siunitx_round_decimal_out_tl } + { + \str_if_eq:VnTF \l__siunitx_process_round_min_tl { 0 } + { + \prop_put:Nnn \l__siunitx_number_in_prop { #1 -integer } { 0 } + \prop_put:NnV \l__siunitx_number_in_prop { #1 -decimal } + \l__siunitx_round_decimal_out_tl + } + { + \exp_after:wN \__siunitx_number_process_round_tidy_aux:w + \l__siunitx_process_round_min_tl . . \q_stop {#1} + } + } + { + \prop_put:NnV \l__siunitx_number_in_prop { #1 -integer } + \l__siunitx_round_integer_out_tl + \tl_if_empty:NTF \l__siunitx_round_decimal_out_tl + { + \prop_remove:Nn \l__siunitx_number_in_prop { #1 -decimal } + \prop_remove:Nn \l__siunitx_number_in_prop { #1 -decimal-marker } + } + { + \prop_put:NnV \l__siunitx_number_in_prop { #1 -decimal } + \l__siunitx_round_decimal_out_tl + } + } + } +\cs_new_protected:Npn \__siunitx_number_process_round_tidy_aux:w + #1 . #2 . #3 \q_stop #4 + { + \prop_put:Nnn \l__siunitx_number_in_prop { comparator } { < } + \prop_put:Nnn \l__siunitx_number_in_prop { #4 -integer } {#1} + \tl_if_empty:nTF {#2} + { \prop_remove:Nn \l__siunitx_number_in_prop { #4 -decimal } } + { \prop_put:Nnn \l__siunitx_number_in_prop { #4 -decimal } {#2} } + } +\cs_new_protected:Npn \__siunitx_number_process_scientific: { + \prop_if_in:NnF \l__siunitx_number_in_prop { complex } + { + \prop_get:NnNF \l__siunitx_number_in_prop { mantissa-integer } + \l__siunitx_tmpa_tl + { \tl_set:Nn \l__siunitx_tmpa_tl { 0 } } + \prop_get:NnNF \l__siunitx_number_in_prop { mantissa-decimal } + \l__siunitx_tmpb_tl + { \tl_clear:N \l__siunitx_tmpb_tl } + \tl_set:Nx \l__siunitx_tmpa_tl + { { \l__siunitx_tmpa_tl } { \l__siunitx_tmpb_tl } } + \prop_get:NnNF \l__siunitx_number_in_prop { exponent-integer } + \l__siunitx_tmpb_tl + { \tl_set:Nn \l__siunitx_tmpb_tl { 0 } } + \group_begin: + \prop_get:NnNT \l__siunitx_number_in_prop { exponent-sign } + \l__siunitx_tmpa_tl + { \tl_put_left:NV \l__siunitx_tmpb_tl \l__siunitx_tmpa_tl } + \exp_args:NNNV \group_end: + \tl_set:Nn \l__siunitx_tmpb_tl \l__siunitx_tmpb_tl + \tl_set:Nx \l__siunitx_tmpa_tl + { \l__siunitx_tmpa_tl { \l__siunitx_tmpb_tl } } + \exp_after:wN \__siunitx_number_process_scientific_aux_i:nnn + \l__siunitx_tmpa_tl + } +} +\cs_new_protected:Npn \__siunitx_number_process_scientific_aux_i:nnn #1#2#3 + { + \bool_set_true:N \l__siunitx_tmp_bool + \tl_map_inline:nn {#1#2} + { + \str_if_eq:nnF {##1} { 0 } + { + \bool_set_false:N \l__siunitx_tmp_bool + \tl_map_break: + } + } + \bool_if:NF \l__siunitx_tmp_bool + { \__siunitx_number_process_scientific_aux_ii:nnn {#1} {#2} {#3} } + } +\cs_new_protected:Npn + \__siunitx_number_process_scientific_aux_ii:nnn #1#2#3 { + \int_compare:nNnTF { \tl_count:n {#1} } > 1 + { \__siunitx_number_process_scientific_large:nnn {#1} {#2} {#3} } + { + \__siunitx_number_if_zero:nTF {#1} + { + \__siunitx_number_process_scientific_small:wn + #2 \q_stop {#3} + } + { + \bool_if:NTF \l__siunitx_process_engineering_bool + { \__siunitx_number_process_scientific_engineering:nnn } + { \__siunitx_number_process_scientific_store:nnn } + {#1} {#2} {#3} + } + + } +} +\cs_new_protected:Npn \__siunitx_number_process_scientific_large:nnn #1#2#3 + { + \cs_set_protected:Npn \__siunitx_number_process_scientific_large_loop:nNN + ##1##2##3 + { + \quark_if_recursion_tail_stop_do:Nn ##3 + { + \__siunitx_number_process_scientific_aux_ii:nnn {##1} { ##2 #2 } + { #3 + 1 } + } + \__siunitx_number_process_scientific_large_loop:nNN { ##1 ##2 } ##3 + } + \__siunitx_number_process_scientific_large_loop:nNN { } #1 + \q_recursion_tail \q_recursion_stop + } +\cs_new_protected:Npn + \__siunitx_number_process_scientific_small:wn #1#2 \q_stop #3 + { \__siunitx_number_process_scientific_aux_ii:nnn {#1} {#2} { #3 - 1 } } +\cs_new_protected:Npn + \__siunitx_number_process_scientific_store:nnn #1#2#3 + { + \prop_put:Nnn \l__siunitx_number_in_prop { mantissa-integer } {#1} + \tl_if_empty:nTF {#2} + { + \prop_remove:Nn \l__siunitx_number_in_prop { mantissa-decimal } + \prop_remove:Nn \l__siunitx_number_in_prop + { mantissa-decimal-marker } + } + { + \prop_put:Nnn \l__siunitx_number_in_prop + { mantissa-decimal } {#2} + \prop_if_in:NnF \l__siunitx_number_in_prop + { mantissa-decimal-marker } + { + \prop_put:Nnn \l__siunitx_number_in_prop + { mantissa-decimal-marker } { . } + } + } + \int_compare:nNnTF {#3} = { 0 } + { + \prop_remove:Nn \l__siunitx_number_in_prop { exponent } + \prop_remove:Nn \l__siunitx_number_in_prop { exponent-sign } + \prop_remove:Nn \l__siunitx_number_in_prop { exponent-integer } + } + { + \prop_put:Nnn \l__siunitx_number_in_prop { exponent } { true } + \int_compare:nNnTF {#3} > { 0 } + { + \int_set:Nn \l__siunitx_tmp_int {#3} + \prop_put:NnV \l__siunitx_number_in_prop + { exponent-integer } \l__siunitx_tmp_int + \prop_remove:Nn \l__siunitx_number_in_prop { exponent-sign } + } + { + \int_set:Nn \l__siunitx_tmp_int { 0 - (#3) } + \prop_put:NnV \l__siunitx_number_in_prop + { exponent-integer } \l__siunitx_tmp_int + \prop_put:Nnn \l__siunitx_number_in_prop { exponent-sign } + { - } + } + } + } +\cs_new_protected:Npn + \__siunitx_number_process_scientific_engineering:nnn #1#2#3 + { + \use:c + { + __siunitx_number_process_scientific_engineering_ + \int_compare:nNnTF {#3} < { 0 } + { + \int_case:nnF { \int_mod:nn { 0 - (#3) } { 3 } } + { + { 1 } { 2 } + { 2 } { 1 } + } + { 0 } + } + { \int_mod:nn {#3} { 3 } } + :nnn + } + {#1} {#2} {#3} + } +\cs_new_eq:cN + { __siunitx_number_process_scientific_engineering_0:nnn } + \__siunitx_number_process_scientific_store:nnn +\cs_new_protected:cpn + { __siunitx_number_process_scientific_engineering_1:nnn } #1#2#3 + { + \tl_if_empty:nTF {#2} + { + \__siunitx_number_process_scientific_store:nnn { #1 0 } { } + { #3 - 1 } + } + { + \use:c + { __siunitx_number_process_scientific_engineering_1:nw } + {#1} #2 \q_stop {#3} + } + } +\cs_new_protected:cpn + { __siunitx_number_process_scientific_engineering_1:nw } + #1#2#3 \q_stop #4 + { + \__siunitx_number_process_scientific_store:nnn + {#1#2} {#3} { #4 - 1 } + } +\cs_new_protected:cpn + { __siunitx_number_process_scientific_engineering_2:nnn } #1#2#3 + { + \tl_if_empty:nTF {#2} + { + \__siunitx_number_process_scientific_store:nnn { #1 00 } { } + { #3 - 2 } + } + { + \use:c + { __siunitx_number_process_scientific_engineering_2_i:nw } + {#1} #2 \q_stop {#3} + } + } +\cs_new_protected:cpn + { __siunitx_number_process_scientific_engineering_2_i:nw } + #1#2#3 \q_stop #4 + { + \tl_if_empty:nTF {#3} + { + \__siunitx_number_process_scientific_store:nnn { #1#2 0 } { } + { #4 - 2 } + } + { + \use:c + { __siunitx_number_process_scientific_engineering_2_ii:nw } + {#1#2} #3 \q_stop {#4} + } + } +\cs_new_protected:cpn + { __siunitx_number_process_scientific_engineering_2_ii:nw } + #1#2#3 \q_stop #4 + { + \__siunitx_number_process_scientific_store:nnn { #1#2 } {#3} + { #4 - 2 } + } +\cs_new_protected:Npn \__siunitx_number_process_sign: { + \bool_if:NF \l__siunitx_process_plus_bool + { + \prop_if_in:NnTF \l__siunitx_number_in_prop { mantissa-sign } + { \__siunitx_number_process_sign_plus:n { mantissa } } + { + \prop_if_in:NnT \l__siunitx_number_in_prop { complex-sign } + { + \prop_if_in:NnF \l__siunitx_number_in_prop { mantissa } + { \__siunitx_number_process_sign_plus:n { complex } } + } + } + \prop_if_in:NnT \l__siunitx_number_in_prop { exponent-sign } + { \__siunitx_number_process_sign_plus:n { exponent } } + } + \tl_if_empty:NF \l__siunitx_process_sign_tl + { + \__siunitx_number_process_sign_add:n { mantissa } + \prop_if_in:NnTF \l__siunitx_number_in_prop { complex } + { \__siunitx_number_process_sign_add:n { complex } } + } +} +\cs_new_protected:Npn \__siunitx_number_process_sign_add:n #1 { + \prop_if_in:NnF \l__siunitx_number_in_prop { #1 -sign } + { + \prop_if_in:NnF \l__siunitx_number_in_prop { #1 -had-sign } + { + \prop_get:NnN \l__siunitx_number_in_prop {#1} + \l__siunitx_tmpa_tl + \tl_if_empty:NTF \l__siunitx_tmpa_tl + { + \prop_put:NnV \l__siunitx_number_in_prop { sign } + \l__siunitx_process_sign_tl + } + { + \prop_put:NnV \l__siunitx_number_in_prop { #1 -sign } + \l__siunitx_process_sign_tl + } + } + } +} +\cs_new_protected:Npn \__siunitx_number_process_sign_plus:n #1 { + \prop_get:NnN \l__siunitx_number_in_prop { #1 -sign } + \l__siunitx_tmpa_tl + \tl_if_eq:NNT \c__siunitx_plus_tl \l__siunitx_tmpa_tl + { + \prop_remove:Nn \l__siunitx_number_in_prop { #1 -sign } + \prop_put:Nnn \l__siunitx_number_in_prop { #1 -had-sign } { true } + } +} +\tl_const:Nn \c__siunitx_plus_tl { + } +\cs_new_protected:Npn \__siunitx_number_process_uncertainty: { + \clist_map_function:nN { mantissa , complex } + \__siunitx_number_process_uncertainty_aux:n +} +\cs_new_protected:Npn + \__siunitx_number_process_uncertainty_aux:n #1 { + \prop_if_in:NnT \l__siunitx_number_in_prop { #1 -uncertainty } + { + \prop_if_in:NnTF \l__siunitx_number_in_prop { #1 -decimal-marker } + { \__siunitx_number_process_uncertainty_decimal:n {#1} } + { \__siunitx_number_process_uncertainty_integer:n {#1} } + } +} +\cs_new_protected:Npn + \__siunitx_number_process_uncertainty_decimal:n #1 { + \__siunitx_number_process_uncertainty_count:nn {#1} { decimal } + \__siunitx_number_process_uncertainty_count:nn {#1} { uncertainty } + \tl_clear:N \l__siunitx_uncertainty_decimal_tl + \tl_clear:N \l__siunitx_uncertainty_integer_tl + \int_compare:nNnTF + { \l__siunitx_process_uncertainty_int } > + { \l__siunitx_process_decimal_int } + { \__siunitx_number_process_uncertainty_separate: } + { \__siunitx_number_process_uncertainty_pad: } + \tl_if_empty:NF \l__siunitx_uncertainty_integer_tl + { + \prop_put:NnV \l__siunitx_number_in_prop + { #1 -uncertainty-integer } + \l__siunitx_uncertainty_integer_tl + } + \prop_put:NnV \l__siunitx_number_in_prop { #1 -uncertainty-decimal } + \l__siunitx_uncertainty_decimal_tl + \prop_get:NnN \l__siunitx_number_in_prop { #1 -decimal-marker } + \l__siunitx_tmpa_tl + \prop_put:NnV \l__siunitx_number_in_prop + { #1 -uncertainty-decimal-marker } \l__siunitx_tmpa_tl +} +\cs_new_protected:Npn + \__siunitx_number_process_uncertainty_count:nn #1#2 { + \prop_get:NnN \l__siunitx_number_in_prop { #1 - #2 } + \l__siunitx_tmpa_tl + \int_set:cn { l__siunitx_process_ #2 _int } + { \tl_count:N \l__siunitx_tmpa_tl } +} +\cs_new_protected:Npn \__siunitx_number_process_uncertainty_pad: { + \int_while_do:nNnn + { \l__siunitx_process_uncertainty_int } < + { \l__siunitx_process_decimal_int } + { + \tl_put_right:Nn \l__siunitx_uncertainty_decimal_tl {0} + \int_incr:N \l__siunitx_process_uncertainty_int + } + \tl_put_right:NV \l__siunitx_uncertainty_decimal_tl + \l__siunitx_tmpa_tl +} +\cs_new_protected:Npn + \__siunitx_number_process_uncertainty_separate: { + \tl_map_function:NN \l__siunitx_tmpa_tl + \__siunitx_number_process_uncertainty_separate_aux:N +} +\cs_new_protected:Npn + \__siunitx_number_process_uncertainty_separate_aux:N #1 { + \int_compare:nNnTF + { \l__siunitx_process_uncertainty_int } > + { \l__siunitx_process_decimal_int } + { \tl_put_right:Nn \l__siunitx_uncertainty_integer_tl {#1} } + { \tl_put_right:Nn \l__siunitx_uncertainty_decimal_tl {#1} } + \int_decr:N \l__siunitx_process_uncertainty_int +} +\cs_new_protected:Npn + \__siunitx_number_process_uncertainty_integer:n #1 { + \prop_get:NnN \l__siunitx_number_in_prop { #1 -uncertainty } + \l__siunitx_tmpa_tl + \prop_put:NnV \l__siunitx_number_in_prop { #1 -uncertainty-integer } + \l__siunitx_tmpa_tl +} +\cs_new_protected:Npn \__siunitx_number_process_zero_fill: { + \__siunitx_number_process_zero_fill_aux:n { integer } + \__siunitx_number_process_zero_fill_aux:n { decimal } +} +\cs_new:Npn \__siunitx_number_process_zero_fill_aux:n #1 { + \bool_if:cT { l__siunitx_process_ #1 _zero_bool } + { + \__siunitx_number_process_zero_fill_aux:nn { mantissa } {#1} + \__siunitx_number_process_zero_fill_aux:nn { complex } {#1} + \__siunitx_number_process_zero_fill_aux:nn { exponent } {#1} + } +} +\cs_new_protected:Npn + \__siunitx_number_process_zero_fill_aux:nn #1#2 { + \prop_if_in:NnT \l__siunitx_number_in_prop { #1 -decimal-marker } + { + \prop_if_in:NnF \l__siunitx_number_in_prop { #1 - #2 } + { \prop_put:Nnn \l__siunitx_number_in_prop { #1 - #2 } { 0 } } + } +} +\cs_new_protected:Npn \__siunitx_number_process_zero_to_integer: + { + \bool_if:NT \l__siunitx_zero_decimal_to_integer_bool + { + \__siunitx_number_process_zero_to_integer_aux:n { mantissa } + \__siunitx_number_process_zero_to_integer_aux:n { complex } + } + } +\cs_new_protected:Npn \__siunitx_number_process_zero_to_integer_aux:n #1 + { + \prop_get:NnNT \l__siunitx_number_in_prop { #1 -decimal } \l__siunitx_tmpa_tl + { + \bool_set_true:N \l__siunitx_tmp_bool + \tl_map_inline:Nn \l__siunitx_tmpa_tl + { + \str_if_eq:nnF {##1} { 0 } + { + \bool_set_false:N \l__siunitx_tmp_bool + \tl_map_break: + } + } + \bool_if:NT \l__siunitx_tmp_bool + { + \prop_remove:Nn \l__siunitx_number_in_prop { #1 -decimal } + \prop_remove:Nn \l__siunitx_number_in_prop { #1 -decimal-marker } + } + } + } +\cs_new_protected:Npn \__siunitx_number_exp_to_prefix: + { + \prop_set_eq:NN \l__siunitx_unit_prop \l__siunitx_unit_saved_prop + \prop_get:NnNT \l__siunitx_number_in_prop { exponent-integer } + \l__siunitx_tmpa_tl + { + \prop_get:NnNT \l__siunitx_number_in_prop { exponent-sign } + \l__siunitx_tmpb_tl + { \tl_put_left:NV \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl } + \prop_if_in:NnT \l__siunitx_unit_prop { per-1 } + { + \tl_set:Nx \l__siunitx_tmpa_tl + { \int_eval:n { - \l__siunitx_tmpa_tl } } + } + \prop_get:NnNT \l__siunitx_unit_prop { prefix-1 } \l__siunitx_tmpb_tl + { + \prop_remove:Nn \l__siunitx_unit_prop { prefix-1 } + \prop_remove:Nn \l__siunitx_unit_prop { prefix-symbol-1 } + \prop_get:NVN \l__siunitx_prefix_forward_prop \l__siunitx_tmpb_tl + \l__siunitx_tmpb_tl + \tl_set:Nx \l__siunitx_tmpa_tl + { \int_eval:n { \l__siunitx_tmpa_tl + \l__siunitx_tmpb_tl } } + } + \prop_get:NnNT \l__siunitx_unit_prop { power-1 } \l__siunitx_tmpb_tl + { + \tl_set:Nx \l__siunitx_tmpa_tl + { \int_eval:n { \l__siunitx_tmpa_tl / \l__siunitx_tmpb_tl } } + } + \prop_get:NVNTF \l__siunitx_prefix_reverse_prop \l__siunitx_tmpa_tl + \l__siunitx_tmpb_tl + { + \prop_remove:Nn \l__siunitx_number_in_prop { exponent } + \use:c + { + __siunitx_ \exp_after:wN \token_to_str:N \l__siunitx_tmpb_tl + _function:w + } + \prop_get:NnN \l__siunitx_unit_prop { total-units } \l__siunitx_tmpa_tl + \int_set:Nn \l__siunitx_unit_int \l__siunitx_tmpa_tl + \cs_set_eq:NN \__siunitx_pm: \pm + \__siunitx_unit_format: + \cs_set_eq:NN \pm \__siunitx_pm: + } + { + \msg_error:nnx { siunitx } { non-convertible-exponent } + { \l__siunitx_tmpa_tl } + } + } + } +\prop_new:N \l__siunitx_number_out_prop +\tl_new:N \l__siunitx_group_sep_tl +\tl_new:N \l__siunitx_output_decimal_tl +\bool_new:N \l__siunitx_complex_after_bool +\bool_new:N \l__siunitx_group_decimal_bool +\bool_new:N \l__siunitx_group_integer_bool +\keys_define:nn { siunitx } { + bracket-negative-numbers .bool_set:N = + \l__siunitx_negative_bracket_bool , + bracket-numbers .bool_set:N = \l__siunitx_brackets_bool, + close-bracket .tl_set:N = \l__siunitx_bracket_close_tl, + complex-root-position .choice:, + complex-root-position + / after-number .code:n = + { \bool_set_true:N \l__siunitx_complex_after_bool } , + complex-root-position + / before-number .code:n = + { \bool_set_false:N \l__siunitx_complex_after_bool } , + copy-complex-root .bool_set:N = + \l__siunitx_output_complex_copy_bool, + copy-decimal-marker .bool_set:N = + \l__siunitx_output_decimal_copy_bool, + exponent-base .tl_set:N = \l__siunitx_exponent_base_tl, + exponent-product .tl_set:N = + \l__siunitx_exponent_product_tl, + group-decimal-digits .meta:n = { group-digits = decimal }, + group-digits .choice: , + group-digits / + decimal .code:n = + { + \bool_set_true:N \l__siunitx_group_decimal_bool + \bool_set_false:N \l__siunitx_group_integer_bool + }, + group-digits / + false .code:n = + { + \bool_set_false:N \l__siunitx_group_decimal_bool + \bool_set_false:N \l__siunitx_group_integer_bool + }, + group-digits / + integer .code:n = + { + \bool_set_false:N \l__siunitx_group_decimal_bool + \bool_set_true:N \l__siunitx_group_integer_bool + }, + group-digits / + true .code:n = + { + \bool_set_true:N \l__siunitx_group_decimal_bool + \bool_set_true:N \l__siunitx_group_integer_bool + }, + group-digits .default:n = true , + group-four-digits .choice:, + group-four-digits / + false .meta:n = { group-minimum-digits = 5 }, + group-four-digits / + true .meta:n = { group-minimum-digits = 4 }, + group-four-digits .default:n = true, + group-integer-digits .meta:n = { group-digits = integer }, + group-minimum-digits .int_set:N = \l__siunitx_group_min_int, + group-separator .code:n = + { \tl_set:Nn \l__siunitx_group_sep_tl { {#1} } }, + negative-color .tl_set:N = \l__siunitx_negative_color_tl, + open-bracket .tl_set:N = \l__siunitx_bracket_open_tl, + output-close-uncertainty .tl_set:N = + \l__siunitx_output_uncert_close_tl, + output-complex-root .tl_set:N = \l__siunitx_output_complex_tl , + output-decimal-marker .code:n = + { \tl_set:Nn \l__siunitx_output_decimal_tl { {#1} } }, + output-exponent-marker .tl_set:N = \l__siunitx_output_exponent_tl, + output-open-uncertainty .tl_set:N = + \l__siunitx_output_uncert_open_tl, + separate-uncertainty .bool_set:N = \l__siunitx_uncert_sep_bool, + tight-spacing .bool_set:N = \l__siunitx_tight_bool, + uncertainty-separator .tl_set:N = \l__siunitx_uncert_sep_tl, +} +\keys_set:nn { siunitx } + { + bracket-numbers = true , % ( + close-bracket = ) , + complex-root-position = after-number , + copy-decimal-marker = false , + exponent-base = 10 , + exponent-product = \times , + group-digits = true , + group-minimum-digits = 5 , + group-separator = \, , + open-bracket = ( , % ) ( + output-close-uncertainty = ) , + output-complex-root = \ensuremath { \mathrm { i } } , + output-decimal-marker = . , + output-open-uncertainty = ( % ) + } +\cs_new_protected:Npn \__siunitx_number_format: { + \prop_if_empty:NF \l__siunitx_number_in_prop + { + \prop_clear:N \l__siunitx_number_out_prop + \__siunitx_number_format_reassemble: + \__siunitx_number_format_complex: + \__siunitx_number_format_sign:n { mantissa } + \__siunitx_number_format_sign:n { exponent } + \__siunitx_number_format_relation: + \__siunitx_number_format_color: + \__siunitx_number_format_final: + } +} +\cs_new_protected:Npn \__siunitx_number_format_brackets:n #1 { + \bool_if:NT \l__siunitx_brackets_bool + { + \prop_if_in:NnT \l__siunitx_number_out_prop { #1 -bracket } + { + \__siunitx_number_format_brackets_aux:n {#1} + \prop_remove:Nn \l__siunitx_number_out_prop { #1 -bracket } + } + } +} +\cs_new_protected:Npn \__siunitx_number_format_brackets_aux:n #1 { + \prop_get:NnNF \l__siunitx_number_out_prop { #1 -result } + \l__siunitx_tmpa_tl + { + \prop_get:NnN \l__siunitx_number_out_prop {#1} \l__siunitx_tmpa_tl + } + \tl_put_left:NV \l__siunitx_tmpa_tl \l__siunitx_bracket_open_tl + \tl_put_right:NV \l__siunitx_tmpa_tl \l__siunitx_bracket_close_tl + \str_if_eq:nnTF {#1} { result } + { \prop_put:NnV \l__siunitx_number_out_prop {#1} \l__siunitx_tmpa_tl } + { + \prop_put:NnV \l__siunitx_number_out_prop { #1 -result } + \l__siunitx_tmpa_tl + } +} +\cs_new_protected:Npn \__siunitx_number_format_color: { + \tl_if_empty:NF \l__siunitx_negative_color_tl + { + \__siunitx_number_format_color_aux:n { mantissa-sign } + \__siunitx_number_format_color_aux:n { sign } + } +} +\cs_new_protected:Npn \__siunitx_number_format_color_aux:n #1 { + \prop_get:NnNT \l__siunitx_number_in_prop {#1} \l__siunitx_tmpa_tl + { + \str_if_eq:VnT \l__siunitx_tmpa_tl { - } + { + \prop_put:NnV \l__siunitx_number_out_prop { color } + \l__siunitx_negative_color_tl + } + } +} +\cs_new_protected:Npn \__siunitx_number_format_complex: { + \prop_if_in:NnT \l__siunitx_number_in_prop { complex-root } + { + \prop_if_in:NnTF \l__siunitx_number_out_prop { complex } + { + \__siunitx_number_format_brackets:n { complex } + \__siunitx_number_format_complex_aux:n { complex } + \__siunitx_number_format_complex_aux:n { complex-result } + \prop_if_in:NnT \l__siunitx_number_out_prop + { complex-uncertainty } + { + \__siunitx_number_format_complex_aux:n + { complex-uncertainty } + } + } + { + \prop_put:NnV \l__siunitx_number_out_prop { complex } + \l__siunitx_output_complex_tl + } + \__siunitx_number_format_join_complex: + } +} +\cs_new_protected:Npn \__siunitx_number_format_complex_aux:n #1 { + \bool_if:NTF \l__siunitx_output_complex_copy_bool + { + \prop_get:NnN \l__siunitx_number_in_prop { complex-root } + \l__siunitx_tmpa_tl + } + { \tl_set_eq:NN \l__siunitx_tmpa_tl \l__siunitx_output_complex_tl } + \prop_get:NnN \l__siunitx_number_out_prop {#1} \l__siunitx_tmpb_tl + \bool_if:NTF \l__siunitx_complex_after_bool + { \tl_put_right:NV \l__siunitx_tmpb_tl \l__siunitx_tmpa_tl } + { \tl_put_left:NV \l__siunitx_tmpb_tl \l__siunitx_tmpa_tl } + \prop_put:NnV \l__siunitx_number_out_prop {#1} \l__siunitx_tmpb_tl +} +\cs_new_protected:Npn \__siunitx_number_format_copy:n #1 { + \prop_get:NnN \l__siunitx_number_in_prop {#1} \l__siunitx_tmpa_tl + \prop_put:NnV \l__siunitx_number_out_prop {#1} \l__siunitx_tmpa_tl +} +\cs_new_protected:Npn \__siunitx_number_format_copy:nn #1#2 { + \prop_get:NnN \l__siunitx_number_out_prop {#1} \l__siunitx_tmpa_tl + \prop_put:NnV \l__siunitx_number_out_prop {#2} \l__siunitx_tmpa_tl +} +\cs_new_protected:Npn \__siunitx_number_format_final: { + \prop_if_in:NnT \l__siunitx_number_out_prop { complex } + { + \prop_if_in:NnF \l__siunitx_number_out_prop { mantissa-result } + { + \__siunitx_number_format_copy:nn { complex } + { mantissa-result } + } + } + \prop_if_in:NnTF \l__siunitx_number_out_prop { exponent } + { + \__siunitx_number_format_final_exponent: + \prop_if_in:NnTF \l__siunitx_number_out_prop { mantissa-result } + { \__siunitx_number_format_final_combined: } + { \__siunitx_number_format_final_exponent_only: } + } + { \__siunitx_number_format_copy:nn { mantissa-result } { result } } + \prop_if_in:NnT \l__siunitx_number_out_prop { mantissa-bracket } + { + \prop_put:Nnn \l__siunitx_number_out_prop { result-bracket } + { true } + \prop_remove:Nn \l__siunitx_number_out_prop { mantissa-bracket } + } + \prop_if_in:NnT \l__siunitx_number_out_prop { comparator } + { + \__siunitx_number_format_brackets:n { result } + \prop_get:NnN \l__siunitx_number_out_prop { comparator } + \l__siunitx_tmpa_tl + \prop_get:NnN \l__siunitx_number_out_prop { result } + \l__siunitx_tmpb_tl + \tl_set:Nx \l__siunitx_tmpa_tl + { + \exp_not:N \mathord + \exp_not:V \l__siunitx_tmpa_tl + \exp_not:V \l__siunitx_tmpb_tl + } + \prop_put:NnV \l__siunitx_number_out_prop { result } + \l__siunitx_tmpa_tl + } +} +\cs_new_protected:Npn \__siunitx_number_format_final_combined: { + \__siunitx_number_format_brackets:n { mantissa } + \prop_get:NnN \l__siunitx_number_out_prop { mantissa-result } + \l__siunitx_tmpa_tl + \tl_if_empty:NT \l__siunitx_output_exponent_tl + { + \tl_put_right:Nx \l__siunitx_tmpa_tl + { + \exp_not:N \ensuremath + { + \bool_if:NTF \l__siunitx_tight_bool + { { \exp_not:V \l__siunitx_exponent_product_tl } } + { { } \exp_not:V \l__siunitx_exponent_product_tl { } } + } + } + } + \prop_get:NnN \l__siunitx_number_out_prop { exponent-result } + \l__siunitx_tmpb_tl + \tl_put_right:NV \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl + \prop_put:NnV \l__siunitx_number_out_prop { result } + \l__siunitx_tmpa_tl + \prop_put:Nnn \l__siunitx_number_out_prop + { result-bracket-exponent } { true } +} +\cs_new_protected:Npn \__siunitx_number_format_final_exponent: { + \prop_get:NnN \l__siunitx_number_out_prop { exponent } + \l__siunitx_tmpa_tl + \tl_if_empty:NTF \l__siunitx_output_exponent_tl + { + \tl_set:Nx \l__siunitx_tmpa_tl + { ^ { \exp_not:V \l__siunitx_tmpa_tl } } + \tl_put_left:NV \l__siunitx_tmpa_tl \l__siunitx_exponent_base_tl + } + { + \tl_set:Nx \l__siunitx_tmpa_tl + { + \exp_not:V \l__siunitx_output_exponent_tl + \exp_not:N \mathord + \exp_not:V \l__siunitx_tmpa_tl + } + } + \prop_put:NnV \l__siunitx_number_out_prop { exponent-result } + \l__siunitx_tmpa_tl +} +\cs_new_protected:Npn + \__siunitx_number_format_final_exponent_only: { + \prop_get:NnNT \l__siunitx_number_in_prop { mantissa-sign } + \l__siunitx_tmpa_tl + { + \prop_get:NnN \l__siunitx_number_out_prop { exponent-result } + \l__siunitx_tmpb_tl + \__siunitx_tl_put_left_math:NV \l__siunitx_tmpb_tl + \l__siunitx_tmpa_tl + \prop_put:NnV \l__siunitx_number_out_prop { exponent-result } + \l__siunitx_tmpb_tl + } + \__siunitx_number_format_copy:nn { exponent-result } { result } +} +\cs_new_protected:Npn \__siunitx_number_format_group:n #1 { + \__siunitx_number_format_group_aux:nn {#1} { integer } + \__siunitx_number_format_group_aux:nn {#1} { decimal } + \prop_if_in:NnTF \l__siunitx_number_out_prop { #1 -integer } + { \__siunitx_number_format_copy:nn { #1 -integer } {#1} } + { \tl_clear:N \l__siunitx_tmpa_tl } + \prop_get:NnNT \l__siunitx_number_in_prop { #1 -decimal-marker } + \l__siunitx_tmpb_tl + { + \bool_if:NTF \l__siunitx_output_decimal_copy_bool + { \tl_set:Nx \l__siunitx_tmpb_tl { { \l__siunitx_tmpb_tl } } } + { + \tl_set_eq:NN \l__siunitx_tmpb_tl + \l__siunitx_output_decimal_tl + } + \tl_put_right:NV \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl + \prop_put:NnV \l__siunitx_number_out_prop { #1 -decimal-marker } + \l__siunitx_tmpb_tl + \prop_get:NnNF \l__siunitx_number_out_prop { #1 -decimal } + \l__siunitx_tmpb_tl + { \tl_clear:N \l__siunitx_tmpb_tl } + \tl_put_right:NV \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl + \prop_put:NnV \l__siunitx_number_out_prop {#1} \l__siunitx_tmpa_tl + } +} +\cs_new_protected:Npn \__siunitx_number_format_group_aux:nn #1#2 { + \prop_if_in:NnT \l__siunitx_number_in_prop { #1 - #2 } + { + \bool_if:cTF { l__siunitx_group_ #2 _bool } + { \__siunitx_number_format_group:nn {#1} {#2} } + { \__siunitx_number_format_copy:n { #1 - #2 } } + } +} +\cs_new_protected:Npn \__siunitx_number_format_group:nn #1#2 + { + \prop_get:NnN \l__siunitx_number_in_prop { #1 - #2 } \l__siunitx_tmpa_tl + \int_compare:nNnTF + { \tl_count:N \l__siunitx_tmpa_tl } < \l__siunitx_group_min_int + { \__siunitx_number_format_copy:n { #1 - #2 } } + { + \tl_clear:N \l__siunitx_tmpb_tl + \use:c { __siunitx_number_format_group_ #2 : } + \prop_put:NnV \l__siunitx_number_out_prop { #1 - #2 } \l__siunitx_tmpb_tl + } + } +\cs_new_protected:Npn \__siunitx_number_format_group_decimal: { + \tl_if_empty:NF \l__siunitx_tmpa_tl + { + \exp_after:wN \__siunitx_number_format_group_decimal_aux:NNNN + \l__siunitx_tmpa_tl { } { } { } + } +} +\cs_new_protected:Npn \__siunitx_number_format_group_decimal_aux:NNNN + #1#2#3#4 { + \tl_if_empty:nTF {#2} + { \tl_put_right:Nn \l__siunitx_tmpb_tl {#1} } + { + \tl_if_empty:nTF {#3} + { \tl_put_right:Nn \l__siunitx_tmpb_tl { #1 #2 } } + { + \tl_put_right:Nn \l__siunitx_tmpb_tl { #1 #2 #3 } + \tl_if_empty:nF {#4} + { + \tl_put_right:NV \l__siunitx_tmpb_tl \l__siunitx_group_sep_tl + \__siunitx_number_format_group_decimal_aux:NNNN #4 + } + } + } +} +\cs_new_protected:Npn \__siunitx_number_format_group_integer: { + \tl_if_empty:NF \l__siunitx_tmpa_tl + { + \__siunitx_number_format_group_integer_setup:V \l__siunitx_tmpa_tl + } +} +\cs_new_protected:Npn \__siunitx_number_format_group_integer_setup:n #1 { + \__siunitx_number_format_group_integer_setup_aux:NNNN + { } #1 { } { } { } +} +\cs_generate_variant:Nn \__siunitx_number_format_group_integer_setup:n + { V } +\cs_new_protected:Npn + \__siunitx_number_format_group_integer_setup_aux:NNNN #1#2#3#4 { + \tl_if_empty:nTF {#2} + { \__siunitx_number_format_group_integer_aux:NNNN #1 \q_nil } + { + \tl_if_empty:nTF {#3} + { + \__siunitx_number_format_group_integer_aux:NNNN { } { } #1#2 + \q_nil + } + { + \tl_if_empty:nTF {#4} + { + \__siunitx_number_format_group_integer_aux:NNNN { } #1#2#3 + \q_nil + } + { + \__siunitx_number_format_group_integer_setup_aux:NNNN + {#1#2#3#4} + } + } + } +} +\cs_new_protected:Npn + \__siunitx_number_format_group_integer_aux:NNNN #1#2#3#4 { + \tl_put_right:Nn \l__siunitx_tmpb_tl {#1#2#3} + \quark_if_nil:nF {#4} + { + \tl_put_right:NV \l__siunitx_tmpb_tl \l__siunitx_group_sep_tl + \__siunitx_number_format_group_integer_aux:NNNN #4 + } +} +\cs_new_protected:Npn \__siunitx_number_format_join_complex: { + \__siunitx_number_format_sign_complex: + \prop_if_in:NnT \l__siunitx_number_out_prop { mantissa } + { + \__siunitx_number_format_brackets:n { mantissa } + \prop_get:NnN \l__siunitx_number_out_prop { mantissa-result } + \l__siunitx_tmpa_tl + \prop_get:NnNF \l__siunitx_number_out_prop { complex-result } + \l__siunitx_tmpb_tl + { + \prop_get:NnN \l__siunitx_number_out_prop { complex } + \l__siunitx_tmpb_tl + } + \tl_put_right:NV \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl + \prop_put:NnV \l__siunitx_number_out_prop { mantissa-result } + \l__siunitx_tmpa_tl + \prop_put:Nnn \l__siunitx_number_out_prop { mantissa-bracket } + { true } + } +} +\cs_new_protected:Npn \__siunitx_number_format_join_uncert: { + \__siunitx_number_format_join_uncert:n { mantissa } + \__siunitx_number_format_join_uncert:n { complex } +} +\cs_new_protected:Npn \__siunitx_number_format_join_uncert:n #1 { + \prop_get:NnNT \l__siunitx_number_out_prop {#1} + \l__siunitx_tmpa_tl + { + \prop_get:NnNTF \l__siunitx_number_out_prop { #1 -uncertainty } + \l__siunitx_tmpb_tl + { + \bool_if:NT \l__siunitx_uncert_sep_bool + { \__siunitx_number_format_join_uncert_pm:N \l__siunitx_tmpb_tl } + \tl_put_right:NV \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl + \prop_put:NnV \l__siunitx_number_out_prop { #1 -result } + \l__siunitx_tmpa_tl + \prop_put:Nnn \l__siunitx_number_out_prop { #1 -bracket } + { true } + } + { \__siunitx_number_format_copy:nn {#1} { #1 -result } } + } +} +\cs_new_protected:Npn \__siunitx_number_format_join_uncert_pm:N #1 + { + \bool_if:NTF \l__siunitx_tight_bool + { \tl_put_left:Nn #1 { \ensuremath { { \pm } } } } + { \tl_put_left:Nn #1 { \ensuremath { { } \pm { } } } } + } +\cs_new_protected:Npn \__siunitx_number_format_reassemble: { + \prop_if_in:NnT \l__siunitx_number_in_prop { mantissa } + { + \__siunitx_number_format_group:n { mantissa } + \__siunitx_number_format_uncertainty:n { mantissa } + } + \prop_if_in:NnT \l__siunitx_number_in_prop { complex } + { + \__siunitx_number_format_group:n { complex } + \__siunitx_number_format_uncertainty:n { complex } + } + \prop_if_in:NnT \l__siunitx_number_in_prop { exponent } + { \__siunitx_number_format_group:n { exponent } } +} +\cs_new_protected:Npn \__siunitx_number_format_relation: { + \prop_get:NnNT \l__siunitx_number_in_prop { comparator } + \l__siunitx_tmpa_tl + { + \tl_set:Nx \l__siunitx_tmpa_tl + { + \exp_not:N \ensuremath + { \exp_not:V \l__siunitx_tmpa_tl } + } + \prop_put:NnV \l__siunitx_number_out_prop { comparator } + \l__siunitx_tmpa_tl + } +} +\cs_new_protected:Npn \__siunitx_number_format_sign:n #1 { + \prop_if_in:NnT \l__siunitx_number_out_prop {#1} + { + \prop_get:NnNT \l__siunitx_number_in_prop { #1 -sign } + \l__siunitx_tmpa_tl + { + \bool_if:NTF \l__siunitx_negative_bracket_bool + { + \str_if_eq:VnTF \l__siunitx_tmpa_tl { - } + { \__siunitx_number_format_sign_negative_brackets:n {#1} } + { \__siunitx_number_format_sign_aux:n {#1} } + } + { \__siunitx_number_format_sign_aux:n {#1} } + } + } +} +\cs_new_protected:Npn \__siunitx_number_format_sign_aux:n #1 { + \tl_clear:N \l__siunitx_tmpb_tl + \tl_put_left:NV \l__siunitx_tmpb_tl \l__siunitx_tmpa_tl + \prop_put:NnV \l__siunitx_number_out_prop { #1 -sign } + \l__siunitx_tmpb_tl + \prop_get:NnN \l__siunitx_number_out_prop {#1} \l__siunitx_tmpa_tl + \tl_put_left:NV \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl + \prop_put:NnV \l__siunitx_number_out_prop {#1} \l__siunitx_tmpa_tl + \prop_get:NnNT \l__siunitx_number_out_prop { #1 -result } + \l__siunitx_tmpa_tl + { + \tl_put_left:NV \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl + \prop_put:NnV \l__siunitx_number_out_prop { #1 -result } + \l__siunitx_tmpa_tl + } +} +\cs_new_protected:Npn + \__siunitx_number_format_sign_negative_brackets:n #1 + { + \__siunitx_number_format_brackets_aux:n {#1} + \prop_get:NnNT \l__siunitx_number_out_prop { #1 } + \l__siunitx_tmpa_tl + { + \tl_put_left:NV \l__siunitx_tmpa_tl \l__siunitx_bracket_open_tl + \tl_put_right:NV \l__siunitx_tmpa_tl \l__siunitx_bracket_close_tl + \prop_put:NnV \l__siunitx_number_out_prop { #1 } + \l__siunitx_tmpa_tl + } + } +\cs_new_protected:Npn \__siunitx_number_format_sign_complex: { + \__siunitx_number_format_sign_complex:n { complex } + \__siunitx_number_format_sign_complex:n { complex-result } +} +\cs_new_protected:Npn \__siunitx_number_format_sign_complex:n #1 { + \prop_if_in:NnT \l__siunitx_number_out_prop {#1} + { + \prop_get:NnNT \l__siunitx_number_in_prop { complex-sign } + \l__siunitx_tmpa_tl + { + \bool_if:NTF \l__siunitx_tight_bool + { + \tl_set:Nx \l__siunitx_tmpa_tl + { \exp_not:N \mathord \exp_not:V \l__siunitx_tmpa_tl } + } + { + \prop_if_in:NnT \l__siunitx_number_out_prop { mantissa } + { + \tl_set:Nx \l__siunitx_tmpa_tl + { { } \exp_not:V \l__siunitx_tmpa_tl { } } + } + } + \tl_clear:N \l__siunitx_tmpb_tl + \tl_put_left:NV \l__siunitx_tmpb_tl \l__siunitx_tmpa_tl + \prop_put:NnV \l__siunitx_number_out_prop { complex-sign } + \l__siunitx_tmpb_tl + \prop_get:NnN \l__siunitx_number_out_prop {#1} + \l__siunitx_tmpa_tl + \tl_put_left:NV \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl + \prop_put:NnV \l__siunitx_number_out_prop {#1} + \l__siunitx_tmpa_tl + } + } +} +\cs_new_protected:Npn \__siunitx_number_format_uncertainty:n #1 { + \prop_if_in:NnTF \l__siunitx_number_in_prop { #1 -uncertainty } + { + \bool_if:NTF \l__siunitx_uncert_sep_bool + { \__siunitx_number_format_uncertainty_sep:n {#1} } + { \__siunitx_number_format_uncertainty_joined:n {#1} } + \__siunitx_number_format_join_uncert: + } + { \__siunitx_number_format_copy:nn {#1} { #1 -result } } +} +\cs_new_protected:Npn + \__siunitx_number_format_uncertainty_joined:n #1 { + \prop_get:NnN \l__siunitx_number_in_prop { #1 -uncertainty } + \l__siunitx_tmpa_tl + \prop_remove:Nn \l__siunitx_number_in_prop { #1 -uncertainty } + \tl_put_left:NV \l__siunitx_tmpa_tl \l__siunitx_output_uncert_open_tl + \tl_put_left:NV \l__siunitx_tmpa_tl \l__siunitx_uncert_sep_tl + \tl_put_right:NV \l__siunitx_tmpa_tl \l__siunitx_output_uncert_close_tl + \prop_get:NnN \l__siunitx_number_out_prop {#1} \l__siunitx_tmpb_tl + \tl_put_right:NV \l__siunitx_tmpb_tl \l__siunitx_tmpa_tl + \prop_put:NnV \l__siunitx_number_out_prop {#1} \l__siunitx_tmpb_tl +} +\cs_new_protected:Npn + \__siunitx_number_format_uncertainty_sep:n #1 { + \prop_if_in:NnT \l__siunitx_number_out_prop { #1 -integer } + { + \prop_if_in:NnF \l__siunitx_number_out_prop + { #1 -uncertainty-integer } + { + \prop_put:Nnn \l__siunitx_number_out_prop + { #1 -uncertainty-integer } { 0 } + } + } + \__siunitx_number_format_group:n { #1 -uncertainty } + \prop_put:NnV \l__siunitx_number_out_prop { #1 -uncertainty } + \l__siunitx_tmpa_tl +} +\tl_new:N \l__siunitx_number_out_tl +\tl_new:N \l__siunitx_number_out_saved_tl +\tl_new:N \l__siunitx_number_fraction_tl +\bool_new:N \l__siunitx_number_compound_bool +\tl_new:N \l__siunitx_quotient_mode_tl +\cs_new_protected:Npn \__siunitx_fraction:nn { } +\keys_define:nn { siunitx } { + fraction-function .code:n = + { \cs_set_protected:Npn \__siunitx_fraction:nn {#1} }, + output-product .tl_set:N = \l__siunitx_output_product_tl, + output-quotient .tl_set:N = \l__siunitx_output_quotient_tl, + parse-numbers .bool_set:N = \l__siunitx_number_parse_bool, + quotient-mode .choice:, + quotient-mode / fraction .code:n = + { \tl_set:Nn \l__siunitx_quotient_mode_tl { fraction } }, + quotient-mode / symbol .code:n = + { \tl_set:Nn \l__siunitx_quotient_mode_tl { symbol } }, +} +\keys_set:nn { siunitx } { + fraction-function = \frac , + output-product = \times , + output-quotient = / , + parse-numbers = true , + quotient-mode = symbol +} +\cs_new_protected:Npn \__siunitx_number_output:n #1 { + \tl_clear:N \l__siunitx_unit_tl + \tl_clear:N \l__siunitx_preunit_tl + \__siunitx_combined_output:n {#1} +} +\cs_generate_variant:Nn \__siunitx_number_output:n { V } +\cs_new_protected:Npn \__siunitx_number_output_bracket: { + \bool_if:NF \l__siunitx_error_bool + { + \bool_if:NT \l__siunitx_number_compound_bool + { \__siunitx_number_format_brackets:n { result } } + } +} +\cs_new_protected:Npn \__siunitx_number_output_color: { + \prop_if_in:NnT \l__siunitx_number_out_prop { color } + { + \prop_get:NnN \l__siunitx_number_out_prop { color } + \l__siunitx_number_color_tl + } +} +\cs_new_protected:Npn \__siunitx_number_output_parse:n #1 { + \__siunitx_number_preprocess:n {#1} + \bool_if:NF \l__siunitx_error_bool + { + \tl_if_empty:NTF \l__siunitx_number_multi_tl + { \__siunitx_number_output_parse_aux: } + { + \use:c + { __siunitx_number_output_ \l__siunitx_number_multi_tl : } + } + } +} +\cs_generate_variant:Nn \__siunitx_number_output_parse:n { V } +\cs_new_protected:Npn \__siunitx_number_output_parse_aux: { + \__siunitx_number_in_parse:V \l__siunitx_number_arg_tl + \bool_if:NF \l__siunitx_error_bool + { + \__siunitx_number_process: + \__siunitx_number_format: + \__siunitx_number_output_color: + \bool_if:NTF \l__siunitx_brackets_bool + { \__siunitx_number_output_single: } + { + \prop_if_in:NnTF \l__siunitx_number_out_prop + { result-bracket } + { \__siunitx_number_output_parts: } + { \__siunitx_number_output_single: } + } + } +} +\cs_new_protected:Npn \__siunitx_number_output_parts: { + \bool_lazy_and:nnTF + { \tl_if_empty_p:N \l__siunitx_pre_unit_tl } + { \tl_if_empty_p:N \l__siunitx_unit_tl } + { \__siunitx_number_output_single: } + { \__siunitx_number_output_parts_aux: } +} +\cs_new_protected:Npn \__siunitx_number_output_parts_aux: { + \bool_if:NTF \l__siunitx_multi_repeat_bool + { + \prop_if_in:NnT \l__siunitx_number_out_prop { mantissa-result } + { + \__siunitx_number_output_parts_aux:n { mantissa } + \__siunitx_number_output_parts_aux:n { complex } + } + \prop_get:NnNT \l__siunitx_number_out_prop { exponent-result } + \l__siunitx_tmpa_tl + { + \prop_if_in:NnT \l__siunitx_number_out_prop { mantissa-result } + { + \tl_put_left:Nx \l__siunitx_tmpa_tl + { + \exp_not:N \ensuremath + { + \bool_if:NTF \l__siunitx_tight_bool + { { \exp_not:V \l__siunitx_exponent_product_tl } } + { { } \exp_not:V \l__siunitx_exponent_product_tl { } } + } + } + \prop_put:NnV \l__siunitx_number_out_prop { exponent } + \l__siunitx_tmpa_tl + } + \__siunitx_number_output_parts_print:n { exponent } + } + } + { \__siunitx_number_output_single: } +} +\cs_new_protected:Npn \__siunitx_number_output_parts_aux:n #1 { + \prop_if_in:NnT \l__siunitx_number_out_prop {#1} + { \__siunitx_number_output_parts_print:n {#1} } + \prop_if_in:NnT \l__siunitx_number_out_prop { #1 -uncertainty } + { + \bool_if:NTF \l__siunitx_tight_bool + { \__siunitx_print:nn { number } { \ensuremath { { \pm } } } } + { \__siunitx_print:nn { number } { \ensuremath { { } \pm { } } } } + \__siunitx_number_output_parts_print:n { #1 -uncertainty } + } +} +\cs_new_protected:Npn \__siunitx_number_output_parts_print:n #1 { + \__siunitx_unit_output_pre_print: + \prop_get:NnN \l__siunitx_number_out_prop {#1} \l__siunitx_tmpa_tl + \__siunitx_print:nV { number } \l__siunitx_tmpa_tl + \__siunitx_unit_output_print: +} +\cs_new_protected:Npn \__siunitx_number_output_product: { + \bool_if:NTF \l__siunitx_product_brackets_bool + { + \bool_lazy_and:nnTF + { \tl_if_empty_p:N \l__siunitx_pre_unit_tl } + { \tl_if_empty_p:N \l__siunitx_unit_tl } + { \__siunitx_number_output_product_aux: } + { \__siunitx_number_output_product_brackets: } + } + { + \bool_if:NTF \l__siunitx_product_repeat_bool + { \__siunitx_number_output_product_aux: } + { + \__siunitx_unit_output_pre_print: + \tl_set_eq:NN \l__siunitx_unit_saved_tl \l__siunitx_unit_tl + \tl_clear:N \l__siunitx_pre_unit_tl + \tl_clear:N \l__siunitx_unit_tl + \group_begin: + \__siunitx_number_output_product_aux: + \group_end: + \tl_set_eq:NN \l__siunitx_unit_tl \l__siunitx_unit_saved_tl + \__siunitx_unit_output_print: + } + } +} +\cs_new_protected:Npn \__siunitx_number_output_product_brackets: { + \__siunitx_unit_output_pre_print: + \__siunitx_print:nV { number } \l__siunitx_bracket_open_tl + \nobreak + \tl_set_eq:NN \l__siunitx_unit_saved_tl \l__siunitx_unit_tl + \tl_clear:N \l__siunitx_pre_unit_tl + \tl_clear:N \l__siunitx_unit_tl + \__siunitx_number_output_product_aux: + \nobreak + \tl_set_eq:NN \l__siunitx_unit_tl \l__siunitx_unit_saved_tl + \__siunitx_print:nV { number } \l__siunitx_bracket_close_tl + \__siunitx_unit_output_print: +} +\cs_new_protected:Npn \__siunitx_number_output_product_aux: { + \bool_set_true:N \l__siunitx_number_compound_bool + \__siunitx_number_preprocess:V \l__siunitx_number_arg_tl + \bool_if:NF \l__siunitx_error_bool + { + \tl_if_empty:NTF \l__siunitx_number_multi_tl + { \__siunitx_number_output_parse_aux: } + { \__siunitx_number_output_quotient: } + \tl_if_empty:NF \l__siunitx_number_next_tl + { + \bool_if:NTF \l__siunitx_tight_bool + { + \__siunitx_print:nn { number } + { \ensuremath { \l__siunitx_output_product_tl } } + } + { + \__siunitx_print:nn { number } + { \ensuremath { { } \l__siunitx_output_product_tl { } } } + } + \__siunitx_number_output_parse:V \l__siunitx_number_next_tl + } + } +} +\cs_new_protected:Npn \__siunitx_number_output_quotient: { + \use:c + { __siunitx_number_output_quotient_ \l__siunitx_quotient_mode_tl : } +} +\cs_new_protected:Npn \__siunitx_number_output_quotient_fraction: { + \bool_set_false:N \l__siunitx_number_compound_bool + \__siunitx_number_output_quotient_aux_i: + \tl_set:Nx \l__siunitx_number_out_tl + { { \exp_not:V \l__siunitx_number_numerator_tl } } + \tl_set:Nx \l__siunitx_tmpa_tl + { { \exp_not:V \l__siunitx_number_denominator_tl } } + \tl_put_right:NV \l__siunitx_number_out_tl \l__siunitx_tmpa_tl + \tl_put_left:Nn \l__siunitx_number_out_tl { \__siunitx_fraction:nn } + \tl_set:Nx \l__siunitx_number_out_tl + { + \exp_not:N \ensuremath + { \exp_not:V \l__siunitx_number_out_tl } + } + \__siunitx_number_output_single_aux: +} +\cs_new_protected:Npn \__siunitx_number_output_quotient_symbol: { + \bool_set_true:N \l__siunitx_number_compound_bool + \__siunitx_number_output_quotient_aux_i: + \tl_set_eq:NN \l__siunitx_number_out_tl + \l__siunitx_number_numerator_tl + \tl_put_right:NV \l__siunitx_number_out_tl \l__siunitx_output_quotient_tl + \tl_put_right:NV \l__siunitx_number_out_tl + \l__siunitx_number_denominator_tl + \__siunitx_number_output_single_aux: +} +\cs_new_protected:Npn \__siunitx_number_output_quotient_aux_i: { + \__siunitx_number_in_parse:V \l__siunitx_number_numerator_tl + \__siunitx_number_output_quotient_aux_ii: + \__siunitx_number_output_color: + \prop_if_in:NnT \l__siunitx_number_out_prop { complex } + { + \prop_if_in:NnT \l__siunitx_number_out_prop { mantissa } + { + \prop_put:Nnn \l__siunitx_number_out_prop + { result-bracket } { true } + \__siunitx_number_format_brackets:n { result } + } + } + \prop_get:NnN \l__siunitx_number_out_prop { result } + \l__siunitx_number_numerator_tl + \__siunitx_number_in_parse:V \l__siunitx_number_denominator_tl + \__siunitx_number_output_quotient_aux_ii: + \prop_if_in:NnT \l__siunitx_number_out_prop + { result-bracket-exponent } + { + \prop_put:Nnn \l__siunitx_number_out_prop { result-bracket } + { true } + } + \__siunitx_number_output_bracket: + \prop_get:NnN \l__siunitx_number_out_prop { result } + \l__siunitx_number_denominator_tl +} +\cs_new_protected:Npn \__siunitx_number_output_quotient_aux_ii: { + \__siunitx_number_process: + \__siunitx_number_format: +} +\cs_new_protected:Npn \__siunitx_number_output_single: { + \bool_lazy_and:nnF + { \tl_if_empty_p:N \l__siunitx_pre_unit_tl } + { \tl_if_empty_p:N \l__siunitx_unit_tl } + { + \prop_if_in:NnF \l__siunitx_number_out_prop { exponent } + { \__siunitx_number_format_brackets:n { result } } + } + \__siunitx_number_output_bracket: + \prop_get:NnN \l__siunitx_number_out_prop { result } + \l__siunitx_number_out_tl + \__siunitx_number_output_single_aux: +} +\cs_new_protected:Npn \__siunitx_number_output_single_aux: { + \__siunitx_unit_output_pre_print: + \quark_if_no_value:NTF \l__siunitx_number_out_tl + { \tl_clear:N \l__siunitx_number_unit_product_tl } + { \__siunitx_print:nV { number } \l__siunitx_number_out_tl } + \__siunitx_unit_output_print: +} +\bool_new:N \l__siunitx_angle_degree_space_bool +\bool_new:N \l__siunitx_angle_minute_space_bool +\box_new:N \l__siunitx_angle_marker_box +\box_new:N \l__siunitx_angle_unit_box +\dim_new:N \l__siunitx_angle_marker_dim +\dim_new:N \l__siunitx_angle_unit_dim +\prop_new:N \l__siunitx_angle_degree_prop +\prop_new:N \l__siunitx_angle_minute_prop +\prop_new:N \l__siunitx_angle_second_prop +\keys_define:nn { siunitx } { + add-arc-degree-zero .bool_set:N = + \l__siunitx_angle_degree_zero_bool , + add-arc-minute-zero .bool_set:N = + \l__siunitx_angle_minute_zero_bool , + add-arc-second-zero .bool_set:N = + \l__siunitx_angle_second_zero_bool , + angle-symbol-over-decimal .bool_set:N = + \l__siunitx_angle_astronomy_bool , + arc-separator .tl_set:N = + \l__siunitx_angle_arc_separator_tl , + number-angle-product .tl_set:N = + \l__siunitx_angle_unit_product_tl , + number-angle-separator .tl_set:N = + \l__siunitx_angle_unit_product_tl , +} +\cs_new_protected:Npn \__siunitx_angle_output:nnn #1#2#3 { + \__siunitx_angle_init: + \IfNoValueTF {#2} + { + \bool_set_false:N \l__siunitx_angle_minute_zero_bool + \bool_set_false:N \l__siunitx_angle_second_zero_bool + \__siunitx_angle_output_aux:nnn {#1} { } { } + } + { + \IfNoValueTF {#3} + { \__siunitx_error:nx { invalid-arc-format } { #1 ; #2 } } + { \__siunitx_angle_output_aux:nnn {#1} {#2} {#3} } + } +} +\cs_new_protected:Npn \__siunitx_angle_output_aux:nnn #1#2#3 { + \tl_if_empty:nTF { #1#2#3 } + { \__siunitx_error:n { empty-arc } } + { + \bool_if:NTF \l__siunitx_number_parse_bool + { \__siunitx_angle_parse:nnn {#1} {#2} {#3} } + { \__siunitx_angle_direct:nnn {#1} {#2} {#3} } + } +} +\cs_new_protected:Npn \__siunitx_angle_init: { + \bool_set_false:N \l__siunitx_angle_degree_space_bool + \bool_set_false:N \l__siunitx_angle_minute_space_bool + \prop_clear:N \l__siunitx_angle_degree_prop + \prop_clear:N \l__siunitx_angle_minute_prop + \prop_clear:N \l__siunitx_angle_second_prop + \tl_clear:N \l__siunitx_preunit_tl + \tl_set_eq:NN \l__siunitx_number_unit_product_tl + \l__siunitx_angle_unit_product_tl + \cs_set_eq:NN \__siunitx_number_in_parse_more:N + \__siunitx_number_in_parse_restricted:N +} +\cs_new_protected:Npn \__siunitx_angle_direct:nnn #1 { + \tl_if_empty:nTF {#1} + { + \bool_if:NTF \l__siunitx_angle_degree_zero_bool + { \__siunitx_angle_direct_aux_i:nnn { 0 } } + { \__siunitx_angle_direct_aux_i:nnn { } } + } + { \__siunitx_angle_direct_aux_i:nnn {#1} } +} +\cs_new_protected:Npn \__siunitx_angle_direct_aux_i:nnn #1#2 { + \tl_if_empty:nTF {#2} + { + \bool_if:NTF \l__siunitx_angle_minute_zero_bool + { \__siunitx_angle_direct_aux_ii:nnn {#1} { 0 } } + { \__siunitx_angle_direct_aux_ii:nnn {#1} { } } + } + { \__siunitx_angle_direct_aux_ii:nnn {#1} {#2} } +} +\cs_new_protected:Npn \__siunitx_angle_direct_aux_ii:nnn #1#2#3 { + \tl_if_empty:nTF {#3} + { + \bool_if:NTF \l__siunitx_angle_second_zero_bool + { \__siunitx_angle_direct_aux_iii:nnn {#1} {#2} { 0 } } + { \__siunitx_angle_direct_aux_iii:nnn {#1} {#2} { } } + } + { \__siunitx_angle_direct_aux_iii:nnn {#1} {#2} {#3} } +} +\cs_new_protected:Npn \__siunitx_angle_direct_aux_iii:nnn #1#2#3 { + \tl_if_empty:nF {#1} + { + \tl_if_empty:nF {#2#3} + { \bool_set_true:N \l__siunitx_angle_degree_space_bool } + } + \tl_if_empty:nF {#2} + { + \tl_if_empty:nF {#3} + { \bool_set_true:N \l__siunitx_angle_minute_space_bool } + } + \__siunitx_angle_print_direct:nnn {#1} {#2} {#3} +} +\cs_new_protected:Npn \__siunitx_angle_parse:nnn #1#2#3 { + \__siunitx_angle_parse_aux:nn {#1} { degree } + \__siunitx_angle_parse_aux:nn {#2} { minute } + \__siunitx_angle_parse_aux:nn {#3} { second } + \__siunitx_angle_check_sign: + \__siunitx_angle_zero_fill: + \prop_if_empty:NF \l__siunitx_angle_degree_prop + { + \prop_if_empty:NF \l__siunitx_angle_minute_prop + { \bool_set_true:N \l__siunitx_angle_degree_space_bool } + \prop_if_empty:NF \l__siunitx_angle_second_prop + { \bool_set_true:N \l__siunitx_angle_degree_space_bool } + } + \prop_if_empty:NF \l__siunitx_angle_minute_prop + { + \prop_if_empty:NF \l__siunitx_angle_second_prop + { \bool_set_true:N \l__siunitx_angle_minute_space_bool } + } + \__siunitx_angle_print: +} +\cs_new_protected:Npn \__siunitx_angle_parse_aux:nn #1#2 { + \prop_clear:N \l__siunitx_number_in_prop + \tl_if_empty:nF {#1} + { + \__siunitx_number_in_init: + \__siunitx_number_in_parse_aux:n {#1} + } + \prop_get:NnNT \l__siunitx_number_in_prop { mantissa-sign-deleted } + \l__siunitx_tmpa_tl + { + \prop_put:NnV \l__siunitx_number_in_prop { mantissa-sign } + \l__siunitx_tmpa_tl + } + \__siunitx_number_process: + \prop_set_eq:cN { l__siunitx_angle_ #2 _prop } + \l__siunitx_number_in_prop +} +\cs_new_protected:Npn \__siunitx_angle_check_sign: { + \prop_if_empty:NTF \l__siunitx_angle_degree_prop + { + \prop_if_empty:NF \l__siunitx_angle_minute_prop + { \__siunitx_angle_check_sign_aux:n { second } } + } + { + \__siunitx_angle_check_sign_aux:n { minute } + \__siunitx_angle_check_sign_aux:n { second } + } +} +\cs_new_protected:Npn \__siunitx_angle_check_sign_aux:n #1 { + \prop_if_in:cnTF { l__siunitx_angle_ #1 _prop } + { mantissa-sign } + { \msg_error:nn { siunitx } { bad-arc-sign } } + { + \prop_if_in:cnT { l__siunitx_angle_ #1 _prop } + { mantissa-sign-deleted } + { \msg_error:nn { siunitx } { bad-arc-sign } } + } +} +\cs_new_protected:Npn \__siunitx_angle_zero_fill: { + \bool_lazy_and:nnT + { \l__siunitx_angle_second_zero_bool } + { \prop_if_empty_p:N \l__siunitx_angle_second_prop } + { + \prop_put:Nnn \l__siunitx_angle_second_prop { mantissa } + { true } + \prop_put:Nnn \l__siunitx_angle_second_prop { mantissa-integer } + { 0 } + } + \bool_lazy_and:nnT + { \l__siunitx_angle_minute_zero_bool } + { \prop_if_empty_p:N \l__siunitx_angle_minute_prop } + { + \prop_put:Nnn \l__siunitx_angle_minute_prop { mantissa } + { true } + \prop_put:Nnn \l__siunitx_angle_minute_prop { mantissa-integer } + { 0 } + \__siunitx_angle_sign_shuffle:nn { second } { minute } + } + \bool_lazy_and:nnT + { \l__siunitx_angle_degree_zero_bool } + { \prop_if_empty_p:N \l__siunitx_angle_degree_prop } + { + \prop_put:Nnn \l__siunitx_angle_degree_prop { mantissa } + { true } + \prop_put:Nnn \l__siunitx_angle_degree_prop { mantissa-integer } + { 0 } + \__siunitx_angle_sign_shuffle:nn { second } { degree } + \__siunitx_angle_sign_shuffle:nn { minute } { degree } + } +} +\cs_new_protected:Npn \__siunitx_angle_sign_shuffle:nn #1#2 { + \__siunitx_angle_sign_shuffle_aux:nnn {#1} {#2} { } + \__siunitx_angle_sign_shuffle_aux:nnn {#1} {#2} { -deleted } +} +\cs_new_protected:Npn \__siunitx_angle_sign_shuffle_aux:nnn + #1#2#3 { + \prop_get:cnN { l__siunitx_angle_ #1 _prop } { mantissa-sign #3 } + \l__siunitx_tmpa_tl + \prop_remove:cn { l__siunitx_angle_ #1 _prop } { mantissa-sign #3 } + \quark_if_no_value:NF \l__siunitx_tmpa_tl + { + \prop_put:cnV { l__siunitx_angle_ #2 _prop } { mantissa-sign #3 } + \l__siunitx_tmpa_tl + } +} +\cs_new_protected:Npn \__siunitx_angle_print: { + \__siunitx_angle_print_aux:nn { degree } { \SIUnitSymbolDegree } + \bool_if:NT \l__siunitx_angle_degree_space_bool + { + \nobreak + \l__siunitx_angle_arc_separator_tl + } + \__siunitx_angle_print_aux:nn { minute } { \SIUnitSymbolArcminute } + \bool_if:NT \l__siunitx_angle_minute_space_bool + { + \nobreak + \l__siunitx_angle_arc_separator_tl + } + \__siunitx_angle_print_aux:nn { second } { \SIUnitSymbolArcsecond } +} +\cs_new_protected:Npn \__siunitx_angle_print_aux:nn #1#2 { + \prop_if_empty:cF { l__siunitx_angle_ #1 _prop } + { + \prop_set_eq:Nc \l__siunitx_number_in_prop + { l__siunitx_angle_ #1 _prop } + \tl_set:Nn \l__siunitx_unit_tl {#2} + \tl_clear:N \l__siunitx_number_out_tl + \__siunitx_number_format: + \__siunitx_number_output_color: + \bool_if:NTF \l__siunitx_angle_astronomy_bool + { \__siunitx_angle_print_astronomy: } + { \__siunitx_number_output_single: } + } +} +\cs_new_protected:Npn \__siunitx_angle_print_astronomy: { + \prop_if_in:NnTF \l__siunitx_number_in_prop + { mantissa-decimal-marker } + { \__siunitx_angle_print_astronomy_aux: } + { \__siunitx_number_output_single: } +} +\cs_new_protected:Npn \__siunitx_angle_print_astronomy_aux: { + \prop_get:NnNF \l__siunitx_number_out_prop { mantissa-sign } + \l__siunitx_tmpa_tl + { \tl_clear:N \l__siunitx_tmpa_tl } + \prop_get:NnNT \l__siunitx_number_out_prop { mantissa-integer } + \l__siunitx_tmpb_tl + { + \tl_put_right:NV \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl + \__siunitx_print:nV { number } \l__siunitx_tmpa_tl + } + \hbox_set:Nn \l__siunitx_angle_marker_box + { + \__siunitx_print:nn { number } { { \l__siunitx_output_decimal_tl } } + } + \hbox_set:Nn \l__siunitx_angle_unit_box + { + \__siunitx_print:nV { unit } \l__siunitx_unit_tl + \skip_horizontal:n { -\scriptspace } + } + \__siunitx_angle_print_astronomy_aux:n { marker } + \__siunitx_angle_print_astronomy_aux:n { unit } + \hbox_set:Nn \l__siunitx_angle_marker_box + { + \box_use:N \l__siunitx_angle_marker_box + \box_use:N \l__siunitx_angle_unit_box + } + \dim_compare:nNnTF + { \l__siunitx_angle_marker_dim } > { \l__siunitx_angle_unit_dim } + { \__siunitx_angle_print_astronomy_marker: } + { \__siunitx_angle_print_astronomy_unit: } + \prop_get:NnNT \l__siunitx_number_out_prop { mantissa-decimal } + \l__siunitx_tmpa_tl + { \__siunitx_print:nV { number } \l__siunitx_tmpa_tl } +} +\cs_new_protected:Npn \__siunitx_angle_print_astronomy_aux:n #1 { + \dim_set:cn { l__siunitx_angle_ #1 _dim } + { \box_wd:c { l__siunitx_angle_ #1 _box } } + \hbox_set_to_wd:cnn { l__siunitx_angle_ #1 _box } { \c_zero_skip } + { + \tex_hss:D + \hbox_unpack:c { l__siunitx_angle_ #1_box } + \tex_hss:D + } +} +\cs_new_protected:Npn \__siunitx_angle_print_astronomy_marker: { + \hbox_set_to_wd:Nnn \l__siunitx_angle_marker_box + { \l__siunitx_angle_marker_dim } + { + \tex_hss:D + \hbox_unpack:N \l__siunitx_angle_marker_box + \tex_hss:D + } + \box_use:N \l__siunitx_angle_marker_box +} +\cs_new_protected:Npn \__siunitx_angle_print_astronomy_unit: { + \hbox_set_to_wd:Nnn \l__siunitx_angle_marker_box + { \l__siunitx_angle_unit_dim } + { + \tex_hss:D + \hbox_unpack:N \l__siunitx_angle_marker_box + \tex_hss:D + } + \box_use:N \l__siunitx_angle_marker_box + \skip_horizontal:N \scriptspace +} +\cs_new_protected:Npn \__siunitx_angle_print_direct:nnn #1#2#3 { + \__siunitx_angle_print_direct_aux:nn {#1} { \SIUnitSymbolDegree } + \bool_if:NT \l__siunitx_angle_degree_space_bool + { + \nobreak + \l__siunitx_angle_arc_separator_tl + } + \__siunitx_angle_print_direct_aux:nn {#2} { \SIUnitSymbolArcminute } + \bool_if:NT \l__siunitx_angle_minute_space_bool + { + \nobreak + \l__siunitx_angle_arc_separator_tl + } + \__siunitx_angle_print_direct_aux:nn {#3} { \SIUnitSymbolArcsecond } +} +\cs_new_protected:Npn \__siunitx_angle_print_direct_aux:nn #1#2 { + \tl_if_empty:nF {#1} + { + \tl_set:Nn \l__siunitx_unit_tl {#2} + \__siunitx_print:nn { number } { \ensuremath {#1} } + \__siunitx_unit_output_print: + } +} +\seq_new:N \l_siunitx_unit_symbolic_seq +\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \of } +\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \highlight } +\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \per } +\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \raiseto } +\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \tothe } +\cs_new_protected:Npn \__siunitx_declare_power_after:Nn #1#2 { + \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} + \cs_set:cpn { __siunitx_ \token_to_str:N #1 _literal:w } + { \__siunitx_textsuperscript:n {#2} } + \cs_set:cpn { __siunitx_ \token_to_str:N #1 _function:w } + { \__siunitx_unit_parse_power_after:n {#2} } +} +\cs_new_protected:Npn \__siunitx_declare_power_before:Nn #1#2 { + \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} + \cs_set:cpn { __siunitx_ \token_to_str:N #1 _literal:w } ##1 + { ##1 \__siunitx_textsuperscript:n {#2} } + \cs_set:cpn { __siunitx_ \token_to_str:N #1 _function:w } + { \__siunitx_unit_parse_power_before:n {#2} } +} +\cs_new_protected:Npn \__siunitx_declare_prefix:Nnnn #1#2#3#4 + { + \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} + \prop_put:Nnn \l__siunitx_prefix_forward_prop {#1} {#4} + \prop_put:Nnn \l__siunitx_prefix_reverse_prop {#4} {#1} + \cs_set:cpn { __siunitx_ \token_to_str:N #1 _literal:w } {#2} + \cs_set:cpn { __siunitx_ \token_to_str:N #1 _function:w } + { + \bool_if:NTF \l__siunitx_prefix_symbols_bool + { \__siunitx_unit_parse_prefix:Nn #1 {#2} } + { \__siunitx_unit_parse_prefix:nn {#3} {#4} } + } + } +\prop_new:N \l__siunitx_prefix_forward_prop +\prop_new:N \l__siunitx_prefix_reverse_prop +\cs_new_protected:Npn \__siunitx_declare_qualifier:Nn #1#2 { + \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} + \cs_set:cpn { __siunitx_ \token_to_str:N #1 _literal:w } + { \text { ~ } ( #2 ) } + \cs_set:cpn { __siunitx_ \token_to_str:N #1 _function:w } + { \__siunitx_unit_parse_qualifier:n {#2} } +} +\cs_new_protected:Npn \__siunitx_declare_unit:Nnn #1#2#3 { + \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} + \cs_set:cpn { __siunitx_ \token_to_str:N #1 _literal:w } {#2} + \cs_set_protected:cpn { __siunitx_ \token_to_str:N #1 _function:w } + { + \__siunitx_unit_if_literal:nTF {#2} + { \__siunitx_unit_parse_unit:Nn #1 {#2} } + {#2} + } + \tl_if_empty:nTF {#3} + { \cs_undefine:c { l__siunitx_ \token_to_str:N #1 _options_tl } } + { + \tl_clear_new:c { l__siunitx_ \token_to_str:N #1 _options_tl } + \tl_set:cn { l__siunitx_ \token_to_str:N #1 _options_tl } {#3} + } +} +\cs_new_protected:Npn \__siunitx_unit_first_token:n #1 { + \exp_last_unbraced:No \token_to_str:N { \tl_head:w #1 \q_stop } +} +\cs_new:cpn { __siunitx_ \token_to_str:N \per _literal:w } { / } +\cs_new_protected:cpn { __siunitx_ \token_to_str:N \per _function:w } { + \bool_set_true:N \l__siunitx_per_bool + \__siunitx_unit_parse_per: +} +\cs_new:cpn { __siunitx_ \token_to_str:N \raiseto _literal:w } #1#2 { + #2 + \__siunitx_textsuperscript:n {#1} +} +\cs_new_protected:cpn { __siunitx_ \token_to_str:N \raiseto _function:w } + #1 { + \__siunitx_unit_parse_power_before:n {#1} +} +\cs_new:cpn { __siunitx_ \token_to_str:N \tothe _literal:w } #1 { + \__siunitx_textsuperscript:n {#1} +} +\cs_new_protected:cpn { __siunitx_ \token_to_str:N \tothe _function:w } + #1 { + \__siunitx_unit_parse_power_after:n {#1} +} +\cs_new:cpn { __siunitx_ \token_to_str:N \of _literal:w } #1 { + \text { ~ } ( #1 ) +} +\cs_new_protected:cpn { __siunitx_ \token_to_str:N \of _function:w } #1 { + \__siunitx_unit_parse_qualifier:n {#1} +} +\AtBeginDocument { + \cs_if_exist:NT \cancel + { + \cs_set_protected:Npn \__siunitx_cancel:n #1 + { \__siunitx__real_cancel:n { \__siunitx_print:nn { unit } {#1} } } + \cs_set_eq:NN \__siunitx__real_cancel:n \cancel + \seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \cancel } + \cs_new_protected:cpn + { __siunitx_ \token_to_str:N \cancel _function:w } + { \__siunitx_unit_parse_special:n { \__siunitx_cancel:n } } + } +} +\cs_new:cpn + { __siunitx_ \token_to_str:N \highlight _literal:w } #1 + { \__siunitx_textcolor:n {#1} } +\cs_new_protected:cpn + { __siunitx_ \token_to_str:N \highlight _function:w } #1 + { \__siunitx_unit_parse_special:n { \__siunitx_textcolor:n {#1} } } +\keys_define:nn { siunitx } { + free-standing-units .bool_set:N = \l__siunitx_create_free_bool , + overwrite-functions .bool_set:N = \l__siunitx_create_overwrite_bool, + space-before-unit .bool_set:N = \l__siunitx_create_prespace_bool , + unit-optional-argument .bool_set:N = \l__siunitx_create_optional_bool , + use-xspace .bool_set:N = \l__siunitx_create_xspace_bool , +} +\__siunitx_option_deactivate:n { + free-standing-units , + overwrite-functions , + space-before-unit , + unit-optional-argument , + use-xspace , +} +\cs_new_protected:Npn \__siunitx_unit_create_empty_functions: + { + \__siunitx_unit_create_functions_aux_i: + \seq_map_function:NN \l_siunitx_unit_symbolic_seq + \__siunitx_unit_create_empty_functions_aux:N + \__siunitx_unit_create_functions_aux_ii: + } +\cs_new_protected:Npn \__siunitx_unit_create_empty_functions_aux:N #1 + { + \cs_if_free:NT #1 + { \cs_set_protected:Npn #1 { \ERROR } } + } +\cs_new_protected:Npn \__siunitx_unit_create_functions: + { + \__siunitx_unit_create_functions_aux_i: + \bool_if:NT \l__siunitx_create_overwrite_bool + { \seq_map_function:NN \l_siunitx_unit_symbolic_seq \cs_undefine:N } + \bool_if:NTF \l__siunitx_create_optional_bool + { + \seq_map_function:NN \l_siunitx_unit_symbolic_seq + \__siunitx_unit_create_with_arg:N + } + { + \seq_map_function:NN \l_siunitx_unit_symbolic_seq + \__siunitx_unit_create:N + } + \__siunitx_unit_create_functions_aux_ii: + \bool_if:NT \l__siunitx_create_xspace_bool + { \RequirePackage { xspace } } + } +\cs_new_protected:Npn \__siunitx_unit_create_functions_aux_i: + { + \@ifpackageloaded { soulpos } + { + \@ifpackageloaded { soul } + { } + { + \cs_set_protected:Npn \__siunitx_unit_create_functions_aux_ii: + { + \cs_undefine:N \hl + \cs_undefine:N \ul + } + } + } + { } + } +\cs_new_protected:Npn \__siunitx_unit_create_functions_aux_ii: { } +\cs_new_protected:Npn \__siunitx_unit_create:N #1 { + \cs_if_free:NT #1 + { + \cs_set:Npx \__siunitx_tmp:w + { + \ProvideDocumentCommand \exp_not:N #1 { } + { + \group_begin: + \exp_not:N \cs_if_free:NF + \exp_not:c + { l__siunitx_ \token_to_str:N #1 _options_tl } + { + \keys_set:nV { siunitx } + \exp_not:c + { l__siunitx_ \token_to_str:N #1 _options_tl } + } + \bool_if:NT \l__siunitx_create_prespace_bool + { \exp_not:N \l__siunitx_number_unit_product_tl } + \exp_not:n { \__siunitx_unit_output:nn {#1} { } } + \group_end: + \bool_if:NT \l__siunitx_create_xspace_bool + { \exp_not:N \xspace } + } + } + \__siunitx_tmp:w + } +} +\cs_new_protected:Npn \__siunitx_unit_create_with_arg:N #1 { + \cs_if_free:NT #1 + { + \cs_set:Npx \__siunitx_tmp:w + { + \ProvideDocumentCommand \exp_not:N #1 { o } + { + \group_begin: + \exp_not:N \cs_if_free:NF + \exp_not:c + { l__siunitx_ \token_to_str:N #1 _options_tl } + { + \keys_set:nV { siunitx } + \exp_not:c + { + l__siunitx_ \token_to_str:N #1 _options_tl + } + } + \exp_not:N \IfNoValueTF {####1} + { + \bool_if:NT \l__siunitx_create_prespace_bool + { \exp_not:N \l__siunitx_number_unit_product_tl } + \exp_not:n { \__siunitx_unit_output:nn {#1} { } } + } + { \SI {####1} { \exp_not:N #1 } } + \group_end: + \bool_if:NT \l__siunitx_create_xspace_bool + { \exp_not:N \xspace } + } + } + \__siunitx_tmp:w + } +} +\AtBeginDocument { + \cs_if_eq:NNT \color \use_none:n + { \cs_set_protected:Npn \color #1 { } } + \cs_set:Npn \__siunitx_tmp:w #1 { } + \cs_if_eq:NNT \color \__siunitx_tmp:w + { \cs_set_protected:Npn \color #1 { } } + \tl_map_function:nN { \bar \color \ng \pm \array@row@rst } + \__siunitx_protect_symbols:N +} +\__siunitx_if_hooks:TF + { + \AddToHook { begindocument / end } [ siunitx ] + { \__siunitx_protect_symbols:N \fg } + } + { + \tl_put_right:Nn \document + { + \__siunitx_protect_symbols:N \fg + \ignorespaces + } + } +\cs_new_protected:Npn \__siunitx_protect_symbols:N #1 { + \cs_if_exist:NT #1 + { + \tl_if_empty:fT { \cs_prefix_spec:N #1 } + { \cs_set_protected:Npx #1 { \exp_not:V #1 } } + } +} +\keys_define:nn { siunitx } { + forbid-literal-units .bool_set:N = + \l__siunitx_unit_forbid_literal_bool, + parse-units .bool_set:N = \l__siunitx_unit_parse_bool +} +\keys_set:nn { siunitx } { + forbid-literal-units = false, + parse-units = true +} +\cs_new_protected:Npn \__siunitx_unit_in:nn #1#2 { + \bool_if:NTF \l__siunitx_unit_parse_bool + { + \tl_if_empty:nF {#1} + { + \__siunitx_unit_if_literal:nTF {#1} + { + \tl_clear:N \l__siunitx_per_mode_tl + \bool_if:NTF \l__siunitx_unit_forbid_literal_bool + { + \msg_error:nnx { siunitx } { literal-unit } + { \exp_not:n {#1} } + } + { + \cs_set_eq:NN \__siunitx_pm: \pm + \__siunitx_unit_format_literal:n {#1} + \cs_set_eq:NN \pm \__siunitx_pm: + } + } + { + \cs_set_eq:NN \__siunitx_pm: \pm + \__siunitx_unit_parse:nn {#1} {#2} + \__siunitx_unit_format: + \prop_set_eq:NN \l__siunitx_unit_saved_prop \l__siunitx_unit_prop + \cs_set_eq:NN \pm \__siunitx_pm: + } + } + } + { \__siunitx_unit_format_literal:n {#1} } +} +\cs_generate_variant:Nn \__siunitx_unit_in:nn { V } +\cs_new:Npn \__siunitx_pm: { } +\cs_new_protected:Npn \__siunitx_unit_if_literal:nTF #1#2#3 { + \group_begin: + \seq_map_function:NN \l_siunitx_unit_symbolic_seq + \__siunitx_unit_if_literal_aux:N + \cs_set_eq:NN \of \use_none:n + \cs_set_eq:NN \highlight \use_none:n + \cs_set_eq:NN \raiseto \use_none:n + \cs_set_eq:NN \tothe \use_none:n + \protected@edef \l__siunitx_tmpa_tl {#1} + \exp_args:NNNV \group_end: + \tl_set:Nn \l__siunitx_tmpa_tl \l__siunitx_tmpa_tl + \tl_if_blank:VTF \l__siunitx_tmpa_tl {#3} {#2} +} +\cs_new_protected:Npn \__siunitx_unit_if_literal_aux:N #1 { + \cs_set_eq:NN #1 \prg_do_nothing: +} +\int_new:N \l__siunitx_unit_int +\prop_new:N \l__siunitx_unit_prop +\prop_new:N \l__siunitx_unit_saved_prop +\bool_new:N \l__siunitx_per_bool +\keys_define:nn { siunitx } + { + exponent-to-prefix .bool_set:N = \l__siunitx_exp_to_prefix_bool , + prefixes-as-symbols .bool_set:N = \l__siunitx_prefix_symbols_bool , + sticky-per .bool_set:N = \l__siunitx_sticky_per_bool + } +\keys_set:nn { siunitx } { prefixes-as-symbols = true } +\cs_new_protected:Npn \__siunitx_unit_parse:nn #1#2 { + \__siunitx_unit_parse_init: + \__siunitx_unit_parse_options:nn {#1} {#2} + #1 +} +\cs_new_protected:Npn \__siunitx_unit_parse_init: + { + \prop_clear:N \l__siunitx_unit_prop + \int_zero:N \l__siunitx_unit_int + \bool_set_false:N \l__siunitx_per_bool + \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq + { \cs_set_eq:Nc ##1 { __siunitx_ \token_to_str:N ##1 _function:w } } + } +\cs_new_protected:Npn \__siunitx_unit_parse_options:nn #1#2 { + \tl_if_single:nT {#1} + { + \cs_if_free:cF + { l__siunitx_ \__siunitx_unit_first_token:n {#1} _options_tl } + { + \keys_set:nv { siunitx } + { l__siunitx_ \__siunitx_unit_first_token:n {#1} _options_tl } + \keys_set:nn { siunitx } {#2} + } + } +} +\cs_new_protected:Npn \__siunitx_unit_parse_power_before:n #1 { + \tl_set:Nx \l__siunitx_tmpa_tl + { power- \int_eval:n { \l__siunitx_unit_int + 1 } } + \prop_put:NVn \l__siunitx_unit_prop \l__siunitx_tmpa_tl {#1} +} +\cs_new_protected:Npn \__siunitx_unit_parse_power_after:n #1 { + \tl_set:Nx \l__siunitx_tmpa_tl + { power- \int_use:N \l__siunitx_unit_int } + \prop_put:NVn \l__siunitx_unit_prop \l__siunitx_tmpa_tl {#1} +} +\cs_new_protected:Npn \__siunitx_unit_parse_prefix:Nn #1#2 + { + \int_incr:N \l__siunitx_unit_int + \tl_set:Nx \l__siunitx_tmpa_tl + { prefix- \int_use:N \l__siunitx_unit_int } + \prop_put:NVn \l__siunitx_unit_prop \l__siunitx_tmpa_tl {#1} + \tl_set:Nx \l__siunitx_tmpa_tl + { prefix-symbol- \int_use:N \l__siunitx_unit_int } + \prop_put:NVn \l__siunitx_unit_prop \l__siunitx_tmpa_tl {#2} + } +\cs_new_protected:Npn \__siunitx_unit_parse_prefix:nn #1#2 + { + \__siunitx_unit_parse_prefix:Nn \ERROR {#2} + \tl_set:Nx \l__siunitx_tmpa_tl + { prefix-base- \int_use:N \l__siunitx_unit_int } + \prop_put:NVn \l__siunitx_unit_prop \l__siunitx_tmpa_tl {#1} + } +\cs_new_protected:Npn \__siunitx_unit_parse_per: { + \tl_set:Nx \l__siunitx_tmpa_tl + { per- \int_eval:n { \l__siunitx_unit_int + 1 } } + \prop_put:NVn \l__siunitx_unit_prop \l__siunitx_tmpa_tl { true } + \bool_if:NT \l__siunitx_sticky_per_bool + { \cs_set_eq:NN \per \__siunitx_unit_parse_per_error: } +} +\cs_new_protected:Npn \__siunitx_unit_parse_per_error: { + \msg_error:nn { siunitx } { duplicate-sticky-per } +} +\cs_new_protected:Npn \__siunitx_unit_parse_qualifier:n #1 { + \tl_set:Nx \l__siunitx_tmpa_tl + { symbol- \int_use:N \l__siunitx_unit_int } + \prop_if_in:NVF \l__siunitx_unit_prop \l__siunitx_tmpa_tl + { \msg_error:nn { siunitx } { qualifier-before-unit } } + \tl_set:Nx \l__siunitx_tmpa_tl + { qualifier- \int_use:N \l__siunitx_unit_int } + \prop_put:NVn \l__siunitx_unit_prop \l__siunitx_tmpa_tl {#1} +} +\cs_new_protected:Npn \__siunitx_unit_parse_special:n #1 { + \tl_set:Nx \l__siunitx_tmpa_tl + { special- \int_eval:n { \l__siunitx_unit_int + 1 } } + \prop_put:NVn \l__siunitx_unit_prop \l__siunitx_tmpa_tl {#1} +} +\cs_new_protected:Npn \__siunitx_unit_parse_unit:Nn #1#2 { + \tl_set:Nx \l__siunitx_tmpa_tl + { prefix-symbol- \int_use:N \l__siunitx_unit_int } + \prop_if_in:NVTF \l__siunitx_unit_prop \l__siunitx_tmpa_tl + { + \tl_set:Nx \l__siunitx_tmpa_tl + { symbol- \int_use:N \l__siunitx_unit_int } + \prop_if_in:NVT \l__siunitx_unit_prop \l__siunitx_tmpa_tl + { \int_incr:N \l__siunitx_unit_int } + } + { \int_incr:N \l__siunitx_unit_int } + \tl_set:Nx \l__siunitx_tmpa_tl + { unit- \int_use:N \l__siunitx_unit_int } + \prop_put:NVn \l__siunitx_unit_prop \l__siunitx_tmpa_tl {#1} + \tl_set:Nx \l__siunitx_tmpa_tl + { symbol- \int_use:N \l__siunitx_unit_int } + \prop_put:NVn \l__siunitx_unit_prop \l__siunitx_tmpa_tl {#2} + \__siunitx_unit_parse_unit_per: +} +\cs_new_protected:Npn \__siunitx_unit_parse_unit_per: { + \bool_if:NT \l__siunitx_sticky_per_bool + { + \bool_if:NT \l__siunitx_per_bool + { + \tl_set:Nx \l__siunitx_tmpa_tl + { per- \int_use:N \l__siunitx_unit_int } + \prop_put:NVn \l__siunitx_unit_prop \l__siunitx_tmpa_tl + { true } + } + } +} +\tl_new:N \l__siunitx_preunit_tl +\tl_new:N \l__siunitx_unit_tl +\tl_new:N \l__siunitx_unit_current_tl +\tl_new:N \l__siunitx_unit_denominator_tl +\tl_new:N \l__siunitx_unit_numerator_tl +\tl_new:N \l__siunitx_unit_saved_tl +\int_new:N \l__siunitx_unit_denominator_int +\int_new:N \l__siunitx_unit_numerator_int +\int_new:N \l__siunitx_unit_prefix_int +\int_new:N \l__siunitx_unit_prefix_base_int +\tl_new:N \l__siunitx_unit_prefix_current_tl +\int_new:N \l__siunitx_unit_prefix_gram_int +\bool_new:N \l__siunitx_omit_unit_space_bool +\bool_new:N \l__siunitx_per_auto_bool +\bool_new:N \l__siunitx_per_fraction_bool +\tl_new:N \l__siunitx_per_mode_tl +\bool_new:N \l__siunitx_power_number_bool +\bool_new:N \l__siunitx_per_two_parts_bool +\tl_new:N \l__siunitx_qualifier_mode_tl +\keys_define:nn { siunitx } { + bracket-unit-denominator .bool_set:N + = \l__siunitx_unit_denominator_bracket_bool, + inter-unit-product .tl_set:N = \l__siunitx_unit_product_tl , + inter-unit-separator .tl_set:N = \l__siunitx_unit_product_tl , + literal-superscript-as-power + .bool_set:N = \l__siunitx_literal_power_bool, + per-mode .choice:, + per-mode / fraction .code:n = + { + \bool_set_false:N \l__siunitx_per_auto_bool + \bool_set_true:N \l__siunitx_per_fraction_bool + \bool_set_true:N \l__siunitx_per_two_parts_bool + \tl_set:Nn \l__siunitx_per_mode_tl { fraction } + }, + per-mode / power .meta:n = { per-mode = reciprocal } , + per-mode / power-positive-first .meta:n = + { per-mode = reciprocal-positive-first } , + per-mode / reciprocal .code:n = + { + \bool_set_false:N \l__siunitx_per_auto_bool + \bool_set_false:N \l__siunitx_per_fraction_bool + \bool_set_false:N \l__siunitx_per_two_parts_bool + \tl_clear:N \l__siunitx_per_mode_tl + }, + per-mode / reciprocal-positive-first .code:n = + { + \bool_set_false:N \l__siunitx_per_auto_bool + \bool_set_false:N \l__siunitx_per_fraction_bool + \bool_set_true:N \l__siunitx_per_two_parts_bool + \tl_clear:N \l__siunitx_per_mode_tl + }, + per-mode / repeated-symbol .code:n = + { + \bool_set_false:N \l__siunitx_per_auto_bool + \bool_set_false:N \l__siunitx_per_fraction_bool + \bool_set_false:N \l__siunitx_per_two_parts_bool + \tl_set:Nn \l__siunitx_per_mode_tl { repeat } + }, + per-mode / symbol .code:n = + { + \bool_set_false:N \l__siunitx_per_auto_bool + \bool_set_true:N \l__siunitx_per_fraction_bool + \bool_set_true:N \l__siunitx_per_two_parts_bool + \tl_set:Nn \l__siunitx_per_mode_tl { symbol } + }, + per-mode / symbol-or-fraction .code:n = + { + \bool_set_true:N \l__siunitx_per_auto_bool + \bool_set_true:N \l__siunitx_per_fraction_bool + \bool_set_true:N \l__siunitx_per_two_parts_bool + \tl_set:Nn \l__siunitx_per_mode_tl { symbol } + }, + per-symbol .tl_set:N = \l__siunitx_per_symbol_tl, + power-font .choice:, + power-font / number .code:n = + { \bool_set_true:N \l__siunitx_power_number_bool }, + power-font / unit .code:n = + { \bool_set_false:N \l__siunitx_power_number_bool }, + qualifier-mode .choice:, + qualifier-mode / brackets .code:n = + { \tl_set:Nn \l__siunitx_qualifier_mode_tl { brackets } }, + qualifier-mode / phrase .code:n = + { \tl_set:Nn \l__siunitx_qualifier_mode_tl { phrase } }, + qualifier-mode / space .code:n = + { \tl_set:Nn \l__siunitx_qualifier_mode_tl { space } }, + qualifier-mode / subscript .code:n = + { \tl_set:Nn \l__siunitx_qualifier_mode_tl { subscript } }, + qualifier-mode / text .code:n = + { \tl_set:Nn \l__siunitx_qualifier_mode_tl { text } }, + qualifier-phrase .tl_set:N = \l__siunitx_qualifier_phrase_tl +} +\keys_set:nn { siunitx } { + bracket-unit-denominator = true, + inter-unit-product = \,, + literal-superscript-as-power = true, + per-mode = reciprocal, + per-symbol = /, + power-font = number, + qualifier-mode = subscript, + qualifier-phrase = { ~ of ~ } +} +\cs_new_protected:Npn \__siunitx_unit_format: { + \prop_put:Nnx \l__siunitx_unit_prop { total-units } + { \int_use:N \l__siunitx_unit_int } + \__siunitx_unit_format_init: + \int_while_do:nNnn { \l__siunitx_unit_int } > { 0 } + { + \__siunitx_unit_format_prefix: + \__siunitx_unit_format_symbol: + \__siunitx_unit_format_qualifier: + \__siunitx_unit_format_power: + \__siunitx_unit_format_add: + \int_decr:N \l__siunitx_unit_int + } + \bool_if:NT \l__siunitx_per_two_parts_bool + { + \bool_if:NTF \l__siunitx_per_fraction_bool + { \__siunitx_unit_format_fraction: } + { \__siunitx_unit_format_sorted: } + } +} +\cs_new_protected:Npn \__siunitx_unit_format_add: { + \bool_if:NTF \l__siunitx_per_two_parts_bool + { + \tl_set:Nx \l__siunitx_tmpb_tl + { per- \int_use:N \l__siunitx_unit_int } + \prop_if_in:NVTF \l__siunitx_unit_prop \l__siunitx_tmpb_tl + { + \__siunitx_unit_format_add_aux:n { _denominator } + \int_incr:N \l__siunitx_unit_denominator_int + } + { + \__siunitx_unit_format_add_aux:n { _numerator } + \int_incr:N \l__siunitx_unit_numerator_int + } + } + { \__siunitx_unit_format_add_aux:n { } } + \tl_clear:N \l__siunitx_unit_current_tl +} +\cs_new_protected:Npn \__siunitx_unit_format_add_aux:n #1 { + \tl_if_empty:cF { l__siunitx_unit #1 _tl } + { + \str_if_eq:VnTF \l__siunitx_per_mode_tl { repeat } + { + \tl_set:Nx \l__siunitx_tmpa_tl + { per- \int_eval:n { \l__siunitx_unit_int + 1 } } + \prop_if_in:NVF \l__siunitx_unit_prop \l__siunitx_tmpa_tl + { + \tl_put_right:NV \l__siunitx_unit_current_tl + \l__siunitx_unit_product_tl + } + } + { + \tl_put_right:NV \l__siunitx_unit_current_tl + \l__siunitx_unit_product_tl + } + } + \tl_set:Nx \l__siunitx_tmpa_tl + { special- \int_use:N \l__siunitx_unit_int } + \prop_get:NVNTF \l__siunitx_unit_prop \l__siunitx_tmpa_tl + \l__siunitx_tmpa_tl + { + \tl_put_left:cx { l__siunitx_unit #1 _tl } + { + \exp_not:V \l__siunitx_tmpa_tl + { \exp_not:V \l__siunitx_unit_current_tl } + } + } + { + \tl_put_left:cV { l__siunitx_unit #1 _tl } + \l__siunitx_unit_current_tl + } +} +\cs_new_protected:Npn \__siunitx_unit_format_fraction: { + \int_compare:nNnT { \l__siunitx_unit_numerator_int } = { 0 } + { + \str_if_eq:VnT \l__siunitx_per_mode_tl { symbol } + { \bool_set_true:N \l__siunitx_omit_unit_space_bool } + } + \int_compare:nNnTF { \l__siunitx_unit_denominator_int } > { 0 } + { + \bool_if:NTF \l__siunitx_per_auto_bool + { \__siunitx_unit_format_fraction_auto: } + { + \use:c + { __siunitx_unit_format_fraction_ \l__siunitx_per_mode_tl : } + } + } + { \tl_set_eq:NN \l__siunitx_unit_tl \l__siunitx_unit_numerator_tl } +} +\cs_new_protected:Npn \__siunitx_unit_format_fraction_fraction: { + \tl_if_empty:NT \l__siunitx_unit_numerator_tl + { \tl_set:Nn \l__siunitx_unit_numerator_tl { 1 } } + \tl_set:Nx \l__siunitx_unit_numerator_tl + { { \exp_not:V \l__siunitx_unit_numerator_tl } } + \tl_put_left:Nn \l__siunitx_unit_numerator_tl + { \__siunitx_print:nn { unit } } + \tl_set:Nx \l__siunitx_unit_numerator_tl + { { \exp_not:V \l__siunitx_unit_numerator_tl } } + \tl_set:Nx \l__siunitx_unit_denominator_tl + { { \exp_not:V \l__siunitx_unit_denominator_tl } } + \tl_put_left:Nn \l__siunitx_unit_denominator_tl + { \__siunitx_print:nn { unit } } + \tl_set:Nx \l__siunitx_unit_denominator_tl + { { \exp_not:V \l__siunitx_unit_denominator_tl } } + \tl_set:Nn \l__siunitx_unit_tl { \__siunitx_fraction:nn } + \tl_put_right:NV \l__siunitx_unit_tl \l__siunitx_unit_numerator_tl + \tl_put_right:NV \l__siunitx_unit_tl \l__siunitx_unit_denominator_tl + \tl_set:Nx \l__siunitx_unit_tl + { \exp_not:N \ensuremath { \exp_not:V \l__siunitx_unit_tl } } +} +\cs_new_protected:Npn \__siunitx_unit_format_fraction_auto: { + \mode_if_math:TF + { + \group_begin: + \__siunitx_unit_format_fraction_fraction: + \exp_args:NNNV \group_end: + \tl_set:Nn \l__siunitx_tmpa_tl \l__siunitx_unit_tl + \group_begin: + \__siunitx_unit_format_fraction_symbol: + \exp_args:NNNV \group_end: + \tl_set:Nn \l__siunitx_tmpb_tl \l__siunitx_unit_tl + \tl_set:Nx \l__siunitx_tmpb_tl + { + \__siunitx_print:nn { unit } + { \exp_not:V \l__siunitx_tmpb_tl } + } + \tl_set:Nx \l__siunitx_unit_tl + { + \exp_not:N \ensuremath { + \tex_mathchoice:D + { \exp_not:V \l__siunitx_tmpa_tl } + { \exp_not:V \l__siunitx_tmpb_tl } + { \exp_not:V \l__siunitx_tmpb_tl } + { \exp_not:V \l__siunitx_tmpb_tl } + } + } + } + { \__siunitx_unit_format_fraction_symbol: } +} +\cs_new_protected:Npn \__siunitx_unit_format_fraction_symbol: { + \__siunitx_unit_format_fraction_symbol_aux: + \int_compare:nNnT { \l__siunitx_unit_denominator_int } > { 1 } + { + \bool_if:NT \l__siunitx_unit_denominator_bracket_bool + { + \tl_put_left:NV \l__siunitx_unit_denominator_tl \l__siunitx_bracket_open_tl + \tl_put_right:NV \l__siunitx_unit_denominator_tl \l__siunitx_bracket_close_tl + } + } + \tl_set_eq:NN \l__siunitx_unit_tl \l__siunitx_unit_numerator_tl + \tl_put_right:NV \l__siunitx_unit_tl \l__siunitx_per_symbol_tl + \tl_put_right:NV \l__siunitx_unit_tl \l__siunitx_unit_denominator_tl +} +\cs_new_protected:Npn + \__siunitx_unit_format_fraction_symbol_aux: { } +\cs_new_protected:Npn + \__siunitx_unit_format_fraction_symbol_aux_alt: { + \tl_if_empty:NT \l__siunitx_unit_numerator_tl + { \tl_set:Nn \l__siunitx_unit_numerator_tl { 1 } } +} +\cs_new_protected:Npn \__siunitx_unit_format_init: { + \bool_set_false:N \l__siunitx_omit_unit_space_bool + \tl_clear:N \l__siunitx_unit_tl + \tl_clear:N \l__siunitx_unit_current_tl + \tl_clear:N \l__siunitx_unit_denominator_tl + \int_zero:N \l__siunitx_unit_prefix_gram_int + \tl_clear:N \l__siunitx_unit_numerator_tl + \int_zero:N \l__siunitx_unit_prefix_base_int + \int_zero:N \l__siunitx_unit_prefix_int + \int_zero:N \l__siunitx_unit_denominator_int + \int_zero:N \l__siunitx_unit_numerator_int + \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq + { \__siunitx_unit_print_literal_aux:N ##1 } +} +\group_begin: + \char_set_catcode_active:N \~ + \cs_new_protected:Npn \__siunitx_unit_format_literal:n #1 + { + \int_zero:N \l__siunitx_unit_prefix_int + \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq + { \__siunitx_unit_print_literal_aux:N ##1 } + \tl_set:Nn \l__siunitx_unit_tl {#1} + \tl_replace_all:NnV \l__siunitx_unit_tl { . } + \l__siunitx_unit_product_tl + \tl_replace_all:NnV \l__siunitx_unit_tl { ~ } + \l__siunitx_unit_product_tl + \bool_if:NT \l__siunitx_literal_power_bool + { + \tl_replace_all:Nnn \l__siunitx_unit_tl { ^ } + { \__siunitx_unit_format_literal_power:n } + \tl_replace_all:Non \l__siunitx_unit_tl { \token_to_str:N ^ } + { \__siunitx_unit_format_literal_power:n } + } + \__siunitx_unit_format_literal_extras: + } +\group_end: +\cs_new_protected:Npn \__siunitx_unit_print_literal_aux:N #1 + { \cs_set_eq:Nc #1 { __siunitx_ \token_to_str:N #1 _literal:w } } +\cs_new_protected:Npn \__siunitx_unit_format_literal_power:n #1 + { \PrintSuperscript { \__siunitx_unit_format_power_aux:n {#1} } } + %\end{macro} +\cs_new_protected:Npn \__siunitx_unit_format_literal_extras: + { + \__siunitx_unit_format_literal_extras_aux:nN { 176 } + \SIUnitSymbolDegree + \__siunitx_unit_format_literal_extras_aux:nN { 181 } + \SIUnitSymbolMicro + \__siunitx_unit_format_literal_extras_aux:nN { 197 } + \SIUnitSymbolAngstrom + } +\cs_new_protected:Npn \__siunitx_unit_format_literal_extras_aux:nN #1#2 + { + \tl_replace_all:Nxn \l__siunitx_unit_tl + { \char_generate:nn { #1 } { 12 } } + {#2} + } +\bool_lazy_or:nnF { \sys_if_engine_luatex_p: } { \sys_if_engine_xetex_p: } + { + \AtBeginDocument + { + \cs_if_exist:NTF \inputencodingname + { + \tl_set:Nn \l__siunitx_tmpa_tl { latin1 , latin5 , latin9 } + \clist_if_in:NVF \l__siunitx_tmpa_tl \inputencodingname + { + \cs_set_eq:NN \__siunitx_unit_format_literal_extras: + \scan_stop: + } + } + { + \cs_set_eq:NN \__siunitx_unit_format_literal_extras: + \scan_stop: + } + } + } +\cs_new_protected:Npn \__siunitx_unit_format_power: { + \tl_set:Nx \l__siunitx_tmpa_tl + { power- \int_use:N \l__siunitx_unit_int } + \prop_get:NVNTF \l__siunitx_unit_prop \l__siunitx_tmpa_tl + \l__siunitx_tmpa_tl + { \__siunitx_unit_format_power_aux: } + { + \tl_set:Nx \l__siunitx_tmpa_tl + { per- \int_use:N \l__siunitx_unit_int } + \prop_if_in:NVT \l__siunitx_unit_prop \l__siunitx_tmpa_tl + { + \tl_set:Nn \l__siunitx_tmpa_tl { 1 } + \__siunitx_unit_format_power_aux: + } + } +} +\cs_new_protected:Npn \__siunitx_unit_format_power_aux: { + \str_if_eq:VnTF \l__siunitx_per_mode_tl { repeat } + { \__siunitx_unit_format_power_repeat: } + { \__siunitx_unit_format_power_per: } + \str_if_eq:VnF \l__siunitx_tmpa_tl { 1 } + { + \__siunitx_unit_format_power_brackets: + \tl_put_right:Nx \l__siunitx_unit_current_tl + { + \exp_not:N \PrintSuperscript + { + \__siunitx_unit_format_power_aux:n + { + \exp_after:wN \__siunitx_unit_format_power:w + \l__siunitx_tmpa_tl . . \q_stop + } + } + } + } +} +\cs_new_protected:Npn \__siunitx_unit_format_power_aux:n #1 { + \bool_if:NTF \l__siunitx_power_number_bool + { \__siunitx_unit_format_power_aux:nn { number } {#1} } + { \__siunitx_unit_format_power_aux:nn { unit } {#1} } +} +\cs_new_protected:Npn \__siunitx_unit_format_power_aux:nn #1#2 { + \bool_if:cTF { l__siunitx_ #1 _math_mode_bool } + { \__siunitx_print:nn {#1} {#2} } + { + \tl_set:Nn \l__siunitx_tmpa_tl {#2} + \tl_replace_all:Nnn \l__siunitx_tmpa_tl { - } + { \text { \textminus } } + \__siunitx_print:nV {#1} \l__siunitx_tmpa_tl + } +} +\cs_new:Npn \__siunitx_unit_format_power:w #1 . #2 . #3 \q_stop + { + \exp_not:n {#1} + \tl_if_blank:nF {#2} + { + \exp_not:V \l__siunitx_output_decimal_tl + \exp_not:n {#2} + } + } +\cs_new_protected:Npn \__siunitx_unit_format_power_brackets: { + \tl_set:Nx \l__siunitx_tmpb_tl + { bracket- \int_use:N \l__siunitx_unit_int } + \prop_if_in:NVT \l__siunitx_unit_prop \l__siunitx_tmpb_tl + { + \tl_put_left:NV \l__siunitx_unit_current_tl \l__siunitx_bracket_open_tl + \tl_put_right:NV \l__siunitx_unit_current_tl \l__siunitx_bracket_close_tl + } +} +\cs_new_protected:Npn \__siunitx_unit_format_power_per: { + \tl_set:Nx \l__siunitx_tmpb_tl + { per- \int_use:N \l__siunitx_unit_int } + \prop_if_in:NVT \l__siunitx_unit_prop \l__siunitx_tmpb_tl + { + \bool_if:NF \l__siunitx_per_fraction_bool + { + \tl_if_in:NnTF \l__siunitx_tmpa_tl { - } + { + \cs_set:Npn \__siunitx_tmp:w ##1 - ##2 \q_stop + { \tl_set:Nn \l__siunitx_tmpa_tl {##2} } + \exp_after:wN \__siunitx_tmp:w \l__siunitx_tmpa_tl \q_stop + } + { \tl_put_left:Nn \l__siunitx_tmpa_tl { - } } + } + } +} +\cs_new_protected:Npn \__siunitx_unit_format_power_repeat: { + \tl_set:Nx \l__siunitx_tmpb_tl + { per- \int_use:N \l__siunitx_unit_int } + \prop_if_in:NVT \l__siunitx_unit_prop \l__siunitx_tmpb_tl + { + \tl_put_left:NV \l__siunitx_unit_current_tl \l__siunitx_per_symbol_tl + } +} +\cs_new_protected:Npn \__siunitx_unit_format_prefix: { + \tl_set:Nx \l__siunitx_tmpa_tl + { prefix-symbol- \int_use:N \l__siunitx_unit_int } + \prop_if_in:NVT \l__siunitx_unit_prop \l__siunitx_tmpa_tl + { + \prop_get:NVN \l__siunitx_unit_prop \l__siunitx_tmpa_tl + \l__siunitx_unit_prefix_current_tl + \bool_if:NTF \l__siunitx_prefix_symbols_bool + { \__siunitx_unit_format_prefix_symbol: } + { \__siunitx_unit_format_prefix_number: } + } +} +\cs_new_protected:Npn \__siunitx_unit_format_prefix_number: { + \tl_set:Nx \l__siunitx_tmpa_tl + { prefix-base- \int_use:N \l__siunitx_unit_int } + \prop_get:NVN \l__siunitx_unit_prop \l__siunitx_tmpa_tl + \l__siunitx_tmpa_tl + \int_compare:nNnT { \l__siunitx_unit_prefix_base_int } = { 0 } + { + \int_set:Nn \l__siunitx_unit_prefix_base_int + { \l__siunitx_tmpa_tl } + } + \int_compare:nNnTF + { \l__siunitx_unit_prefix_base_int } = { \l__siunitx_tmpa_tl } + { \__siunitx_unit_format_prefix_number_calc: } + { \msg_error:nn { siunitx } { prefix-base-mismatch } } +} +\cs_new_protected:Npn \__siunitx_unit_format_prefix_number_calc: { + \tl_set:Nx \l__siunitx_tmpa_tl + { power- \int_use:N \l__siunitx_unit_int } + \prop_get:NVNF \l__siunitx_unit_prop \l__siunitx_tmpa_tl + \l__siunitx_tmpa_tl + { \tl_set:Nn \l__siunitx_tmpa_tl { 1 } } + \tl_set:Nx \l__siunitx_tmpb_tl + { unit- \int_use:N \l__siunitx_unit_int } + \prop_get:NVN \l__siunitx_unit_prop \l__siunitx_tmpb_tl + \l__siunitx_tmpb_tl + \str_if_eq:VnT \l__siunitx_tmpb_tl { \gram } + { + \tl_set:Nx \l__siunitx_unit_prefix_current_tl + { \int_eval:n { \l__siunitx_unit_prefix_current_tl - 3 } } + \tl_set:Nx \l__siunitx_tmpb_tl + { symbol- \int_use:N \l__siunitx_unit_int } + \prop_put:NVn \l__siunitx_unit_prop \l__siunitx_tmpb_tl { kg } + } + \tl_set:Nx \l__siunitx_unit_prefix_current_tl + { + \int_eval:n + { \l__siunitx_unit_prefix_current_tl * \l__siunitx_tmpa_tl } + } + \tl_set:Nx \l__siunitx_tmpa_tl + { per- \int_use:N \l__siunitx_unit_int } + \prop_if_in:NVTF \l__siunitx_unit_prop \l__siunitx_tmpa_tl + { + \int_set:Nn \l__siunitx_unit_prefix_int + { + \l__siunitx_unit_prefix_int + - \l__siunitx_unit_prefix_current_tl + } + } + { + \int_set:Nn \l__siunitx_unit_prefix_int + { + \l__siunitx_unit_prefix_int + + \l__siunitx_unit_prefix_current_tl + } + } +} +\cs_new_protected:Npn \__siunitx_unit_format_prefix_symbol: { + \tl_set_eq:NN \l__siunitx_unit_current_tl + \l__siunitx_unit_prefix_current_tl +} +\cs_new_protected:Npn \__siunitx_unit_format_qualifier: { + \tl_set:Nx \l__siunitx_tmpa_tl + { qualifier- \int_use:N \l__siunitx_unit_int } + \prop_get:NVNT \l__siunitx_unit_prop \l__siunitx_tmpa_tl + \l__siunitx_tmpa_tl + { + \use:c + { + __siunitx_unit_format_qualifier_ + \l__siunitx_qualifier_mode_tl : + } + } +} +\cs_new_protected:Npn \__siunitx_unit_format_qualifier_brackets: { + \tl_put_right:NV \l__siunitx_unit_current_tl \l__siunitx_bracket_open_tl + \tl_put_right:NV \l__siunitx_unit_current_tl \l__siunitx_tmpa_tl + \tl_put_right:NV \l__siunitx_unit_current_tl \l__siunitx_bracket_close_tl +} +\cs_new_protected:Npn \__siunitx_unit_format_qualifier_phrase: + { + \tl_put_right:NV \l__siunitx_unit_current_tl \l__siunitx_qualifier_phrase_tl + \tl_put_right:NV \l__siunitx_unit_current_tl \l__siunitx_tmpa_tl + \tl_set:Nx \l__siunitx_tmpa_tl + { bracket- \int_use:N \l__siunitx_unit_int } + \prop_put:NVn \l__siunitx_unit_prop \l__siunitx_tmpa_tl { true } + } +\char_set_catcode_active:N \~ +\cs_new_protected:Npn \__siunitx_unit_format_qualifier_space: { + \tl_put_right:Nn \l__siunitx_unit_current_tl { \text { ~ } } + \tl_put_right:NV \l__siunitx_unit_current_tl \l__siunitx_tmpa_tl + \tl_set:Nx \l__siunitx_tmpa_tl + { bracket- \int_use:N \l__siunitx_unit_int } + \prop_put:NVn \l__siunitx_unit_prop \l__siunitx_tmpa_tl { true } +} +\char_set_catcode_space:N \~ +\cs_new_protected:Npn \__siunitx_unit_format_qualifier_subscript: { + \tl_put_right:Nx \l__siunitx_unit_current_tl + { \exp_not:N \PrintSubscript { \exp_not:V \l__siunitx_tmpa_tl } } +} +\cs_new_protected:Npn \__siunitx_unit_format_qualifier_text: { + \tl_put_right:NV \l__siunitx_unit_current_tl \l__siunitx_tmpa_tl +} +\cs_new_protected:Npn \__siunitx_unit_format_sorted: + { + \tl_set:Nx \l__siunitx_unit_tl + { + \exp_not:V \l__siunitx_unit_numerator_tl + \bool_lazy_or:nnF + { \tl_if_empty_p:N \l__siunitx_unit_numerator_tl } + { \tl_if_empty_p:N \l__siunitx_unit_denominator_tl } + { + \exp_not:N \l__siunitx_unit_product_tl + } + \exp_not:V \l__siunitx_unit_denominator_tl + } + } +\cs_new_protected:Npn \__siunitx_unit_format_symbol: { + \tl_set:Nx \l__siunitx_tmpa_tl + { symbol- \int_use:N \l__siunitx_unit_int } + \prop_get:NVNTF \l__siunitx_unit_prop \l__siunitx_tmpa_tl + \l__siunitx_tmpa_tl + { + \tl_put_right:NV \l__siunitx_unit_current_tl \l__siunitx_tmpa_tl + } + { \__siunitx_unit_format_symbol_aux: } +} +\cs_new_protected:Npn \__siunitx_unit_format_symbol_aux: { + \msg_error:nn { siunitx } { prefix-only } +} +\cs_new_protected:Npn \__siunitx_unit_format_symbol_aux_alt: { + \int_compare:nNnTF { \l__siunitx_unit_int } = { 1 } + { + \prop_remove:Nn \l__siunitx_unit_prop { prefix-1 } + \prop_remove:Nn \l__siunitx_unit_prop { prefix-symbol-1 } + \prop_remove:Nn \l__siunitx_unit_prop { prefix-base-1 } + \prop_remove:Nn \l__siunitx_unit_prop { total-units } + \prop_if_empty:NF \l__siunitx_unit_prop + { \msg_error:nn { siunitx } { prefix-only } } + } + { \msg_error:nn { siunitx } { prefix-only } } +} +\bool_new:N \l__siunitx_multi_brackets_bool +\bool_new:N \l__siunitx_multi_repeat_bool +\bool_new:N \l__siunitx_product_brackets_bool +\bool_new:N \l__siunitx_product_power_bool +\bool_new:N \l__siunitx_product_repeat_bool +\bool_new:N \l__siunitx_number_unit_repeat_bool +\keys_define:nn { siunitx } { + allow-number-unit-breaks .bool_set:N = + \l__siunitx_number_unit_breaks_bool, + multi-part-units .choice:, + multi-part-units + / brackets .code:n = + { + \bool_set_true:N \l__siunitx_multi_brackets_bool + \bool_set_false:N \l__siunitx_multi_repeat_bool + }, + multi-part-units + / repeat .code:n = + { + \bool_set_false:N \l__siunitx_multi_brackets_bool + \bool_set_true:N \l__siunitx_multi_repeat_bool + }, + multi-part-units + / single .code:n = + { + \bool_set_false:N \l__siunitx_multi_brackets_bool + \bool_set_false:N \l__siunitx_multi_repeat_bool + }, + number-unit-product .tl_set:N = + \l__siunitx_number_unit_product_tl, + number-unit-separator .tl_set:N = + \l__siunitx_number_unit_product_tl, + product-units .choice:, + product-units + / brackets .code:n = + { + \bool_set_true:N \l__siunitx_product_brackets_bool + \bool_set_false:N \l__siunitx_product_power_bool + \bool_set_false:N \l__siunitx_product_repeat_bool + }, + product-units + / brackets-power .code:n = + { + \bool_set_true:N \l__siunitx_product_brackets_bool + \bool_set_true:N \l__siunitx_product_power_bool + \bool_set_false:N \l__siunitx_product_repeat_bool + }, + product-units + / power .code:n = + { + \bool_set_false:N \l__siunitx_product_brackets_bool + \bool_set_true:N \l__siunitx_product_power_bool + \bool_set_false:N \l__siunitx_product_repeat_bool + }, + product-units + / repeat .code:n = + { + \bool_set_false:N \l__siunitx_product_brackets_bool + \bool_set_false:N \l__siunitx_product_power_bool + \bool_set_true:N \l__siunitx_product_repeat_bool + }, + product-units + / single .code:n = + { + \bool_set_false:N \l__siunitx_product_brackets_bool + \bool_set_false:N \l__siunitx_product_power_bool + \bool_set_false:N \l__siunitx_product_repeat_bool + }, +} +\keys_set:nn { siunitx } { + multi-part-units = brackets, + number-unit-product = \, , + product-units = repeat +} +\cs_new_protected:Npn \__siunitx_unit_output:nn #1#2 { + \cs_set_eq:NN \__siunitx_unit_format_symbol_aux: + \__siunitx_unit_format_symbol_aux_alt: + \cs_set_eq:NN \__siunitx_unit_format_fraction_symbol_aux_ii: + \__siunitx_unit_format_fraction_symbol_aux_alt: + \__siunitx_unit_in:nn {#1} {#2} + \int_compare:nNnTF { \l__siunitx_unit_prefix_int } = { 0 } + { + \str_if_eq:VnT \l__siunitx_per_mode_tl { symbol } + { + \int_compare:nNnT { \l__siunitx_unit_numerator_int } = { 0 } + { + \bool_if:NT \l__siunitx_unit_parse_bool + { \__siunitx_print:nn { unit } { 1 } } + } + } + } + { + \tl_set:Nx \l__siunitx_tmpa_tl + { + \int_use:N \l__siunitx_unit_prefix_base_int + \exp_not:N \PrintSuperscript + { \int_use:N \l__siunitx_unit_prefix_int } + } + \__siunitx_print:nV { number } \l__siunitx_tmpa_tl + \__siunitx_unit_output_number_sep: + } + \__siunitx_print:nV { unit } \l__siunitx_unit_tl +} +\cs_generate_variant:Nn \__siunitx_unit_output:nn { V } +\cs_new_protected:Npn \__siunitx_unit_output_number_sep: { + \bool_if:NTF \l__siunitx_number_unit_breaks_bool + { \penalty \binoppenalty } { \nobreak } + \bool_if:NTF \l__siunitx_per_auto_bool + { + \mode_if_math:TF + { + \tex_mathchoice:D + { \l__siunitx_number_unit_product_tl } + { \__siunitx_unit_output_number_sep_aux: } + { \__siunitx_unit_output_number_sep_aux: } + { \__siunitx_unit_output_number_sep_aux: } + } + { \__siunitx_unit_output_number_sep_aux: } + } + { \__siunitx_unit_output_number_sep_aux: } +} +\cs_new_protected:Npn \__siunitx_unit_output_number_sep_aux: { + \bool_if:NF \l__siunitx_omit_unit_space_bool + { \l__siunitx_number_unit_product_tl } +} +\cs_new_protected:Npn \__siunitx_unit_output_pre_print: { + \tl_if_empty:NF \l__siunitx_pre_unit_tl + { + \nobreak + \__siunitx_print:nV { unit } \l__siunitx_pre_unit_tl + } +} +\cs_new_protected:Npn \__siunitx_unit_output_print: { + \int_compare:nNnF { \l__siunitx_unit_prefix_int } = { 0 } + { + \tl_set:Nx \l__siunitx_tmpa_tl + { + \bool_if:NTF \l__siunitx_tight_bool + { + \exp_not:N \ensuremath + { { \exp_not:V \l__siunitx_exponent_product_tl } } + } + { + \exp_not:N \ensuremath + { { } \exp_not:V \l__siunitx_exponent_product_tl { } } + } + \int_use:N \l__siunitx_unit_prefix_base_int + ^ { \int_use:N \l__siunitx_unit_prefix_int } + } + \__siunitx_print:nV { number } \l__siunitx_tmpa_tl + } + \tl_if_empty:NF \l__siunitx_unit_tl + { + \__siunitx_unit_output_number_sep: + \__siunitx_print:nV { unit } \l__siunitx_unit_tl + } +} +\keys_define:nn { siunitx } { + preunit .tl_set:N = \l__siunitx_preunit_tl , +} +\tl_new:N \l__siunitx_pre_unit_tl +\int_new:N \l__siunitx_number_product_int +\cs_new_protected:Npn \__siunitx_combined:nnnn #1#2#3#4 { + \IfNoValueTF {#3} + { \tl_clear:N \l__siunitx_pre_unit_tl } + { + \group_begin: + \__siunitx_unit_in:nn {#3} {#1} + \cs_set_eq:NN \l__siunitx_pre_unit_tl \l__siunitx_unit_tl + \exp_args:NNNo \group_end: + \tl_set:Nn \l__siunitx_pre_unit_tl { \l__siunitx_unit_tl } + } + \cs_set_eq:NN \l__siunitx_brackets_bool + \l__siunitx_multi_brackets_bool + \__siunitx_combined_unit:nnn {#2} {#4} {#1} + \__siunitx_combined_output:n {#2} +} +\cs_new_protected:Npn \__siunitx_combined_output:n #1 { + \bool_if:NTF \l__siunitx_number_parse_bool + { + \tl_clear:N \l__siunitx_number_out_tl + \bool_set_false:N \l__siunitx_number_compound_bool + \__siunitx_number_output_parse:n {#1} + } + { + \__siunitx_unit_output_pre_print: + \__siunitx_print:nn { number } { \ensuremath {#1} } + \__siunitx_unit_output_print: + } +} +\cs_new_protected:Npn \__siunitx_combined_unit:nnn #1#2#3 { + \bool_if:NTF \l__siunitx_product_power_bool + { + \__siunitx_combined_product_count:n {#1} + \int_compare:nNnTF { \l__siunitx_number_product_int } > { 0 } + { + \int_incr:N \l__siunitx_number_product_int + \tl_set:Nn \l__siunitx_tmpa_tl {#2} + \tl_set:Nx \l__siunitx_tmpb_tl + { \tothe { \exp_not:V \l__siunitx_number_product_int } } + \tl_put_right:NV \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl + \__siunitx_unit_in:Vn \l__siunitx_tmpa_tl {#3} + } + { \__siunitx_unit_in:nn {#2} {#3} } + } + { \__siunitx_unit_in:nn {#2} {#3} } +} +\cs_new_protected:Npn \__siunitx_combined_product_count:n #1 { + \int_zero:N \l__siunitx_number_product_int + \tl_set:Nn \l__siunitx_tmpa_tl {#1} + \tl_map_function:NN \l__siunitx_input_product_tl + \__siunitx_combined_product_count_aux:N +} +\cs_new_protected:Npn \__siunitx_combined_product_count_aux:N #1 { + \tl_if_in:NnT \l__siunitx_tmpa_tl {#1} + { + \int_incr:N \l__siunitx_number_product_int + \tl_remove_once:Nn \l__siunitx_tmpa_tl {#1} + \__siunitx_combined_product_count_aux:N #1 + } +} +\bool_new:N \l__siunitx_list_brackets_bool +\bool_new:N \l__siunitx_list_repeat_bool +\tl_new:N \l__siunitx_list_current_tl +\tl_new:N \l__siunitx_list_tl +\keys_define:nn { siunitx } + { + list-final-separator .tl_set:N = \l__siunitx_list_separator_final_tl , + list-pair-separator .tl_set:N = \l__siunitx_list_separator_pair_tl , + list-separator .tl_set:N = \l__siunitx_list_separator_tl , + list-units .choice:, + list-units + / brackets .code:n = + { + \bool_set_true:N \l__siunitx_list_brackets_bool + \bool_set_false:N \l__siunitx_list_repeat_bool + }, + list-units + / repeat .code:n = + { + \bool_set_false:N \l__siunitx_list_brackets_bool + \bool_set_true:N \l__siunitx_list_repeat_bool + }, + list-units + / single .code:n = + { + \bool_set_false:N \l__siunitx_list_brackets_bool + \bool_set_false:N \l__siunitx_list_repeat_bool + } + } +\keys_set:nn { siunitx } + { + list-final-separator = { ~ and ~ } , + list-pair-separator = { ~ and ~ } , + list-separator = { , ~ } , + list-units = repeat +} +\cs_new_protected:Npn \__siunitx_list_numbers:n #1 + { + \tl_clear:N \l__siunitx_unit_tl + \tl_clear:N \l__siunitx_preunit_tl + \__siunitx_list_numbers_aux_i:n {#1} + } +\cs_new_protected:Npn \__siunitx_list_numbers_aux_i:n #1 + { + \bool_set_true:N \l__siunitx_list_first_bool + \tl_clear:N \l__siunitx_list_current_tl + \int_compare:nNnTF { \tl_count:n {#1} } > 2 + { + \tl_map_function:nN {#1} \__siunitx_list_numbers_aux_ii:n + \l__siunitx_list_tl + \l__siunitx_list_separator_final_tl + \l__siunitx_list_current_tl + } + { + \int_compare:nNnTF { \tl_count:n {#1} } = 2 + { \__siunitx_list_numbers_aux:nn #1 } + { \__siunitx_combined_output:n #1 } + } + } +\cs_new_protected:Npn \__siunitx_list_numbers_aux_ii:n #1 + { + \tl_if_empty:NTF \l__siunitx_list_tl + { \tl_set_eq:NN \l__siunitx_list_tl \l__siunitx_list_current_tl } + { + \tl_put_right:NV \l__siunitx_list_tl \l__siunitx_list_separator_tl + \tl_put_right:NV \l__siunitx_list_tl \l__siunitx_list_current_tl + } + \tl_set:Nn \l__siunitx_list_current_tl { \__siunitx_combined_output:n {#1} } + } +\cs_new_protected:Npn \__siunitx_list_numbers_aux:nn #1#2 + { + \__siunitx_combined_output:n {#1} + \l__siunitx_list_separator_pair_tl + \__siunitx_combined_output:n {#2} + } +\cs_new_protected:Npn \__siunitx_list_units:nnn #1#2#3 + { + \__siunitx_unit_parse_options:nn {#2} {#3} + \bool_if:NTF \l__siunitx_list_repeat_bool + { + \__siunitx_unit_in:nn {#2} {#3} + \__siunitx_list_numbers_aux_i:n {#1} + } + { + \bool_if:NT \l__siunitx_process_fixed_bool + { \bool_set_true:N \l__siunitx_process_drop_exponent_bool } + \bool_if:NT \l__siunitx_list_brackets_bool + { \__siunitx_print:nV { number } \l__siunitx_bracket_open_tl } + \__siunitx_list_numbers:n {#1} + \bool_if:NT \l__siunitx_list_brackets_bool + { \__siunitx_print:nV { number } \l__siunitx_bracket_close_tl } + \__siunitx_range_exponent: + \__siunitx_unit_output_number_sep: + \__siunitx_unit_output:nn {#2} {#3} + } + } +\bool_new:N \l__siunitx_range_brackets_bool +\bool_new:N \l__siunitx_range_repeat_bool +\keys_define:nn { siunitx } { + range-phrase .tl_set:N = \l__siunitx_range_phrase_tl, + range-units .choice:, + range-units + / brackets .code:n = + { + \bool_set_true:N \l__siunitx_range_brackets_bool + \bool_set_false:N \l__siunitx_range_repeat_bool + }, + range-units + / repeat .code:n = + { + \bool_set_false:N \l__siunitx_range_brackets_bool + \bool_set_true:N \l__siunitx_range_repeat_bool + }, + range-units + / single .code:n = + { + \bool_set_false:N \l__siunitx_range_brackets_bool + \bool_set_false:N \l__siunitx_range_repeat_bool + }, +} +\keys_set:nn { siunitx } { + range-phrase = { ~ to ~ }, + range-units = repeat, +} +\cs_new_protected:Npn \__siunitx_range_numbers:nn #1#2 + { + \__siunitx_range_numbers_aux:n {#1} + \l__siunitx_range_phrase_tl + \__siunitx_range_numbers_aux:n {#2} + } +\cs_new_protected:Npn \__siunitx_range_numbers_aux:n #1 + { + \bool_if:NTF \l__siunitx_number_parse_bool + { + \tl_clear:N \l__siunitx_number_out_tl + \tl_clear:N \l__siunitx_number_out_saved_tl + \bool_set_false:N \l__siunitx_number_compound_bool + \__siunitx_number_output_parse:n {#1} + \bool_if:NT \l__siunitx_number_compound_bool + { \msg_error:nnx { siunitx } { multi-part-range } {#1} } + } + { + \__siunitx_unit_output_pre_print: + \__siunitx_print:nn { number } {#1} + \__siunitx_unit_output_print: + } + } +\cs_new_protected:Npn \__siunitx_range_unit:nnnn #1#2#3#4 { + \__siunitx_unit_parse_options:nn {#1} {#2} + \bool_if:NTF \l__siunitx_range_repeat_bool + { + \__siunitx_unit_in:nn {#1} {#2} + \__siunitx_range_numbers_aux:n {#3} + \l__siunitx_range_phrase_tl + \__siunitx_range_numbers_aux:n {#4} + } + { + \bool_if:NT \l__siunitx_process_fixed_bool + { \bool_set_true:N \l__siunitx_process_drop_exponent_bool } + \bool_if:NT \l__siunitx_range_brackets_bool + { \__siunitx_print:nV { number } \l__siunitx_bracket_open_tl } + \__siunitx_range_numbers:nn {#3} {#4} + \bool_if:NT \l__siunitx_range_brackets_bool + { \__siunitx_print:nV { number } \l__siunitx_bracket_close_tl } + \__siunitx_range_exponent: + \__siunitx_unit_output_number_sep: + \__siunitx_unit_output:nn {#1} {#2} + } +} +\cs_new_protected:Npn \__siunitx_range_exponent: + { + \bool_if:NT \l__siunitx_process_fixed_bool + { + \tl_set_eq:NN \l__siunitx_tmpa_tl \l__siunitx_exponent_product_tl + \bool_if:NT \l__siunitx_tight_bool + { + \tl_set:Nx \l__siunitx_tmpa_tl + { \exp_not:N \mathord \exp_not:o \l__siunitx_tmpa_tl } + } + \tl_set:Nx \l__siunitx_tmpa_tl + { + \exp_not:N \ensuremath { { } \exp_not:o \l__siunitx_tmpa_tl { } } + 10 \exp_not:N \PrintSuperscript + { \int_use:N \l__siunitx_process_fixed_int } + } + \__siunitx_print:nV { number } \l__siunitx_tmpa_tl + } + } +\AtBeginDocument { + \@ifpackageloaded { cellspace } + { + \cs_if_exist:NT \NC@find@S + { + \newcolumntype { C } [1] + { > { \bcolumn #1 \@nil } #1 < { \ecolumn } } + \cs_set:Npn \__siunitx_tmp:w #1 \NC@do S #2 \q_stop + { \NC@list { #1 #2 } } + \exp_after:wN \__siunitx_tmp:w \tex_the:D \NC@list \q_stop + \cs_undefine:N \NC@find@S + \msg_new:nnn { siunitx } { moved-cellspace-column } + { Column~type~for~cellspace~package~moved~to~'#1'. } + \msg_warning:nnn { siunitx } { moved-cellspace-column } { C } + \ifcellspace@m + \def \env@matrix + { + \hskip -\arraycolsep + \let \@ifnextchar \new@ifnextchar + \array + { + * { \c@MaxMatrixCols } + { > { \bcolumn c \@nil $ } c < { $ \ecolumn } } @ { } + } + } + \fi + } + } + { } +} +\cs_new_protected:Npn \__siunitx_table_rewrite_create:N #1 { + \newcolumntype {#1} { } + \cs_set_protected:Npn + \__siunitx_table_rewrite_create_aux:w \NC@do ##1##2 \NC@do #1 + { \NC@list { \NC@do ##1 \NC@do #1 ##2 } } + \exp_after:wN \__siunitx_table_rewrite_create_aux:w \tex_the:D \NC@list + \exp_args:NNc \renewcommand * { NC@rewrite@ #1 } [1] [ ] + { + \@temptokena \exp_after:wN + { + \tex_the:D \@temptokena + > { \__siunitx_table_collect_begin:Nn #1 {##1} } + c + < { \__siunitx_table_print: } + } + \NC@find + } +} +\AtBeginDocument + { + \@ifpackageloaded { mdwtab } + { + \cs_set_protected:Npn \__siunitx_table_rewrite_create:N #1 + { + \newcolumntype {#1} [1] [] + { + > { \__siunitx_table_collect_begin:Nn #1 {##1} } + c + < { \__siunitx_table_print: } + } + } + } + { } + } +\cs_new_protected:Npn \__siunitx_table_rewrite_create_aux:w { } +\AtBeginDocument { \__siunitx_table_rewrite_create:N s } +\AtBeginDocument { \__siunitx_table_rewrite_create:N S } +\tl_new:N \l__siunitx_table_collect_tl +\tl_new:N \l__siunitx_table_collect_pre_tl +\tl_new:N \l__siunitx_table_collect_post_tl +\tl_new:N \l__siunitx_number_valid_tl +\bool_new:N \l__siunitx_table_math_bool +\bool_new:N \l__siunitx_table_collect_pre_bool +\bool_new:N \l__siunitx_table_collect_post_bool +\cs_new_protected:Npn \__siunitx_table_collect_begin:Nn #1#2 + { + \keys_set:nn { siunitx } {#2} + \__siunitx_table_collect_begin:Nw #1 + } +\cs_new_protected:Npn \__siunitx_table_collect_begin:Nw #1#2 \ignorespaces + { \use:c { __siunitx_table_collect_begin_ #1 : } #2 } +\cs_new_protected:Npn \__siunitx_table_collect_begin_s: { + \cs_set_eq:NN \__siunitx_table_collect_token:N + \__siunitx_table_collect_token_s:N + \cs_set_eq:NN \__siunitx_table_print: \__siunitx_table_print_s: + \__siunitx_table_collect_init_s: + \__siunitx_table_collect_get: +} +\cs_new_protected:Npn \__siunitx_table_collect_begin_S: { + \cs_set_eq:NN \__siunitx_table_collect_token:N + \__siunitx_table_collect_token_S:N + \cs_set_eq:NN \__siunitx_table_print: \__siunitx_table_print_S: + \__siunitx_table_collect_init_S: + \__siunitx_detect_font: + \bool_if:NTF \l__siunitx_number_parse_bool + { \__siunitx_table_collect_get: } + { \__siunitx_table_print_S_direct: } +} +\cs_new_protected:Npn \__siunitx_table_collect_braced:n #1 { } +\cs_new_protected:Npn \__siunitx_table_collect_expand:N #1 { + \cs_if_eq:NNTF #1 \color + { + \bool_if:NTF \l__siunitx_table_collect_pre_bool + { + \tl_clear:N \l__siunitx_number_color_tl + \tl_clear:N \l__siunitx_unit_color_tl + \tl_put_right:Nn \l__siunitx_table_collect_pre_tl {#1} + } + { + \bool_set_true:N \l__siunitx_table_collect_post_bool + \tl_put_right:Nn \l__siunitx_table_collect_post_tl {#1} + } + } + { + \__siunitx_cs_if_tl:NTF #1 + { + \tl_use:N \l__siunitx_table_collect_pre_tl + \tl_clear:N \l__siunitx_table_collect_pre_tl + \cs_set:Npn \__siunitx_table_collect_next: + { \exp_after:wN \__siunitx_table_collect_get: #1 } + } + { + \bool_if:NTF \l__siunitx_table_collect_pre_bool + { + \tl_put_right:Nn \l__siunitx_table_collect_pre_tl {#1} + \__siunitx_table_collect_expand_math:N #1 + } + { + \bool_set_true:N \l__siunitx_table_collect_post_bool + \tl_put_right:Nn \l__siunitx_table_collect_post_tl {#1} + } + } + } +} +\cs_new_protected:Npn \__siunitx_table_collect_expand_math:N #1 { + \token_if_math_toggle:NTF #1 + { + \bool_if:NTF \l__siunitx_table_math_bool + { \bool_set_false:N \l__siunitx_table_math_bool } + { \bool_set_true:N \l__siunitx_table_math_bool } + } + { + \cs_if_eq:NNTF #1 \( % \) + { \bool_set_true:N \l__siunitx_table_math_bool } + { % \( + \cs_if_eq:NNT #1 \) + { \bool_set_false:N \l__siunitx_table_math_bool } + } + } +} +\cs_new_protected:Npn \__siunitx_table_collect_get: + { + \cs_set_eq:NN \__siunitx_table_collect_next: + \__siunitx_table_collect_get: + \peek_catcode_ignore_spaces:NTF \c_group_begin_token + { \__siunitx_table_collect_braced:n } + { \__siunitx_table_collect_not_braced:N } + } +\cs_new_protected:Npn \__siunitx_table_collect_init: { + \tl_clear:N \l__siunitx_table_collect_tl + \tl_clear:N \l__siunitx_table_collect_pre_tl + \tl_clear:N \l__siunitx_table_collect_post_tl + \bool_set_false:N \l__siunitx_table_collect_post_bool + \bool_set_false:N \l__siunitx_table_math_bool +} +\cs_new_protected:Npn \__siunitx_table_collect_init_s: { + \__siunitx_table_collect_init: + \bool_set_false:N \l__siunitx_table_collect_pre_bool + \cs_set_protected:Npn \__siunitx_table_collect_braced:n ##1 + { + \tl_put_right:Nn \l__siunitx_table_collect_tl { {##1} } + \__siunitx_table_collect_next: + } +} +\cs_new_protected:Npn \__siunitx_table_collect_init_S: { + \__siunitx_number_in_init: + \tl_set:Nx \l__siunitx_number_valid_tl + { + \exp_not:V \l__siunitx_input_complex_tl + \exp_not:V \l__siunitx_input_decimal_tl + \exp_not:V \l__siunitx_input_digit_tl + \exp_not:V \l__siunitx_input_exponent_tl + \exp_not:V \l__siunitx_input_ignore_tl + \exp_not:V \l__siunitx_input_comparator_tl + \exp_not:V \l__siunitx_input_uncert_close_tl + \exp_not:V \l__siunitx_input_uncert_open_tl + \exp_not:V \l__siunitx_input_sign_tl + \exp_not:V \l__siunitx_input_symbol_tl + } + \bool_set_true:N \l__siunitx_table_collect_pre_bool + \cs_set_protected:Npn \__siunitx_table_collect_braced:n ##1 + { + \bool_if:NTF \l__siunitx_table_collect_pre_bool + { \tl_put_right:Nn \l__siunitx_table_collect_pre_tl { {##1} } } + { + \bool_set_true:N \l__siunitx_table_collect_post_bool + \tl_put_right:Nn \l__siunitx_table_collect_post_tl { {##1} } + } + \__siunitx_table_collect_next: + } +} +\cs_new_protected:Npn \__siunitx_table_collect_next: { } +\cs_new_protected:Npn \__siunitx_table_collect_newline: { + \__siunitx_table_print: + \cs_set_eq:NN \__siunitx_table_print: \prg_do_nothing: + \tabularnewline +} +\cs_new_protected:Npn \__siunitx_table_collect_end: { + \__siunitx_table_print: + \cs_set_eq:NN \__siunitx_table_print: \prg_do_nothing: + \end +} +\cs_new_protected:Npn \__siunitx_table_collect_not_braced:N #1 + { + \token_if_eq_meaning:NNF #1 \tex_ignorespaces:D + { + \token_if_eq_meaning:NNF #1 \tex_unskip:D + { \__siunitx_table_collect_not_braced_aux_i:N #1 } + } + \__siunitx_table_collect_next: + } +\AtBeginDocument + { + \@ifpackageloaded { mdwtab } + { + \cs_set_protected:Npn \__siunitx_table_collect_not_braced:N #1 + { + \token_if_eq_meaning:NNF #1 \tex_ignorespaces:D + { + \token_if_eq_meaning:NNF #1 \tex_unskip:D + { + \token_if_eq_meaning:NNF #1 \tab@setcr + { + \token_if_eq_meaning:NNF #1 \@maybe@unskip + { \__siunitx_table_collect_not_braced_aux_i:N #1 } + } + } + } + \__siunitx_table_collect_next: + } + } + { } + } +\cs_new_protected:Npn \__siunitx_table_collect_not_braced_aux_i:N #1 { + \cs_set:Npn \__siunitx_table_collect_not_braced_aux_ii:N ##1 + { + \token_if_eq_meaning:NNT #1 ##1 + { \cs_set_eq:NN \__siunitx_table_collect_next: ##1 } + } + \tl_map_function:nN + { \cs:w \scan_stop: \__siunitx_table_print: } + \__siunitx_table_collect_not_braced_aux_ii:N + \token_if_eq_meaning:NNT \__siunitx_table_collect_next: + \__siunitx_table_collect_get: + { + \token_if_eq_meaning:NNTF #1 \tabularnewline + { + \cs_set_eq:NN \__siunitx_table_collect_next: + \__siunitx_table_collect_newline: + } + { + \token_if_eq_meaning:NNTF #1 \end + { + \cs_set_eq:NN \__siunitx_table_collect_next: + \__siunitx_table_collect_end: + } + { \__siunitx_table_collect_token:N #1 } + } + } +} +\cs_new_protected:Npn \__siunitx_table_collect_not_braced_aux_ii:N #1 { } +\cs_new_protected:Npn \__siunitx_table_collect_token:N #1 { } +\cs_new_protected:Npn \__siunitx_table_collect_token_s:N #1 { + \tl_put_right:Nn \l__siunitx_table_collect_tl {#1} +} +\cs_new_protected:Npn \__siunitx_table_collect_token_S:N #1 { + \bool_if:NTF \l__siunitx_table_collect_post_bool + { \tl_put_right:Nn \l__siunitx_table_collect_post_tl {#1} } + { + \tl_if_in:NnTF \l__siunitx_number_valid_tl {#1} + { + \bool_set_false:N \l__siunitx_table_collect_pre_bool + \tl_put_right:Nn \l__siunitx_table_collect_tl {#1} + } + { \__siunitx_table_collect_expand:N #1 } + } +} +\skip_const:Nn \c__siunitx_one_fill_skip { 0pt plus 1fill } +\AtBeginDocument + { + \@ifpackageloaded { colortbl } + { + \cs_new_protected:Npn \__siunitx_table_colortbl_correction: + { + \skip_horizontal:n { 0pt plus -0.5fill } + \tex_kern:D \c_zero_skip + } + } + { \cs_new_protected:Npn \__siunitx_table_colortbl_correction: { } } + } +\cs_new_protected:Npn \__siunitx_table_align_left:n #1 + { + \__siunitx_table_colortbl_correction: + \skip_horizontal:n {#1} + \tex_kern:D \c_zero_skip + } +\cs_new_protected:Npn \__siunitx_table_align_right:n #1 + { + \skip_horizontal:n { \c__siunitx_one_fill_skip - #1 } + \tex_kern:D \c_zero_skip + \__siunitx_table_colortbl_correction: + } +\cs_new_eq:NN \__siunitx_table_column_begin:n \__siunitx_table_align_left:n +\cs_new_eq:NN \__siunitx_table_column_end:n \__siunitx_table_align_right:n +\keys_define:nn { siunitx } + { + table-column-width .code:n = + { + \dim_compare:nNnTF {#1} = { \c_zero_dim } + { + \cs_set_eq:NN \__siunitx_table_column_begin:n + \__siunitx_table_align_left:n + \cs_set_eq:NN \__siunitx_table_column_end:n + \__siunitx_table_align_right:n + } + { + \cs_set_protected:Npn \__siunitx_table_column_begin:n ##1 + { + \__siunitx_table_colortbl_correction: + \tex_hbox:D to \dim_eval:n {#1} + \c_group_begin_token + \skip_horizontal:n {##1} + \tex_kern:D \c_zero_skip + } + \cs_set_protected:Npn \__siunitx_table_column_end:n ##1 + { + \skip_horizontal:n { \c__siunitx_one_fill_skip - ##1 } + \tex_kern:D \c_zero_skip + \c_group_end_token + \__siunitx_table_colortbl_correction: + } + } + } + } +\skip_new:N \l__siunitx_table_unit_align_skip +\keys_define:nn { siunitx } + { + table-unit-alignment .choice:, + table-unit-alignment / + center .code:n = + { + \skip_set:Nn \l__siunitx_table_unit_align_skip + { 0pt plus 0.5fill } + }, + table-unit-alignment / + left .code:n = + { \skip_set:Nn \l__siunitx_table_unit_align_skip { \c_zero_skip } }, + table-unit-alignment / + right .code:n = + { + \skip_set:Nn \l__siunitx_table_unit_align_skip + { 0pt plus 1fill } + } + } +\keys_set:nn { siunitx } { table-unit-alignment = center } +\cs_new_protected:Npn \__siunitx_table_print_s: + { + \__siunitx_table_column_begin:n { \l__siunitx_table_unit_align_skip } + \tl_if_empty:NF \l__siunitx_table_collect_tl + { \__siunitx_unit_output:Vn \l__siunitx_table_collect_tl { } } + \__siunitx_table_column_end:n { \l__siunitx_table_unit_align_skip } + } +\prop_new:N \l__siunitx_table_model_prop +\dim_new:N \l__siunitx_table_exponent_dim +\dim_new:N \l__siunitx_table_integer_dim +\dim_new:N \l__siunitx_table_mantissa_dim +\dim_new:N \l__siunitx_table_marker_dim +\dim_new:N \l__siunitx_table_result_dim +\dim_new:N \l__siunitx_table_uncert_dim +\dim_new:N \l__siunitx_table_fill_pre_dim +\dim_new:N \l__siunitx_table_fill_post_dim +\dim_new:N \l__siunitx_table_fill_mid_dim +\box_new:N \l__siunitx_table_pre_box +\box_new:N \l__siunitx_table_post_box +\box_new:N \l__siunitx_table_mantissa_box +\box_new:N \l__siunitx_table_result_box +\skip_new:N \l__siunitx_table_number_align_skip +\skip_new:N \l__siunitx_table_text_align_skip +\cs_new_protected:Npn \__siunitx_table_print_S_direct_main: { } +\cs_new_protected:Npn \__siunitx_table_print_S_parsed: { } +\cs_new_protected:Npn \__siunitx_table_print_S_reserved_store_fill:n #1 { } +\keys_define:nn { siunitx } + { + table-align-comparator .choice:, + table-align-comparator / + false .code:n = + { + \cs_set_eq:NN \__siunitx_table_print_S_reserved_store_fill:n + \__siunitx_table_print_S_reserved_store_fill_pre:n + }, + table-align-comparator / + true .code:n = + { + \cs_set_eq:NN \__siunitx_table_print_S_reserved_store_fill:n + \__siunitx_table_print_S_reserved_store_fill_mid:n + }, + table-align-comparator .default:n = true, + table-align-exponent .bool_set:N = + \l__siunitx_table_align_exponent_bool, + table-align-text-pre .bool_set:N = + \l__siunitx_table_align_text_pre_bool, + table-align-text-post .bool_set:N = + \l__siunitx_table_align_text_post_bool, + table-align-uncertainty .bool_set:N = \l__siunitx_table_align_uncert_bool, + table-auto-round .bool_set:N = \l__siunitx_table_auto_round_bool, + table-number-alignment .choice:, + table-number-alignment / + center .code:n = + { + \skip_set:Nn \l__siunitx_table_number_align_skip + { 0pt plus 0.5fill } + \cs_set_eq:NN \__siunitx_table_print_S_direct_main: + \__siunitx_table_print_S_direct_reserved: + \cs_set_eq:NN \__siunitx_table_print_S_parsed: + \__siunitx_table_print_S_reserved: + }, + table-number-alignment / + center-decimal-marker .code:n = + { + \skip_set:Nn \l__siunitx_table_number_align_skip + { 0pt plus 0.5fill } + \cs_set_eq:NN \__siunitx_table_print_S_direct_main: + \__siunitx_table_print_S_direct_centered: + \cs_set_eq:NN \__siunitx_table_print_S_parsed: + \__siunitx_table_print_S_centered: + }, + table-number-alignment / + left .code:n = + { + \skip_zero:N \l__siunitx_table_number_align_skip + \cs_set_eq:NN \__siunitx_table_print_S_direct_main: + \__siunitx_table_print_S_direct_reserved: + \cs_set_eq:NN \__siunitx_table_print_S_parsed: + \__siunitx_table_print_S_reserved: + }, + table-number-alignment / + right .code:n = + { + \skip_set:Nn \l__siunitx_table_number_align_skip + { 0pt plus 1fill } + \cs_set_eq:NN \__siunitx_table_print_S_direct_main: + \__siunitx_table_print_S_direct_reserved: + \cs_set_eq:NN \__siunitx_table_print_S_parsed: + \__siunitx_table_print_S_reserved: + }, + table-omit-exponent .bool_set:N = + \l__siunitx_table_omit_exponent_bool, + table-text-alignment .choice:, + table-text-alignment / + center .code:n = + { + \skip_set:Nn \l__siunitx_table_text_align_skip + { 0pt plus 0.5fill } + }, + table-text-alignment / + left .code:n = + { \skip_zero:N \l__siunitx_table_text_align_skip }, + table-text-alignment / + right .code:n = + { + \skip_set:Nn \l__siunitx_table_text_align_skip + { 0pt plus 1fill } + }, + table-comparator .choice:, + table-comparator / + false .code:n = + { \prop_remove:Nn \l__siunitx_table_model_prop { comparator } }, + table-comparator / + true .code:n = + { \prop_put:Nnn \l__siunitx_table_model_prop { comparator } { > } }, + table-comparator .default:n = true, + table-figures-decimal .code:n = + { + \int_compare:nNnTF {#1} = 0 + { + \prop_remove:Nn \l__siunitx_table_model_prop { mantissa-decimal } + \prop_remove:Nn \l__siunitx_table_model_prop { mantissa-decimal-raw } + \prop_remove:Nn \l__siunitx_table_model_prop + { mantissa-decimal-marker } + \prop_if_in:NnTF \l__siunitx_table_model_prop { mantissa-integer } + { + \prop_put:Nnn \l__siunitx_table_model_prop { mantissa } + { true } + } + { \prop_remove:Nn \l__siunitx_table_model_prop { mantissa } } + } + { + \prop_put:Nnx \l__siunitx_table_model_prop { mantissa-decimal } + { \prg_replicate:nn {#1} { 8 } } + \prop_put:Nnn \l__siunitx_table_model_prop { mantissa-decimal-raw } + {#1} + \prop_put:Nnn \l__siunitx_table_model_prop { mantissa } { true } + \prop_put:NnV \l__siunitx_table_model_prop + { mantissa-decimal-marker } \l__siunitx_output_decimal_tl + } + }, + table-figures-exponent .code:n = + { + \int_compare:nNnTF {#1} = 0 + { \prop_remove:Nn \l__siunitx_table_model_prop { exponent-integer } } + { + \prop_put:Nnx \l__siunitx_table_model_prop { exponent-integer } + { \prg_replicate:nn {#1} { 8 } } + \prop_put:Nnn \l__siunitx_table_model_prop { exponent } { true } + } + }, + table-figures-integer .code:n = + { + \int_compare:nNnTF {#1} = 0 + { + \prop_remove:Nn \l__siunitx_table_model_prop { mantissa-integer } + \prop_if_in:NnTF \l__siunitx_table_model_prop { mantissa-decimal } + { + \prop_put:Nnn \l__siunitx_table_model_prop { mantissa } + { true } + } + { \prop_remove:Nn \l__siunitx_table_model_prop { mantissa } } + } + { + \prop_put:Nnx \l__siunitx_table_model_prop { mantissa-integer } + { \prg_replicate:nn {#1} { 8 } } + \prop_put:Nnn \l__siunitx_table_model_prop { mantissa } { true } + } + }, + table-figures-uncertainty .code:n = + { + \int_compare:nNnTF {#1} = 0 + { \prop_remove:Nn \l__siunitx_table_model_prop { mantissa-uncertainty } } + { + \prop_put:Nnx \l__siunitx_table_model_prop { mantissa-uncertainty } + { \prg_replicate:nn {#1} { 8 } } + } + }, + table-parse-only .bool_set:N = \l__siunitx_table_parse_only_bool, + table-space-text-pre .tl_set:N = \l__siunitx_table_pre_tl, + table-space-text-post .tl_set:N = \l__siunitx_table_post_tl, + table-sign-exponent .choice:, + table-sign-exponent / true .code:n = + { \prop_put:Nnn \l__siunitx_table_model_prop { exponent-sign } { - } }, + table-sign-exponent / false .code:n = + { \prop_remove:Nn \l__siunitx_table_model_prop { exponent-sign } }, + table-sign-exponent .default:n = true, + table-sign-mantissa .choice:, + table-sign-mantissa / true .code:n = + { \prop_put:Nnn \l__siunitx_table_model_prop { mantissa-sign } { - } }, + table-sign-mantissa / false .code:n = + { \prop_remove:Nn \l__siunitx_table_model_prop { mantissa-sign } }, + table-sign-mantissa .default:n = true, + } +\keys_define:nn { siunitx } + { + table-alignment .meta:n = + { + table-number-alignment = #1, + table-text-alignment = #1, + table-unit-alignment = #1 + } + } +\keys_define:nn { siunitx } + { + table-format .code:n = + { + \bool_set_eq:NN \l__siunitx_process_plus_saved_bool \l__siunitx_process_plus_bool + \bool_set_true:N \l__siunitx_process_plus_bool + \__siunitx_number_in_parse:n {#1} + \prop_set_eq:NN \l__siunitx_table_model_prop \l__siunitx_number_in_prop + \tl_clear:N \l__siunitx_tmpa_tl + \prop_get:NnNT \l__siunitx_number_in_prop { mantissa-integer } + \l__siunitx_tmpb_tl + { + \tl_set:Nx \l__siunitx_tmpa_tl + { table-figures-integer = \l__siunitx_tmpb_tl } + } + \prop_get:NnNT \l__siunitx_number_in_prop { mantissa-decimal } + \l__siunitx_tmpb_tl + { + \clist_put_right:Nx \l__siunitx_tmpa_tl + { table-figures-decimal = \l__siunitx_tmpb_tl } + } + \prop_get:NnNT \l__siunitx_number_in_prop { mantissa-uncertainty } + \l__siunitx_tmpb_tl + { + \clist_put_right:Nx \l__siunitx_tmpa_tl + { table-figures-uncertainty = \l__siunitx_tmpb_tl } + } + \prop_if_in:NnTF \l__siunitx_number_in_prop { mantissa-sign } + { + \clist_put_right:Nn \l__siunitx_tmpa_tl + { table-sign-mantissa =true } + } + { + \clist_put_right:Nn \l__siunitx_tmpa_tl + { table-sign-mantissa =false } + } + \prop_get:NnNT \l__siunitx_number_in_prop { exponent-integer } + \l__siunitx_tmpb_tl + { + \clist_put_right:Nx \l__siunitx_tmpa_tl + { table-figures-exponent = \l__siunitx_tmpb_tl } + } + \prop_if_in:NnTF \l__siunitx_number_in_prop { exponent-sign } + { + \clist_put_right:Nn \l__siunitx_tmpa_tl + { table-sign-exponent =true } + } + { + \clist_put_right:Nn \l__siunitx_tmpa_tl + { table-sign-exponent =false } + } + \clist_put_right:Nn \l__siunitx_tmpa_tl + { table-number-alignment = center } + \keys_set:nV { siunitx } \l__siunitx_tmpa_tl + \bool_set_eq:NN \l__siunitx_process_plus_bool \l__siunitx_process_plus_saved_bool + } + } +\bool_new:N \l__siunitx_process_plus_saved_bool +\cs_new_protected:Npn \__siunitx_table_print_S: + { + \bool_if:NTF \l__siunitx_table_collect_pre_bool + { + \__siunitx_table_column_begin:n { \l__siunitx_table_text_align_skip } + \l__siunitx_table_collect_pre_tl + \__siunitx_table_column_end:n { \l__siunitx_table_text_align_skip } + } + { + \__siunitx_table_column_begin:n { \l__siunitx_table_number_align_skip } + \bool_if:NTF \l__siunitx_table_parse_only_bool + { \__siunitx_table_print_S_no_alignment: } + { \__siunitx_table_print_S_alignment: } + \bool_if:NTF \l__siunitx_table_align_text_pre_bool + { \__siunitx_table_print_S_pre_aligned: } + { \__siunitx_table_print_S_pre_not_aligned: } + \box_use:N \l__siunitx_table_result_box + \bool_if:NTF \l__siunitx_table_align_text_post_bool + { \__siunitx_table_print_S_post_aligned: } + { \__siunitx_table_print_S_post_not_aligned: } + \__siunitx_table_column_end:n { \l__siunitx_table_number_align_skip } + } + } +\cs_new_protected:Npn \__siunitx_table_print_S_no_alignment: + { + \l__siunitx_table_collect_pre_tl + \__siunitx_number_output:V \l__siunitx_table_collect_tl + \l__siunitx_table_collect_post_tl + } +\cs_new_protected:Npn \__siunitx_table_print_S_alignment: + { \__siunitx_table_print_S_parsed: } +\cs_new_protected:Npn \__siunitx_table_print_S_parse: + { + \bool_set_false:N \l__siunitx_error_bool + \__siunitx_number_in_parse:V \l__siunitx_table_collect_tl + \bool_if:NF \l__siunitx_error_bool + { + \bool_if:NTF \l__siunitx_table_omit_exponent_bool + { + \bool_set_true:N \l__siunitx_process_fixed_bool + \__siunitx_number_process: + \prop_remove:Nn \l__siunitx_number_in_prop { exponent } + \prop_remove:Nn \l__siunitx_number_in_prop { exponent-integer } + } + { \__siunitx_number_process: } + \__siunitx_number_format: + \__siunitx_number_output_color: + } + } +\cs_new_protected:Npn \__siunitx_table_print_S_measure:NN #1#2 + { + \tl_if_empty:NTF #1 + { \dim_zero:N #2 } + { + \group_begin: + \hbox_set:Nn \l__siunitx_tmp_box + { \__siunitx_print:nV { number } #1 } + \exp_args:NNNo \group_end: + \dim_set:Nn #2 { \dim_use:N \box_wd:N \l__siunitx_tmp_box } + } + } +\cs_new_protected:Npn \__siunitx_table_print_S_pre_aligned: + { + \box_use:N \l__siunitx_table_pre_box + \hbox_to_wd:nn { \l__siunitx_table_fill_pre_dim } { \tex_hfil:D } + } +\cs_new_protected:Npn \__siunitx_table_print_S_pre_not_aligned: + { + \hbox_to_wd:nn { \l__siunitx_table_fill_pre_dim } { \tex_hfil:D } + \box_use:N \l__siunitx_table_pre_box + } +\cs_new_protected:Npn \__siunitx_table_print_S_post_aligned: + { + \hbox_to_wd:nn { \l__siunitx_table_fill_post_dim } { \tex_hfil:D } + \box_use:N \l__siunitx_table_post_box + } +\cs_new_protected:Npn \__siunitx_table_print_S_post_not_aligned: + { + \box_use:N \l__siunitx_table_post_box + \hbox_to_wd:nn { \l__siunitx_table_fill_post_dim } { \tex_hfil:D } + } +\cs_new_protected:Npn \__siunitx_table_print_S_centered: + { + \__siunitx_table_print_S_centered_ends: + \bool_if:NT \l__siunitx_table_math_bool { \c_math_toggle_token } + \__siunitx_table_print_S_parse: + \bool_if:NF \l__siunitx_error_bool + { + \__siunitx_table_print_S_centered_measure: + \bool_if:NT \l__siunitx_table_math_bool { \c_math_toggle_token } + \dim_set:Nn \l__siunitx_table_fill_pre_dim + { + \l__siunitx_table_result_dim + - \l__siunitx_table_integer_dim + - \l__siunitx_table_marker_dim + } + \dim_compare:nNnTF \l__siunitx_table_integer_dim > + \l__siunitx_table_fill_pre_dim + { \__siunitx_table_print_S_centered_integer: } + { \__siunitx_table_print_S_centered_decimal: } + } + } +\cs_new_protected:Npn \__siunitx_table_print_S_centered_ends: + { + \hbox_set:Nn \l__siunitx_table_pre_box + { + { + \l__siunitx_table_collect_pre_tl + \bool_if:NT \l__siunitx_table_math_bool + { + \scan_stop: + \c_math_toggle_token + } + } + } + \dim_compare:nNnT + { \box_wd:N \l__siunitx_table_pre_box } = \c_zero_dim + { + \box_clear:N \l__siunitx_table_pre_box + \l__siunitx_table_collect_pre_tl + \bool_set_false:N \l__siunitx_font_set_bool + } + \hbox_set:Nn \l__siunitx_table_post_box + { + \bool_if:NT \l__siunitx_table_math_bool + { + \c_math_toggle_token + \scan_stop: + } + \l__siunitx_table_collect_post_tl + } + \dim_compare:nNnTF + { \box_wd:N \l__siunitx_table_pre_box } > + { \box_wd:N \l__siunitx_table_post_box } + { + \hbox_set_to_wd:Nnn \l__siunitx_table_post_box + { \box_wd:N \l__siunitx_table_pre_box } + { + \hbox_unpack:N \l__siunitx_table_post_box + \tex_hfil:D + } + } + { + \hbox_set_to_wd:Nnn \l__siunitx_table_pre_box + { \box_wd:N \l__siunitx_table_post_box } + { + \tex_hfil:D + \hbox_unpack:N \l__siunitx_table_pre_box + } + } + } +\cs_new_protected:Npn \__siunitx_table_print_S_centered_measure: + { + \__siunitx_table_print_S_centered_measure_int_part: + \__siunitx_table_print_S_centered_measure_marker: + \__siunitx_table_print_S_centered_measure_result: + } +\cs_new_protected:Npn \__siunitx_table_print_S_centered_measure_int_part: + { + \prop_get:NnNF \l__siunitx_number_out_prop { comparator } \l__siunitx_tmpa_tl + { \tl_clear:N \l__siunitx_tmpa_tl } + \prop_get:NnNT \l__siunitx_number_out_prop { mantissa-sign } + \l__siunitx_tmpb_tl + { \tl_put_right:No \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl } + \prop_get:NnNT \l__siunitx_number_out_prop { mantissa-integer } + \l__siunitx_tmpb_tl + { \tl_put_right:No \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl } + \__siunitx_table_print_S_measure:NN \l__siunitx_tmpa_tl + \l__siunitx_table_integer_dim + } +\cs_new_protected:Npn \__siunitx_table_print_S_centered_measure_marker: + { + \__siunitx_table_print_S_measure:NN \l__siunitx_output_decimal_tl + \l__siunitx_table_marker_dim + } +\cs_new_protected:Npn \__siunitx_table_print_S_centered_measure_result: + { + \prop_get:NnN \l__siunitx_number_out_prop { result } \l__siunitx_tmpa_tl + \hbox_set:Nn \l__siunitx_table_result_box + { \__siunitx_print:nV { number } \l__siunitx_tmpa_tl } + \dim_set:Nn \l__siunitx_table_result_dim + { \box_wd:N \l__siunitx_table_result_box } + } +\cs_new_protected:Npn \__siunitx_table_print_S_centered_integer: + { + \dim_set:Nn \l__siunitx_table_fill_post_dim + { \l__siunitx_table_integer_dim - \l__siunitx_table_fill_pre_dim } + \dim_zero:N \l__siunitx_table_fill_pre_dim + } +\cs_new_protected:Npn \__siunitx_table_print_S_centered_decimal: + { + \dim_sub:Nn \l__siunitx_table_fill_pre_dim + { \l__siunitx_table_integer_dim } + \dim_zero:N \l__siunitx_table_fill_post_dim + } +\cs_new_protected:Npn \__siunitx_table_print_S_reserved: + { + \__siunitx_table_print_S_reserved_init: + \__siunitx_table_print_S_reserved_ends: + \bool_if:NT \l__siunitx_table_auto_round_bool + { \__siunitx_table_print_S_reserved_round_auto: } + \__siunitx_table_print_S_parse: + \bool_if:NF \l__siunitx_error_bool + { + \bool_if:NT \l__siunitx_table_math_bool { \c_math_toggle_token } + \__siunitx_table_print_S_reserved_comparator: + \__siunitx_table_print_S_reserved_mantissa: + \__siunitx_table_print_S_reserved_exponent: + \bool_if:NT \l__siunitx_table_math_bool { \c_math_toggle_token } + } + } +\cs_new_protected:Npn \__siunitx_table_print_S_reserved_init: + { + \dim_zero:N \l__siunitx_table_fill_mid_dim + \dim_zero:N \l__siunitx_table_fill_post_dim + \prop_set_eq:NN \l__siunitx_number_in_prop \l__siunitx_table_model_prop + \__siunitx_number_process_sign: + \__siunitx_number_process_zero_fill: + \__siunitx_number_process_mantissa: + \prop_if_in:NnF \l__siunitx_number_in_prop { symbolic } + { \__siunitx_number_process_uncertainty: } + \__siunitx_number_format: + \prop_get:NnNT \l__siunitx_table_model_prop { mantissa-decimal-raw } + \l__siunitx_tmpa_tl + { + \prop_put:NnV \l__siunitx_number_out_prop { mantissa-decimal-raw } + \l__siunitx_tmpa_tl + } + \prop_set_eq:NN \l__siunitx_table_model_prop \l__siunitx_number_out_prop + } +\cs_new_protected:Npn \__siunitx_table_print_S_reserved_ends: + { + \hbox_set:Nn \l__siunitx_table_pre_box + { + { + \l__siunitx_table_collect_pre_tl + \bool_if:NT \l__siunitx_table_math_bool + { + \scan_stop: + \c_math_toggle_token + } + } + } + \dim_compare:nNnT + { \box_wd:N \l__siunitx_table_pre_box } = \c_zero_dim + { + \box_clear:N \l__siunitx_table_pre_box + \l__siunitx_table_collect_pre_tl + \bool_set_false:N \l__siunitx_font_set_bool + } + \hbox_set:Nn \l__siunitx_tmp_box { { \l__siunitx_table_pre_tl } } + \hbox_set_to_wd:Nnn \l__siunitx_table_pre_box + { \box_wd:N \l__siunitx_tmp_box } + { + \tex_hfil:D + \hbox_unpack:N \l__siunitx_table_pre_box + } + \hbox_set:Nn \l__siunitx_tmp_box { \l__siunitx_table_post_tl } + \hbox_set_to_wd:Nnn \l__siunitx_table_post_box + { \box_wd:N \l__siunitx_tmp_box } + { + { + \bool_if:NT \l__siunitx_table_math_bool + { + \c_math_toggle_token + \scan_stop: + } + \l__siunitx_table_collect_post_tl + } + \tex_hfil:D + } + } +\cs_new_protected:Npn \__siunitx_table_print_S_reserved_round_auto: + { + \prop_get:NnNTF \l__siunitx_table_model_prop { mantissa-decimal-raw } + \l__siunitx_tmpa_tl + { \int_set:Nn \l__siunitx_process_precision_int { \l__siunitx_tmpa_tl } } + { \int_zero:N \l__siunitx_process_precision_int } + \tl_set:Nn \l__siunitx_round_tl { places } + } +\cs_new_protected:Npn \__siunitx_table_print_S_reserved_comparator: + { + \prop_get:NnNTF \l__siunitx_table_model_prop { comparator } + \l__siunitx_tmpa_tl + { + \hbox_set:Nn \l__siunitx_tmp_box + { \__siunitx_print:nV { number } \l__siunitx_tmpa_tl } + \prop_get:NnNTF \l__siunitx_number_out_prop { comparator } + \l__siunitx_tmpa_tl + { + \hbox_set_to_wd:Nnn \l__siunitx_table_result_box + { \box_wd:N \l__siunitx_tmp_box } + { \__siunitx_print:nV { number } \l__siunitx_tmpa_tl } + } + { + \dim_add:Nn \l__siunitx_table_fill_pre_dim + { \box_wd:N \l__siunitx_tmp_box } + \cs_set_eq:NN \__siunitx_table_print_S_reserved_store_fill:n + \__siunitx_table_print_S_reserved_store_fill_pre:n + } + } + { + \cs_set_eq:NN \__siunitx_table_print_S_reserved_store_fill:n + \__siunitx_table_print_S_reserved_store_fill_pre:n + \prop_if_in:NnT \l__siunitx_number_out_prop { comparator } + { + \msg_error:nnx { siunitx } { table-partial-number } + { a~comparator } + } + } + } +\cs_new_protected:Npn \__siunitx_table_print_S_reserved_store_fill_pre:n + { \dim_add:Nn \l__siunitx_table_fill_pre_dim } +\cs_new_protected:Npn \__siunitx_table_print_S_reserved_store_fill_mid:n + { \dim_add:Nn \l__siunitx_table_fill_mid_dim } +\cs_new_protected:Npn \__siunitx_table_print_S_reserved_mantissa: + { + \prop_get:NnNTF \l__siunitx_table_model_prop { mantissa } + \l__siunitx_tmpa_tl + { + \hbox_set:Nn \l__siunitx_tmp_box + { \__siunitx_print:nV { number } \l__siunitx_tmpa_tl } + \prop_get:NnNTF \l__siunitx_number_out_prop { mantissa } + \l__siunitx_tmpa_tl + { + \dim_set:Nn \l__siunitx_table_mantissa_dim + { \box_wd:N \l__siunitx_tmp_box } + \hbox_set:Nn \l__siunitx_table_mantissa_box + { \__siunitx_print:nV { number } \l__siunitx_tmpa_tl } + \__siunitx_table_print_S_reserved_mantissa_parts: + } + { + \__siunitx_table_print_S_reserved_store_fill:n + { \box_wd:N \l__siunitx_tmp_box } + } + } + { + \prop_if_in:NnT \l__siunitx_number_out_prop { mantissa } + { + \msg_error:nnx { siunitx } { table-partial-number } + { a~mantissa } + } + } + } +\cs_new_protected:Npn \__siunitx_table_print_S_reserved_mantissa_parts: + { + \__siunitx_table_print_S_reserved_mantissa_integer: + \hbox_set:Nn \l__siunitx_table_result_box + { + \hbox_unpack:N \l__siunitx_table_result_box + \hbox_to_wd:nn { \l__siunitx_table_fill_mid_dim } { \tex_hfil:D } + \hbox_unpack:N \l__siunitx_table_mantissa_box + } + \dim_set:Nn \l__siunitx_table_fill_mid_dim + { + \l__siunitx_table_mantissa_dim + - \box_wd:N \l__siunitx_table_mantissa_box + - \l__siunitx_table_integer_dim + } + \__siunitx_table_print_S_reserved_mantissa_uncert: + } +\cs_new_protected:Npn \__siunitx_table_print_S_reserved_mantissa_integer: + { + \prop_get:NnNF \l__siunitx_table_model_prop { mantissa-sign } + \l__siunitx_tmpa_tl + { \tl_clear:N \l__siunitx_tmpa_tl } + \prop_get:NnNT \l__siunitx_table_model_prop { mantissa-integer } + \l__siunitx_tmpb_tl + { \tl_put_right:No \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl } + \__siunitx_table_print_S_measure:NN \l__siunitx_tmpa_tl + \l__siunitx_table_integer_dim + \prop_get:NnNF \l__siunitx_number_out_prop { mantissa-sign } + \l__siunitx_tmpa_tl + { \tl_clear:N \l__siunitx_tmpa_tl } + \prop_get:NnNT \l__siunitx_number_out_prop { mantissa-integer } + \l__siunitx_tmpb_tl + { \tl_put_right:No \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl } + \tl_if_empty:NF \l__siunitx_tmpa_tl + { + \__siunitx_table_print_S_measure:NN \l__siunitx_tmpa_tl + \l__siunitx_tmp_dim + \dim_sub:Nn \l__siunitx_table_integer_dim { \l__siunitx_tmp_dim } + } + \__siunitx_table_print_S_reserved_store_fill:n + { \l__siunitx_table_integer_dim } + } +\cs_new_protected:Npn \__siunitx_table_print_S_reserved_mantissa_uncert: + { + \prop_get:NnNT \l__siunitx_table_model_prop { mantissa-uncertainty } + \l__siunitx_tmpa_tl + { + \__siunitx_number_format_join_uncert_pm:N \l__siunitx_tmpa_tl + \hbox_set:Nn \l__siunitx_tmp_box + { \__siunitx_print:nV { number } \l__siunitx_tmpa_tl } + \prop_get:NnNTF \l__siunitx_number_out_prop { mantissa-uncertainty } + \l__siunitx_tmpa_tl + { + \dim_set:Nn \l__siunitx_table_uncert_dim + { \box_wd:N \l__siunitx_tmp_box } + \__siunitx_number_format_join_uncert_pm:N \l__siunitx_tmpa_tl + \hbox_set:Nn \l__siunitx_tmp_box + { \__siunitx_print:nV { number } \l__siunitx_tmpa_tl } + \bool_if:NTF \l__siunitx_table_align_uncert_bool + { \__siunitx_table_print_S_reserved_mantissa_uncert_aligned: } + { \__siunitx_table_print_S_reserved_mantissa_uncert_not_aligned: } + } + { + \cs_set_eq:NN \__siunitx_table_print_S_reserved_store_fill:n + \__siunitx_table_print_S_reserved_store_fill_mid:n + \__siunitx_table_print_S_reserved_store_fill:n + { \box_wd:N \l__siunitx_tmp_box } + } + } + } +\cs_new_protected:Npn + \__siunitx_table_print_S_reserved_mantissa_uncert_aligned: + { + \hbox_set:Nn \l__siunitx_table_result_box + { + \hbox_unpack:N \l__siunitx_table_result_box + \hbox_to_wd:nn { \l__siunitx_table_fill_mid_dim } { \tex_hfil:D } + \hbox_unpack:N \l__siunitx_tmp_box + } + \dim_set:Nn \l__siunitx_table_fill_mid_dim + { \l__siunitx_table_uncert_dim - \box_wd:N \l__siunitx_tmp_box } + } +\cs_new_protected:Npn + \__siunitx_table_print_S_reserved_mantissa_uncert_not_aligned: + { + \hbox_set:Nn \l__siunitx_table_result_box + { + \hbox_unpack:N \l__siunitx_table_result_box + \hbox_unpack:N \l__siunitx_tmp_box + } + \dim_add:Nn \l__siunitx_table_fill_mid_dim + { + \l__siunitx_table_uncert_dim + - \box_wd:N \l__siunitx_tmp_box + } + } +\cs_new_protected:Npn \__siunitx_table_print_S_reserved_exponent: + { + \prop_get:NnNTF \l__siunitx_table_model_prop { exponent-result } + \l__siunitx_tmpa_tl + { + \prop_if_in:NnT \l__siunitx_table_model_prop { mantissa } + { \__siunitx_table_print_S_reserved_exponent_product: } + \hbox_set:Nn \l__siunitx_tmp_box + { \__siunitx_print:nV { number } \l__siunitx_tmpa_tl } + \prop_get:NnNTF \l__siunitx_number_out_prop { exponent-result } + \l__siunitx_tmpa_tl + { + \dim_set:Nn \l__siunitx_table_exponent_dim + { \box_wd:N \l__siunitx_tmp_box } + \tl_if_empty:NT \l__siunitx_output_exponent_tl + { + \prop_if_in:NnTF \l__siunitx_number_out_prop { mantissa } + { \__siunitx_table_print_S_reserved_exponent_product: } + { \__siunitx_table_print_S_reserved_exponent_product_correction: } + } + \hbox_set:Nn \l__siunitx_tmp_box + { \__siunitx_print:nV { number } \l__siunitx_tmpa_tl } + \bool_if:NTF \l__siunitx_table_align_exponent_bool + { \__siunitx_table_print_S_reserved_exponent_aligned: } + { \__siunitx_table_print_S_reserved_exponent_not_aligned: } + } + { + \dim_set:Nn \l__siunitx_table_fill_post_dim + { \l__siunitx_table_fill_mid_dim + \box_wd:N \l__siunitx_tmp_box } + } + } + { + \prop_if_in:NnT \l__siunitx_number_out_prop { exponent-result } + { + \msg_error:nnx { siunitx } { table-partial-number } + { an~exponent } + } + \dim_set_eq:NN \l__siunitx_table_fill_post_dim + \l__siunitx_table_fill_mid_dim + } + } +\cs_new_protected:Npn \__siunitx_table_print_S_reserved_exponent_product: + { + \tl_set_eq:NN \l__siunitx_tmpb_tl \l__siunitx_exponent_product_tl + \bool_if:NT \l__siunitx_tight_bool + { + \tl_set:Nx \l__siunitx_tmpb_tl + { \exp_not:N \mathord \exp_not:o \l__siunitx_tmpb_tl } + } + \tl_set:Nx \l__siunitx_tmpa_tl + { + \exp_not:N \ensuremath { { } \exp_not:o \l__siunitx_tmpb_tl { } } + \exp_not:o \l__siunitx_tmpa_tl + } + } +\cs_new_protected:Npn + \__siunitx_table_print_S_reserved_exponent_product_correction: + { + \group_begin: + \tl_clear:N \l__siunitx_tmpa_tl + \__siunitx_table_print_S_reserved_exponent_product: + \tl_set:Nx \l__siunitx_tmpa_tl + { { } \exp_not:o \l__siunitx_tmpa_tl { } } + \__siunitx_table_print_S_measure:NN \l__siunitx_tmpa_tl \l__siunitx_tmp_dim + \exp_args:NNNo \group_end: + \dim_set:Nn \l__siunitx_tmp_dim { \dim_use:N \l__siunitx_tmp_dim } + \__siunitx_table_print_S_reserved_store_fill:n { \l__siunitx_tmp_dim } + \dim_sub:Nn \l__siunitx_table_exponent_dim { \l__siunitx_tmp_dim } + } +\cs_new_protected:Npn \__siunitx_table_print_S_reserved_exponent_aligned: + { + \hbox_set:Nn \l__siunitx_table_result_box + { + \hbox_unpack:N \l__siunitx_table_result_box + \hbox_to_wd:nn { \l__siunitx_table_fill_mid_dim } { \tex_hfil:D } + \hbox_unpack:N \l__siunitx_tmp_box + } + \dim_set:Nn \l__siunitx_table_fill_post_dim + { + \l__siunitx_table_exponent_dim + - \box_wd:N \l__siunitx_tmp_box + } + } +\cs_new_protected:Npn + \__siunitx_table_print_S_reserved_exponent_not_aligned: + { + \hbox_set:Nn \l__siunitx_table_result_box + { + \hbox_unpack:N \l__siunitx_table_result_box + \hbox_unpack:N \l__siunitx_tmp_box + } + \dim_set:Nn \l__siunitx_table_fill_post_dim + { + \l__siunitx_table_fill_mid_dim + + \l__siunitx_table_exponent_dim + - \box_wd:N \l__siunitx_tmp_box + } + } +\cs_new_protected:Npn \__siunitx_table_print_S_direct: + { + \peek_catcode_ignore_spaces:NTF \c_group_begin_token + { \__siunitx_table_print_S_direct_text:n } + { \__siunitx_table_print_S_direct_main: } + } +\cs_new_protected:Npn \__siunitx_table_print_S_direct_text:n #1 + { + \__siunitx_table_column_begin:n { \l__siunitx_table_text_align_skip } + #1 + \__siunitx_table_column_end:n { \l__siunitx_table_text_align_skip } + } +\cs_new_protected:Npn \__siunitx_table_print_S_direct_centered: + { + \cs_set_eq:NN \__siunitx_table_print: + \__siunitx_table_print_S_direct_centered_end: + \hbox_set:Nn \l__siunitx_tmp_box + { \ensuremath { \l__siunitx_output_decimal_tl } } + \hbox_set_to_wd:Nnn \l__siunitx_table_post_box + { \box_wd:N \l__siunitx_tmp_box } + { \tex_hfil:D } + \hbox_set:Nw \l__siunitx_table_pre_box + \c_math_toggle_token + \tl_map_function:NN \l__siunitx_input_decimal_tl + \__siunitx_table_print_S_direct_centered_aux:N + } +\cs_new_protected:Npn \__siunitx_table_print_S_direct_centered_aux:N #1 + { + \char_set_active_eq:NN #1 \__siunitx_table_print_S_direct_centered_begin: + \char_set_mathcode:nn { `#1 } { "8000 } + } +\cs_new_protected:Npn \__siunitx_table_print_S_direct_centered_begin: + { + \c_math_toggle_token + \hbox_set_end: + \hbox_set:Nw \l__siunitx_table_post_box + \c_math_toggle_token + \l__siunitx_output_decimal_tl + } +\cs_new_protected:Npn \__siunitx_table_print_S_direct_centered_end: + { + \c_math_toggle_token + \hbox_set_end: + \dim_compare:nNnTF + { \box_wd:N \l__siunitx_table_pre_box } > + { \box_wd:N \l__siunitx_table_post_box } + { + \hbox_set_to_wd:Nnn \l__siunitx_table_post_box + { \box_wd:N \l__siunitx_table_pre_box } + { + \hbox_unpack:N \l__siunitx_table_post_box + \tex_hfil:D + } + } + { + \hbox_set_to_wd:Nnn \l__siunitx_table_pre_box + { \box_wd:N \l__siunitx_table_post_box } + { + \tex_hfil:D + \hbox_unpack:N \l__siunitx_table_pre_box + } + } + \box_use:N \l__siunitx_table_pre_box + \box_use:N \l__siunitx_table_post_box + } +\cs_new_protected:Npn \__siunitx_table_print_S_direct_reserved: + { + \cs_set_eq:NN \__siunitx_table_print: + \__siunitx_table_print_S_direct_reserved_end: + \prop_get:NnNF \l__siunitx_table_model_prop { mantissa-integer } + \l__siunitx_tmpa_tl + { \tl_clear:N \l__siunitx_tmpa_tl } + \hbox_set:Nn \l__siunitx_tmp_box + { + \ensuremath + { + \prop_get:NnNT \l__siunitx_table_model_prop { mantissa-sign } + \l__siunitx_tmpb_tl + { \l__siunitx_tmpb_tl } + \l__siunitx_tmpa_tl + } + } + \dim_set:Nn \l__siunitx_table_integer_dim + { \box_wd:N \l__siunitx_tmp_box } + \prop_get:NnNF \l__siunitx_table_model_prop { mantissa-decimal } + \l__siunitx_tmpa_tl + { \tl_clear:N \l__siunitx_tmpa_tl } + \hbox_set:Nn \l__siunitx_tmp_box + { + \ensuremath + { + \l__siunitx_output_decimal_tl + \l__siunitx_tmpa_tl + } + } + \hbox_set_to_wd:Nnn \l__siunitx_table_post_box + { \box_wd:N \l__siunitx_tmp_box } + { \tex_hfil:D } + \tex_setbox:D \l__siunitx_table_pre_box \tex_hbox:D to \l__siunitx_table_integer_dim + \c_group_begin_token + \c_math_toggle_token + \tl_map_function:NN \l__siunitx_input_decimal_tl + \__siunitx_table_print_S_direct_reserved_aux:N + \tex_hfill:D + } +\cs_new_protected:Npn \__siunitx_table_print_S_direct_reserved_aux:N #1 + { + \char_set_active_eq:NN #1 \__siunitx_table_print_S_direct_reserved_begin: + \char_set_mathcode:nn { `#1 } { "8000 } + } +\cs_new_protected:Npn \__siunitx_table_print_S_direct_reserved_begin: + { + \c_math_toggle_token + \c_group_end_token + \tex_setbox:D \l__siunitx_table_post_box \tex_hbox:D to \box_wd:N \l__siunitx_tmp_box + \c_group_begin_token + \c_math_toggle_token + \l__siunitx_output_decimal_tl + } +\cs_new_protected:Npn \__siunitx_table_print_S_direct_reserved_end: + { + \c_math_toggle_token + \tex_hfil:D + \c_group_end_token + \__siunitx_table_align_left:n { \l__siunitx_table_number_align_skip } + \box_use:N \l__siunitx_table_pre_box + \box_use:N \l__siunitx_table_post_box + \__siunitx_table_align_right:n { \l__siunitx_table_number_align_skip } + } +\keys_set:nn { siunitx } + { + table-align-comparator = true, + table-align-exponent = true, + table-align-text-pre = true, + table-align-text-post = true, + table-align-uncertainty = true, + table-omit-exponent = false, + table-parse-only = false, + table-number-alignment = center-decimal-marker, + table-text-alignment = center, + table-figures-decimal = 2, + table-figures-integer = 3 + } +\keys_define:nn { siunitx } + { redefine-symbols .bool_set:N = \l__siunitx_redefine_symbols_bool } +\keys_set:nn { siunitx } { redefine-symbols = true } +\AtBeginDocument + { + \bool_if:NT \l__siunitx_redefine_symbols_bool + { + \@ifpackageloaded { fourier } + { + \__siunitx_option_unchanged:Nnn \l__siunitx_ohm_text_tl + { \textohm } + { \text { \ensuremath { \l__siunitx_ohm_math_tl } } } + } + { } + \@ifpackageloaded { mathptmx } + { + \__siunitx_option_unchanged:Nnn \l__siunitx_ohm_text_tl + { \textohm } + { \text { \ensuremath { \l__siunitx_ohm_math_tl } } } + } + { } + \str_if_eq:VnT \encodingdefault { OT1 } + { + \__siunitx_option_unchanged:Nnn \l__siunitx_angstrom_math_tl + { \text { \AA } } + { \text { \capitalring { A } } } + \__siunitx_option_unchanged:Nnn \l__siunitx_angstrom_text_tl + { \AA } + { \capitalring { A } } + } + \@ifpackageloaded { unicode-math } + { + \exp_args:NNnx + \__siunitx_option_unchanged:Nnn \l__siunitx_ohm_math_tl + { \text { \ensuremath { \Omega } } } + { \char_generate:nn { "03A9 } { 12 } } + } + { } + \@ifpackageloaded { upgreek } + { + \__siunitx_option_unchanged:Nnn \l__siunitx_ohm_math_tl + { \text { \ensuremath { \Omega } } } + { \text { \ensuremath { \Upomega } } } + } + { + \cs_if_exist:NT \upOmega + { + \__siunitx_option_unchanged:Nnn \l__siunitx_ohm_math_tl + { \text { \ensuremath { \Omega } } } + { \text { \ensuremath { \upOmega } } } + } + } + } + } +\keys_define:nn { siunitx } { + math-angstrom .tl_set:N = \l__siunitx_angstrom_math_tl, + math-arcminute .tl_set:N = \l__siunitx_arcminute_math_tl, + math-arcsecond .tl_set:N = \l__siunitx_arcsecond_math_tl, + math-celsius .tl_set:N = \l__siunitx_celsius_math_tl, + math-degree .tl_set:N = \l__siunitx_degree_math_tl, + math-micro .tl_set:N = \l__siunitx_micro_math_tl, + math-ohm .tl_set:N = \l__siunitx_ohm_math_tl +} +\keys_set:nn { siunitx } { + math-angstrom = \text { \AA }, + math-arcminute = { } ^ { \prime }, + math-arcsecond = { } ^ { \prime \prime }, + math-celsius = \text { \textdegree } \__siunitx_unit_mathrm:n { C } , + math-degree = \text { \textdegree }, + math-micro = \text { \textmu }, + math-ohm = \text { \ensuremath { \Omega } }, +} +\keys_define:nn { siunitx } { + text-angstrom .tl_set:N = \l__siunitx_angstrom_text_tl, + text-arcminute .tl_set:N = \l__siunitx_arcminute_text_tl, + text-arcsecond .tl_set:N = \l__siunitx_arcsecond_text_tl, + text-celsius .tl_set:N = \l__siunitx_celsius_text_tl, + text-degree .tl_set:N = \l__siunitx_degree_text_tl, + text-micro .tl_set:N = \l__siunitx_micro_text_tl, + text-ohm .tl_set:N = \l__siunitx_ohm_text_tl, +} +\keys_set:nn { siunitx } { + text-angstrom = \AA, + text-arcminute = \ensuremath { { } ^ { \prime } }, + text-arcsecond = \ensuremath { { } ^ { \prime \prime } }, + text-celsius = \text { \textdegree } C, + text-degree = \text { \textdegree }, + text-micro = \textmu , + text-ohm = \textohm +} +\cs_new_protected:Npn \__siunitx_symbol_new:n #1 + { + \cs_set_protected:cpn { SIUnitSymbol #1 } + { + \use:c + { + l__siunitx_ + \str_foldcase:n {#1} + _ + \mode_if_math:TF { math } { text } + _tl + } + } + } +\__siunitx_symbol_new:n { Angstrom } +\__siunitx_symbol_new:n { Arcminute } +\__siunitx_symbol_new:n { Arcsecond } +\__siunitx_symbol_new:n { Celsius } +\__siunitx_symbol_new:n { Degree } +\__siunitx_symbol_new:n { Micro } +\__siunitx_symbol_new:n { Ohm } +\clist_new:N \l__siunitx_pgf_link_clist +\cs_new_protected:Npn \__siunitx_pgf_link: { + \clist_clear:N \l__siunitx_pgf_link_clist + \str_if_eq:VnT \l__siunitx_round_tl { figure } + { + \clist_put_right:Nn \l__siunitx_pgf_link_clist { fixed } + \clist_put_right:Nn \l__siunitx_pgf_link_clist + { fixed~zerofill = true } + } + \clist_put_right:Nx \l__siunitx_pgf_link_clist + { precision = \int_use:N \l__siunitx_process_precision_int } + \clist_put_right:Nx \l__siunitx_pgf_link_clist + { + set~decimal~separator = + { { \exp_not:V \l__siunitx_output_decimal_tl } } + } + \clist_put_right:Nx \l__siunitx_pgf_link_clist + { set~thousands~separator = { \exp_not:V \l__siunitx_group_sep_tl } } + \clist_put_right:Nx \l__siunitx_pgf_link_clist + { + min~exponent~for~1000~sep = \int_eval:n { \l__siunitx_group_min_int - 1 } + } + \bool_lazy_or:nnF + { \l__siunitx_group_decimal_bool } { \l__siunitx_group_integer_bool } + { + \clist_put_right:Nn \l__siunitx_pgf_link_clist + { min~exponent~for~1000~sep = 999 } + } + \bool_if:NTF \l__siunitx_process_integer_zero_bool + { + \clist_put_right:Nn \l__siunitx_pgf_link_clist + { skip~0. = false } + } + { + \clist_put_right:Nn \l__siunitx_pgf_link_clist + { skip~0. = true } + } + \str_if_eq:VnTF \l__siunitx_process_sign_tl { + } + { + \clist_put_right:Nn \l__siunitx_pgf_link_clist + { showpos = true } + } + { + \clist_put_right:Nn \l__siunitx_pgf_link_clist + { showpos = false } + } + \use:x + { + \exp_not:N \pgfqkeys + { /pgf/number~format } + { \exp_not:V \l__siunitx_pgf_link_clist } + } +} +\msg_new:nnnn { siunitx } { bad-arc-sign } + { Incorrect~use~of~sign~in~degree-minute-second~angle. } + { Only~the~highest~value~part~of~an~angle~can~have~a~sign. } +\msg_new:nnnn { siunitx } { color-not-loaded } + { Package~"color"~not~loaded. } + { The~command~\token_to_str:N \color \ is~not~available. } +\msg_new:nnnn { siunitx } { duplicate-complex-root-token } + { Duplicate~complex~root~token~'#1'~in~input. } + { Only~one~complex~root~token~can~appear~in~a~single~number. } +\msg_new:nnnn { siunitx } { duplicate-decimal-token } + { Duplicate~decimal~marker~token~'#1'~in~input. } + { Only~one~decimal~marker~token~can~appear~in~a~single~number. } +\msg_new:nnnn { siunitx } { duplicate-exponent-token } + { Duplicate~exponent~marker~token~'#1'~in~input. } + { Only~one~exponent~marker~token~can~appear~in~a~single~number. } +\msg_new:nnnn { siunitx } { duplicate-quotient-token } + { Duplicate~quotient~token. } + { Only~one~quotient~token~can~appear~in~a~single~number. } +\msg_new:nnnn { siunitx } { duplicate-sticky-per } + { Duplicate~\token_to_str:N \per. } + { + When~the~'sticky-per'~option~is~active,~only~one + \token_to_str:N \per may~appear~in~a~unit. + } +\msg_new:nnnn { siunitx } { empty-arc } + { Empty~degree-minute-second~angle. } + { The~angle~given~does~not~contain~any~numbers. } +\msg_new:nnnn { siunitx } { empty-uncertainty } + { Empty~uncertainty~given~in~'#1'. } + { The~number~given~contains~an~empty~uncertainty. } +\msg_new:nnnn { siunitx } { ending-product-token } + { Misplaced~product~token. } + { A~number~cannot~end~with~a~product~token. } +\msg_new:nnnn { siunitx } { ending-quotient-token } + { Misplaced~quotient~token. } + { A~number~cannot~end~with~a~quotient~token. } +\msg_new:nnnn { siunitx } { invalid-arc-format } + { Invalid~degree-minute-second angle~'#1'. } + { + Angles~given~in~degree-minute-second~format~should~contain~two~';' + symbols~to~divide~up~the~parts~of~the~input. + } +\msg_new:nnnn { siunitx } { invalid-number } + { Invalid~numerical~input~'#1'. } + { + The~input~given~as~a~number~does~not~make~logical~sense.~ + This~happens,~for~example,~if~a~number~only~contains~a~sign. + } +\msg_new:nnnn { siunitx } { invalid-token-in-exponent } + { Invalid~exponent~in~numerical~input~'#1'. } + { + The~exponent~part~of~a~number~cannot~contain~an~uncertainty~or~ + complex~part: \\ + the~input~given~appears~to~contain~one~of~these~in~the~exponent. + } +\msg_new:nnnn { siunitx } { invalid-token-in-number } + { Invalid~token~'#1'~in~numerical~input. } + { + Numbers~can~only~contain~tokens~defined~using~the~ + 'input-...'~options:\\ + the~token~'#1'~is~not~set~up~as~a~valid~part~of~a~number. + } +\msg_new:nnnn { siunitx } { invalid-token-in-uncertainty } + { Invalid~uncertainty~in~numerical~input~'#1'. } + { + The~uncertainty~part~of~a~number~may~only~contain~digits~or~ + symbols. + } +\msg_new:nnnn { siunitx } { literal-unit } + { Literal~units~disabled. } + { + You~gave~the~literal~input~'#1'~ + but~literal~unit~output~is~disabled. + } +\msg_new:nnnn { siunitx } { misplaced-sign-token } + { Misplaced~sign~token~'#1'. } + { Sign~tokens~can~only~come~at~the~beginning~of~a~number. } +\msg_new:nnnn { siunitx } { misplaced-complex-root-token } + { Misplaced~complex~token~in~numerical~input~'#1'. } + { + The~root~token~must~come~either~before~or~after~the~real~digits~ + of~the~complex~part. + } +\msg_new:nnnn { siunitx } { misplaced-uncertainty-token } + { Misplaced~uncertainty~token~'#1'. } + { + The~uncertainty~in~a~number~must~be~given~between~a~set~of~ + delimiters~as~defined~by~the\\ + \ \ 'input-open-uncertainty'~and~'input-close-uncertainty'~ + options. + } +\msg_new:nnnn { siunitx } { multi-part-range } + { Numerical~range~with~multiple~parts. } + { + The~input~'#1'~is~a~number~which~has~more~than~one~part: \\ + ranges~can~only~contain~one~number~in~each~part. + } +\msg_new:nnn { siunitx } { non-convertible-exponent } + { Exponent~'#1'~cannot~be~converted~into~a~symbolic~prefix. } +\msg_new:nnn { siunitx } { option-not-available } + { Option~'#1'~not~available~in~strict~mode. } +\msg_new:nnn { siunitx } { option-preamble-only } + { Option~'#1'~only~available~in~the~preamble. } +\msg_new:nnnn { siunitx } { prefix-base-mismatch } + { Prefix~bases~do~not~match. } + { + You~have~asked~for~prefixes~to~be~converted~into~a~power,~ + but~the~bases~do~not~match. + } +\msg_new:nnn { siunitx } { prefix-only } + { Prefix~with~no~unit. } +\msg_new:nnnn { siunitx } { qualifier-before-unit } + { Qualifier~before~unit. } + { Unit~qualifiers~have~to~follow~after~units,~not~before~them. } +\msg_new:nnnn { siunitx } { restricted-number } + { Token~'#1'~forbidden~in~restricted~numerical~input. } + { + The~current~input~must~be~a~real~number~and~cannot~contain: \\ + \ -~an~exponent; \\ + \ -~an~uncertainty; \\ + \ -~a~complex~part. + } +\msg_new:nnnn { siunitx } { starting-product-token } + { Misplaced~product~token. } + { A~number~cannot~begin~with~a~product~token. } +\msg_new:nnnn { siunitx } { starting-quotient-token } + { Misplaced~quotient~token. } + { A~number~cannot~begin~with~a~quotient~token. } +\msg_new:nnnn { siunitx } { table-partial-number } + { No~space~reserved~for~#1~\msg_line_context:. } + { + The~number~in~the~current~table~cell~contains~#1~part, + but~you~did~not~reserve~any~space~to~print~it: \\ + it~will~be~missing~in~the~output. + } +\msg_new:nnnn { siunitx } { unknown-option } + { Unknown~option~'#1'. } + { + The~option~file~'#1'~is~not~known~by~siunitx: + perhaps~it~is~spelled~incorrectly. + } +\msg_new:nnnn { siunitx } { version-1-option } + { Version~1~option~'#1'~detected. } + { + Use: \\ + \ \ \token_to_str:N \usepackage [ version-1-compatibility ] + \iow_char:N \{ siunitx \token_to_str:N \iow_char:N \} \\ + in~the~preamble~to~load~the~appropriate~code. + } +\NewDocumentCommand \DeclareBinaryPrefix { m m m } { + \__siunitx_declare_prefix:Nnnn #1 {#2} { 2 } {#3} +} +\NewDocumentCommand \DeclareSIPostPower { m m } { + \__siunitx_declare_power_after:Nn #1 {#2} +} +\NewDocumentCommand \DeclareSIPrefix { m m m } { + \__siunitx_declare_prefix:Nnnn #1 {#2} { 10 } {#3} +} +\NewDocumentCommand \DeclareSIPrePower { m m } { + \__siunitx_declare_power_before:Nn #1 {#2} +} +\NewDocumentCommand \DeclareSIQualifier { m m } { + \__siunitx_declare_qualifier:Nn #1 {#2} +} +\NewDocumentCommand \DeclareSIUnit { O { } m m } { + \__siunitx_declare_unit:Nnn #2 {#3} {#1} +} +\NewDocumentCommand \DeclareSIUnitWithOptions { m m m } { + \__siunitx_declare_unit:Nnn #1 {#2} {#3} +} +\@onlypreamble \DeclareBinaryPrefix +\@onlypreamble \DeclareSIPostPower +\@onlypreamble \DeclareSIPrefix +\@onlypreamble \DeclareSIPrePower +\@onlypreamble \DeclareSIQualifier +\@onlypreamble \DeclareSIUnit +\@onlypreamble \DeclareSIUnitWithOptions +\cs_new_protected:Npn \SendSettingsToPgf { \__siunitx_pgf_link: } +\NewDocumentCommand \ang { o > { \SplitArgument { 2 } { ; } } m } { + \group_begin: + \IfNoValueF {#1} + { \keys_set:nn { siunitx } {#1} } + \__siunitx_angle_output:nnn #2 + \group_end: +} +\NewDocumentCommand \num { o m } { + \leavevmode + \group_begin: + \bool_set_false:N \l__siunitx_font_set_bool + \IfNoValueF {#1} + { \keys_set:nn { siunitx } {#1} } + \__siunitx_number_output:n {#2} + \group_end: +} +\NewDocumentCommand \numlist { o > { \SplitList { ; } } m } { + \leavevmode + \group_begin: + \bool_set_false:N \l__siunitx_font_set_bool + \IfNoValueF {#1} + { \keys_set:nn { siunitx } {#1} } + \__siunitx_list_numbers:n {#2} + \group_end: +} +\NewDocumentCommand \numrange { o m m } { + \leavevmode + \group_begin: + \bool_set_false:N \l__siunitx_font_set_bool + \IfNoValueF {#1} + { \keys_set:nn { siunitx } {#1} } + \__siunitx_range_numbers:nn {#2} {#3} + \group_end: +} +\NewDocumentCommand \SIlist { o > { \SplitList { ; } } m m } { + \leavevmode + \group_begin: + \bool_set_false:N \l__siunitx_font_set_bool + \IfNoValueTF {#1} + { \__siunitx_list_units:nnn {#2} {#3} { } } + { + \keys_set:nn { siunitx } {#1} + \__siunitx_list_units:nnn {#2} {#3} {#1} + } + \group_end: +} +\NewDocumentCommand \SIrange { o m m m } { + \leavevmode + \group_begin: + \bool_set_false:N \l__siunitx_font_set_bool + \IfNoValueTF {#1} + { \__siunitx_range_unit:nnnn {#4} { } {#2} {#3} } + { + \keys_set:nn { siunitx } {#1} + \__siunitx_range_unit:nnnn {#4} {#1} {#2} {#3} + } + \group_end: +} +\NewDocumentCommand \SI { o m o m } { + \leavevmode + \group_begin: + \bool_set_false:N \l__siunitx_font_set_bool + \IfNoValueTF {#1} + { \__siunitx_combined:nnnn { } {#2} {#3} {#4} } + { + \keys_set:nn { siunitx } {#1} + \__siunitx_combined:nnnn {#1} {#2} {#3} {#4} + } + \group_end: +} +\NewDocumentCommand \sisetup { m } { + \keys_set:nn { siunitx } {#1} +} +\NewDocumentCommand \tablenum { o m } { + \leavevmode + \group_begin: + \bool_set_false:N \l__siunitx_font_set_bool + \IfNoValueF {#1} + { \keys_set:nn { siunitx } {#1} } + \bool_if:NTF \l__siunitx_number_parse_bool + { + \tl_set:Nn \l__siunitx_table_collect_tl {#2} + \bool_set_false:N \l__siunitx_table_collect_pre_bool + \__siunitx_table_print_S: + } + { \__siunitx_table_print_S_direct: #2 \__siunitx_table_print: } + \group_end: +} +\NewDocumentCommand \si { o m } { + \leavevmode + \group_begin: + \bool_set_false:N \l__siunitx_font_set_bool + \IfNoValueTF {#1} + { \__siunitx_unit_output:nn {#2} { } } + { + \keys_set:nn { siunitx } {#1} + \__siunitx_unit_output:nn {#2} {#1} + } + \group_end: +} +\cs_new_protected:Npn \__siunitx_contents_bookmarks: + { + \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq + { \__siunitx_unit_print_literal_aux:N ##1 } + \cs_if_exist:NT \FB@fg + { \cs_set_eq:NN \fg \FB@fg } + \msg_redirect_name:nnn { xparse } { redefine-command } { none } + \cs_set_eq:NN \num \numInBookmark + \cs_set_eq:NN \numrange \numrangeInBookmark + \cs_set_eq:NN \si \siInBookmark + \cs_set_eq:NN \SI \SIInBookmark + \cs_set_eq:NN \SIrange \SIrangeInBookmark + \cs_set_eq:NN \si \siInBookmark + \cs_set_eq:NN \highlight \use_ii:nn + \cs_set_eq:NN \__siunitx_textsuperscript:n \use:n + \cs_set:Npn \SIUnitSymbolAngstrom { \AA } + \cs_set:Npn \SIUnitSymbolArcminute { ' } + \cs_set:Npn \SIUnitSymbolArcsecond { '' } + \cs_set:Npn \SIUnitSymbolCelsius { \textcelsius } + \cs_set:Npn \SIUnitSymbolDegree { \textdegree } + \cs_set:Npn \SIUnitSymbolMicro { \textmu } + \cs_set:Npn \SIUnitSymbolOhm { \textohm } + } +\DeclareExpandableDocumentCommand \numInBookmark { o m } {#2} +\DeclareExpandableDocumentCommand \numrangeInBookmark { o m m } + { #2 \l__siunitx_range_phrase_tl #3 } +\DeclareExpandableDocumentCommand \SIInBookmark { o m o m } + { \IfNoValueF {#3} {#3} #2 ~ #4 } +\DeclareExpandableDocumentCommand \SIlistInBookmark + { o m m } { \__siunitx_bookmark_SIlist_map:nn {#1} {#2} } +\DeclareExpandableDocumentCommand \SIrangeInBookmark + { o m m m } { #2 ~ #4 \l__siunitx_range_phrase_tl #3 ~ #4 } +\DeclareExpandableDocumentCommand \siInBookmark { o m } {#2} +\cs_new:Npn \__siunitx_bookmark_SIlist_map:nn #1#2 { + \__siunitx_bookmark_SIlist_map_aux:nw {#2} #1 ; \q_recursion_tail ; + \q_recursion_tail ; \q_recursion_stop +} +\cs_new:Npn \__siunitx_bookmark_SIlist_map_aux:nw #1#2 ; #3 ; #4 { + #2 ~ #1 + \quark_if_recursion_tail_stop:n {#3} + \quark_if_recursion_tail_stop_do:nn {#4} + { + \l__siunitx_list_separator_final_tl + #3 ~ #1 + } + \l__siunitx_list_separator_tl + \__siunitx_bookmark_SIlist_map_aux:nw {#1} #3 ; #4 +} +\AtBeginDocument { + \@ifpackageloaded { hyperref } + { \pdfstringdefDisableCommands { \__siunitx_contents_bookmarks: } } + { } +} +\DeclareSIUnit \kilogram { \kilo \gram } +\DeclareSIUnit \metre { m } +\DeclareSIUnit \meter { \metre } +\DeclareSIUnit \mole { mol } +\DeclareSIUnit \second { s } +\DeclareSIUnit \ampere { A } +\DeclareSIUnit \kelvin { K } +\DeclareSIUnit \candela { cd } +\DeclareSIUnit \gram { g } +\DeclareSIPrefix \yocto { y } { -24 } +\DeclareSIPrefix \zepto { z } { -21 } +\DeclareSIPrefix \atto { a } { -18 } +\DeclareSIPrefix \femto { f } { -15 } +\DeclareSIPrefix \pico { p } { -12 } +\DeclareSIPrefix \nano { n } { -9 } +\DeclareSIPrefix \micro { \SIUnitSymbolMicro } { -6 } +\DeclareSIPrefix \milli { m } { -3 } +\DeclareSIPrefix \centi { c } { -2 } +\DeclareSIPrefix \deci { d } { -1 } +\DeclareSIPrefix \deca { da } { 1 } +\DeclareSIPrefix \deka { da } { 1 } +\DeclareSIPrefix \hecto { h } { 2 } +\DeclareSIPrefix \kilo { k } { 3 } +\DeclareSIPrefix \mega { M } { 6 } +\DeclareSIPrefix \giga { G } { 9 } +\DeclareSIPrefix \tera { T } { 12 } +\DeclareSIPrefix \peta { P } { 15 } +\DeclareSIPrefix \exa { E } { 18 } +\DeclareSIPrefix \zetta { Z } { 21 } +\DeclareSIPrefix \yotta { Y } { 24 } +\DeclareSIUnit \becquerel { Bq } +\DeclareSIUnit \celsius { \SIUnitSymbolCelsius } +\DeclareSIUnit \degreeCelsius { \SIUnitSymbolCelsius } +\DeclareSIUnit \coulomb { C } +\DeclareSIUnit \farad { F } +\DeclareSIUnit \gray { Gy } +\DeclareSIUnit \hertz { Hz } +\DeclareSIUnit \henry { H } +\DeclareSIUnit \joule { J } +\DeclareSIUnit \katal { kat } +\DeclareSIUnit \lumen { lm } +\DeclareSIUnit \lux { lx } +\DeclareSIUnit \newton { N } +\DeclareSIUnit \ohm { \SIUnitSymbolOhm } +\DeclareSIUnit \pascal { Pa } +\DeclareSIUnit \radian { rad } +\DeclareSIUnit \siemens { S } +\DeclareSIUnit \sievert { Sv } +\DeclareSIUnit \steradian { sr } +\DeclareSIUnit \tesla { T } +\DeclareSIUnit \volt { V } +\DeclareSIUnit \watt { W } +\DeclareSIUnit \weber { Wb } +\DeclareSIUnit [ number-unit-product = ] \arcmin { \arcminute } +\DeclareSIUnit [ number-unit-product = ] + \arcminute { \SIUnitSymbolArcminute } +\DeclareSIUnit [ number-unit-product = ] + \arcsecond { \SIUnitSymbolArcsecond } +\DeclareSIUnit \day { d } +\DeclareSIUnit[ number-unit-product = ] \degree { \SIUnitSymbolDegree } +\DeclareSIUnit \hectare { ha } +\DeclareSIUnit \hour { h } +\DeclareSIUnit \litre { l } +\DeclareSIUnit \liter { L } +\DeclareSIUnit \minute { min } +\DeclareSIUnit \percent { \char 37 } +\DeclareSIUnit \tonne { t } +\DeclareSIUnit \astronomicalunit { au } +\DeclareSIUnit \atomicmassunit { u } +\DeclareSIUnit \electronvolt { eV } +\DeclareSIUnit \dalton { Da } +\group_begin: +\cs_set_eq:NN \endgroup \group_end: +\char_set_catcode_math_subscript:N \_ +\use:n + { + \endgroup + \DeclareSIUnit \clight { \text { \ensuremath { c _ { 0 } } } } + \DeclareSIUnit \electronmass + { \text { \ensuremath { m _ { \textup { e } } } } } + } +\DeclareSIUnit \planckbar { \text { \ensuremath { \hbar } } } +\DeclareSIUnit \elementarycharge { \text { \ensuremath { e } } } +\group_begin: +\cs_set_eq:NN \endgroup \group_end: +\char_set_catcode_math_subscript:N \_ +\use:n + { + \endgroup + \DeclareSIUnit \bohr { \text { \ensuremath { a _ { 0 } } } } + \DeclareSIUnit \hartree + { \text { \ensuremath { E _ { \textup { h } } } } } + } +\DeclareSIUnit \angstrom { \SIUnitSymbolAngstrom } +\DeclareSIUnit \bar { bar } +\DeclareSIUnit \barn { b } +\DeclareSIUnit \bel { B } +\DeclareSIUnit \decibel { \deci \bel } +\DeclareSIUnit \knot { kn } +\DeclareSIUnit \mmHg { mmHg } +\DeclareSIUnit \nauticalmile { M } +\DeclareSIUnit \neper { Np } +\DeclareSIPrePower \square { 2 } +\DeclareSIPostPower \squared { 2 } +\DeclareSIPrePower \cubic { 3 } +\DeclareSIPostPower \cubed { 3 } +\keys_define:nn { siunitx } { + strict .code:n = + { + \keys_set:nn { siunitx } + { + bracket-numbers = true, + detect-family = false, + detect-mode = false, + detect-shape = false, + detect-weight = false, + multi-part-units = brackets, + parse-numbers = true, + parse-units = true, + product-units = repeat + } + \__siunitx_strict_option:n + { + bracket-numbers , + detect-family , + detect-italic , + detect-mode , + detect-shape , + detect-weight , + multi-part-units , + parse-numbers , + parse-units , + product-units + } + \keys_define:nn { siunitx } + { + per-mode / repeated-symbol .code:n = + { + \msg_warning:nnx { siunitx } { option-not-available } + { per-mode~=~repeated-symbol } + } + } + } +} +\__siunitx_option_deactivate:n { strict } +\cs_new_protected:Npn \__siunitx_strict_option:n #1 { + \clist_map_function:nN {#1} \__siunitx_strict_option_aux:n +} +\cs_new_protected:Npn \__siunitx_strict_option_aux:n #1 { + \keys_define:nn { siunitx } + { #1 .code:n = + { \msg_warning:nnx { siunitx } { option-not-available } {#1} } + } +} +\keys_define:nn { siunitx } { + locale .choice:, + locale / + DE .meta:n = + { + exponent-product = \ensuremath { \cdot } , + inter-unit-product = \, , + output-decimal-marker = { , } + }, + locale / + FR .meta:n = + { + exponent-product = \ensuremath { \times } , + inter-unit-product = \, , + output-decimal-marker = { , } + }, + locale / + UK .meta:n = + { + exponent-product = \ensuremath { \times } , + inter-unit-product = \, , + output-decimal-marker = . + }, + locale / + US .meta:n = { locale = UK }, + locale / + USA .meta:n = { locale = UK }, + locale / + ZA .meta:n = + { + exponent-product = \ensuremath { \times } , + inter-unit-product = \ensuremath { \cdot } , + output-decimal-marker = { , } + }, +} +\file_if_exist:nT { translator.sty } + { + \RequirePackage { translator } + \usedictionary { translator-basic-dictionary } + \providetranslation [ to = English ] + { to~(numerical~range) } { to } + \providetranslation [ to = French ] + { to~(numerical~range) } { \`a } + \providetranslation [ to = German ] + { to~(numerical~range) } { bis } + \providetranslation [ to = Spanish ] + { to~(numerical~range) } { a } + \sisetup + { + list-final-separator = { ~ \translate { and } ~ }, + list-pair-separator = { ~ \translate { and } ~ }, + range-phrase = { ~ \translate { to~(numerical~range) } ~ } + } + } +\tl_const:Nn \c__siunitx_configuration_ext_tl { cfg } +\keys_define:nn { siunitx } + { + abbreviations .choice:, + abbreviations / + true .code:n = { \__siunitx_load_abbreviations: }, + abbreviations / + false .code:n = + { \cs_set_eq:NN \__siunitx_load_abbreviations: \prg_do_nothing: } , + abbreviations .default:n = true , + binary-units .choice:, + binary-units / + true .code:n = { \AtBeginDocument { \__siunitx_load_binary: } }, + binary-units / + false .code:n = + { \cs_set_eq:NN \__siunitx_load_binary: \prg_do_nothing: } , + binary-units .default:n = true + } +\cs_new_protected:Npn \__siunitx_load_abbreviations: + { + \@onefilewithoptions { siunitx-abbreviations } [ ] [ ] + \c__siunitx_configuration_ext_tl + } +\cs_new_protected:Npn \__siunitx_load_binary: + { + \@onefilewithoptions { siunitx-binary } [ ] [ ] + \c__siunitx_configuration_ext_tl + } +\AtBeginDocument { \__siunitx_load_abbreviations: } +\__siunitx_option_deactivate:n { abbreviations , binary } +\keys_define:nn { siunitx } + { + version-1-compatibility .choice: , + version-1-compatibility / + true .code:n = + { + \@onefilewithoptions { siunitx-version-1 } [ ] [ ] + \c__siunitx_configuration_ext_tl + }, + version-1-compatibility / + false .code:n = { } , + version-1-compatibility .default:n = true + } +\__siunitx_option_deactivate:n { version-1-compatibility } +\keys_define:nn { siunitx } { + load-configurations .code:n = + { + \clist_if_in:nnT {#1} { version-1 } + { + \@onefilewithoptions { siunitx-version-1 } [ ] [ ] + \c__siunitx_configuration_ext_tl + } + } +} +\__siunitx_option_deactivate:n { load-configurations } +\file_if_exist:nT { siunitx . \c__siunitx_configuration_ext_tl } + { + \@onefilewithoptions { siunitx } [ ] [ ] + \c__siunitx_configuration_ext_tl + } +\ProcessKeysOptions { siunitx } +\AtBeginDocument { + \bool_if:NTF \l__siunitx_create_free_bool + { \__siunitx_unit_create_functions: } + { \__siunitx_unit_create_empty_functions: } +} +%% Copyright (C) 2008-2021 by +%% Joseph Wright <joseph.wright@morningstar2.co.uk> +%% +%% It may be distributed and/or modified under the conditions of +%% the LaTeX Project Public License (LPPL), either version 1.3c of +%% this license or (at your option) any later version. The latest +%% version of this license is in the file: +%% http://www.latex-project.org/lppl.txt +%% +%% This work is "maintained" (as per LPPL maintenance status) by +%% Joseph Wright. +%% +%% This work consists of the file siunitx.dtx +%% and the derived files siunitx.pdf, +%% siunitx.sty and +%% siunitx.ins. +%% +%% End of file `siunitx-v2.sty'. diff --git a/macros/latex/contrib/siunitx/siunitx-version-1.cfg b/macros/latex/contrib/siunitx/siunitx-version-1.cfg new file mode 100644 index 0000000000..4eb5b97e05 --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx-version-1.cfg @@ -0,0 +1,750 @@ +%% +%% This is file `siunitx-version-1.cfg', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% siunitx-v2.dtx (with options: `config,version-1') +%% --------------------------------------------------------------- +%% The siunitx package --- A comprehensive (SI) units package +%% Maintained by Joseph Wright +%% E-mail: joseph.wright@morningstar2.co.uk +%% Released under the LaTeX Project Public License v1.3c or later +%% See http://www.latex-project.org/lppl.txt +%% --------------------------------------------------------------- +%% +\ProvidesExplFile {siunitx-version-1.cfg} {2021-04-17} {2.8e} + {siunitx: Version 1 settings} +\keys_define:nn { siunitx } { + addsign .choice: , + addsign / + all .meta:n = { explicit-sign = + }, + addsign / + exp .meta:n = { explicit-sign = + }, + addsign / + false .meta:n = { explicit-sign = }, + addsign / + mant .meta:n = { explicit-sign = + }, + addsign / + none .meta:n = { explicit-sign = }, + addsign / + true .meta:n = { explicit-sign = + }, + addsign .default:n = { true }, + allowlitunits .meta:n = { free-standing-units = #1 }, + allowlitunits .default:n = { true }, + allowoptarg .meta:n = { unit-optional-argument = #1 }, + allowoptargs .default:n = { true }, + allowzeroexp .meta:n = { retain-zero-exponent = #1 }, + allowzeroexp .default:n = { true }, + alsoload .code:n = , + angformat .code:n = , + anglesep .choice: , + anglesep / + cdot .meta:n = + { arc-separator = \ensuremath { { } \cdot { } } }, + anglesep / + comma .meta:n = { arc-separator = \ensuremath { { {,} } } }, + anglesep / + fullstop .meta:n = { arc-separator = \ensuremath { { { . } } } }, + anglesep / + med .meta:n = { arc-separator = \ensuremath { \: } }, + anglesep / + medium .meta:n = { arc-separator = \ensuremath { \: } }, + anglesep / + none .meta:n = { arc-separator = }, + anglesep / + period .meta:n = { arc-separator = \ensuremath { { { . } } } }, + anglesep / + space .meta:n = { arc-separator = \text { ~ } }, + anglesep / + stop .meta:n = { arc-separator = \ensuremath { { { . } } } }, + anglesep / + thick .meta:n = { arc-separator = \ensuremath { \; } }, + anglesep / + thin .meta:n = { arc-separator = \ensuremath { \, } }, + anglesep / + tightcdot .meta:n = + { arc-separator = \ensuremath { \bgroup \cdot \egroup } }, + anglesep / + tighttimes .meta:n = + { arc-separator = \ensuremath { \bgroup \times \egroup } }, + anglesep / + times .meta:n = { arc-separator = \ensuremath { \times } }, + anglesep / + unknown .meta:n = { arc-separator = \ensuremath {#1} }, + astroang .meta:n = + { angle-symbol-over-decimal = #1 }, + astroang .default:n = { true }, + closeerr .meta:n = { close-bracket = \ensuremath {#1} }, + closefrac .meta:n = { close-bracket = \ensuremath {#1} }, + closerange .meta:n = { close-bracket = \ensuremath {#1} }, + colour .code:n = { color = #1 }, + colorall .code:n = , + colourall .code:n = , + colorneg .code:n = , + colourneg .code:n = , + colorunits .meta:n = , + colourunits .meta:n = , + colorvalues .meta:n = , + colourvalues .meta:n = , + decimalsymbol .choice: , + decimalsymbol / + cdot .meta:n = + { output-decimal-marker = \ensuremath { { } \cdot { } } }, + decimalsymbol / + comma .meta:n = { output-decimal-marker = { \ensuremath { { , } } } }, + decimalsymbol / + fullstop .meta:n = { output-decimal-marker = { \ensuremath { { . } } } }, + decimalsymbol / + period .meta:n = { output-decimal-marker = { \ensuremath { { . } } } }, + decimalsymbol / + stop .meta:n = { output-decimal-marker = { \ensuremath { { . } } } }, + decimalsymbol / + tightcdot .code:n = + { output-decimal-marker = \ensuremath { \bgroup \cdot \egroup } }, + decimalsymbol / + unknown .meta:n = { output-decimal-marker = \ensuremath {#1} }, + debug .code:n = , + detectdisplay .meta:n = { detect-display-math = #1 }, + detectdisplay .default:n = { true }, + digitsep .choice: , + digitsep / + cdot .meta:n = + { group-separator = \ensuremath { { } \cdot { } } }, + digitsep / + comma .meta:n = { group-separator = \ensuremath { { , } } }, + digitsep / + fullstop .meta:n = { group-separator = \ensuremath { . } }, + digitsep / + med .meta:n = { group-separator = \ensuremath { \: } }, + digitsep / + medium .meta:n = { group-separator = \ensuremath { \: } }, + digitsep / + none .meta:n = { group-separator = }, + digitsep / + period .meta:n = { group-separator = \ensuremath { . } }, + digitsep / + space .meta:n = { group-separator = \text { ~ } }, + digitsep / + stop .meta:n = { group-separator = \ensuremath { . } }, + digitsep / + thick .meta:n = { group-separator = \ensuremath { \; } }, + digitsep / + thin .meta:n = { group-separator = \ensuremath { \, } }, + digitsep / + tightcdot .meta:n = + { group-separator = \ensuremath { \bgroup \cdot \egroup } }, + digitsep / + tighttimes .meta:n = + { group-separator = \ensuremath { \bgroup \times \egroup } }, + digitsep / + times .meta:n = { group-separator = \ensuremath { \times } }, + digitsep / + unknown .meta:n = { group-separator = \ensuremath {#1} }, + dp .meta:n = + { + round-mode = places, + round-precision = #1, + }, + emulate .code:n = , + errspace .choice: , + errspace / + med .meta:n = { uncertainty-separator = \ensuremath { \: } }, + errspace / + medium .meta:n = { uncertainty-separator = \ensuremath { \: } }, + errspace / + none .meta:n = { uncertainty-separator = }, + errspace / + space .meta:n = { uncertainty-separator = \text { ~ } }, + errspace / + thick .meta:n = { uncertainty-separator = \ensuremath { \; } }, + errspace / + thin .meta:n = { uncertainty-separator = \ensuremath { \, } }, + errspace / + unknown .meta:n = { uncertainty-separator = \ensuremath {#1} }, + eVcorra .code:n = , + eVcorrb .code:n = , + expbase .choice: , + expbase / + ten .meta:n = { exponent-base = 10 }, + expbase / + two .meta:n = { exponent-base = 2 }, + expbase / + unknown .meta:n = { exponent-base = #1 }, + expproduct .choice: , + expproduct / + cdot .meta:n = + { exponent-product = \ensuremath { { } \cdot { } } }, + expproduct / + tightcdot .meta:n = + { exponent-product = \ensuremath { \bgroup \cdot \egroup } }, + expproduct / + tighttimes .meta:n = + { exponent-product = \ensuremath { \bgroup \times \egroup } }, + expproduct / + times .meta:n = { exponent-product = \ensuremath { \times } }, + expproduct / + unknown .meta:n = { exponent-product = \ensuremath {#1} }, + fixdp .choice:, + fixdp / + false .meta:n = { round-mode = none }, + fixdp / + true .meta:n = { round-mode = places }, + fixdp .default:n = { true }, + fixsf .choice: , + fixsf / + false .meta:n = { round-mode = none }, + fixsf / + true .meta:n = { round-mode = figures }, + fixsf .default:n = { true }, + fraction .choice: , + fraction / + frac .meta:n = { fraction-function = \frac }, + fraction / + nice .meta:n = { fraction-function = \frac }, + fraction / + sfrac .meta:n = { fraction-function = \sfrac }, + fraction / + ugly .meta:n = + { + fraction-function = \frac , + per-mode = symbol-or-fraction + }, + inlinebold .meta:n = { detect-inline-weight = #1 }, + log .code:n = , + load .code:n = , + loctolang .code:n = , + mathOmega .meta:n = { math-ohm = #1 }, + mathcelsius .meta:n = { math-celsius = #1 }, + mathdegree .meta:n = { math-degree = #1 }, + mathminute .meta:n = { math-arcminute = #1 }, + mathmu .meta:n = { math-micro = #1 }, + mathringA .meta:n = { math-angstrom = #1 }, + mathrm .code:n = + { \use:x { \keys_set:nn { siunitx } { math-rm = \exp_not:c {#1} } } }, + mathsOmega .meta:n = { math-ohm = #1 }, + mathscelsius .meta:n = { math-celsius = #1 }, + mathsdegree .meta:n = { math-degree = #1 }, + mathsecond .meta:n = { math-arcsecond = #1 }, + mathsf .code:n = + { \use:x { \keys_set:nn { siunitx } { math-sf = \exp_not:c {#1} } } }, + mathsminute .meta:n = { math-arcminute = #1 }, + mathsmu .meta:n = { math-micro = #1 }, + mathsringA .meta:n = { math-angstrom = #1 }, + mathsrm .code:n = + { \use:x { \keys_set:nn { siunitx } { math-rm= \exp_not:c {#1} } } }, + mathssecond .meta:n = { math-arcsecond = #1 }, + mathssf .code:n = + { \use:x { \keys_set:nn { siunitx } { math-sf = \exp_not:c {#1} } } }, + mathstt .code:n = + { \use:x { \keys_set:nn { siunitx } { math-tt = \exp_not:c {#1} } } }, + mathtt .code:n = + { \use:x { \keys_set:nn { siunitx } { math-tt = \exp_not:c {#1} } } }, + negcolor .meta:n = { negative-color = #1 }, + negcolour .meta:n = { negative-color = #1 }, + noload .code:n = , + numaddn .meta:n = { input-symbols = #1 }, + numcloseerr .meta:n = { input-close-uncertainty = #1 }, + numdecimal .meta:n = { input-decimal-markers = #1 }, + numdigits .meta:n = { input-digits = #1 }, + numdiv .meta:n = { input-quotient = #1 }, + numexp .meta:n = { input-exponent-markers = #1 }, + numgobble .meta:n = { input-ignore = #1 }, + numopenerr .meta:n = { input-open-uncertainty = #1 }, + numprod .meta:n = { input-product = #1 }, + numsign .meta:n = { input-signs = #1 }, + obeyall .meta:n = { detect-all = #1 }, + obeyall .default:n = { true }, + obeybold .meta:n = { detect-weight = #1 }, + obeybold .default:n = { true }, + obeyfamily .meta:n = { detect-family = #1 }, + obeyfamily .default:n = { true }, + obeyitalic .meta:n = { detect-shape = #1 }, + obeyitalic .default:n = { true }, + obeymode .meta:n = { detect-mode = #1 }, + obeymode .default:n = { true }, + openerr .meta:n = { open-bracket = \ensuremath {#1} }, + openfrac .meta:n = { open-bracket = \ensuremath {#1} }, + openrange .meta:n = { open-bracket = \ensuremath {#1} }, + padangle .choice: , + padangle / + all .meta:n = + { + add-arc-degree-zero = true, + add-arc-minute-zero = true, + add-arc-second-zero = true + }, + padangle / + both .meta:n = + { + add-arc-degree-zero = true, + add-arc-minute-zero = true, + add-arc-second-zero = true + }, + padangle / + false .meta:n = + { + add-arc-degree-zero = false, + add-arc-minute-zero = false, + add-arc-second-zero = false + }, + padangle / + large .meta:n = + { + add-arc-degree-zero = true, + add-arc-minute-zero = true, + add-arc-second-zero = false + }, + padangle / + none .meta:n = + { + add-arc-degree-zero = false, + add-arc-minute-zero = false, + add-arc-second-zero = false + }, + padangle / + small .meta:n = + { + add-arc-degree-zero = false, + add-arc-minute-zero = true, + add-arc-second-zero = true + }, + true .meta:n = + { + add-arc-degree-zero = true, + add-arc-minute-zero = true, + add-arc-second-zero = true + }, + padnumber .choice: , + padnumber / + all .meta:n = + { + add-decimal-zero = true, + add-integer-zero = true + }, + padnumber / + both .meta:n = + { + add-decimal-zero = true, + add-integer-zero = true + }, + padnumber / + false .meta:n = + { + add-decimal-zero = false, + add-integer-zero = false + }, + padnumber / + leading .meta:n = + { + add-decimal-zero = true, + add-integer-zero = false + }, + padnumber / + none .meta:n = + { + add-decimal-zero = false, + add-integer-zero = false + }, + padnumber / + trailing .meta:n = + { + add-decimal-zero = false, + add-integer-zero = true + }, + padnumber / + true .meta:n = + { + add-decimal-zero = true, + add-integer-zero = true + }, + per .choice: , + per / + frac .meta:n = { per-mode = fraction }, + per / + fraction .meta:n = { per-mode = fraction }, + per / + reciprocal .meta:n = { per-mode = reciprocal }, + per / + slash .meta:n = { per-mode = symbol }, + prefixbase .code:n = , + prefixproduct .code:n = , + prefixsymbolic .meta:n = { prefixes-as-symbols = #1 }, + prefixsymbolic .default:n = { true }, + prespace .meta:n = { space-before-unit = #1 }, + prespace .default:n = { true }, + redefsymbols .meta:n = { redefine-symbols = #1 }, + redefsymbols .default:n = { true }, + repeatunits .choice: , + repeatunits / + false .meta:n = + { + multi-part-units = single, + product-units = single, + range-units = single + }, + repeatunits / + power .meta:n = + { + multi-part-units = repeat, + product-units = power, + range-units = repeat + }, + repeatunits / + true .meta:n = + { + multi-part-units = repeat, + product-units = repeat, + range-units = repeat + }, + repeatunits .default:n = { true }, + retainplus .meta:n = { retain-explicit-plus = #1 }, + retainplus .default:n = { true }, + seperr .meta:n = { separate-uncertainty = #1 }, + seperr .default:n = { true }, + sepfour .meta:n = { group-four-digits = true }, + sepfour .default:n = { true }, + sf .meta:n = + { + round-mode = figures, + round-precision = #1, + }, + sign .meta:n = { explicit-sign = #1 }, + slash .choice: , + slash / + slash .meta:n = { per-symbol = \ensuremath { / } }, + slash / + unknown .meta:n = { per-symbol = \ensuremath {#1} }, + stickyper .meta:n = { sticky-per = #1 }, + stickyper .default:n = { true }, + strictarc .code:n = , + tabalign .code:n = + { + \str_if_eq:nnTF {#1} { centre } + { \keys_set:nn { siunitx } { table-alignment = center } } + { \keys_set:nn { siunitx } { table-alignment = #1 } } + }, + tabalignexp .code:n = { table-align-exponent = #1 }, + tabautofit .meta:n = { table-auto-round = #1 }, + tabautofit .default:n = { true }, + tabexpalign .code:n = { table-align-exponent = #1 }, + tabformat .meta:n = { table-format = #1 }, + tabnumalign .code:n = + { + \str_if_eq:nnTF {#1} { centre } + { \keys_set:nn { siunitx } { table-number-alignment = center } } + { + \str_if_eq:nnTF {#1} { centredecimal } + { + \keys_set:nn { siunitx } + { table-number-alignment = center-decimal-marker } + } + { + \str_if_eq:nnTF {#1} { centerdecimal } + { + \keys_set:nn { siunitx } + { table-number-alignment = center-decimal-marker } + } + { + \keys_set:nn { siunitx } + { table-number-alignment = #1 } + } + } + } + }, + tabparseonly .meta:n = { table-parse-only = #1 }, + tabparseonly .default:n = { true }, + tabtextalign .code:n = + { + \str_if_eq:nnTF {#1} { centre } + { \keys_set:nn { siunitx } { table-text-alignment = center } } + { \keys_set:nn { siunitx } { table-text-alignment = #1 } } + }, + tabunitalign .code:n = + { + \str_if_eq:nnTF {#1} { centre } + { \keys_set:nn { siunitx } { table-unit-alignment = center } } + { \keys_set:nn { siunitx } { table-unit-alignment = #1 } } + }, + textOmega .meta:n = { text-ohm = #1 }, + textcelsius .meta:n = { text-celsius = #1 }, + textdegree .meta:n = { text-degree = #1 }, + textminute .meta:n = { text-arcminute = #1 }, + textmode .choice: , + textmode / + true .meta:n = { mode = text }, + textmode / + false .meta:n = { mode = math }, + textmode .default:n = { true }, + textmu .meta:n = { text-micro = #1 }, + textringA .meta:n = { text-angstrom = #1 }, + textrm .code:n = + { \use:x { \keys_set:nn { siunitx } { text-rm = \exp_not:c {#1} } } }, + textsecond .meta:n = { text-arcsecond = #1 }, + textsf .code:n = + { \use:x { \keys_set:nn { siunitx } { text-sf = \exp_not:c {#1} } } }, + texttt .code:n = + { \use:x { \keys_set:nn { siunitx } { text-tt = \exp_not:c {#1} } } }, + tightpm .meta:n = { tight-spacing = #1 }, + tightpm .default:n = { true }, + tophrase .meta:n = { range-phrase = #1 }, + trapambigerr .choice: , + trapambigerr + / false .meta:n = { multi-part-units = single }, + trapambigerr + / true .meta:n = { multi-part-units = brackets }, + trapambigerr .default:n = { true }, + trapambigfrac .meta:n = { bracket-numbers = #1 }, + trapambigfrac .default:n = { true }, + trapambigrange .choice: , + trapambigrange + / false .meta:n = { range-units = single }, + trapambigrange + / true .meta:n = { range-units = brackets }, + trapambigrange .default:n = { true }, + unitcolor .meta:n = { unit-color = #1 }, + unitcolour .meta:n = { unit-color = #1 }, + unitmathrm .code:n = + { \use:x { \keys_set:nn { siunitx } { unit-math-rm = \exp_not:c {#1} } } }, + unitmathsf .code:n = + { \use:x { \keys_set:nn { siunitx } { unit-math-sf = \exp_not:c {#1} } } }, + unitmathsrm .code:n = + { \use:x { \keys_set:nn { siunitx } { unit-math-rm = \exp_not:c {#1} } } }, + unitmathssf .code:n = + { \use:x { \keys_set:nn { siunitx } { unit-math-sf = \exp_not:c {#1} } } }, + unitmathstt .code:n = + { \use:x { \keys_set:nn { siunitx } { unit-math-tt = \exp_not:c {#1} } } }, + unitmathtt .code:n = + { \use:x { \keys_set:nn { siunitx } { unit-math-tt = \exp_not:c {#1} } } }, + unitmode .meta:n = { unit-mode = #1 }, + unitsep .choice: , + unitsep / + cdot .meta:n = + { inter-unit-product = \ensuremath { { } \cdot { } } }, + unitsep / + comma .meta:n = { inter-unit-product = { {,} } }, + unitsep / + fullstop .meta:n = { inter-unit-product = { { . } } }, + unitsep / + med .meta:n = { inter-unit-product = \ensuremath { \: } }, + unitsep / + medium .meta:n = { inter-unit-product = \ensuremath { \: } }, + unitsep / + none .meta:n = { inter-unit-product = }, + unitsep / + period .meta:n = { inter-unit-product = { { . } } }, + unitsep / + space .meta:n = { inter-unit-product = \text { ~ } }, + unitsep / + stop .meta:n = { inter-unit-product = { { . } } }, + unitsep / + thick .meta:n = { inter-unit-product = \ensuremath { \; } }, + unitsep / + thin .meta:n = { inter-unit-product = \, }, + unitsep / + tightcdot .meta:n = + { inter-unit-product = \ensuremath { \bgroup \cdot \egroup } }, + unitsep / + tighttimes .meta:n = + { inter-unit-product = \ensuremath { \bgroup \times \egroup } }, + unitsep / + times .meta:n = { inter-unit-product = \ensuremath { \times } }, + unitsep / + unknown .meta:n = { inter-unit-product = \ensuremath {#1} }, + unitspace .choice: , + unitspace / + med .meta:n = { inter-unit-product = \ensuremath { \: } }, + unitspace / + medium .meta:n = { inter-unit-product = \ensuremath { \: } }, + unitspace / + none .meta:n = { inter-unit-product = }, + unitspace / + space .meta:n = { inter-unit-product = \text { ~ } }, + unitspace / + thick .meta:n = { inter-unit-product = \ensuremath { \; } }, + unitspace / + thin .meta:n = { inter-unit-product = \, }, + unitspace / + unknown .meta:n = { inter-unit-product = \ensuremath {#1} }, + valuecolor .meta:n = { number-color = #1 }, + valuecolour .meta:n = { number-color = #1 }, + valuemathrm .code:n = + { \use:x { \keys_set:nn { siunitx } { number-math-rm = \exp_not:c {#1} } } }, + valuemathsf .code:n = + { \use:x { \keys_set:nn { siunitx } { number-math-sf = \exp_not:c {#1} } } }, + valuemathsrm .code:n = + { \use:x { \keys_set:nn { siunitx } { number-math-rm = \exp_not:c {#1} } } }, + valuemathssf .code:n = + { \use:x { \keys_set:nn { siunitx } { number-math-sf = \exp_not:c {#1} } } }, + valuemathstt .code:n = + { \use:x { \keys_set:nn { siunitx } { number-math-tt = \exp_not:c {#1} } } }, + valuemathtt .code:n = + { \use:x { \keys_set:nn { siunitx } { number-math-tt = \exp_not:c {#1} } } }, + valuemode .meta:n = { number-mode = #1 }, + valuesep .choice: , + valuesep / + cdot .meta:n = + { number-unit-product = \ensuremath { { } \cdot { } } }, + valuesep / + comma .meta:n = { number-unit-product = { {,} } }, + valuesep / + fullstop .meta:n = { number-unit-product = { { . } } }, + valuesep / + med .meta:n = { number-unit-product = \ensuremath { \: } }, + valuesep / + medium .meta:n = { number-unit-product = \ensuremath { \: } }, + valuesep / + none .meta:n = { number-unit-product = }, + valuesep / + period .meta:n = { number-unit-product = { { . } } }, + valuesep / + space .meta:n = { number-unit-product = \text { ~ } }, + valuesep / + stop .meta:n = { number-unit-product = { { . } } }, + valuesep / + thick .meta:n = { number-unit-product = \ensuremath { \; } }, + valuesep / + thin .meta:n = { number-unit-product = \, }, + valuesep / + tightcdot .meta:n = + { number-unit-product = \ensuremath { \bgroup \cdot \egroup } }, + valuesep / + tighttimes .meta:n = + { number-unit-product = \ensuremath { \bgroup \times \egroup } }, + valuesep / + times .meta:n = { number-unit-product = \ensuremath { \times } }, + valuesep / + unknown .meta:n = { number-unit-product = \ensuremath {#1} }, + xspace .meta:n = { use-xspace = #1 }, + xspace .default:n = { true }, +} +\keys_define:nn { siunitx } { + unknown .code:n = + { + \msg_error:nnx { siunitx } { unknown-option } + { \exp_not:V \l_keys_key_tl } + } +} +\keys_set:nn { siunitx } {free-standing-units = true} +\cs_new_eq:NN \newunit \DeclareSIUnit +\cs_new_eq:NN \renewunit \DeclareSIUnit +\cs_new_eq:NN \provideunit \DeclareSIUnit +\NewDocumentCommand \newpower { o m m } { + \IfNoValueTF {#1} + { \DeclareSIPrePower #2 {#3} } + { \DeclareSIPostPower #2 {#3} } +} +\NewDocumentCommand \renewpower { o m m } { + \IfNoValueTF {#1} + { \DeclareSIPrePower #2 {#3} } + { \DeclareSIPostPower #2 {#3} } +} +\NewDocumentCommand \providepower { o m m } { + \IfNoValueTF {#1} + { \DeclareSIPrePower #2 {#3} } + { \DeclareSIPostPower #2 {#3} } +} +\NewDocumentCommand \newprefix { o m m m } { + \IfNoValueTF {#1} + { \DeclareSIPrefix #2 {#3} {#4} } + { \DeclareBinaryPrefix #2 {#3} {#4} } +} +\NewDocumentCommand \renewprefix { o m m m } { + \IfNoValueTF {#1} + { \DeclareSIPrefix #2 {#3} {#4} } + { \DeclareBinaryPrefix #2 {#3} {#4} } +} +\NewDocumentCommand \provideprefix { o m m m } { + \IfNoValueTF {#1} + { \DeclareSIPrefix #2 {#3} {#4} } + { \DeclareBinaryPrefix #2 {#3} {#4} } +} +\NewDocumentCommand \newqualifier { m m } { + \__siunitx_declare_qualifier:Nn #1 {#2} +} +\cs_new_eq:NN \renewqualifier \newqualifier +\cs_new_eq:NN \providequalifier \newqualifier +\DeclareSIPrePower \Square { 2 } +\DeclareSIPrePower \ssquare { 2 } +\DeclareSIUnit \BAR { \bar } +\DeclareSIUnit \bbar { \bar } +\DeclareSIUnit \Day { \day } +\DeclareSIUnit \dday { \day } +\DeclareSIUnit \Gray { \gray } +\DeclareSIUnit \ggray { \gray } +\DeclareSIUnit \atomicmass { \atomicmassunit } +\DeclareSIUnit \arcmin { \arcminute } +\DeclareSIUnit \arcsec { \arcsecond } +\DeclareSIUnit \are { a } +\DeclareSIUnit \curie { Ci } +\DeclareSIUnit \gal { Gal } +\DeclareSIUnit \millibar { \milli \bar } +\DeclareSIUnit \rad { rad } +\DeclareSIUnit \rem { rem } +\DeclareSIUnit \roentgen { R } +\DeclareSIUnit \micA { \micro \ampere } +\DeclareSIUnit \micmol { \micro \mole } +\DeclareSIUnit \micl { \micro \litre } +\DeclareSIUnit \micL { \micro \liter } +\DeclareSIUnit \nanog { \nano \gram } +\DeclareSIUnit \micg { \micro \gram } +\DeclareSIUnit \picm { \pico \metre } +\DeclareSIUnit \micm { \micro \metre } +\DeclareSIUnit \Sec { \second } +\DeclareSIUnit \mics { \micro \second } +\DeclareSIUnit \cmc { \centi \metre \cubed } +\DeclareSIUnit \dmc { \deci \metre \cubed } +\DeclareSIUnit \cms { \centi \metre \squared } +\DeclareSIUnit \centimetrecubed { \centi \metre \cubed } +\DeclareSIUnit \centimetresquared { \centi \metre \squared } +\DeclareSIUnit \cubiccentimetre { \centi \metre \cubed } +\DeclareSIUnit \cubicdecimetre { \deci \metre \cubed } +\DeclareSIUnit \squarecentimetre { \centi \metre \squared } +\DeclareSIUnit \squaremetre { \metre \squared } +\DeclareSIUnit \squarekilometre { \kilo \metre \squared } +\DeclareSIUnit \parsec { pc } +\DeclareSIUnit \lightyear { ly } +\DeclareSIUnit \gmol { g \text { - } mol } +\DeclareSIUnit \kgmol { kg \text { - } mol } +\DeclareSIUnit \lbmol { lb \text { - } mol } +\DeclareSIUnit \molar { \mole \per \cubic \deci \metre } +\DeclareSIUnit \Molar { \textsc { m } } +\DeclareSIUnit \torr { Torr } +\DeclareSIUnit \gon { gon } +\DeclareSIUnit \clight { \text { \ensuremath { c } } } +\DeclareSIUnit \micron { \micro \metre } +\DeclareSIUnit \mrad { \milli \rad } +\DeclareSIUnit \gauss { G } +\DeclareSIUnit \eVperc { \eV \per \clight } +\DeclareSIUnit \nanobarn { \nano \barn } +\DeclareSIUnit \picobarn { \pico \barn } +\DeclareSIUnit \femtobarn { \femto \barn } +\DeclareSIUnit \attobarn { \atto \barn } +\DeclareSIUnit \zeptobarn { \zepto \barn } +\DeclareSIUnit \yoctobarn { \yocto \barn } +\DeclareSIUnit \nb { \nano \barn } +\DeclareSIUnit \pb { \pico \barn } +\DeclareSIUnit \fb { \femto \barn } +\DeclareSIUnit \ab { \atto \barn } +\DeclareSIUnit \zb { \zepto \barn } +\DeclareSIUnit \yb { \yocto \barn } +\NewDocumentCommand \requiresiconfigs { m } + { \keys_set:nn { siunitx } { version-1-compatibility } } +%% Copyright (C) 2008-2021 by +%% Joseph Wright <joseph.wright@morningstar2.co.uk> +%% +%% It may be distributed and/or modified under the conditions of +%% the LaTeX Project Public License (LPPL), either version 1.3c of +%% this license or (at your option) any later version. The latest +%% version of this license is in the file: +%% http://www.latex-project.org/lppl.txt +%% +%% This work is "maintained" (as per LPPL maintenance status) by +%% Joseph Wright. +%% +%% This work consists of the file siunitx.dtx +%% and the derived files siunitx.pdf, +%% siunitx.sty and +%% siunitx.ins. +%% +%% End of file `siunitx-version-1.cfg'. diff --git a/macros/latex/contrib/siunitx/siunitx.dtx b/macros/latex/contrib/siunitx/siunitx.dtx index 0125c29569..887d0c0311 100644 --- a/macros/latex/contrib/siunitx/siunitx.dtx +++ b/macros/latex/contrib/siunitx/siunitx.dtx @@ -1,17892 +1,720 @@ % \iffalse meta-comment -%<*internal> -\iffalse -%</internal> -%<*readme> -siunitx - A comprehensive (SI) units package -============================================== - -Physical quantities have both numbers and units, and each -physical quantity should be expressed as the product of a number -and a unit. Typesetting physical quantities requires care to -ensure that the combined mathematical meaning of the number-unit -combination is clear. In particular, the SI units system lays -down a consistent set of units with rules on how these are to be -used. However, different countries and publishers have differing -conventions on the exact appearance of numbers (and units). The -`siunitx` package provides a set of tools for authors to typeset -quantities in a consistent way. The package has an extended set -of configuration options which make it possible to follow -varying typographic conventions with the same input syntax. The -package includes automated processing of numbers and units, and -the ability to control tabular alignment of numbers. - -Installation ------------- - -The package is supplied in `dtx` format and as a pre-extracted -zip file, `siunitx.tds.zip`. The later is most convenient for -most users: simply unzip this in your local texmf directory . If -you want to unpack the `.dtx` yourself, running `tex -siunitx.dtx` will extract the package whereas `latex -siunitx.dtx` will extract it and also typeset the documentation. - -The package requires LaTeX3 support as provided in the -`l3kernel` and `l3packages` bundles. Both of these are available -on [CTAN](http://www.ctan.org/) as ready-to-install zip files. -Suitable versions are available in MiKTeX 2.9 and TeX Live 2015 -(updating the relevant packages online may be necessary). -LaTeX3, and so `siunitx`, requires the e-TeX extensions: these -are available on all modern TeX systems. - -Typesetting the documentation requires a number of packages in -addition to those needed to use the package. This is mainly -because of the number of demonstration items included in the -text. To compile the documentation without error, you will -need the packages: - - `amsmath` - - `booktabs` - - `cancel` - - `caption` - - `cleveref` - - `colortbl` - - `csquotes` - - `datatool` - - `helvet` - - `mathpazo` - - `multirow` - - `listings` - - `pgfplots` - - `xcolor` -%</readme> -%<*internal> -\fi -\def\nameofplainTeX{plain} -\ifx\fmtname\nameofplainTeX\else - \expandafter\begingroup -\fi -%</internal> -%<*install> -\input l3docstrip.tex -\keepsilent -\askforoverwritefalse -\preamble ---------------------------------------------------------------- -The siunitx package --- A comprehensive (SI) units package -Maintained by Joseph Wright -E-mail: joseph.wright@morningstar2.co.uk -Released under the LaTeX Project Public License v1.3c or later -See http://www.latex-project.org/lppl.txt ---------------------------------------------------------------- - -\endpreamble -\postamble -Copyright (C) 2008-2021 by - Joseph Wright <joseph.wright@morningstar2.co.uk> - -It may be distributed and/or modified under the conditions of -the LaTeX Project Public License (LPPL), either version 1.3c of -this license or (at your option) any later version. The latest -version of this license is in the file: - http://www.latex-project.org/lppl.txt - -This work is "maintained" (as per LPPL maintenance status) by - Joseph Wright. - -This work consists of the file siunitx.dtx - and the derived files siunitx.pdf, - siunitx.sty and - siunitx.ins. -\endpostamble -\usedir{tex/latex/siunitx} -\generate{ - \file{\jobname.sty}{\from{\jobname.dtx}{package}} - \file{siunitx-abbreviations.cfg} - {\from{\jobname.dtx}{config,abbreviations}} - \file{siunitx-binary.cfg}{\from{\jobname.dtx}{config,binary}} - \file{siunitx-version-1.cfg}{\from{\jobname.dtx}{config,version-1}} -} -%</install> -%<install>\endbatchfile -%<*internal> -\usedir{source/latex/siunitx} -\generate{ - \file{\jobname.ins}{\from{\jobname.dtx}{install}} -} -\nopreamble\nopostamble -\usedir{doc/latex/siunitx} -\generate{ - \file{README.md}{\from{\jobname.dtx}{readme}} -} -\ifx\fmtname\nameofplainTeX - \expandafter\endbatchfile -\else - \expandafter\endgroup -\fi -%</internal> -%<*driver|package> -\RequirePackage{expl3}[2020/01/12] -\RequirePackage{xparse} -%</driver|package> -%<*driver> -\documentclass{l3doc} -\usepackage[german,french,spanish,UKenglish]{babel} -\usepackage[table]{xcolor} -\usepackage{amsmath,booktabs,cancel,caption,colortbl,csquotes} -\usepackage{datatool,helvet,multirow,pgfplots,siunitx,xfrac,xtab} -\usepackage[capitalise]{cleveref} -\usepackage[final]{listings} -\usepackage[osf]{mathpazo} -\AtBeginDocument{\shorthandoff{<>}} -\crefformat{section}{#2Section~#1#3} -\Crefformat{section}{#2Section~#1#3} -\crefformat{subsection}{#2Section~#1#3} -\Crefformat{subsection}{#2Section~#1#3} -\crefformat{figure}{#2Figure~#1#3} -\Crefformat{figure}{#2Figure~#1#3} -\crefformat{table}{#2Table~#1#3} -\Crefformat{table}{#2Table~#1#3} -\crefrangeformat{table}{#3Tables~#1#4 to~#5#2#6} -\Crefrangeformat{table}{#3Tables~#1#4 to~#5#2#6} -\crefmultiformat{table}{#2Tables~#1#3}{ and~#2#1#3}{, #2#1#3}{, and~#2#1#3} -\Crefmultiformat{table}{#2Tables~#1#3}{ and~#2#1#3}{, #2#1#3}{, and~#2#1#3} -% Silence annoying fp package messages -\FPmessagesfalse -\pgfplotsset{compat = newest} -\sisetup{binary-units} -\DeclareSIUnit{\KWH}{kWh} -\DeclareSIPrePower\quartic{4} -\DeclareSIPostPower\tothefourth{4} -\DeclareSIQualifier\catalyst{cat} -\DeclareSIQualifier\isotropic{i} -\DeclareSIQualifier\polymer{pol} -\newlength\mylength -%\DisableImplementation -\begin{document} - \DocInput{\jobname.dtx} -\end{document} -%</driver> -% \fi -% -%\makeatletter -% -%^^A Some short cuts for the tables -%\NewDocumentCommand\DescribePrefix{m}{^^A -% \expandafter\SpecialUsageIndex\expandafter{\csname #1\endcsname}^^A -% #1 & \cs{#1} & \expandafter\si\expandafter{\csname #1\endcsname} -%} -%\NewDocumentCommand\DescribeUnit{m}{^^A -% \expandafter\SpecialUsageIndex\expandafter{\csname #1\endcsname}^^A -% #1 & -% \cs{#1} & -% \expandafter\si\expandafter{\csname #1\endcsname} -%} -%\NewDocumentCommand\DescribeNamedUnit{mm}{^^A -% \expandafter\SpecialUsageIndex\expandafter{\csname #2\endcsname}^^A -% #1 & -% \cs{#2} & -% \expandafter\si\expandafter{\csname #2\endcsname} -%} -% -%^^A For creating examples with nice highlighting of code, and so -%^^A on; based on the system used in the listings source (lstsample). -%\lst@RequireAspects{writefile} -%\newsavebox{\LaTeXdemo@box} -%\lstnewenvironment{LaTeXdemo}[1][code and example] -% {^^A -% \global\let\lst@intname\@empty -% \expandafter\let\expandafter\LaTeXdemo@end -% \csname LaTeXdemo@#1@end\endcsname -% \@nameuse{LaTeXdemo@#1}^^A -% } -% {\LaTeXdemo@end} -%\newcommand*\LaTeXdemo@new[3]{^^A -% \expandafter\newcommand\expandafter*\expandafter -% {\csname LaTeXdemo@#1\endcsname}{#2}^^A -% \expandafter\newcommand\expandafter*\expandafter -% {\csname LaTeXdemo@#1@end\endcsname}{#3}^^A -%} -%\newcommand*\LaTeXdemo@common{^^A -% \setkeys{lst} -% { -% basicstyle = \small\ttfamily, -% basewidth = 0.51em, -% gobble = 3, -% keywordstyle = \color{blue}, -% language = [LaTeX]{TeX}, -% moretexcs = -% { -% addto, -% ampere, -% ang, -% angstrom, -% becquerel, -% bel, -% bit, -% bottomrule, -% byte, -% cancel, -% candela, -% centi, -% color, -% coulomb, -% cubed, -% cubic, -% deci, -% decibel, -% degree, -% degreeCelsius, -% DeclareBinaryPrefix, -% DeclareRobustCommand, -% DeclareSIPostPower, -% DeclareSIPrefix, -% DeclareSIPrePower, -% DeclareSIQualifier, -% DeclareSIUnit, -% DTLdisplaydb, -% DTLforeach, -% DTLiffirstrow, -% DTLmul, -% DTLnewdb, -% DTLnewdbentry, -% DTLnewrow, -% farad, -% fontspec, -% gram, -% gray, -% henry, -% highlight, -% hour, -% Hz, -% joule, -% kelvin, -% kibi, -% kilo, -% kilogram, -% kWh, -% litre, -% lumen, -% lux, -% mathnormal, -% metre, -% mebi, -% micro, -% midrule, -% milli, -% mm, -% mole, -% multirow, -% num, -% numlist, -% numrange, -% of, -% pascal, -% per, -% percent, -% protected, -% radian, -% raiseto, -% robustify, -% rowcolor, -% second, -% selectlanguage, -% SendSettingsToPgf, -% si, -% SI, -% SIlist, -% SIrange, -% sievert, -% sisetup, -% SIUnitSymbolDegree, -% square, -% squared, -% tablenum, -% tesla, -% texorpdfstring, -% text, -% textmu, -% toprule, -% tothe, -% translate, -% unit, -% volt, -% watt -% } -% }^^A -%} -%\newcommand*\LaTeXdemo@input{^^A -% \MakePercentComment -% \catcode`\^^M=10\relax -% \small -% \begingroup -% \setkeys{lst} -% { -% SelectCharTable=\lst@ReplaceInput{\^\^I}{\lst@ProcessTabulator} -% }^^A -% \leavevmode -% \input{\jobname.tmp}^^A -% \endgroup -% \MakePercentIgnore -%} -%\LaTeXdemo@new{code and example} -% {^^A -% \setbox\LaTeXdemo@box=\hbox\bgroup -% \lst@BeginAlsoWriteFile{\jobname.tmp}^^A -% \LaTeXdemo@common -% } -% {^^A -% \lst@EndWriteFile -% \egroup -% \begin{center} -% \ifdim\wd\LaTeXdemo@box>0.48\linewidth\relax -% \hbox to\linewidth{\box\LaTeXdemo@box\hss}^^A -% \begin{minipage}{\linewidth} -% \LaTeXdemo@input -% \end{minipage} -% \else -% \begin{minipage}{0.48\linewidth} -% \LaTeXdemo@input -% \end{minipage} -% \hfill -% \begin{minipage}{0.48\linewidth} -% \hbox to\linewidth{\box\LaTeXdemo@box\hss}^^A -% \end{minipage} -% \fi -% \end{center} -% } -%\LaTeXdemo@new{code and float}{^^A -% \lst@BeginAlsoWriteFile{siunitx.tmp}^^A -% \LaTeXdemo@common -%}{^^A -% \lst@EndWriteFile -% \LaTeXdemo@input -%} -%\LaTeXdemo@new{code only} -% {\LaTeXdemo@common}{} -% -%^^A Turning of the marginpar warnings is a bit awkward. -%^^A It is achieved by temporarily disabling \@latex@warning@no@line -%\let\latex@addmarginpar\@addmarginpar -%\let\latex@warning@no@line\@latex@warning@no@line -%\def\@addmarginpar{^^A -% \let\@latex@warning@no@line\@gobble -% \latex@addmarginpar -% \let\@latex@warning@no@line\latex@warning@no@line -%} -% -%\ProvideDocumentCommand\opt{m}{\texttt{#1}} -% -%\makeatother -% -%\GetFileInfo{\jobname.sty} -% -%\title{^^A -% \textsf{siunitx} --- A comprehensive (SI) units package\thanks{^^A -% This file describes \fileversion, last revised \filedate.^^A -% }^^A -%} -%\author{^^A -% Joseph Wright\thanks -% {^^A -% E-mail: \href{mailto:joseph.wright@morningstar2.co.uk} -% {\texttt{joseph.wright@morningstar2.co.uk}}^^A -% }^^A -%} -%\date{Released \filedate} -% -%\maketitle -% -%\changes{v0.6}{2008/02/18}{First public testing release (as \pkg{si})} -%\changes{v1.0}{2008/06/15}{First official release} -%\changes{v1.1}{2008/09/28}{Package extended to a greater range of unit -% types} -%\changes{v1.2}{2009/01/22}{Correct handling for ranges of numbers -% added} -%\changes{v1.3}{2009/09/20}{Better definition for micro symbol} -%\changes{v1.4}{2010/01/16}{Detect entire document in non-serif font} -%\changes{v2.0}{2010/05/23}{Complete re-write of package to add many new -% features} -%\changes{v2.0c}{2010/06/07}{Mixed literal and macro units now print -% more reliably} -%\changes{v2.0d}{2010/06/10}{Fix error in \opt{table-format} option -% concerning exponent signs} -%\changes{v2.0e}{2010/06/20}{Correct behaviour of \cs{pm} in numbers -% when \texttt{abbreviations} configuration is loaded: problem -% introduced in v2.0c} -%\changes{v2.0f}{2010/06/27}{Fix issue with spacing of multiplication -% sign in text mode} -%\changes{v2.0g}{2010/06/28}{Fix issue with complex numbers in -% quotients} -%\changes{v2.0g}{2010/06/28}{Repair broken \opt{bracket-numbers} -% option} -%\changes{v2.0g}{2010/06/28}{Improve handling of complex root token} -%\changes{v2.0g}{2010/06/28}{Introduce localisation for text values} -%\changes{v2.0h}{2010/06/29}{Actually get localisation into the -% code} -%\changes{v2.0j}{2010/06/30}{Ensure symbols specified in -% \opt{input-symbols} are always printed in math mode} -%\changes{v2.0k}{2010/07/04}{Fix for \pkg{babel} French settings with -% \cs{fg} in tabular material} -%\changes{v2.0l}{2010/07/07}{Further adjustments to \pkg{babel} support} -%\changes{v2.0p}{2010/07/28}{Actually get change from v2.0o working} -%\changes{v2.0q}{2010/07/29}{Errors with free-standing unit code fixed} -%\changes{v2.0q}{2010/07/29}{Deal with bad definition of \cs{color} -% by \pkg{textpos} package} -%\changes{v2.0s}{2010/08/08}{Correct errors in rounding code when -% precision requested is zero decimal places} -%\changes{v2.0t}{2010/08/24}{Replace \cs{exp_afer:wN} in code for -% \cs{per} with \cs{exp_after:wN}} -%\changes{v2.0u}{2010/09/14}{Fix second possible issue with -% \pkg{textpos} package and \cs{color}} -%\changes{v2.0u}{2010/09/14}{Prevent infinite loop if \cs{SI} function -% is used with an empty number} -%\changes{v2.0v}{2010/09/26}{Internal changes reflecting \pkg{expl3} -% updates} -%\changes{v2.0w}{2010/09/29}{Deal with internal function used by -% REV\TeX{} in tables} -%\changes{v2.0x}{2010/10/05}{Fix bug when detecting single prefixes -% and converting prefixes to numbers} -%\changes{v2.1a}{2010/11/05}{Ensure that output of list separators is -% in text mode} -%\changes{v2.1a}{2010/11/05}{Print prefixes correctly in text mode -% when converting to numerical value} -%\changes{v2.1b}{2010/11/05}{Bug in printing code for complex part with -% no number fixed} -%\changes{v2.1b}{2010/11/05}{Bug in hyphen printing when detecting mode -% sorted} -%\changes{v2.1c}{2010/11/11}{Discourage line break between number and -% unit even when it is permitted} -%\changes{v2.1c}{2010/11/14}{After reviewing internals, \cs{numlist}, -% \cs{numrange}, \cs{SIlist} and \cs{SIrange} are documented as -% requiring text mode due to issues with spacing and line breaks} -%\changes{v2.1c}{2010/11/14}{Auto-detect math mode in tables and -% correct output accordingly} -%\changes{v2.1e}{2010/11/22}{Fix issues with text mode symbols and -% \pkg{fontspec} package} -%\changes{v2.1g}{2010/12/21}{Checks on the versions of \pkg{expl3} and -% \pkg{xparse} installed} -%\changes{v2.1h}{2011/01/18}{Detect AMS display-like environments} -%\changes{v2.1j}{2011/02/01}{Allow for loading of \pkg{inputenc} package -% with no options} -%\changes{v2.1k}{2011/02/09}{Bug fix when printing superscript minus -% signs and using \pkg{fontspec} package} -%\changes{v2.1m}{2011/03/18}{Avoid expansion of erroneous literal -% units when these are forbidden} -%\changes{v2.1m}{2011/03/20}{Ensure some output occurs in all cases -% when \opt{round-precision} is set to \opt{0} and \opt{round-mode} -% is set to \opt{places}} -%\changes{v2.1n}{2011/03/31}{Consistent behaviour for -% \opt{round-integer-to-decimal} when \opt{round-precision} is 0} -%\changes{v2.1o}{2011/04/03}{Fix incorrect font choice when -% \pkg{arev} package is loaded} -%\changes{v2.1o}{2011/04/03}{Account for negative exponents -% when using \opt{fixed-exponent} system} -%\changes{v2.1p}{2011/04/04}{Bad table alignment when some rows -% contain comparators fixed} -%\changes{v2.1p}{2011/04/04}{Poor position of comparators in -% numbers fixed} -%\changes{v2.2a}{2011/04/15}{Fix issue with \texttt{*} tokens in -% tabular preambles} -%\changes{v2.2a}{2011/04/15}{Expand macros with arguments correctly -% in tables} -%\changes{v2.2a}{2011/04/16}{Group digits for input containing symbolic -% entries} -%\changes{v2.2a}{2011/04/16}{Insert tokens correctly when last tabular cell -% does not end \texttt{\textbackslash\textbackslash}} -%\changes{v2.2a}{2011/04/16}{Fix bug with literal units and auto-insertion -% of \num{1} when \opt{per-mode} is \opt{symbol}} -%\changes{v2.2b}{2011/04/17}{Make \cs{of} work in hyper-linked sections} -%\changes{v2.2b}{2011/04/17}{Fix bug with \cs{highlight} macro when -% no colour support is loaded} -%\changes{v2.2b}{2011/04/19}{Fix bad formatting of negative exponents when -% using the \opt{output-exponent-marker} option} -%\changes{v2.2c}{2011/04/20}{Fix bad interaction with \pkg{cellspace} package} -%\changes{v2.2d}{2011/04/28}{Fix the \opt{strict} option} -%\changes{v2.2e}{2011/05/23}{Fix incorrect interpretation of complex numbers -% with no real part} -%\changes{v2.2g}{2011/06/02}{Correctly space \cs{degree} and similar units -% in lists and ranges when only a single unit is given} -%\changes{v2.2h}{2011/06/03}{Fix bug in significant figures rounding code -% for some integer part values} -%\changes{v2.2i}{2011/06/15}{Fix \opt{detect-mode} option inside -% table cells} -%\changes{v2.2j}{2011/06/26}{Fix incorrect line breaking in \cs{SIrange}} -%\changes{v2.2k}{2011/06/27}{Fix behaviour of subscripts inside alignments -% when printing in text mode} -%\changes{v2.2l}{2011/06/30}{Fix loss of main unit when \opt{per-mode} is set -% to \opt{symbol} and a pre-unit is used} -%\changes{v2.3}{2011/06/19}{New implementation for alignment in \texttt{S} -% column} -%\changes{v2.3a}{2011/07/09}{Restore fix in v2.2l missing in v2.3} -%\changes{v2.3b}{2011/08/08}{Adjust internal load order so that -% \opt{free-standing-units} works correctly for abbreviations} -%\changes{v2.3c}{2011/07/12}{Fix display of \( \pm \) in numbers when -% \opt{separate-uncertainty} is \opt{true} and literal units are used} -%\changes{v2.3d}{2011/08/18}{Fix broken superscript display in literal unit -% mode} -%\changes{v2.3e}{2011/09/09}{Internal changes to work with \LaTeX3 -% updates} -%\changes{v2.3f}{2011/09/03}{Fix processing of numbers in tables when entire -% number is invalid} -%\changes{v2.3g}{2011/10/06}{Deal with erroneous leading zero in some -% fixed exponent cases} -%\changes{v2.3h}{2011/10/14}{Ensure math mode for exponent products in all -% circumstances} -%\changes{v2.3h}{2011/10/14}{Improvements to output when using \pkg{tex4ht}} -%\changes{v2.4}{2011/11/03}{Reduce number of math mode options, improving -% consistency of output} -%\changes{v2.4a}{2011/11/28}{Extend search-and-replace code for UTF-8 -% characters} -%\changes{v2.4a}{2011/12/04}{Use a more cautious approach to changing -% settings at the start of the document} -%\changes{v2.4b}{2011/12/06}{Erroneous doubled \texttt{\#} corrected} -%\changes{v2.4c}{2011/12/09}{Erroneous check for text mode sanserif font fixed} -%\changes{v2.4d}{2011/12/09}{Fix for edge-case user commands in captions -% where the command clashes with a unit name} -%\changes{v2.4e}{2011/12/11}{Fix issue with \pkg{inputenc} package and -% some of the recent special symbol changes} -%\changes{v2.4f}{2011/12/21}{Allow easier use of headings when not parsing -% numbers in tables} -%\changes{v2.4f}{2011/12/23}{Fix bug with detection of bold font in table -% cells} -%\changes{v2.4g}{2012/01/06}{Update internals to match changes in \pkg{expl3} -% which caused issues with some tokens in numerical arguments} -%\changes{v2.4h}{2012/01/15}{Bug fix for implementation of -% \opt{reciprocal-positive-first}} -%\changes{v2.4i}{2012/01/19}{Bug fix for rounding with large numbers of -% decimal places} -%\changes{v2.4j}{2012/01/26}{Leave vertical mode before any document-level -% commands} -%\changes{v2.4k}{2012/03/22}{Internal changes to allow for \pkg{breqn} -% package tricks} -%\changes{v2.4l}{2012/03/23}{Fix a load-order issue with \pkg{soulpos} -% package} -%\changes{v2.4m}{2012/04/03}{Correct bug in \cs{SIlist} when only a single -% number is given} -%\changes{v2.4n}{2012/04/04}{Allow conversion of numbers with more than -% nine digits to scientific notation} -% \changes{v2.5}{2012/04/07}{Fixed table code to give fewer underfull -% boxes when comparators are used} -% \changes{v2.5}{2015/04/07}{Added \opt{zero-decimal-to-integer} option} -% \changes{v2.5}{2012/04/07}{Added \opt{omit-uncertainty} option} -% \changes{v2.5}{2012/04/08}{Modified \opt{fixed-exponent} such that it can -% remove an exponent part} -% \changes{v2.5}{2012/04/08}{Modified number of intrinsically-mathematical -% options} -% \changes{v2.5a}{2012/04/19}{Fixed support for \enquote{dynamic} nature of spacing -% in free standing units (bug introduced in v2.5)} -% \changes{v2.5b}{2012/04/20}{Fixed treatement \texttt{\^} and \texttt{\_} -% in literal units when \pkg{breqn} package is loaded} -% \changes{v2.5b}{2012/04/20}{Added support for \pkg{eulervm} package} -% \changes{v2.5c}{2012/04/03}{Fixed conversion of numbers with more than -% nine digits when using fixed exponents} -% \changes{v2.5c}{2012/05/03}{Modified treatment entirely empty cells in -% \texttt{s} columns} -% \changes{v2.5d}{2012/06/11}{Extend range of settings automatically altered -% to use UTF-8 values is appropriate} -% \changes{v2.5d}{2012/06/11}{Added \opt{qualifier-phrase} option} -% \changes{v2.5d}{2012/06/11}{Added \opt{phrase} choice for \opt{qualifier-mode} -% option} -% \changes{v2.5e}{2012/06/13}{Fixed an internal error in unit expansion -% introduced in v2.4f} -% \changes{v2.5f}{2012/07/16}{Modified internals to track \pkg{expl3} changes} -% \changes{v2.5g}{2012/07/22}{Fixed \opt{binary-units} option} -% \changes{v2.5h}{2012/08/28}{Modified literal unit test to allow spaces in -% units to be ignored} -% \changes{v2.5i}{2012/09/11}{Fixed alignment of values without uncertainties in -% columns where space is reserved for uncertainties} -% \changes{v2.5j}{2012/09/18}{Fixed rounding when uncertainties are present} -% \changes{v2.5k}{2012/09/20}{Fixed a warning with \pkg{amsmath} related to fraction -% functions} -% \changes{v2.5k}{2012/11/13}{Fixed handling spaces correctly after start of document} -% \changes{v2.5l}{2012/11/21}{Modified internals to track \pkg{expl3} changes} -% \changes{v2.5m}{2012/11/27}{Fixed bug with UTF-8 engines and literal units} -% \changes{v2.5m}{2012/11/27}{Fixed \cs{highlight} behavior in bookmarks} -% \changes{v2.5m}{2012/11/27}{Modified loading of \opt{binary-units}} -% \changes{v2.5m}{2012/11/27}{Fixed right-to-left mode with \pkg{bidi} -% package} -% \changes{v2.5n}{2012/12/29}{Fixed transmission of grouping information by -% \cs{SendSettingsToPgf}} -% \changes{v2.5o}{2013/01/09}{Modified internals to track \pkg{expl3} changes} -% \changes{v2.5p}{2013/02/01}{Fixed printing of \cs{pm} and \cs{mp} when used -% as signs in text mode} -% \changes{v2.5q}{2013/03/10}{Fixed use active \texttt{-} in numbersn} -% \changes{v2.5q}{2013/03/10}{Fixed binary units in tables} -% \changes{v2.5r}{2013/07/11}{Modified internals to track \pkg{expl3} changes} -% \changes{v2.5s}{2013/07/31}{Modified internals to track \pkg{expl3} changes} -% \changes{v2.6}{2013/11/19}{Fixed loading when \pkg{mdwtab} is in use} -% \changes{v2.6}{2014/09/03}{Fixed minus sign when \pkg{tex4ht} is in use} -% \changes{v2.6}{2014/09/03}{Fixed spacing when printing comparators} -% \changes{v2.6}{2014/09/03}{Modified treatment of hard spaces (\texttt{\~}) in -% argument of \cs{num}} -% \changes{v2.6}{2014/09/03}{Modified standard setting for \opt{mode} option -% to \opt{math}} -% \changes{v2.6}{2014/09/04}{Fixed printing of uncertainties when the -% input is an integer and the uncertainty is given as a separate part} -% \changes{v2.6}{2014/09/04}{Fixed definition \cs{fg} in -% bookmarks when \pkg{babel} is loaded with the \opt{french} option} -% \changes{v2.6}{2014/09/05}{Fixed printing exponent in tables when -% \opt{output-exponent-marker} is active} -% \changes{v2.6a}{2014/09/15}{Modified glyph selection when \pkg{fontspec} -% is detected} -% \changes{v2.6b}{2014/09/27}{Modified range of font shapes which can be -% detected} -% \changes{v2.6c}{2014/10/01}{Fixed use of \cs{micro} when \pkg{fontspec} -% is loaded but \pkg{unicode-math} is not} -% \changes{v2.6d}{2014/10/07}{Fixed conversion of \enquote{long} to -% \enquote{short} uncertainty values with integer mantissas} -% \changes{v2.6e}{2015/01/21}{Modified symbol selection where \pkg{fontspec} -% and certain other packages are in use} -% \changes{v2.6f}{2015/04/01}{Fixed \opt{table-sign-exponent} and -% \opt{table-sign-mantissa} options when set \opt{false}} -% \changes{v2.6f}{2015/04/04}{Modified detection of \pkg{mathspec}} -% \changes{v2.6g}{2015/06/24}{Fixed issue with empty table cells} -% \changes{v2.6h}{2015/07/17}{Modified internals to track \pkg{expl3} changes} -% \changes{v2.6i}{2015/08/18}{Fixed rounding of numbers with large numbers of -% digits} -% \changes{v2.6i}{2015/08/18}{Fixed behaviour of \cs{cancel} when printing -% in math mode} -% \changes{v2.6j}{2015/09/01}{Fixed printing of all units when -% \opt{exponent-to-prefix} is set} -% \changes{v2.6j}{2015/09/01}{Fixed appearance of $\pm$ when -% \opt{exponent-to-prefix} is set} -% \changes{v2.6k}{2015/09/12}{Modified internals to track \pkg{expl3} changes} -% \changes{v2.6l}{2015/09/14}{Fixed an internal error} -% \changes{v2.6m}{2015/10/15}{Fixed an issue with \pkg{mwtab}} -% \changes{v2.6n}{2015/12/31}{Modified definition for degree Celsius} -% \changes{v2.6n}{2015/12/31}{Fixed {\aa}ngstr{\"o}m symbol with \LuaTeX{}} -% \changes{v2.6o}{2016/01/05}{Added support for unit powers when converting exponents -% to prefixes} -% \changes{v2.6p}{2016/01/13}{Added support for reciprocal powers when converting -% exponents to prefixes} -% \changes{v2.6p}{2016/01/19}{Modified definition for degree Celsius} -% \changes{v2.6q}{2016/03/01}{Fixed font selection when document commands are -% used inside table cells in \texttt{S} columns} -% \changes{v2.6r}{2016/06/06}{Fixed color safety issue} -% \changes{v2.6r}{2016/08/14}{Fixed internal \pkg{expl3} usage issues} -% \changes{v2.6r}{2016/08/21}{Fixed handling \texttt{e0}} -% \changes{v2.6r}{2016/08/21}{Added a warning when color support is not available} -% \changes{v2.6s}{2016/09/02}{Removed one excess warning} -% \changes{v2.7}{2016/11/11}{Added first documented code level interfaces} -% \changes{v2.7}{2016/11/23}{Fixed behavior when \pkg{cellspace} is applied to -% math mode material} -% \changes{v2.7b}{2017/01/28}{Fixed large numbers in scientific mode} -% \changes{v2.7c}{2017/02/01}{Fixed spacing of integers in tables when -% aligning decimal marker to center} -% \changes{v2.7d}{2017/02/19}{Fixed doubled pre-number tokens in tables} -% \changes{v2.7e}{2017/03/06}{Modified treatment of \texttt{+} } -% \changes{v2.7f}{2017/03/23}{Fixed spacing with \opt{reciprocal-positive-first} -% setting} -% \changes{v2.7g}{2017/05/19}{Fixed an issue with recent \pkg{expl3} update} -% \changes{v2.7h}{2017/06/12}{Modified code internals} -% \changes{v2.7i}{2017/07/23}{Fixed an incorrect variable name} -% \changes{v2.7k}{2017/11/01}{Fixed formatting of units when not parsed} -% \changes{v2.7l}{2018/03/11}{Modified \pkg{unicode-math} support} -% \changes{v2.7m}{2018/03/20}{Modified definition of \cs{astronomicalunit} unit} -% \changes{v2.7n}{2018/04/27}{Fixed symbolic input and digit grouping} -% \changes{v2.7q}{2018/05/11}{Fixed patching of \pkg{cellspace} columns} -% \changes{v2.7r}{2018/05/16}{Fixed issue in tabulars when REV\TeX{} is in use} -% \changes{v2.7s}{2018/05/17}{Modified package date format} -% \changes{v2.7t}{2018/06/08}{Fix inclusion of sign in astronomy-style -% angles} -% \changes{v2.7t}{2019/10/10}{Fix \opt{round-half} when \opt{even} at zero precision} -% \changes{v2.7u}{2020/01/15}{Modified internals to track \pkg{expl3} changes} -% \changes{v2.7v}{2020/02/17}{Fix appearance of superscript decimals with -% comma decimal marker} -% \changes{v2.8}{2020/02/20}{Use companion font symbols (now always loaded by -% the kernel)} -% \changes{v2.8}{2020/02/20}{Allow \cs{ohm} to appear correctly in PDF -% bookmarks} -% \changes{v2.8a}{2020/02/23}{Correct appearance of ohm when -% \pkg{unicode-math} is loaded} -% \changes{v2.8b}{2020/02/25}{Correct appearance of ohm when -% \pkg{newtxmath} is loaded} -% -%\begin{abstract} -% Physical quantities have both numbers and units, and each physical -% quantity should be expressed as the product of a number and a unit. -% Typesetting physical quantities requires care to ensure that the -% combined mathematical meaning of the number--unit combination is -% clear. In particular, the SI units system lays down a consistent -% set of units with rules on how these are to be used. However, -% different countries and publishers have differing conventions on -% the exact appearance of numbers (and units). -% -% The \pkg{siunitx} package provides a set of tools for authors -% to typeset quantities in a consistent way. The package has an -% extended set of configuration options which make it possible to -% follow varying typographic conventions with the same input syntax. -% The package includes automated processing of numbers and units, and -% the ability to control tabular alignment of numbers. -%\end{abstract} -% -%\tableofcontents -% -%\begin{documentation} -% -%\section{Introduction} -% -% The correct application of units of measurement is very important -% in technical applications. For this reason, carefully-crafted -% definitions of a coherent units system have been laid down by the -% \emph{Conf\'erence G\'en\'erale des Poids et -% Mesures} (CGPM): this has resulted in the \emph{Syst\`eme -% International d'Unit\'es} (SI). At the same time, typographic -% conventions for correctly displaying both numbers and units exist to -% ensure that no loss of meaning occurs in printed matter. -% -% \pkg{siunitx} aims to provide a unified method for \LaTeX{} users to -% typeset numbers and units correctly and easily. The design -% philosophy of \pkg{siunitx} is to follow the agreed rules by -% default, but to allow variation through option settings. In this way, -% users can use \pkg{siunitx} to follow the requirements of -% publishers, co-authors, universities, \emph{etc}.~without needing to -% alter the input at all. -% -%\section{Installation} -% -% The package is supplied in \file{dtx} format and as a pre-extracted -% zip file, \file{\jobname.tds.zip}. The later is most convenient for -% most users: simply unzip this in your local texmf directory and -% run \texttt{texhash} to update the database of file locations. If -% you want to unpack the \file{dtx} yourself, running -% \texttt{tex \jobname.dtx} will extract the package whereas -% \texttt{latex \jobname.dtx} will extract it and also typeset the -% documentation. -% -% The package requires \LaTeX3 support as provided in the -% \pkg{l3kernel} and \pkg{l3packages} bundles. Both of these are available -% on \href{http://www.ctan.org}{\textsc{ctan}} as ready-to-install -% zip files. Suitable versions are available in MiK\TeX{}~2.9 and -% \TeX{}~Live 2015 (updating the relevant packages online may be -% necessary). \LaTeX3, and so \pkg{siunitx}, requires the \eTeX{} -% extensions: these are available on all modern \TeX{} systems. -% -% Typesetting the documentation requires a number of packages in -% addition to those needed to use the package. This is mainly -% because of the number of demonstration items included in the text. To -% compile the documentation without error, you will need the packages: -%\begin{itemize} -% \item \pkg{amsmath} -% \item \pkg{booktabs} -% \item \pkg{cancel} -% \item \pkg{caption} -% \item \pkg{cleveref} -% \item \pkg{colortbl} -% \item \pkg{csquotes} -% \item \pkg{helvet} -% \item \pkg{mathpazo} -% \item \pkg{multirow} -% \item \pkg{listings} -% \item \pkg{pgfplots} -% \item \pkg{xcolor} -%\end{itemize} -% -%\section{\pkg{siunitx} for the impatient} -% -% The package provides the user macros: -%\begin{itemize} -% \item \cs{ang}\oarg{options}\marg{angle} -% \item \cs{num}\oarg{options}\marg{number} -% \item \cs{si}\oarg{options}\marg{unit} -% \item \cs{SI}\oarg{options}\marg{number}\oarg{pre-unit}\marg{unit} -% \item \cs{numlist}\oarg{options}\marg{numbers} -% \item \cs{numrange}\oarg{options}\marg{numbers}\marg{number2} -% \item \cs{SIlist}\oarg{options}\marg{numbers}\marg{unit} -% \item \cs{SIrange}\oarg{options}\marg{number1}\marg{number2}^^A -% \marg{unit} -% \item \cs{sisetup}\marg{options} -% \item \cs{tablenum}\oarg{options}\marg{number} -%\end{itemize} -% plus the \texttt{S} and \texttt{s} column types for decimal -% alignments and units in tabular environments. These user macros and -% column types are designed for -% typesetting numbers and units with control of appearance and with -% intelligent processing. -% -% Numbers are processed with understanding of exponents, complex numbers -% and multiplication. -%\begin{LaTeXdemo} -% \num{12345,67890} \\ -% \num{1+-2i} \\ -% \num{.3e45} \\ -% \num{1.654 x 2.34 x 3.430} -%\end{LaTeXdemo} -% -% The unit system can interpret units given as text to be used directly -% or as macro-based units. In the latter case, different formatting is -% possible. -%\begin{LaTeXdemo} -% \si{kg.m.s^{-1}} \\ -% \si{\kilogram\metre\per\second} \\ -% \si[per-mode=symbol] -% {\kilogram\metre\per\second} \\ -% \si[per-mode=symbol] -% {\kilogram\metre\per\ampere\per\second} -%\end{LaTeXdemo} -% -% Simple lists and ranges of numbers can be handled. -%\begin{LaTeXdemo} -% \numlist{10;20;30} \\ -% \SIlist{0.13;0.67;0.80}{\milli\metre} \\ -% \numrange{10}{20} \\ -% \SIrange{0.13}{0.67}{\milli\metre} -%\end{LaTeXdemo} -% -% By default, all text is typeset in the current upright math -% font. This can be changed by setting the appropriate options: -% "\sisetup{detect-all}" will use the current font for typesetting. -% -%\section{Using the \pkg{siunitx} package} -% -%\subsection{Loading the package} -% -% The package should be loaded in the usual \LaTeXe{} way. -%\begin{LaTeXdemo}[code only] -% \usepackage{siunitx} -%\end{LaTeXdemo} -% The key--value options described later in this document can be used -% when loading the package, for example -%\begin{LaTeXdemo}[code only] -% \usepackage[version-1-compatibility]{siunitx} -%\end{LaTeXdemo} -% to use options from version 1 of the package. -% -%\subsection{Numbers} -% -%\begin{function}{\num} -% \begin{syntax} -% \cs{num}\oarg{options}\marg{number} -% \end{syntax} -%\end{function} -% Numbers are automatically formatted by the \cs{num} macro. This -% takes one optional argument, \meta{options}, and one mandatory one, -% \meta{number}. The contents of \meta{number} are automatically -% formatted. The formatter removes both \enquote{soft} (\verb*" ") and -% \enquote{hard} spaces (\cs{,} and "~"), automatically identifies -% exponents (by default -% marked using \texttt{e}, \texttt{E}, \texttt{d} or \texttt{D}) and -% adds the appropriate spacing of large numbers. With the standard -% settings a leading zero is added before a decimal marker, if needed: -% both \enquote{\texttt{.}} and \enquote{\texttt{,}} are recognised as -% decimal markers. -%\begin{LaTeXdemo} -% \num{123} \\ -% \num{1234} \\ -% \num{12345} \\ -% \num{0.123} \\ -% \num{0,1234} \\ -% \num{.12345} \\ -% \num{3.45d-4} \\ -% \num{-e10} -%\end{LaTeXdemo} -% Note that numbers are parsed before typesetting, which does -% have a performance overhead (only obvious with very large amounts -% of numerical input). The parser understands a range of input syntaxes, -% as demonstrated above. -% -%\begin{function}{\numlist} -% \begin{syntax} -% \cs{numlist}\oarg{options}\marg{numbers} -% \end{syntax} -%\end{function} -%\changes{v2.0}{2010/05/23}{Introduced \cs{numlist} and \cs{SIlist} -% functions} -% Lists of numbers may be processed using the \cs{numlist} function. -% Each \meta{number} is given within the list of \meta{numbers} within -% a brace pair, as the list can have a flexible length. This function -% should be used in text mode, a common feature of all of the list and -% range functions provided by \pkg{siunitx}.\footnote{The reason for -% this restriction is that the separators between items may involve -% text-mode spaces which must be able to vanish at line breaks. It is -% not possible to achieve this effect from inside math mode.} -%\begin{LaTeXdemo} -% \numlist{10;30;50;70} -%\end{LaTeXdemo} -% -%\begin{function}{\numrange} -% \begin{syntax} -% \cs{numrange}\oarg{options}\marg{number1}\marg{number2} -% \end{syntax} -%\end{function} -% Simple ranges of numbers can be handled using the \cs{numrange} -% function. This acts in the same way as \cs{num}, but inserts a -% phrase or other text between the two entries. This function should -% be used in text mode. -%\begin{LaTeXdemo} -% \numrange{10}{30} -%\end{LaTeXdemo} -% -%\begin{function}{\ang} -% \begin{syntax} -% \cs{ang}\oarg{options}\marg{angle} -% \end{syntax} -%\end{function} -% Angles can be typeset using the \cs{ang} command. The -% \meta{angle} can be given either as a decimal number or as a -% semi-colon separated list of degrees, minutes and seconds, which -% is called \enquote{arc format} in this document. The numbers which -% make up an angle are processed using the same system as other numbers. -%\begin{LaTeXdemo} -% \ang{10} \\ -% \ang{12.3} \\ -% \ang{4,5} \\ -% \ang{1;2;3} \\ -% \ang{;;1} \\ -% \ang{+10;;} \\ -% \ang{-0;1;} -%\end{LaTeXdemo} -% -%\subsection{Units} -% -%\begin{function}{\si} -% \begin{syntax} -% \cs{si}\oarg{options}\marg{unit} -% \end{syntax} -%\end{function} -% The symbol for a unit can be typeset using the \cs{si} macro: this -% provides full control over output format for the unit. Like the -% \cs{num} macro, \cs{si} takes one optional and one mandatory -% argument. The unit formatting system can accept two types of input. -% When the \meta{si} contains literal items (for example letters or -% numbers) then \pkg{siunitx} converts \texttt{.} and "~" into -% inter-unit product and correctly positions sub- and superscripts -% specified using "_" and "^". The formatting methods will work with -% both math and text mode. -%\begin{LaTeXdemo} -% \si{kg.m/s^2} \\ -% \si{g_{polymer}~mol_{cat}.s^{-1}} -%\end{LaTeXdemo} -% The second operation mode for the \cs{si} macro is an -% \enquote{interpreted} system, Here, each unit, SI multiple prefix and -% power is given a macro name. These are entered in a method very -% similar to the reading of the unit name in English. -%\begin{LaTeXdemo} -% \si{\kilo\gram\metre\per\square\second} \\ -% \si{\gram\per\cubic\centi\metre} \\ -% \si{\square\volt\cubic\lumen\per\farad} \\ -% \si{\metre\squared\per\gray\cubic\lux} \\ -% \si{\henry\second} -%\end{LaTeXdemo} -% On its own, this is less convenient than the direct method, although -% it does use meaning rather than appearance for input. However, the -% package allows you to define new unit macros; a large number of -% pre-defined abbreviations are also supplied. More importantly, by -% defining macros for units, instead of literal input, new -% functionality is made available. By altering the settings used by the -% package, the same input can yield a variety of different output -% formats. For example, the \cs{per} macro can give reciprocal powers, -% slashes or be used to construct units as fractions. -% -%\begin{function}{\SI} -% \begin{syntax} -% \cs{SI}\oarg{options}\marg{number}\oarg{preunit}\marg{unit} -% \end{syntax} -%\end{function} -% Very often, numbers and units are given together. Formally, the -% value of a quantity is the product of the number and the unit, the -% space being regarded as a multiplication sign \cite{SI:5.3.3}. The -% \cs{SI} macro combines the functionality of \cs{num} and -% \cs{si}, and makes this both possible and easy. The \meta{number} -% and \meta{si} arguments work exactly like those for the \cs{num} and -% \cs{si} macros, respectively. \meta{preunit} is a unit to be typeset -% \emph{before} the numerical value (most likely to be a currency). -%\begin{LaTeXdemo} -% \SI[mode=text]{1.23}{J.mol^{-1}.K^{-1}} \\ -% \SI{.23e7}{\candela} \\ -% \SI[per-mode=symbol]{1.99}[\$]{\per\kilogram} \\ -% \SI[per-mode=fraction]{1,345}{\coulomb\per\mole} -%\end{LaTeXdemo} -% -% It is possible to set up the unit macros to be available outside of -% the \cs{SI} and \cs{si} functions. This is not the standard -% behaviour as there is the risk of name clashes (for example, \cs{bar} -% is used by other packages, and several packages define \cs{degree}). -% Full details of using \enquote{stand alone} units are found in -% \cref{sec:units:creating}. -% -%\begin{function}{\SIlist} -% \begin{syntax} -% \cs{SIlist}\oarg{options}\marg{numbers}\marg{unit} -% \end{syntax} -%\end{function} -% Lists of numbers with units can be handled using the \cs{SIlist} -% function. The behaviour of this function is similar to \cs{numlist}, -% but with the addition of a unit to each number. This function should -% be used in text mode. -%\begin{LaTeXdemo} -% \SIlist{10;30;45}{\metre} -%\end{LaTeXdemo} -% -%\begin{function}{\SIrange} -% \begin{syntax} -% \cs{SIrange}\oarg{options}\marg{number1}\marg{number2}\marg{unit} -% \end{syntax} -%\end{function} -% Ranges of numbers with units can be handled using the \cs{SIrange} -% function. The behaviour of this function is similar to \cs{numrange}, -% but with the addition of a unit to each number. This function should -% be used in text mode. -%\begin{LaTeXdemo} -% \SIrange{10}{30}{\metre} -%\end{LaTeXdemo} -% -%\subsection{The unit macros} -% -% The package always defines the basic set of SI units with macro names. -% This includes the base SI units, the derived units with special names -% and the prefixes. A small number of powers are also given pre-defined -% names. Full details of units in the SI are available -% on-line~\cite{BIPM}. -% -% The seven base SI units are always defined -% (\cref{tab:unit:base}). In addition, the macro \cs{meter} is -% available as an alias for \cs{metre}, for users of US spellings. -% The full details of the base units are given in the SI -% Brochure~\cite{SI:2.1}. -%\begin{table} -% \caption{SI base units.} -% \label{tab:unit:base} -% \centering -% \begin{tabular}{lll} -% \toprule -% Unit & Macro & Symbol \\ -% \midrule -% \DescribeUnit{ampere} \\ -% \DescribeUnit{candela} \\ -% \DescribeUnit{kelvin} \\ -% \DescribeUnit{kilogram} \\ -% \DescribeUnit{metre} \\ -% \DescribeUnit{mole} \\ -% \DescribeUnit{second} \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -% The SI also lists a number of units which have special names and -% symbols \cite{SI:2.2.2}: these are listed in -% \cref{tab:unit:derived}. As a short-cut for the degree Celsius, -% the unit \cs{celsius} is defined equivalent to \cs{degreeCelsius} . -%\begin{table} -% \caption{Coherent derived units in the SI with special names and -% symbols.} -% \label{tab:unit:derived} -% \centering -% \begin{tabular}{lll>{\qquad}lll} -% \toprule -% Unit & Macro & Symbol & Unit & Macro & Symbol \\ -% \midrule -% \DescribeUnit{becquerel} & -% \DescribeUnit{newton} \\ -% \DescribeNamedUnit{degree Celsius}{degreeCelsius} & -% \DescribeUnit{ohm} \\ -% \DescribeUnit{coulomb} & -% \DescribeUnit{pascal} \\ -% \DescribeUnit{farad} & -% \DescribeUnit{radian} \\ -% \DescribeUnit{gray} & -% \DescribeUnit{siemens} \\ -% \DescribeUnit{hertz} & -% \DescribeUnit{sievert} \\ -% \DescribeUnit{henry} & -% \DescribeUnit{steradian} \\ -% \DescribeUnit{joule} & -% \DescribeUnit{tesla} \\ -% \DescribeUnit{katal} & -% \DescribeUnit{volt} \\ -% \DescribeUnit{lumen} & -% \DescribeUnit{watt} \\ -% \DescribeUnit{lux} & -% \DescribeUnit{weber} \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -% In addition to the official SI units, \pkg{siunitx} also provides -% macros for a number of units which are accepted for use in the SI -% although they are not SI units. \cref{tab:unit:accepted} lists -% the \enquote{accepted} units \cite{SI:4.1.T6}. Some units are -% fundamental physical quantities, and these are non-SI but can be used -% within the SI (\cref{tab:unit:physical}, \cite{SI:4.1.T7}). -% There are also a set of non-SI units which are used in certain -% defined circumstances (\cref{tab:unit:other}), although they are -% not necessarily officially sanctioned \cite{SI:4.1.T8}. -% \DescribeMacro{\percent} -% The package also predefines the \cs{percent} macro. While this is not a -% unit, it is used in the same way in many cases and is therefore provided -% on the grounds of realism. -%\begin{table} -% \caption{Non-SI units accepted for use with the -% International System of Units.} -% \label{tab:unit:accepted} -% \centering -% \begin{tabular}{lll} -% \toprule -% Unit & Macro & Symbol \\ -% \midrule -% \DescribeUnit{day} \\ -% \DescribeUnit{degree} \\ -% \DescribeUnit{hectare} \\ -% \DescribeUnit{hour} \\ -% \DescribeUnit{litre} \\ -% \SpecialUsageIndex{\liter}^^A -% & \cs{liter} & \si{\liter} \\ -% \DescribeNamedUnit{minute (plane angle)}{arcminute} \\ -% \DescribeNamedUnit{minute (time)}{minute} \\ -% \DescribeNamedUnit{second (plane angle)}{arcsecond} \\ -% \DescribeUnit{tonne} \\ -% \bottomrule -% \end{tabular} -%\end{table} -%\begin{table} -% \changes{v2.0j}{2010/06/30}{Correct \cs{hartree} unit appearance} -% \caption{Non-SI units whose values in SI units must be obtained -% experimentally.} -% \label{tab:unit:physical} -% \centering -% \begin{tabular}{lll} -% \toprule -% Unit & Macro & Symbol \\ -% \midrule -% \DescribeNamedUnit{astronomical unit}{astronomicalunit} \\ -% \DescribeNamedUnit{atomic mass unit}{atomicmassunit} \\ -% \DescribeUnit{bohr} \\ -% \DescribeNamedUnit{speed of light}{clight} \\ -% \DescribeUnit{dalton} \\ -% \DescribeNamedUnit{electron mass}{electronmass} \\ -% \DescribeUnit{electronvolt} \\ -% \DescribeNamedUnit{elementary charge}{elementarycharge} \\ -% \DescribeUnit{hartree} \\ -% \DescribeNamedUnit{reduced Planck constant}{planckbar} \\ -% \bottomrule -% \end{tabular} -%\end{table} -%\begin{table} -% \caption{Other non-SI units.} -% \label{tab:unit:other} -% \centering -% \begin{tabular}{lll} -% \toprule -% Unit & Macro & Symbol \\ -% \midrule -% \DescribeNamedUnit{{\aa}ngstr{\"o}m}{angstrom} \\ -% \DescribeUnit{bar} \\ -% \DescribeUnit{barn} \\ -% \DescribeUnit{bel} \\ -% \DescribeUnit{decibel} \\ -% \DescribeUnit{knot} \\ -% \DescribeNamedUnit{millimetre of mercury}{mmHg} \\ -% \DescribeNamedUnit{nautical mile}{nauticalmile} \\ -% \DescribeUnit{neper} \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -% In addition to the units themselves, \pkg{siunitx} provides -% pre-defined macros for all of the SI prefixes -% (\cref{tab:unit:prefix}, \cite{SI:3.1}). The spelling -% \enquote{\cs{deka}} is provided for US users as an alternative to -% \cs{deca}. -%\begin{table} -% \caption{SI prefixes.} -% \label{tab:unit:prefix} -% \centering -% \begin{tabular}{llc>{$}l<{$}>{\qquad}llc>{$}l<{$}} -% \toprule -% Prefix & Macro & Symbol & \multicolumn{1}{l}{Power} & -% Prefix & Macro & Symbol & \multicolumn{1}{l}{Power} \\ -% \midrule -% \DescribePrefix{yocto} & -24 & -% \DescribePrefix{deca} & 1 \\ -% \DescribePrefix{zepto} & -21 & -% \DescribePrefix{hecto} & 2 \\ -% \DescribePrefix{atto} & -18 & -% \DescribePrefix{kilo} & 3 \\ -% \DescribePrefix{femto} & -15 & -% \DescribePrefix{mega} & 6 \\ -% \DescribePrefix{pico} & -12 & -% \DescribePrefix{giga} & 9 \\ -% \DescribePrefix{nano} & -9 & -% \DescribePrefix{tera} & 12 \\ -% \DescribePrefix{micro} & -6 & -% \DescribePrefix{peta} & 15 \\ -% \DescribePrefix{milli} & -3 & -% \DescribePrefix{exa} & 18 \\ -% \DescribePrefix{centi} & -2 & -% \DescribePrefix{zetta} & 21 \\ -% \DescribePrefix{deci} & -1 & -% \DescribePrefix{yotta} & 24 \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -% A small number of pre-defined powers are provided as macros. -% \cs{square} and \cs{cubic} are intended for use before units, with -% \cs{squared} and \cs{cubed} going after the unit. -%\begin{LaTeXdemo} -% \si{\square\becquerel} \\ -% \si{\joule\squared\per\lumen} \\ -% \si{\cubic\lux\volt\tesla\cubed} -%\end{LaTeXdemo} -% Generic powers can be inserted on a one-off basis using the \cs{tothe} -% and \cs{raiseto} macros. These are the only macros for units which -% take an argument: -%\begin{LaTeXdemo} -% \si{\henry\tothe{5}} \\ -% \si{\raiseto{4.5}\radian} -%\end{LaTeXdemo} -% Reciprocal powers are indicated using the \cs{per} macro. This applies -% to the next unit only, unless the \opt{sticky-per} option -% is turned on. -%\begin{LaTeXdemo} -% \si{\joule\per\mole\per\kelvin} \\ -% \si{\joule\per\mole\kelvin} \\ -% \si{\per\henry\tothe{5}} \\ -% \si{\per\square\becquerel} -%\end{LaTeXdemo} -%\changes{v2.0i}{2010/06/29}{Correct behaviour of \cs{of} function -% so it actually works (bug introduced in v2.0d)} -% As for generic powers, generic qualifiers are also available using -% the \cs{of} function: -%\begin{LaTeXdemo} -% \si{\kilogram\of{metal}} \\ -% \SI[qualifier-mode = brackets] -% {0.1}{\milli\mole\of{cat}\per\kilogram\of{prod}} -%\end{LaTeXdemo} -% -%\changes{v2.2}{2011/04/05}{Support use of \cs{cancel} macro in units} -%\changes{v2.2}{2011/04/06}{New \cs{highlight} macro for selective -% colour in units} -% If the \pkg{cancel} package is loaded, it is possible to -% \enquote{cancel out} units using the \cs{cancel} macro. This applies -% to the next unit, in a similar manner to a prefix. The \cs{highlight} -% macro is also available to selectively colour units. Both \cs{cancel} -% and \cs{highlight} are of course outside of the normal semantic -% meaning of units, but are provided as they may be useful in some -% cases. -%\begin{LaTeXdemo} -% \si[per-mode = fraction] -% {\cancel\kilogram\metre\per\cancel\kilogram\per\second} \\ -% \si{\highlight{red}\kilogram\metre\per\second} \\ -% \si[unit-color = purple] -% {\highlight{red}\kilogram\metre\per\second} -%\end{LaTeXdemo} -% -% When using the unit macros, the package is able to validate the -% input given. As part of this, stand-alone unit prefixes can be used -% with the \cs{si} macro -%\begin{LaTeXdemo} -% \si{\kilo} \\ -% \si{\micro} \\ -% \si[prefixes-as-symbols = false]{\kilo} -%\end{LaTeXdemo} -% However, the package only allows a single prefix to be used in this -% way: multiple prefixes will give an error, as will trying to give -% a number without a unit. So the following will raise errors: -%\begin{LaTeXdemo}[code only] -% \si{\kilo\gram\micro} \\ -% \SI{10}{\micro} -%\end{LaTeXdemo} -% -%\subsection{Creating new macros} -% -% The various macro components of a unit have to be defined before -% they can be used. The package supplies a number of common definitions, -% but new definitions are also possible. As the definition of a logical -% unit should remain the same in a single document, these creation -% functions are all preamble-only. -% -%\DescribeMacro{\DeclareSIUnit} -%\changes{v2.2}{2011/04/01}{Extend \cs{DeclareSIUnit} to take -% optional argument} -%\begin{syntax} -% \cs{DeclareSIUnit}\oarg{options}\marg{unit}\marg{symbol} -%\end{syntax} -% New units are produced using the \cs{DeclareSIUnit} macro. -% \meta{symbol} can contain literal input, other units, multiple -% prefixes, powers and \cs{per}, although literal text should not be -% intermixed with unit macros. Units can be created with \meta{options} -% from the usual list understood by \pkg{siunitx}, and apply the -% specific unit macro only. The (first) optional argument to \cs{SI} -% and \cs{si} can be used to override the settings for the unit. A -% typical example is the \cs{degree} unit. -%\begin{LaTeXdemo} -% \SI{3.1415}{\degree} -%\end{LaTeXdemo} -% This is declared in the package as: -%\begin{LaTeXdemo}[code only] -% \DeclareSIUnit[number-unit-product = {}] -% \degree{\SIUnitSymbolDegree} -%\end{LaTeXdemo} -% The spacing can still be altered at point of use: -%\begin{LaTeXdemo} -% \SI{67890}{\degree} \\ -% \SI[number-unit-product = \,]{67890}{\degree} -%\end{LaTeXdemo} -% The meaning of a pre-defined unit can be altered by using -% \cs{DeclareSIUnit} after loading \pkg{siunitx}. This will overwrite -% the original definition with the newer version. -% -%\DescribeMacro{\DeclareSIPrefix} -%\DescribeMacro{\DeclareBinaryPrefix} -%\begin{syntax} -% \cs{DeclareSIPrefix}\marg{prefix}\marg{symbol}\marg{powers-ten} -% \cs{DeclareBinaryPrefix}\marg{prefix}\marg{symbol}\marg{powers-two} -%\end{syntax} -% The standard SI powers of ten are defined by the package, and are -% described above. However, the user can define new prefixes with -% \cs{DeclareSIPrefix}. The \cs{DeclareBinaryPrefix} function is also -% available for creating binary prefixes, with the same syntax -% (\meta{powers-ten} being replaced by \meta{powers-two}). For -% example, \cs{kilo} and \cs{kibi} are defined: -%\begin{LaTeXdemo}[code only] -% \DeclareSIPrefix\kilo{k}{3} -% \DeclareBinaryPrefix\kibi{Ki}{10} -%\end{LaTeXdemo} -% -%\DescribeMacro{\DeclareSIPostPower} -%\DescribeMacro{\DeclareSIPrePower} -%\begin{syntax} -% \cs{DeclareSIPostPower}\marg{power}\marg{num} -% \cs{DeclareSIPrePower}\marg{power}\marg{num} -%\end{syntax} -% These create power macros to appear before or after the unit they -% apply to. For example, the preamble to a document might contain: -%\begin{LaTeXdemo}[code only] -% \DeclareSIPrePower\quartic{4} -% \DeclareSIPostPower\tothefourth{4} -%\end{LaTeXdemo} -% with the functions then used in the document as: -%\begin{LaTeXdemo} -% \si{\kilogram\tothefourth}\\ -% \si{\quartic\metre} -%\end{LaTeXdemo} -% -%\DescribeMacro{\DeclareSIQualifier} -% Following the syntax of the other macros, qualifiers are created -% with the syntax \cs{DeclareSIQualifier}\marg{qualifier}\marg{symbol}. -% In contrast to the other parts of a unit, there are no pre-defined -% qualifiers. It is therefore entirely up to the user to create these. -% For example, to identify the mass of a product created when using -% a particular catalyst, the preamble could contain: -%\begin{LaTeXdemo}[code only] -% \DeclareSIQualifier\polymer{pol} -% \DeclareSIQualifier\catalyst{cat} -%\end{LaTeXdemo} -% and then in the body the document could read: -%\begin{LaTeXdemo} -% \SI{1.234}{\gram\polymer\per\mole\catalyst\per\hour} -%\end{LaTeXdemo} -% -%\subsection{Tabular material} -% -% Aligning numbers in tabular content is handled by a new column -% type, the \texttt{S} column. This new column type can align material -% using a number of different strategies, with the aim of flexibility -% of output without needing to alter the input. The method used -% as standard is to place the decimal marker in the number at the -% centre of the cell and to align the material appropriately -% (\cref{tab:S:standard}). -% -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \caption{Standard behaviour of the \texttt{S} column type.} -% \label{tab:S:standard} -% \centering -% \begin{tabular}{S} -% \toprule -% {Some Values} \\ -% \midrule -% 2.3456 \\ -% 34.2345 \\ -% -6.7835 \\ -% 90.473 \\ -% 5642.5 \\ -% 1.2e3 \\ -% e4 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -% The \texttt{S} column will attempt to automatically detect -% material which should be placed before or after a number, and will -% maintain the alignment of the numerical data -% (\cref{tab:S:extras}). If the material could be mistaken for -% part of a number, it should be protected by braces. The use of -% \cs{color} in a table cell will also be detected and will override any -% general colour applied by \pkg{siunitx}. -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \caption{Detection of surrounding material in an \texttt{S} -% column.} -% \label{tab:S:extras} -% \centering -% \begin{tabular}{S[color=orange]} -% \toprule -% {Some Values} \\ -% \midrule -% 12.34 \\ -% \color{purple} 975,31 \\ -% 44.268 \textsuperscript{\emph{a}} \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\begin{function}{\tablenum} -% \begin{syntax} -% \cs{tablenum}\oarg{options}\marg{number} -% \end{syntax} -%\end{function} -%\changes{v2.2}{2011/03/20}{Add new \cs{tablenum} macro to allow -% complex table alignments} -%\changes{v2.2g}{2011/06/02}{Ensure \cs{tablenum} works correctly when -% \opt{parse-numbers} is set \opt{false}} -% Within more complex tables, aligned numbers may be desirable within -% the argument of \cs{multicolumn} or -% \cs{multirow}.\footnote{Provided by the \pkg{multirow} package} The -% \cs{tablenum} function is available to achieve alignment in these -% situations: this is, in effect, a macro version of the \texttt{S} macro -% (\cref{tab:tablenum}). -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \caption{Controlling complex alignment with the \cs{tablenum} -% macro.} -% \label{tab:tablenum} -% \centering -% \begin{tabular}{lr} -% \toprule -% Heading & Heading \\ -% \midrule -% Info & More info \\ -% Info & More info \\ -% \multicolumn{2}{c}{\tablenum[table-format = 4.4]{12,34}} \\ -% \multicolumn{2}{c}{\tablenum[table-format = 4.4]{333.5567}} \\ -% \multicolumn{2}{c}{\tablenum[table-format = 4.4]{4563.21}} \\ -% \bottomrule -% \end{tabular} -% \hfil -% \begin{tabular}{lr} -% \toprule -% Heading & Heading \\ -% \midrule -% \multirow{2}*{\tablenum{88,999}} & aaa \\ -% & bbb \\ -% \multirow{2}*{\tablenum{33,435}} & ccc \\ -% & ddd \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -% As a complement to the \texttt{S} column type, \pkg{siunitx} also provides -% a second column type, \texttt{s}. This is intended for producing -% columns of units. This allows both macro-based and explicit units to -% be printed easily (\cref{tab:s:demo}). -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \centering -% \caption{Units in tables.} -% \label{tab:s:demo} -% \begin{tabular}{s} -% \toprule -% \multicolumn{1}{c}{Unit} \\ -% \midrule -% \metre\squared\per\second \\ -% \pascal \\ -% m.s^{-1} \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -% As the \cs{si} macro can take literal or macro input, the \texttt{s} -% column cannot validate the input. \emph{Everything} in an \texttt{s} -% column is therefore passed to the \cs{si} macro for processing. To -% prevent this, you have to use \cs{multicolumn}, as is shown in -% \cref{tab:s:processing}. Notice that braces alone do not prevent -% processing and colouring of the cell contents. -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \centering -% \caption{The \texttt{s} column processes everything.} -% \label{tab:s:processing} -% \sisetup{color = orange} -% \begin{tabular}{ss} -% \toprule -% {Unit} & \multicolumn{1}{c}{Unit}\\ -% \midrule -% {\si{m^3}} & \multicolumn{1}{c}{\si{m^3}} \\ -% \kilogram & \kilogram \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\section{Comprehensive details of package control options} -% -%\subsection{The key--value control system} -% -%\DescribeMacro{\sisetup} -% The behaviour of the \pkg{siunitx} package is controlled by a -% number of key--value options. These can be given globally using -% the \cs{sisetup} function or locally as the optional argument to the -% user macros. -% -% The package uses a range of different key types: -%\begin{description} -% \item[\texttt{Choice}] Takes a limited number of choices, which -% are described separately for each key. -% \item[\texttt{Integer}] Requires a number as the argument. -% \item[\texttt{Length}] Requires a length, either as a literal -% value such as "2.0 cm", or stored as a \LaTeX{} length, or -% \TeX{} dimension. -% \item[\texttt{Literal}] A key which uses the value(s) given directly, -% either to check input (for example the \texttt{input-digits} key) -% or in output. -% \item[\texttt{Macro}] Requires a macro, which may need a single -% argument. -% \item[\texttt{Math}] Similar to a \texttt{literal} option, but the -% input is always used in math mode, irrespective of other -% \pkg{siunitx} settings. Thus to text-mode only input must be -% placed inside the argument of a \cs{text} macro. -% \item[\texttt{Meta}] These are options which actually apply -% a number of other options. As such, they do not take any -% value at all. -% \item[\texttt{Switch}] These are on--off switches, and recognise -% \opt{true} and \opt{false}. Giving just the key name also -% turns the key on. -%\end{description} -% The tables of option names use these descriptions to indicate how the -% keys should be used. -% -%\subsection{Detecting fonts} -% -% The \pkg{siunitx} package controls the font used to print output -% independently of the surrounding material. The standard method is to -% ignore the surroundings entirely, and to use the current body fonts. -% However, the package can detect and follow surrounding bold, italic -% and font family changes. The font detection options are summarised in -% \cref{tab:opt:font:det}. -%\begin{table} -% \centering -% \caption{Font detection options.} -% \label{tab:opt:font:det} -% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} -% \toprule -% \multicolumn{1}{l}{Option name} & -% Type & -% \multicolumn{1}{l}{Default} \\ -% \midrule -% detect-all & Meta & \meta{none} \\ -% detect-display-math & Switch & false \\ -% detect-family & Switch & false \\ -% detect-inline-family & Choice & text \\ -% detect-inline-weight & Choice & text \\ -% detect-mode & Switch & false \\ -% detect-none & Meta & \meta{none} \\ -% detect-shape & Switch & false \\ -% detect-weight & Switch & false \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -%\DescribeOption{detect-weight} -%\DescribeOption{detect-family} -%\DescribeOption{detect-shape} -%\DescribeOption{detect-mode} -%\changes{v2.0o}{2010/07/21}{Extend \opt{detect-italic} option -% to other shapes, renaming as \opt{detect-shape} as a result} -% The options \opt{detect-weight} and \opt{detect-shape} set detection -% of the prevailing font weight and font shape states, respectively. The -% font shape state is only checked if the surrounding material is not in -% math mode (as math text is always italic). The \opt{detect-shape} -% option is an extension of the older \opt{detect-italic} option, which -% is retained for backward compatibility. Detecting the current -% family (roman, sans serif or monospaced) is controlled by the -% \opt{detect-family} setting, while the current mode (text or math) -% is detected using the \opt{detect-mode} switch. -%\DescribeOption{detect-all} -%\DescribeOption{detect-none} -% For convenience, all of the preceding options can be turned on or -% off in one go using the \opt{detect-all} and \opt{detect-none} -% options. As the names indicate, \opt{detect-all} sets all -% of \opt{detect-weight}, \opt{detect-family}, \opt{detect-shape} -% and \opt{detect-mode} to \texttt{true}, while \opt{detect-none} -% sets all of them to \texttt{false}. -% -%\DescribeOption{detect-inline-family} -%\DescribeOption{detect-inline-weight} -%\changes{v2.1k}{2011/02/09}{Remove \opt{combined} choice for option -% \opt{detect-inline-weight}} -%\changes{v2.1k}{2011/02/09}{New option \opt{detect-inline-family}} -%\changes{v2.1l}{2011/02/10}{Error in font family detection introduced -% in v2.1k corrected} -% When \pkg{siunitx} macros are used in in-line math, the detection -% of font weight and font family can be tuned using the -% \opt{detect-inline-family} and \opt{detect-inline-weight} options. -% Both of these take the choices \opt{text} and \opt{math}. -%\begin{LaTeXdemo} -% \sisetup{ -% detect-family = true, -% detect-inline-family = math -% }% -% $\num{1234}$ \\ -% { \sffamily $\num{1234}$ } \\ -% $ \mathsf { \num{1234}} $ \\ -% \sisetup{detect-inline-family = text} -% { \sffamily $\num{1234}$ } \\ -% $ \mathsf { \num{1234} } $ \\ -% \sisetup{ -% detect-weight = true, -% detect-inline-weight = math -% }% -% $\num{5678}$ \\ -% { \boldmath $\num{5678}$ } \\ -% { \bfseries $\num{5678}$ } \\ -% \sisetup{detect-inline-weight = text} -% { \boldmath $\num{5678}$ } \\ -% { \bfseries $\num{5678}$ } -%\end{LaTeXdemo} -% -%\DescribeOption{detect-display-math} -% The font detection system can treat displayed mathematical content -% in two ways. This is controlled by the \opt{detect-display-math} -% option. When set \opt{true}, display mathematics is treated -% independently from the body of the document. Thus the local -% \emph{math} font is checked for matching. In contrast, when set -% \opt{false}, display material is treated with the current running -% text font.\footnote{Here, \enquote{display} math means either typeset -% in \TeX's display math mode or using the AMS display-like -% environments. Simply using \cs{displaystyle} will not make otherwise -% in line math be detected as display math.} -%\begin{LaTeXdemo} -% \sffamily -% Some text -% \sisetup{ -% detect-family, -% detect-display-math = true -% } -% \[ x = \SI{1.2e3}{\kilogram\kelvin\candela} \] -% More text -% \sisetup{detect-display-math = false} -% \[ y = \SI{3}{\metre\second\mole} \] -%\end{LaTeXdemo} -% -%\subsection{Font settings} -% -% The relationship between font family detected and font family used -% for output is not fixed. The font detected by the package in the -% surrounding material does not have to match that used for -% output (\cref{tab:opt:font:set}). -% -%\begin{table} -% \centering -% \caption{^^A -% Font options (also available as \opt{number-\ldots} and -% \opt{unit-\ldots} versions). -% } -% \label{tab:opt:font:set} -% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} -% \toprule -% \multicolumn{1}{l}{Option name} & -% Type & -% \multicolumn{1}{l}{Default} \\ -% \midrule -% color & Literal & \meta{none} \\ -% math-rm & Macro & \cs{mathrm} \\ -% math-sf & Macro & \cs{mathsf} \\ -% math-tt & Macro & \cs{mathtt} \\ -% mode & Choice & math \\ -% text-rm & Macro & \cs{rmfamily} \\ -% text-sf & Macro & \cs{sffamily} \\ -% text-tt & Macro & \cs{ttfamily} \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -%\DescribeOption{mode} -% The \opt{mode} option determines whether \pkg{siunitx} uses -% math or text mode when printing output. The choices are \opt{math} and -% \opt{text}. When using math mode, text is printed using a math font -% whereas in text mode a text font is used. The extent to which this is -% visually obvious depends on the fonts in use in the document. This -% manual uses old style (lower-case) figures in text mode to highlight -% the differences. This option has no effect if the \opt{detect-mode} -% switch is \opt{true}. -% -%\DescribeOption{math-rm} -%\DescribeOption{math-sf} -%\DescribeOption{math-tt} -%\DescribeOption{text-rm} -%\DescribeOption{text-sf} -%\DescribeOption{text-tt} -% If font family detection is inactive, \pkg{siunitx} uses the font -% family stored in either \opt{math-rm} or \opt{text-rm} for -% output. The choice of \opt{math} or \opt{text} depends on the -% \opt{mode} setting. If font family detection is active, -% \pkg{siunitx} may be using a sans serif or monospaced font for -% output. In math mode, these are stored in \opt{math-sf} and -% \opt{math-tt}, and for text mode in \opt{text-sf} and \opt{text-tt}. -% Notice that the detected and output font families can differ. -%\begin{LaTeXdemo} -% \sisetup{detect-family}% -% \num{1234} \\ -% { \sffamily \num{1234} } \\ -% \SI{99}{\metre} \\ -% \sisetup{math-rm = \mathtt}% -% \SI{99}{\metre} -%\end{LaTeXdemo} -% -%\DescribeOption{color} -% The colour of printed output can be set using the \opt{color} -% option. When no colour is given, printing follows the surrounding -% text. In contrast, when a specific colour is given, it is used -% irrespective of the surroundings. As there are a number of different -% colour models available, it is left to user to load \pkg{color} or -% a more powerful colour package such as \pkg{xcolor}. -%\begin{LaTeXdemo} -% \color{red} -% Some text \\ -% \SI{4}{\metre\per\sievert} \\ -% More text \\ -% \SI[color = blue]{4}{\metre\per\sievert} \\ -% Still red here! -%\end{LaTeXdemo} -% -% Every one of the font options can be given independently for units -% and number, with the prefixes \opt{unit-} and \opt{number-}, -% respectively. This allows fine control of output. -%\begin{LaTeXdemo} -% \SI{4}{\angstrom} \\ -% \SI[number-color = green]{4}{\angstrom} \\ -% \SI[unit-color = green]{4}{\angstrom} -%\end{LaTeXdemo} -% -%\subsection{Parsing numbers} -% -% The package uses a sophisticated parsing system to understand -% numbers. This allows \pkg{siunitx} to carry out a range of -% formatting, as described later. All of the input options take lists of -% literal tokens, and are summarised in \cref{tab:opt:num:in}. -% -%\begin{table} -% \centering -% \caption{Options for number parsing.} -% \label{tab:opt:num:in} -% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} -% \toprule -% \multicolumn{1}{l}{Option name} & -% Type & -% \multicolumn{1}{l}{Default} \\ -% \midrule ^^A ( -% input-close-uncertainty & Literal & ) \\ -% input-comparators & Literal & -% <=>\cs{approx}\cs{ge}\cs{geq} \\ -% & & \cs{gg}\cs{le}\cs{leq}\cs{ll} \cs{sim} \\ -% input-complex-roots & Literal & ij \\ -% input-decimal-markers & Literal & ., \\ -% input-digits & Literal & 0123456789 \\ -% input-exponent-markers & Literal & dDeE \\ -% input-ignore & Literal & \meta{none} \\ -% input-open-uncertainty & Literal & ( \\ ^^A ) -% input-protect-tokens & Literal & -% \cs{approx}\cs{dots}\cs{ge}\cs{geq}\cs{gg}\cs{le} \\ -% & & \cs{leq}\cs{ll}\cs{mp}\cs{pi}\cs{pm}\cs{sim} \\ -% input-signs & Literal & +-\cs{pm}\cs{mp} \\ -% input-uncertainty-signs & Literal & \cs{pm} \\ -% input-symbols & Literal & \cs{pi}\cs{dots} \\ -% parse-numbers & Switch & true \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -%\DescribeOption{input-digits} -%\DescribeOption{input-decimal-markers} -%\DescribeOption{input-signs} -%\DescribeOption{input-exponent-markers} -% The basic parts of a number are the digits, any sign and a separator -% between the integer and decimal parts. These are stored in the input -% options \opt{input-digits}, \opt{input-decimal-markers} and -% \opt{input-signs}, respectively. More than one input decimal marker -% can be used: it will be converted by the package to the appropriate -% output marker. Numbers which include an exponent part also require -% a marker for the exponent: this again is taken from the range of -% tokens in the \opt{input-exponent-markers} option. -% -%\DescribeOption{input-symbols} -%\DescribeOption{input-ignore} -% As well as \enquote{normal} digits, the package will interpret -% symbolic \enquote{numbers} (such as \cs{pi}) correctly if they are -% included in the \opt{input-symbols} list. Symbols are always -% printed in math mode. Tokens given in the \opt{input-ignore} list -% are totally passed over by \pkg{siunitx}: they will be removed from -% the input with no further processing. -% -%\DescribeOption{input-comparators} -%\changes{v2.1}{2010/10/26}{New \opt{input-comparators} option -% for numbers greater than, less than and so on} -% In addition to signs, \pkg{siunitx} can recognise comparators, such -% as \texttt{<}. The package will automatically carry out conversions -% for "<<", ">>", "<=" and ">=" to \cs{ll}, \cs{gg}, \cs{le} and -% \cs{ge}, respectively: -%\begin{LaTeXdemo} -% \num{< 10} \\ -% \SI{>> 5}{\metre} \\ -% \num{\le 0.12} -%\end{LaTeXdemo} -% -%\DescribeOption{input-open-uncertainty} -%\DescribeOption{input-close-uncertainty} -% In some fields, it is common to give the uncertainty in a number -% in brackets after the main part of the number, for example -% \enquote{\num{1.234(5)}}. The opening and closing symbols used for -% this type of input are set as \opt{input-open-uncertainty} and -% \opt{input-close-uncertainty}. -%\DescribeOption{input-uncertainty-signs} -%\changes{v2.2}{2011/04/03}{New \opt{input-uncertainty-signs} -% option} -% Alternatively, the uncertainty may be given as a separate part -% following a sign. Which signs are valid for this operation is -% determined by the \opt{input-uncertainty-signs} option. As with -% other signs, the combination \texttt{+-} will automatically be -% converted to \cs{pm} internally. -%\begin{LaTeXdemo} -% \num{9.99(9)} \\ -% \num{9.99 +- 0.09} \\ -% \num{9.99 \pm 0.09} \\ -% \num{123 +- 4.5} \\ -% \num{12.3 +- 6} -%\end{LaTeXdemo} -% -%\DescribeOption{input-complex-roots} -% When using complex numbers in input, the complex root -% \( ( \mathrm{i} = \sqrt{-1} \, ) \) is indicated by one of the tokens stored -% in \opt{input-complex-roots}. The parser understands complex root -% symbols given either before or after the associated number (but will -% detect any invalid arrangement): -%\begin{LaTeXdemo} -% \num{9.99 + 88.8i} \\ -% \num{9.99 + i88.8} -%\end{LaTeXdemo} -% -%\DescribeOption{input-protect-tokens} -% Some symbols can be problematic under expansion in \LaTeXe. To allow -% these to be used in input without issue, the package can protect these -% tokens while expanding input. Symbols to be protected in this way -% should be listed in \opt{input-protect-tokens}. -% -%\DescribeOption{parse-numbers} -% The \opt{parse-numbers} option turns the entire parsing system on -% and off. The option is made available for two reasons. First, if -% all of the numbers in a document are to be reproduced \enquote{as -% given}, turning off the parser will represent a significant saving in -% processing required. Second, it allows the use of arbitrary \TeX{} -% code in numbers. If the parser is turned off, the input will be -% printed in math mode (requiring \cs{text} to protect any text -% in the number). -%\begin{LaTeXdemo} -% \num[parse-numbers = false]{\sqrt{2}} \\ -% \SI[parse-numbers = false]{\sqrt{3}}{\metre} -%\end{LaTeXdemo} -% -%\subsection{Post-processing numbers} -% -% Before typesetting numbers, various post-processing steps can be -% carried out. These involve adding or removing information from the -% number in a systematic way; the options are summarised in -% \cref{tab:opt:num:post}. -% -%\begin{table} -% \centering -% \caption{Number post-processing options.} -% \label{tab:opt:num:post} -% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} -% \toprule -% \multicolumn{1}{l}{Option name} & -% Type & -% \multicolumn{1}{l}{Default} \\ -% \midrule -% add-decimal-zero & Switch & true \\ -% add-integer-zero & Switch & true \\ -% explicit-sign & Literal & \meta{none} \\ -% fixed-exponent & Integer & 0 \\ -% minimum-integer-digits & Integer & 0 \\ -% omit-uncertainty & Switch & false \\ -% retain-explicit-plus & Switch & false \\ -% retain-unity-mantissa & Switch & true \\ -% retain-zero-exponent & Switch & false \\ -% round-half & Choice & up \\ -% round-integer-to-decimal & Switch & false \\ -% round-minimum & Literal & 0 \\ -% round-mode & Choice & off \\ -% round-precision & Integer & 2 \\ -% scientific-notation & Switch & false \\ -% zero-decimal-to-integer & Switch & false \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -%\DescribeOption{round-mode} -%\DescribeOption{round-precision} -%\changes{v2.1n}{2011/03/31}{Set output to 0 when \opt{round-mode} -% is \opt{figures} and \opt{round-precision} is 0} -% The \pkg{siunitx} package can round numerical input to a fixed -% number of significant figures or decimal places. This is controlled by -% the \opt{round-mode} option, which takes the choices \opt{off}, -% \opt{figures} and \opt{places}. When rounding is turned on, the -% number of digits used (either decimal places or significant figures in -% the mantissa) is set using the \opt{round-precision} option. No rounding will -% take place if the number contains an uncertainty component. -%\begin{LaTeXdemo} -% \num{1.23456} \\ -% \num{14.23} \\ -% \num{0.12345(9)} \\ -% \sisetup{ -% round-mode = places, -% round-precision = 3 -% }% -% \num{1.23456} \\ -% \num{14.23} \\ -% \num{0.12345(9)} \\ -% \sisetup{ -% round-mode = figures, -% round-precision = 3 -% }% -% \num{1.23456} \\ -% \num{14.23} \\ -% \num{0.12345(9)} -%\end{LaTeXdemo} -%\DescribeOption{round-integer-to-decimal} -%\changes{v2.1}{2010/10/25}{New \opt{zero-integer-to-decimal} option -% to convert integers to decimals on rounding} -% The standard settings for \pkg{siunitx} do not add a decimal part -% if none was given in the input. The \opt{round-integer-to-decimal} -% option can be used to allow this conversion as part of the rounding -% process. -%\begin{LaTeXdemo} -% \num[round-mode = figures]{1} \\ -% \num[round-mode = places]{1} \\ -% \sisetup{round-integer-to-decimal} -% \num[round-mode = figures]{1} \\ -% \num[round-mode = places]{1} -%\end{LaTeXdemo} -% \DescribeOption{zero-decimal-to-integer} -% It may be desirable to convert decimals to integers if the decimal part is -% zero. This is set up using the \opt{zero-decimal-to-integer} option. -%\begin{LaTeXdemo} -% \num{2.0} \\ -% \num{2.1} \\ -% \sisetup{zero-decimal-to-integer} -% \num{2.0} \\ -% \num{2.1} -%\end{LaTeXdemo} -%\DescribeOption{round-minimum} -%\changes{v2.1}{2010/10/27}{New \opt{round-minimum} option -% to set a floor for rounding numbers downward} -% There are cases in which rounding will result in the number reaching -% zero. It may be desirable to show such results as below a threshold -% value. This can be achieved by setting \opt{round-minimum} to the -% threshold value. There will be no effect when rounding to a number of -% significant figures as it is not possible to obtain the value zero in -% these cases. -%\begin{LaTeXdemo} -% \sisetup{round-mode = places}% -% \num{0.0055} \\ -% \num{0.0045} \\ -% \sisetup{round-minimum = 0.01}% -% \num{0.0055} \\ -% \num{0.0045} -%\end{LaTeXdemo} -% \DescribeOption{round-half} -% \changes{v2.4}{2011/1/04}{New \opt{round-half} option} -% In cases where the rounded part of a number is exactly half, there are -% two common methods for \enquote{breaking the tie}. The choice of method -% is determined by the option \opt{round-half}, which recognises the -% choices \opt{up} and \opt{even}. -%\begin{LaTeXdemo} -% \sisetup{round-mode = places, round-half = up}% -% \num{0.055} \\ -% \num{0.045} \\ -% \sisetup{round-half = even}% -% \num{0.055} \\ -% \num{0.045} -%\end{LaTeXdemo} -% -%\DescribeOption{add-decimal-zero} -%\DescribeOption{add-integer-zero} -% It is possible to give real (floating point) numbers as input omitting -% the decimal or the integer parts of the number (for example \num{.123} -% or \num{123.}). The options \opt{add-decimal-zero} and -% \opt{add-integer-zero} allow the package to \enquote{fill in} the -% missing zero. -%\begin{LaTeXdemo} -% \num{123.} \\ -% \num{456} \\ -% \num{.789} \\ -% \sisetup{ -% add-decimal-zero = false, -% add-integer-zero = false, -% }% -% \num{123.} \\ -% \num{456} \\ -% \num{.789} -%\end{LaTeXdemo} -%\DescribeOption{minimum-integer-digits} -%\changes{v2.2}{2011/04/04}{New \opt{minimum-integer-digits} option} -% Related is the \opt{minimum-integer-digits} option. This applies -% only to the integer part of the mantissa, and ensures that it will -% contain at least the specified number of digits. This is achieved -% by padding with zeros if needed. -%\begin{LaTeXdemo} -% \num{123} \\ -% \num[minimum-integer-digits = 1]{123} \\ -% \num[minimum-integer-digits = 2]{123} \\ -% \num[minimum-integer-digits = 3]{123} \\ -% \num[minimum-integer-digits = 4]{123} -%\end{LaTeXdemo} -% -%\DescribeOption{explicit-sign} -%\DescribeOption{retain-explicit-plus} -% The inclusion of a leading plus sign is usually unnecessary for -% positive numbers, and so the \opt{retain-explicit-plus} option is -% available to control whether these are printed. At the same time, it -% may be useful to force all numbers to have a sign. This behaviour -% is controlled by the \opt{explicit-sign} option: this is used if -% given and if no sign was present in the input. -%\begin{LaTeXdemo} -% \num{+345} \\ -% \num[retain-explicit-plus]{+345} \\ -% \num[explicit-sign = -]{345} \\ -% \num[explicit-sign = -]{+345} -%\end{LaTeXdemo} -% -%\DescribeOption{retain-unity-mantissa} -%\DescribeOption{retain-zero-exponent} -% The retention of a zero exponent is controlled by the -% \opt{retain-zero-exponent} option. The retention of a mantissa of one -% is likewise controlled by the \opt{retain-unity-mantissa} option. -%\begin{LaTeXdemo} -% \num{1e4} \\ -% \num[retain-unity-mantissa = false]{1e4} \\ -% \num{444e0} \\ -% \num[retain-zero-exponent = true]{444e0} -%\end{LaTeXdemo} -% -%\DescribeOption{scientific-notation} -%\changes{v2.1}{2010/10/13}{New \opt{scientific-notation} option -% for to use exponent form for numbers in all cases} -%\changes{v2.2}{2011/04/04}{Extend \opt{scientific-notation} option -% to include \opt{engineering} mode} -%\DescribeOption{fixed-exponent} -% Numbers can be converted to scientific notation by the package. This -% is controlled by the \opt{scientific-notation} option, which takes -% choices \opt{false}, \opt{true}, \opt{fixed} and -% \opt{engineering}. The \opt{fixed} setting will use the exponent value -% by the \opt{fixed-exponent} option. When \opt{engineering} is set, -% the exponent is always a power of three. -%\begin{LaTeXdemo} -% \num{0.001} \\ -% \num{0.0100} \\ -% \num{1200} \\ -% \sisetup{scientific-notation = true}% -% \num{0.001} \\ -% \num{0.0100} \\ -% \num{1200} \\ -% \sisetup{scientific-notation = engineering}% -% \num{0.001} \\ -% \num{0.0100} \\ -% \num{1200} \\ -% \sisetup{ -% fixed-exponent = 2, -% scientific-notation = fixed, -% }% -% \num{0.001} \\ -% \num{0.0100} \\ -% \num{1200} -%\end{LaTeXdemo} -% When used with a \opt{fixed-exponent} of zero, this may be used to remove -% scientific notation from the input -%\begin{LaTeXdemo} -% \num{1.23e4} \\ -% \num[scientific-notation = fixed, fixed-exponent = 0]{1.23e4} -%\end{LaTeXdemo} -% Note that these options apply after any removal of unit mantissa, -% zero exponent, \emph{etc.} -% -% \DescribeOption{omit-uncertainty} -% The printing of an uncertainty can be suppressed entirely using the -% \opt{omit-uncertainty} option. -%\begin{LaTeXdemo} -% \num{0.01(2)} \\ -% \num[omit-uncertainty]{0.01(2)} -%\end{LaTeXdemo} -% -%\subsection{Printing numbers} -% -% Actually printing numbers is controlled by a number of settings, -% which apply ideas such as differing decimal markers, digit -% grouping and so on. All of these options are concerned with the -% appearance of output, rather than the data it conveys. The options are -% summarised in \cref{tab:opt:num:out}. -% -%\begin{table} -% \centering -% \caption{Output options for numbers.} -% \label{tab:opt:num:out} -% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} -% \toprule -% \multicolumn{1}{l}{Option name} & -% Type & -% \multicolumn{1}{l}{Default} \\ -% \midrule -% bracket-negative-numbers & Switch & false \\ -% bracket-numbers & Switch & true \\ ^^A ( -% close-bracket & Literal & ) \\ -% complex-root-position & Choice & after-number \\ -% copy-complex-root & Choice & false \\ -% copy-decimal-marker & Choice & false \\ -% exponent-base & Literal & 10 \\ -% exponent-product & Math & \verb=\times= \\ -% group-digits & Choice & true \\ -% group-minimum-digits & integer & 5 \\ -% group-separator & Literal & \cs{,} \\ -% negative-color & Literal & \meta{none} \\ -% open-bracket & Literal & ( -% \\ ^^A ) ( -% output-close-uncertainty & Literal & ) \\ -% output-complex-root & Literal & \verb=\ensuremath{\mathrm{i}}= \\ -% output-decimal-marker & Literal & . \\ -% output-exponent-marker & Literal & \meta{none} \\ -% output-open-uncertainty & Literal & ( \\ ^^A ) -% separate-uncertainty & Switch & false \\ -% tight-spacing & Switch & false \\ -% uncertainty-separator & Literal & \meta{none} \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -%\DescribeOption{group-digits} -%\changes{v2.2a}{2011/04/15}{Add missing default for \opt{group-digits} option} -% \changes{v2.3}{2011/06/06}{Extend \opt{group-digits} option, deprecating -% \opt{group-decimal-digits} and \opt{group-integer-digits}} -%\DescribeOption{group-four-digits} -%\DescribeOption{group-separator} -% Grouping digits into blocks of three is a common method to increase -% the ease of reading of numbers. The \opt{group-digits} choice controls -% whether this behaviour applies, and takes the values \opt{true}, \opt{false}, -% \opt{decimal} and \opt{integer}. Grouping can be activated separately for -% the integer and decimal parts of a number using the appropriately-named -% values. -%\begin{LaTeXdemo} -% \num{12345.67890} \\ -% \num[group-digits = false]{12345.67890} \\ -% \num[group-digits = decimal]{12345.67890} \\ -% \num[group-digits = integer]{12345.67890} -%\end{LaTeXdemo} -% The separator used between groups of digits is stored by the -% \opt{group-separator} option. This takes literal input and may be -% used in math mode: for a text-mode full space use |\text{~}|. -%\begin{LaTeXdemo} -% \num{12345} \\ -% \num[group-separator = {,}]{12345} \\ -% \num[group-separator = \text{~}]{12345} -%\end{LaTeXdemo} -% \DescribeOption{group-minimum-digits} -% \changes{v2.3}{2011/06/06}{New \opt{group-minimum-digits} option to -% replace \opt{group-four-digits}} -% Grouping is not always applied to smaller numbers, and the option -% \opt{group-minimum-digits} is available to specify how many digits must -% be present before grouping is applied. The number of digits is considered -% separately for the integer and decimal parts of the number: grouping -% does not \enquote{cross the boundary}. -%\begin{LaTeXdemo} -% \num{1234} \\ -% \num[group-minimum-digits = 4]{1234} \\ -% \num{1234.5678} \\ -% \num[group-minimum-digits = 4]{1234.5678} -%\end{LaTeXdemo} -% -%\DescribeOption{output-complex-root} -%\DescribeOption{output-decimal-marker} -%\DescribeOption{copy-complex-root} -%\changes{v2.1}{2010/10/02}{New \opt{copy-complex-root} option for -% moving input complex root to output} -%\DescribeOption{copy-decimal-marker} -% The decimal marker used in output is set using the -% \opt{output-decimal-marker} option. This can differ from the input -% marker, as can the root of $\sqrt{-1}$, which is stored in the -% \opt{output-complex-root} option. The standard setting uses \cs{mathrm} -% in math mode to give an upright -% \enquote{i}: this can easily be altered. The complex root or decimal -% marker from the input can be used in the output by setting the -% \opt{copy-complex-root} and \opt{copy-decimal-marker} options, -% respectively. -%\begin{LaTeXdemo} -% \num{1.23} \\ -% \num[output-decimal-marker = {,}]{1.23} \\ -% \num{1+2i} \\ -% \num[output-complex-root = \text{\ensuremath{i}}]{1+2i} \\ -% \num[output-complex-root = j]{1+2i} \\ -% \num[copy-complex-root]{1+2j} \\ -% \num[copy-decimal-marker]{555,555} -%\end{LaTeXdemo} -% -%\DescribeOption{complex-root-position} -% The position of the complex root can be adjusted to place it -% either before or after the associated numeral in a complex number -% using the \opt{complex-root-position} option. -%\begin{LaTeXdemo} -% \num{67-0.9i} \\ -% \num[complex-root-position = before-number]{67-0.9i} \\ -% \num[complex-root-position = after-number]{67-0.9i} -%\end{LaTeXdemo} -% -%\DescribeOption{exponent-base} -%\DescribeOption{exponent-product} -% When exponents are present in the input, the -% \opt{exponent-base} and \opt{exponent-product} options set the obvious -% parts of the output. Notice that the base is in the current mode, but -% the product sign is always in math mode. -%\begin{LaTeXdemo} -% \num[exponent-product = \times]{1e2} \\ -% \num[exponent-product = \cdot]{1e2} \\ -% \num[exponent-base = 2]{1e2} -%\end{LaTeXdemo} -%\DescribeOption{output-exponent-marker} -%\changes{v2.2}{2011/04/03}{New \opt{output-exponent-marker} option} -% Alternatively, if the \opt{output-exponent-marker} option is -% set then the value stored will be used in place of the normal -% product and base combination. This will normally be set up to -% ensure math or text mode. -%\begin{LaTeXdemo} -% \num[output-exponent-marker = \text{e}]{1e2} \\ -% \num[output-exponent-marker = \ensuremath{\mathrm{E}}]{1e2} -%\end{LaTeXdemo} -% -%\DescribeOption{separate-uncertainty} -%\DescribeOption{uncertainty-separator} -%\DescribeOption{output-open-uncertainty} -%\DescribeOption{output-close-uncertainty} -% When input is given including an uncertainty in a number, it can be -% printed either with the uncertainty in brackets or as a separate -% number. This behaviour is controlled by the -% \opt{separate-uncertainty} choice. If the uncertainty is given in -% brackets, a space may be added between the main number and the -% uncertainty: this is stored using the \opt{uncertainty-separator} -% option. The opening and closing brackets used are stored in -% \opt{output-open-uncertainty} and -% \opt{output-close-uncertainty}, respectively. -%\begin{LaTeXdemo} -% \num{1.234(5)} \\ -% \num[separate-uncertainty = true]{1.234(5)} \\ -% \sisetup{ -% output-open-uncertainty = [, -% output-close-uncertainty = ], -% uncertainty-separator = {\,} -% } -% \num{1.234(5)} -%\end{LaTeXdemo} -% Notice that \pkg{siunitx} correctly interprets uncertainties which -% cross the decimal marker position whether these are separated out -% or not. -%\begin{LaTeXdemo} -% \num{8.2(13)} \\ -% \num[separate-uncertainty]{8.2(13)} -%\end{LaTeXdemo} -% -%\DescribeOption{bracket-numbers} -%\DescribeOption{open-bracket} -%\DescribeOption{close-bracket} -% There are certain combinations of numerical input which can be -% ambiguous. This can be corrected by adding brackets in the appropriate -% place, and is controlled by the \opt{bracket-numbers} switch. The -% opening and closing brackets used are stored in \opt{open-bracket} and -% \opt{close-bracket}, respectively. Note that \opt{bracket-numbers} -% only applies to numbers without units: for numbers with units -% see the \opt{multi-part-units} option. -%\begin{LaTeXdemo} -% \num{1+2i e10} \\ -% \num[bracket-numbers = false]{1+2i e10} \\ -% \sisetup{ -% open-bracket = \{, -% close-bracket = \}, -% } -% \num{1+2i e10} -%\end{LaTeXdemo} -% -%\DescribeOption{negative-color} -% \pkg{siunitx} can detect negative mantissa values and alter print -% colour accordingly. This is disabled by setting the option to an empty -% value. -%\begin{LaTeXdemo} -% \num{-15673} \\ -% \num[negative-color = red]{-15673} -%\end{LaTeXdemo} -% -%\DescribeOption{bracket-negative-numbers} -%\changes{v2.2}{2011/04/02}{New \opt{bracket-negative-numbers} option} -% A common means to display negative numbers in financial situations -% is to place them in brackets. This can be carried out automatically -% using the \opt{bracket-negative-numbers} option. -%\begin{LaTeXdemo} -% \num{-15673} \\ -% \num[bracket-negative-numbers]{-15673} \\ -% \SI{-10}{\metre} \\ -% \SI[bracket-negative-numbers]{-10}{\metre} -%\end{LaTeXdemo} -% -%\DescribeOption{tight-spacing} -%\changes{v2.0y}{2010/10/09}{Error with \opt{tight-spacing} option -% and exponents corrected} -% Under some circumstances is may be desirable to \enquote{squeeze} -% the output spacing. This is turned on using the \opt{tight-spacing} -% switch, which compresses spacing where possible. -%\begin{LaTeXdemo} -% \num{1 \pm 2i e3} \\ -% \num[tight-spacing = true]{1 \pm 2i e3} -%\end{LaTeXdemo} -% -%\subsection{Multi-part numbers} -% -% \pkg{siunitx} recognises the idea of products and quotients in -% numbers, both with and without units. These multi-part numbers have -% a number of options affecting how they are processed. The options are -% summarised in \cref{tab:opt:num:multi}. -% -%\begin{table} -% \centering -% \caption{Multi-part number options.} -% \label{tab:opt:num:multi} -% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} -% \toprule -% \multicolumn{1}{l}{Option name} & -% Type & -% \multicolumn{1}{l}{Default} \\ -% \midrule ^^A ( -% fraction-function & Macro & \cs{frac} \\ -% input-product & Literal & x \\ -% input-quotient & Literal & / \\ -% output-product & Math & \verb=\times= \\ -% output-quotient & Literal & / \\ -% quotient-mode & Choice & symbol \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -%\DescribeOption{input-product} -%\DescribeOption{input-quotient} -% The options \opt{input-product} and \opt{input-quotient} contain the -% tokens used to determine if a number contains multiple parts. -%\begin{LaTeXdemo} -% \num{1 x 2 x 3} \\ -% \num{1e4 x 2(3) x 3/4} \\ -% \num[input-product=*]{4 * 5 * 6} \\ -% \num{ 1 / 2e4 } \\ -% \num{ 1e2 / 3e4 } -%\end{LaTeXdemo} -%\DescribeOption{output-product} -%\DescribeOption{output-quotient} -% The symbols used for printing products and quotients are stored using -% the options \opt{output-product} and \opt{output-quotient}. -%\begin{LaTeXdemo} -% \num[output-product = \cdot]{4.87 x 5.321 x 6.90545} \\ -% \num[output-quotient = \text{ div }]{1 / 2} -%\end{LaTeXdemo} -% -%\DescribeOption{quotient-mode} -% For quotients, there is the possibility to print output either using -% a slash, or using the \cs{frac} macro. This is controlled by the -% \opt{quotient} choice option, which takes values \opt{symbol} and -% \opt{fraction}. -%\begin{LaTeXdemo} -% \num{1 / 2e4} \\ -% \num[quotient-mode = fraction]{1 / 2e4} -%\end{LaTeXdemo} -% -%\DescribeOption{fraction-function} -% The function used when \opt{quotient-mode = fraction} is set is -% determined by the \opt{fraction-function} option. This should -% be set to a function which takes two arguments, and presumably -% creates some type of fraction. Most alternatives to the standard -% \cs{frac} function will involve loading additional packages: the -% demonstrations here need \pkg{amsmath} and -% \pkg{xfrac}. -%\begin{LaTeXdemo} -% \sisetup{quotient-mode = fraction} -% \num{1 / 1} -% \num[fraction-function = \dfrac]{1 / 2} -% \num[fraction-function = \sfrac]{1 / 3} -% \num[fraction-function = \tfrac]{1 / 4} -%\end{LaTeXdemo} -% -%\subsection{Lists and ranges of numbers} -% -% Lists and ranges of numbers have a small number of specialised -% options, which apply to these more unusual input forms -% (\cref{tab:opt:num:list}). -% -%\begin{table} -% \centering -% \caption{Output options for lists and ranges of numbers.} -% \label{tab:opt:num:list} -% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} -% \toprule -% \multicolumn{1}{l}{Option name} & -% Type & -% \multicolumn{1}{l}{Default} \\ -% \midrule -% list-final-separator & Literal & \verb*= and = \\ -% list-pair-separator & Literal & \verb*= and = \\ -% list-separator & Literal & \verb*=, = \\ -% range-phrase & Literal & \verb*= to = \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -% \DescribeOption{list-final-separator} -% \DescribeOption{list-pair-separator} -% \changes{v2.4}{2011/11/02}{New \opt{list-pair-separator} option} -% \DescribeOption{list-separator} -% Lists of numbers are printed with a separator between each item, -% which is stored using the \opt{list-separator} option. The -% separator before the last item of a list may be different, and -% is therefore set using the \opt{list-final-separator} option. -% The separator used for exactly two items is set using the -% \opt{list-pair-separator} option. Any -% spaces needed should be included in the option settings: none are -% added within the code. These items are printed in text mode. -%\begin{LaTeXdemo} -% \numlist{0.1;0.2;0.3} \\ -% \numlist[list-separator = {; }]{0.1;0.2;0.3} \\ -% \numlist[list-final-separator = {, }]{0.1;0.2;0.3} \\ -% \numlist[ -% list-separator = { and }, -% list-final-separator = { and finally } -% ]{0.1;0.2;0.3} \\ -% \numlist{0.1;0.2} \\ -% \numlist[list-pair-separator = {, and }]{0.1;0.2} -%\end{LaTeXdemo} -% -%\DescribeOption{range-phrase} -% Ranges of numbers can be given as input. These will have an -% appropriate word or symbol inserted between the two entries: this -% is stored using the \opt{range-phrase} option. The phrase should -% include any necessary spaces: no extra space is added. -%\begin{LaTeXdemo} -% \numrange{5}{100} \\ -% \numrange[range-phrase = --]{5}{100} -%\end{LaTeXdemo} -% -% \changes{v2.4}{2011/11/04}{Automatically compress exponents for lists and -% ranges when fixed exponents are active} -% For lists and ranges when a single unit is given, \pkg{siunitx} will -% automatically \enquote{compress} exponents when a fixed exponent is in -% use. -%\begin{LaTeXdemo} -% \sisetup{ -% fixed-exponent = 3 , -% list-units = brackets , -% range-units = brackets , -% scientific-notation = fixed -% }% -% \SIrange{1e3}{7e3}{\metre} \\ -% \SIlist{1e3;2e3;3e3}{\kg} -%\end{LaTeXdemo} -% -%\subsection{Angles} -% -% Angle processing provided by the \cs{ang} function has a set of -% options which apply in addition to the general ones set up for number -% processing (\cref{tab:opt:ang}). -% -%\begin{table} -% \centering -% \caption{Angle options.} -% \label{tab:opt:ang} -% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} -% \toprule -% \multicolumn{1}{l}{Option name} & -% Type & -% \multicolumn{1}{l}{Default} \\ -% \midrule -% add-arc-degree-zero & Switch & false \\ -% add-arc-minute-zero & Switch & false \\ -% add-arc-second-zero & Switch & false \\ -% angle-symbol-over-decimal & Switch & false \\ -% arc-separator & Literal & \meta{empty} \\ -% number-angle-product & Literal & \meta{empty} \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -%\DescribeOption{number-angle-product} -% The separator between the number and angle symbol (degrees, minutes -% or seconds) can be set using the \opt{number-angle-product} -% option, independent of the related \opt{number-unit-product} -% option used by the \cs{SI} function. -%\begin{LaTeXdemo} -% \ang{2.67} \\ -% \ang[number-angle-product = \,]{2.67} -%\end{LaTeXdemo} -% -%\DescribeOption{arc-separator} -% When angles are printed in arc format, the separation of the different -% parts is set up using the \opt{arc-separator} option. -%\begin{LaTeXdemo} -% \ang{6;7;6.5} \\ -% \ang[arc-separator = \,]{6;7;6.5} -%\end{LaTeXdemo} -% -%\DescribeOption{add-arc-degree-zero} -%\DescribeOption{add-arc-minute-zero} -%\DescribeOption{add-arc-second-zero} -% Zero-filling for the degree, minute or second parts of an arc is -% controlled using the \opt{add-arc-degree-zero}, -% \opt{add-arc-minute-zero} and \opt{add-arc-second-zero} options. -% All are off as standard. -%\begin{LaTeXdemo} -% \ang{-1;;} \\ -% \ang{;-2;} \\ -% \ang{;;-3} \\ -% \sisetup{add-arc-degree-zero} -% \ang{-1;;} \\ -% \ang{;-2;} \\ -% \ang{;;-3} \\ -% \sisetup{add-arc-minute-zero} -% \ang{-1;;} \\ -% \ang{;-2;} \\ -% \ang{;;-3} \\ -% \sisetup{add-arc-second-zero} -% \ang{-1;;} \\ -% \ang{;-2;} \\ -% \ang{;;-3} -%\end{LaTeXdemo} -% -%\DescribeOption{angle-symbol-over-decimal} -% In some subject areas, most notably astronomy, the angle symbols -% are given over the decimal marker, rather than at the end of the -% number. This behaviour is available using the -% \opt{angle-symbol-over-decimal} option. -%\begin{LaTeXdemo} -% \ang{45.697} \\ -% \ang{6;7;6.5} \\ -% \ang[angle-symbol-over-decimal]{45.697} \\ -% \ang[angle-symbol-over-decimal]{6;7;6.5} -%\end{LaTeXdemo} -% -%\subsection{Creating units} -%\label{sec:units:creating} -% -% The various macro units are created at the start of the document. -% \pkg{siunitx} can define these such that they are only available for -% use within the \cs{si} and \cs{SI} functions, or can make the unit -% macros available throughout the document body. There are a number of -% settings which control this creation process -% (\cref{tab:opt:units:def}). As a result, these options all apply -% in the preamble only. -% -%\begin{table} -% \centering -% \caption{Unit creation options.} -% \label{tab:opt:units:def} -% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} -% \toprule -% \multicolumn{1}{l}{Option name} & -% Type & -% \multicolumn{1}{l}{Default} \\ -% \midrule ^^A ( -% free-standing-units & Switch & false \\ -% overwrite-functions & Switch & false \\ -% space-before-unit & Switch & false \\ -% unit-optional-argument & Switch & false \\ -% use-xspace & Switch & false \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -%\DescribeOption{free-standing-units} -%\changes{v2.1d}{2010/11/14}{Apply unit options when -% \opt{free-standing-units} is active} -%\changes{v2.1e}{2010/11/22}{Further corrections when applying unit -% options when \opt{free-standing-units} is active} -%\DescribeOption{overwrite-functions} -% The \opt{free-standing-units} option controls whether the unit macros -% exist outside of the \cs{si} and \cs{SI} arguments. When this option -% is \opt{true}, \pkg{siunitx} creates the macros for general use. -% The standard method to achieve this does not overwrite any existing -% macros: this behaviour can be altered using the -% \opt{overwrite-functions} switch. -% -%\DescribeOption{space-before-unit} -%\DescribeOption{unit-optional-argument} -%\changes{v2.1f}{2010/11/24}{Typo in definition for -% \opt{unit-optional-argument} implementation corrected} -%\DescribeOption{use-xspace} -% When \enquote{free standing} unit macros are created, their behaviour -% can be adjusted by a number of options. These are mainly intended for -% emulating the input syntax of older packages. The option -% \opt{unit-optional-argument} gives the same behaviour for the -% inputs -%\begin{LaTeXdemo}[code only] -% \SI{10}{\metre} -%\end{LaTeXdemo} -% and -%\begin{LaTeXdemo}[code only] -% \metre[10]. -%\end{LaTeXdemo} -% The \opt{space-before-unit} and \opt{use-xspace} options control -% the behaviour at the \enquote{ends} of the unit macros. Activating -% \opt{space-before-unit} inserts the number--unit space before the -% unit is printed. This is suitable for the input syntax -%\begin{LaTeXdemo}[code only] -% 30\metre -%\end{LaTeXdemo} -% but does mean that the unit macros are incorrectly spaced in running -% text. On the other hand, the \opt{use-xspace} option attempts to -% correctly space input such as -%\begin{LaTeXdemo}[code only] -% \metre is the symbol for metres. -%\end{LaTeXdemo} -% -%\subsection{Loading additional units} -% -% \DescribeOption{abbreviations} -% As standard, \pkg{siunitx} loads a set of abbreviated versions of the -% SI units (\cref{tab:unit:abbr}). The standard \pkg{siunitx} settings only -% create these abbreviations within the scope of the \cs{si} and \cs{SI} -% functions, meaning that no clashes should occur (for example with the -% standard \cs{pm} symbol). Loading of these abbreviations can be prevented -% by setting the option \opt{abbreviations = false} in the preamble. -% -%\begin{center} -% \changes{v2.0n}{2010/07/15}{More abbreviated units} -% \changes{v2.3b}{2011/07/27}{More abbreviated units} -% \tablecaption{Abbreviated units.} -% \label{tab:unit:abbr} -% \tablefirsthead{^^A -% \toprule -% \multicolumn{1}{l}{Unit} & -% \multicolumn{1}{l}{Abbreviation} & -% \multicolumn{1}{l}{Symbol} \\ -% \midrule -% } -% \tablehead{^^A -% \multicolumn{3}{l}{\emph{Continued from previous page}} \\ -% \toprule -% \multicolumn{1}{l}{Unit} & -% \multicolumn{1}{l}{Abbreviation} & -% \multicolumn{1}{l}{Symbol} \\ -% \midrule -% } -% \tabletail{^^A -% \bottomrule -% \multicolumn{3}{r}{\emph{Continued on next page}} \\ -% } -% \tablelasttail{\bottomrule} -% \begin{xtabular}{lcc} -% \DescribeNamedUnit{femtogram}{fg} \\ -% \DescribeNamedUnit{picogram}{pg} \\ -% \DescribeNamedUnit{nanogram}{ng} \\ -% \DescribeNamedUnit{microgram}{ug} \\ -% \DescribeNamedUnit{milligram}{mg} \\ -% \DescribeNamedUnit{gram}{g} \\ -% \DescribeNamedUnit{kilogram}{kg} \\ -% \DescribeNamedUnit{atomic mass unit}{amu} \\ -% -% \midrule -% -% \DescribeNamedUnit{picometre}{pm} \\ -% \DescribeNamedUnit{nanometre}{nm} \\ -% \DescribeNamedUnit{micrometre}{um} \\ -% \DescribeNamedUnit{millimetre}{mm} \\ -% \DescribeNamedUnit{centimetre}{cm} \\ -% \DescribeNamedUnit{decimetre}{dm} \\ -% \DescribeNamedUnit{metre}{m} \\ -% \DescribeNamedUnit{kilometre}{km} \\ -% -% \midrule -% -% \DescribeNamedUnit{attosecond}{as} \\ -% \DescribeNamedUnit{femtosecond}{fs} \\ -% \DescribeNamedUnit{picosecond}{ps} \\ -% \DescribeNamedUnit{nanosecond}{ns} \\ -% \DescribeNamedUnit{microsecond}{us} \\ -% \DescribeNamedUnit{millisecond}{ms} \\ -% \DescribeNamedUnit{second}{s} \\ -% -% \midrule -% -% \DescribeNamedUnit{femtomole}{fmol} \\ -% \DescribeNamedUnit{picomole}{pmol} \\ -% \DescribeNamedUnit{nanomole}{nmol} \\ -% \DescribeNamedUnit{micromole}{umol} \\ -% \DescribeNamedUnit{millimole}{mmol} \\ -% \DescribeNamedUnit{mole}{mol} \\ -% \DescribeNamedUnit{kilomole}{kmol} \\ -% -% \midrule -% -% \DescribeNamedUnit{picoampere}{pA} \\ -% \DescribeNamedUnit{nanoampere}{nA} \\ -% \DescribeNamedUnit{microampere}{uA} \\ -% \DescribeNamedUnit{milliampere}{mA} \\ -% \DescribeNamedUnit{ampere}{A} \\ -% \DescribeNamedUnit{kiloampere}{kA} \\ -% -% \midrule -% -% \DescribeNamedUnit{microlitre}{ul} \\ -% \DescribeNamedUnit{millilitre}{ml} \\ -% \DescribeNamedUnit{litre}{l} \\ -% \DescribeNamedUnit{hectolitre}{hl} \\ -% \DescribeNamedUnit{microliter}{uL} \\ -% \DescribeNamedUnit{milliliter}{mL} \\ -% \DescribeNamedUnit{liter}{L} \\ -% \DescribeNamedUnit{hectoliter}{hL} \\ -% -% \midrule -% -% \DescribeNamedUnit{millihertz}{mHz} \\ -% \DescribeNamedUnit{hertz}{Hz} \\ -% \DescribeNamedUnit{kilohertz}{kHz} \\ -% \DescribeNamedUnit{megahertz}{MHz} \\ -% \DescribeNamedUnit{gigahertz}{GHz} \\ -% \DescribeNamedUnit{terahertz}{THz} \\ -% -% \midrule -% -% \DescribeNamedUnit{millinewton}{mN} \\ -% \DescribeNamedUnit{newton}{N} \\ -% \DescribeNamedUnit{kilonewton}{kN} \\ -% \DescribeNamedUnit{meganewton}{MN} \\ -% -% \midrule -% -% \DescribeNamedUnit{pascal}{Pa} \\ -% \DescribeNamedUnit{kilopascal}{kPa} \\ -% \DescribeNamedUnit{megapacal}{MPa} \\ -% \DescribeNamedUnit{gigapascal}{GPa} \\ -% -% \midrule -% -% \DescribeNamedUnit{milliohm}{mohm} \\ -% \DescribeNamedUnit{kilohm}{kohm} \\ -% \DescribeNamedUnit{megohm}{Mohm} \\ -% -% \midrule -% -% \DescribeNamedUnit{picovolt}{pV} \\ -% \DescribeNamedUnit{nanovolt}{nV} \\ -% \DescribeNamedUnit{microvolt}{uV} \\ -% \DescribeNamedUnit{millivolt}{mV} \\ -% \DescribeNamedUnit{volt}{V} \\ -% \DescribeNamedUnit{kilovolt}{kV} \\ -% -% \midrule -% -% \DescribeNamedUnit{watt}{W} \\ -% \DescribeNamedUnit{microwatt}{uW} \\ -% \DescribeNamedUnit{milliwatt}{mW} \\ -% \DescribeNamedUnit{kilowatt}{kW} \\ -% \DescribeNamedUnit{megawatt}{MW} \\ -% \DescribeNamedUnit{gigawatt}{GW} \\ -% \DescribeNamedUnit{joule}{J} \\ -% \DescribeNamedUnit{microjoule}{uJ} \\ -% \DescribeNamedUnit{millijoule}{mJ} \\ -% \DescribeNamedUnit{kilojoule}{kJ} \\ -% \DescribeNamedUnit{electronvolt}{eV} \\ -% \DescribeNamedUnit{millielectronvolt}{meV} \\ -% \DescribeNamedUnit{kiloelectronvolt}{keV} \\ -% \DescribeNamedUnit{megaelectronvolt}{MeV} \\ -% \DescribeNamedUnit{gigaelectronvolt}{GeV} \\ -% \DescribeNamedUnit{teraelectronvolt}{TeV} \\ -% \DescribeNamedUnit{kilowatt hour}{kWh} \\ -% -% \midrule -% -% \DescribeNamedUnit{farad}{F} \\ -% \DescribeNamedUnit{femtofarad}{fF} \\ -% \DescribeNamedUnit{picofarad}{pF} \\ -% -% \midrule -% -% \DescribeNamedUnit{kelvin}{K} \\ -% -% \midrule -% -% \DescribeNamedUnit{decibel}{dB} \\ -% -% \end{xtabular} -%\end{center} -% -% \DescribeOption{binary-units} -% \DescribeMacro{\bit} -% \DescribeMacro{\byte} -% Binary data is expressed in units of bits and bytes. These are -% normally given prefixes which use powers of two, rather than the -% powers of ten used by the SI prefixes. As these binary prefixes are -% closely related to the SI prefixes, they are defined by \pkg{siunitx} -% but do have to be loaded using \opt{binary-units = true} (or -% simply \opt{binary-units}) -% (\cref{tab:unit:binary}). The units \cs{bit} and \cs{byte} are -% then also available. -%\begin{LaTeXdemo} -% \SI{100}{\mebi\byte} \\ -% \SI[prefixes-as-symbols=false]{30}{\kibi\bit} -%\end{LaTeXdemo} -% -%\begin{table} -% \caption{Binary prefixes.} -% \label{tab:unit:binary} -% \centering -% \begin{tabular}{llc>{$}l<{$}} -% \toprule -% Prefix & Macro & Symbol & \multicolumn{1}{l}{Power} \\ -% \midrule -% \DescribePrefix{kibi} & 10 \\ -% \DescribePrefix{mebi} & 20 \\ -% \DescribePrefix{gibi} & 30 \\ -% \DescribePrefix{tebi} & 40 \\ -% \DescribePrefix{pebi} & 50 \\ -% \DescribePrefix{exbi} & 60 \\ -% \DescribePrefix{zebi} & 70 \\ -% \DescribePrefix{yobi} & 80 \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -% \DescribeOption{version-1-compatibility} -% A configuration file is also included which will use settings -% and define macros as defined by version 1 of \pkg{siunitx}: this -% can be accessed with the option \opt{version-1-compatibility}. -% This is intended to allow easy transition to version 2: users -% should update their source to use the new interfaces and functions. -% -% Users upgrading from version 1 of \pkg{siunitx} will notice that -% the various \enquote{specialist} units available in version 1 are -% no longer provided as loadable options.\footnote{They are included -% in the loaded configuration file \opt{version-1}, but this is intended -% purely to ease transition to version 2.} These are not included in -% version 2 as the criteria for inclusion of such units are far from -% clear, and it is difficult to justify providing clearly non-SI -% units in the package. For reference, appropriate definitions for -% the units which where provided in version 1 are as follows. -%\begin{LaTeXdemo}[code only] -% % Astronomy -% \DeclareSIUnit\parsec{pc} -% \DeclareSIUnit\lightyear{ly} -% -% % Chemical engineering -% \DeclareSIUnit\gmol{g\text{-}mol} -% \DeclareSIUnit\kgmol{kg\text{-}mol} -% \DeclareSIUnit\lbmol{lb\text{-}mol} -% -% % Chemistry -% \DeclareSIUnit\molar{\mole\per\cubic\deci\metre} -% \DeclareSIUnit\Molar{\textsc{m}} -% \DeclareSIUnit\torr{torr} -% -% % Geophysics -% \DeclareSIUnit\gon{gon} -% -% % High energy physics -% \DeclareSIUnit\micron{\micro\metre} -% \DeclareSIUnit\mrad{\milli\rad} -% \DeclareSIUnit\gauss{G} -% \DeclareSIUnit\eVperc{\eV\per\clight} -% \DeclareSIUnit\nanobarn{\nano\barn} -% \DeclareSIUnit\picobarn{\pico\barn} -% \DeclareSIUnit\femtobarn{\femto\barn} -% \DeclareSIUnit\attobarn{\atto\barn} -% \DeclareSIUnit\zeptobarn{\zepto\barn} -% \DeclareSIUnit\yoctobarn{\yocto\barn} -% \DeclareSIUnit\nb{\nano\barn} -% \DeclareSIUnit\pb{\pico\barn} -% \DeclareSIUnit\fb{\femto\barn} -% \DeclareSIUnit\ab{\atto\barn} -% \DeclareSIUnit\zb{\zepto\barn} -% \DeclareSIUnit\yb{\yocto\barn} -%\end{LaTeXdemo} -% Users can use a local configuration file to make additional units -% available on a local basis, as described in \cref{sec:config:local}. -% -%\subsection{Using units} -% -% Part of the power of \pkg{siunitx} is the ability to alter the output -% format for units without changing the input. The behaviour of units -% is therefore controlled by a number of options which alter either the -% processing of units or the output directly -% (\cref{tab:opt:units:out}). -% -%\begin{table} -% \centering -% \caption{Unit output options.} -% \label{tab:opt:units:out} -% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} -% \toprule -% \multicolumn{1}{l}{Option name} & -% Type & -% \multicolumn{1}{l}{Default} \\ -% \midrule -% bracket-unit-denominator & Switch & true \\ -% forbid-literal-units & Switch & false \\ -% literal-superscript-as-power & Switch & true \\ -% inter-unit-product & Literal & \cs{,} \\ -% parse-units & Switch & true \\ -% per-mode & Choice & reciprocal \\ -% per-symbol & Literal & / \\ -% power-font & Choice & number \\ -% prefixes-as-symbols & Switch & true \\ -% qualifier-mode & Choice & subscript \\ -% sticky-per & Switch & false \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -%\DescribeOption{forbid-literal-units} -% Some users may prefer to completely disable the use of literal input -% in units, for example to enforce consistency. This can be -% accomplished by setting the \opt{forbid-literal-units} switch. With -% this option enabled, only macro-based units can be used in a document. -% -%\DescribeOption{inter-unit-product} -% The separator between each unit is stored using the -% \opt{inter-unit-product} option. The standard setting is a thin -% space: another common choice is a centred dot. To get the correct -% spacing it is necessary to use |\ensuremath{{}\cdot{}}| in the latter case. -%\begin{LaTeXdemo} -% \si{\farad\squared\lumen\candela} \\ -% \si[inter-unit-product = \ensuremath{{}\cdot{}}] -% {\farad\squared\lumen\candela} -%\end{LaTeXdemo} -% -%\DescribeOption{per-mode} -%\changes{v2.1i}{2011/01/27}{Improved logic for \opt{per-mode} setting -% \opt{symbol-or-fraction}} -%\changes{v2.2}{2011/04/05}{Include leading \( 1 \) when \opt{per-mode} -% is set to \opt{symbol} and there are no numerator units in \cs{si} -% arguments} -%\DescribeOption{per-symbol} -%\DescribeOption{bracket-unit-denominator} -% The handling of \cs{per} is altered using the \opt{per-mode} choice -% option. The standard setting is \opt{reciprocal}, meaning that -% \cs{per} generates reciprocal powers for units. Setting the option -% to \opt{fraction} uses the \cs{frac} function to typeset the positive -% and negative powers of a unit separately. -%\begin{LaTeXdemo} -% \si{\joule\per\mole\per\kelvin} \\ -% \si{\metre\per\second\squared} \\ -% \si[per-mode=fraction]{\joule\per\mole\per\kelvin} \\ -% \si[per-mode=fraction]{\metre\per\second\squared} -%\end{LaTeXdemo} -% The closely-related \opt{reciprocal-positive-first} setting acts in -% the same way but places all of the positive powers before any negative -% ones. -%\begin{LaTeXdemo} -% \si{\ampere\per\mole\second} \\ -% \si[per-mode = reciprocal-positive-first] -% {\ampere\per\mole\second} -%\end{LaTeXdemo} -% It is possible to use a symbol (usually \texttt{/}) to separate the -% two parts of a unit by setting \opt{per-mode} to \opt{symbol}; the -% symbol used is stored using the setting \opt{per-symbol}. This method -% for displaying units can be ambiguous, and so brackets are added -% unless \opt{bracket-unit-denominator} is set to \opt{false}. -% Notice that \opt{bracket-unit-denominator} only applies when -% \opt{per-mode} is set to \opt{symbol} or \opt{symbol-or-fraction}. -%\begin{LaTeXdemo} -% \sisetup{per-mode = symbol}% -% \si{\joule\per\mole\per\kelvin} \\ -% \si{\metre\per\second\squared} \\ -% \si[per-symbol = \text{~div~}]{\joule\per\mole\per\kelvin} \\ -% \si[bracket-unit-denominator = false]{\joule\per\mole\per\kelvin} -%\end{LaTeXdemo} -% The often-requested (but mathematically invalid) -% \opt{repeated-symbol} option is also available to repeat the symbol -% for each \cs{per}. -%\begin{LaTeXdemo} -% \si[per-mode=repeated-symbol]{\joule\per\mole\per\kelvin} -%\end{LaTeXdemo} -% Finally, it is possible for the behaviour of the \cs{per} function -% to depend on the prevailing math style. Setting \opt{per-mode} to -% \opt{symbol-or-fraction} will use the \opt{symbol} setting for -% in line math, and the \opt{fraction} setting when used in -% \cs{displaystyle} math. -%\begin{LaTeXdemo} -% \sisetup{per-mode = symbol-or-fraction}% -% \( \si{\joule\per\mole\per\kelvin} \) -% \[ \si{\joule\per\mole\per\kelvin} \] -% \si{\joule\per\mole\per\kelvin} \\ -% \( -% \displaystyle -% \si{\joule\per\mole\per\kelvin} -% \) -% \[ -% \textstyle -% \si{\joule\per\mole\per\kelvin} -% \] -%\end{LaTeXdemo} -% -%\DescribeOption{sticky-per} -% By default, \cs{per} applies only to the next unit -% given.\footnote{This is the standard method of reading units in -% English: for example, \si{\joule\per\mole\per\kelvin} is pronounced -% \enquote{joules per mole per kelvin}.} By setting the -% \opt{sticky-per} flag, this behaviour is changed so that \cs{per} -% applies to all subsequent units. -%\begin{LaTeXdemo} -% \si{\pascal\per\gray\henry} \\ -% \si[sticky-per]{\pascal\per\gray\henry} -%\end{LaTeXdemo} -% -%\DescribeOption{power-font} -%\changes{v2.1}{2010/10/12}{New \opt{power-font} option for controlling -% whether superscript powers are treated as numbers or units} -% The font used for the powers in units can be typeset using the -% current number or unit font. This may be of use when the font used -% for numbers and units are very different, for example when the -% \pkg{euler} package is loaded. Note that this setting applies to all -% printing options for numbers, including the color used for displaying -% the number. -%\begin{LaTeXdemo} -% \si{\metre\per\second\squared} \\ -% \si[power-font = unit]{\metre\per\second\squared} -%\end{LaTeXdemo} -% \DescribeOption{literal-superscript-as-power} -% \changes{v2.3}{2011/06/08}{New \opt{literal-superscript-as-power} option for -% controlling how literal units superscripts behave} -% When printing units in \enquote{literal} mode, it is possible that simply -% printing superscripts \enquote{as is} may lead to poor appearance for the -% numbers. This is most likely if the text font of the document uses -% old style (lower case) numerals, but the math font uses lining (upper -% case) numerals. It is therefore possible to treat superscripts within -% literal units as powers, and thus for the \opt{power-font} option to -% apply within these literal units. This behaviour is controlled using the -% \opt{literal-superscript-as-power} switch. -%\begin{LaTeXdemo} -% \si{m.s^{2}} \\ -% \si[literal-superscript-as-power = false]{m.s^{2}} -%\end{LaTeXdemo} -% -%\DescribeOption{qualifier-mode} -%\changes{v2.1c}{2010/11/13}{New \opt{text} choice for -% \opt{qualifier-mode} option} -% \DescribeOption{qualifier-phrase} -% Unit qualifiers can be printed in three different formats, set by the -% \opt{qualifier-mode} option. The standard setting is \opt{subscript}, -% while the options \opt{brackets}, \opt{phrase}, \opt{space} and \opt{text} -% are also possible. With the last settings, powers can lead to ambiguity and -% are automatically detected and brackets added as appropriate. -%\begin{LaTeXdemo} -% \si{\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ -% \si[qualifier-mode = brackets] -% {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ -% \si[qualifier-mode = subscript] -% {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ -% \si[qualifier-mode = space] -% {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ -% \si[qualifier-mode = text] -% {\deci\bel\isotropic} -%\end{LaTeXdemo} -% The \opt{phrase} setting for \opt{qualifier-mode} uses the text stored using -% \opt{qualifier-phrase} to separate the qualifier. -%\begin{LaTeXdemo} -% \si[qualifier-mode = phrase] -% {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ -% \si[qualifier-mode = phrase, qualifier-phrase = { by }] -% {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ -%\end{LaTeXdemo} -% -%\DescribeOption{prefixes-as-symbols} -% The unit prefixes (\cs{kilo}, \emph{etc}.) are normally given as -% letters. However, the package can convert these into numerical powers. -% This is controlled by the \opt{prefixes-as-symbols} switch option. -% This correctly deals with the kilogram, which is a base unit even -% though it involves a prefix. -%\begin{LaTeXdemo} -% \si{\milli\litre\per\mole\deci\ampere} \\ -% \SI{10}{\kilo\gram\squared\deci\second} \\ -% \si[prefixes-as-symbols=false]{\milli\litre\per\mole\deci\ampere}\\ -% \SI[prefixes-as-symbols=false]{10}{\kilo\gram\squared\deci\second} -%\end{LaTeXdemo} % -%\DescribeOption{parse-units} -% Normally, \pkg{siunitx} is used with the unit parse enabled, and -% only prints units directly if there is literal input. However, if -% the input is known to be essentially consistent and high performance -% is desired, then the parser can be turned off using the -% \opt{parse-units} switch. -%\begin{LaTeXdemo} -% \SI{300}{\MHz} \\ -% \SI[parse-units = false]{300}{\MHz} -%\end{LaTeXdemo} +% File: siunitx.dtx Copyright (C) 2008-2019,2021 Joseph Wright % -%\subsection{Numbers with units} +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file % -% Some options apply to the combination of units and numbers, rather -% than to units or numbers alone (\cref{tab:opt:units:numbers}). +% https://www.latex-project.org/lppl.txt % -%\begin{table} -% \centering -% \caption{Options for numbers with units.} -% \label{tab:opt:units:numbers} -% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} -% \toprule -% \multicolumn{1}{l}{Option name} & -% Type & -% \multicolumn{1}{l}{Default} \\ -% \midrule ^^A ( -% allow-number-unit-breaks & Switch & false \\ -% exponent-to-prefix & Switch & false \\ -% list-units & Choice & repeat \\ -% multi-part-units & Choice & brackets \\ -% number-unit-product & Literal & \cs{,} \\ -% product-units & Choice & repeat \\ -% range-units & Choice & repeat \\ -% \bottomrule -% \end{tabular} -%\end{table} +% This file is part of the "siunitx bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. % -%\DescribeOption{allow-number-unit-breaks} -% Usually, the combination of a number and unit is regarded as a single -% mathematical entity which should not be split across lines. However, -% there are cases (very long units, narrow columns, \emph{etc}.) where -% breaks may be needed. This can be turned on using the -% \opt{allow-number-unit-breaks} option. -%\begin{LaTeXdemo} -% \begin{minipage}{2.55 cm} -% % Gives an underfull hbox -% Some filler text \SI{10}{\metre} \\ -% \sisetup{allow-number-unit-breaks} -% Some filler text \SI{10}{\metre} -% \end{minipage} -%\end{LaTeXdemo} +% The released version of this bundle is available from CTAN. % -%\DescribeOption{number-unit-product} -% The product symbol between the number and unit is set using the -% \opt{number-unit-product} option. -%\begin{LaTeXdemo} -% \SI{2.67}{\farad} \\ -% \SI[number-unit-product = \ ]{2.67}{\farad} \\ -% \SI[number-unit-product = ]{2.67}{\farad} -%\end{LaTeXdemo} +% ----------------------------------------------------------------------- % -%\DescribeOption{multi-part-units} -% When a number has multiple parts (such as a separate uncertainty) then -% the unit must apply to all parts of the number. How this is shown is -% controlled using the \opt{multi-part-units} options. The standard -% setting is \opt{brackets}, which will place the entire numerical part -% in brackets and use a single unit symbol. Alternative options are -% \opt{repeat} (print the unit for each part of the number) and -% \opt{single} (print only one unit symbol: mathematically incorrect). -%\begin{LaTeXdemo} -% \sisetup{separate-uncertainty}% -% \SI{12.3(4)}{\kilo\gram} \\ -% \SI[multi-part-units = brackets]{12.3(4)}{\kilo\gram} \\ -% \SI[multi-part-units = repeat]{12.3(4)}{\kilo\gram} \\ -% \SI[multi-part-units = single]{12.3(4)}{\kilo\gram} -%\end{LaTeXdemo} -% It is important to notice that numbers with units are not affected by -% the setting of \opt{bracket-numbers}, which applies to \enquote{pure} -% numbers only. For example: -%\begin{LaTeXdemo} -% \sisetup{separate-uncertainty,bracket-numbers = false}% -% \num{1.234(5)e-4} \\ -% \SI{1.234(5)e-4}{\metre} -%\end{LaTeXdemo} -% The reason is that the requirements to bracket values with units are -% fundamentally different from those for numbers alone. Some -% combinations which are mathematically valid in the absence of a unit -% become invalid when a unit is present. +% The development version of the bundle can be found at % -%\DescribeOption{product-units} -% When a product of quantities is given, the resulting units can be -% displayed in a number of ways, set using the \opt{product-units} -% option. The standard setting is \opt{repeat}, which prints one -% unit symbol for each numbers. Alternatives are \opt{brackets}, -% \opt{brackets-power}, \opt{power}, \opt{repeat} and \opt{single}. -% This option does not affect the application of brackets for each -% number within the product list: it only sets those around the -% entire list. -%\begin{LaTeXdemo} -% \SI{2 x 3 x 4}{\metre} \\ -% \SI[product-units = brackets]{2 x 3 x 4}{\metre} \\ -% \SI[product-units = brackets-power]{2 x 3 x 4}{\metre} \\ -% \SI[product-units = power]{2 x 3 x 4}{\metre} \\ -% \SI[product-units = repeat]{2 x 3 x 4}{\metre} \\ -% \SI[product-units = single]{2 x 3 x 4}{\metre} -%\end{LaTeXdemo} +% https://github.com/josephwright/siunitx % -%\DescribeOption{list-units} -%\DescribeOption{range-units} -% The \opt{list-units} and \opt{range-units} options determine how -% the \cs{SIlist} and \cs{SIrange} functions display units, -% respectively. The standard setting for both is \opt{repeat}, where -% each number will be printed with a unit. Alternatives are -% \opt{brackets} and \opt{single}. Any brackets needed on individual -% numbers within a product are controlled by the \opt{brackets-numbers} -% option (\emph{i.e}.~they are treated as pure numbers). -% These options do not affect the application of brackets for each -% number within the list or range: they only set those around the -% entire group. -%\begin{LaTeXdemo} -% \SIlist{2;4;6;8}{\tesla} \\ -% \SIlist[list-units = brackets]{2;4;6;8}{\tesla} \\ -% \SIlist[list-units = repeat]{2;4;6;8}{\tesla} \\ -% \SIlist[list-units = single]{2;4;6;8}{\tesla} \\ -% \SIrange{2}{4}{\degreeCelsius} \\ -% \SIrange[range-units = brackets]{2}{4}{\degreeCelsius} \\ -% \SIrange[range-units = repeat]{2}{4}{\degreeCelsius} \\ -% \SIrange[range-units = single]{2}{4}{\degreeCelsius} -%\end{LaTeXdemo} +% for those people who are interested. % -% \DescribeOption{exponent-to-prefix} -% \changes{v2.4}{2011/11/06}{New \opt{exponent-to-prefix} option} -% When the \opt{exponent-to-prefix} option is set \opt{true}, the package -% will attempt to convert any exponents in quantities into unit prefixes, -% and will attach these to the first unit given. This process is only -% possible if the exponent is one for which a prefix is available, and -% retains the number of significant figures in the input. -%\begin{LaTeXdemo} -% \SI{1700}{\g} \\ -% \SI{1.7e3}{\g} \\ -% \sisetup{exponent-to-prefix}% -% \SI{1700}{\g} \\ -% \SI{1.7e3}{\g} \\ -% \sisetup{fixed-exponent = 3, scientific-notation = fixed}% -% \SI{1700}{\g} \\ -% \SI{1.7e3}{\g} -%\end{LaTeXdemo} +% ----------------------------------------------------------------------- % -%\subsection{Tabular material} -% -% Processing of material in tables obeys the same settings as described -% for the functions already described. However, there are some settings -% which apply only to the layout of tabular material -% (\cref{tab:opt:tables}). -% -%\begin{table} -% \centering -% \caption{Options for tabular material.} -% \label{tab:opt:tables} -% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} -% \toprule -% \multicolumn{1}{l}{Option name} & -% Type & -% \multicolumn{1}{l}{Default} \\ -% \midrule ^^A ( -% table-align-comparator & Switch & true \\ -% table-align-exponent & Switch & true \\ -% table-align-text-pre & Switch & true \\ -% table-align-text-post & Switch & true \\ -% table-align-uncertainty & Switch & true \\ -% table-alignment & Choice & \meta{none} \\ -% table-auto-round & Switch & false \\ -% table-column-width & Length & 0 pt \\ -% table-comparator & Switch & false \\ -% table-figures-decimal & Integer & 2 \\ -% table-figures-exponent & Integer & 0 \\ -% table-figures-integer & Integer & 3 \\ -% table-figures-uncertainty & Integer & 0 \\ -% table-format & Special & \meta{none} \\ -% table-number-alignment & Choice & -% center-decimal-marker \\ -% table-parse-only & Switch & false \\ -% table-omit-exponent & Switch & true \\ -% table-space-text-pre & Literal & \meta{empty} \\ -% table-space-text-post & Literal & \meta{empty} \\ -% table-sign-exponent & Switch & false \\ -% table-sign-mantissa & Switch & false \\ -% table-text-alignment & Choice & center \\ -% table-unit-alignment & Choice & center \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -%\DescribeOption{table-parse-only} -% The main use of the \texttt{S} column is to control the alignment of -% the resulting output. However, it is possible to turn off alignment -% entirely and only use the number parser of \pkg{siunitx}. This is -% achieved using the \opt{table-parse-only} switch, as illustrated -% in \cref{tab:S:parse}. -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \centering -% \caption{Parsing without aligning in an \texttt{S} column.} -% \label{tab:S:parse} -% \begin{tabular} -% { -% S -% S[table-parse-only] -% } -% \toprule -% {Decimal-centred} & -% {Simple centring} \\ -% \midrule -% 12.345 & 12.345 \\ -% 6,78 & 6,78 \\ -% -88.8(9) & -88.8(9) \\ -% 4.5e3 & 4.5e3 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\DescribeOption{table-number-alignment} -% The alignment of numbers with the boundaries of the \texttt{S} -% column is controlled using the \opt{table-number-alignment} option, -% which takes the values \opt{center-decimal-marker}, \opt{center}, -% \opt{left} and \opt{right}. The \opt{center-decimal-marker} places the -% decimal marker for the number at the centre of the column. This does -% not need any information in advance, and so is the standard setting. -% It works best for approximately symmetrical input (equal numbers of -% digits before and after the decimal). On the other hand, the -% \opt{center}, \opt{left} and \opt{right} options require space to be -% reserved for the numbers, and then use this fixed space to align with -% the edges of the column. The different alignment choices are -% illustrated in \cref{tab:S:align}, which uses somewhat -% exaggerated column headings to show the relative position of the -% cell contents. -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \caption{Aligning the \texttt{S} column.} -% \label{tab:S:align} -% \centering -% \sisetup{ -% table-figures-integer = 2, -% table-figures-decimal = 4 -% } -% \begin{tabular}{ -% S -% S[table-number-alignment = center] -% S[table-number-alignment = left] -% S[table-number-alignment = right] -% } -% \toprule -% {Some Values} & {Some Values} & {Some Values} & {Some Values} \\ -% \midrule -% 2.3456 & 2.3456 & 2.3456 & 2.3456 \\ -% 34.2345 & 34.2345 & 34.2345 & 34.2345 \\ -% 56.7835 & 56.7835 & 56.7835 & 56.7835 \\ -% 90.473 & 90.473 & 90.473 & 90.473 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% Many of the other table options do not apply when -% \opt{table-number-alignment = center-decimal-marker} is set, as this -% mode always centres the marker at the expense of any other -% choices. -% -%\DescribeOption{table-figures-decimal} -%\DescribeOption{table-figures-exponent} -%\DescribeOption{table-figures-integer} -%\DescribeOption{table-figures-uncertainty} -% The space reserved by \pkg{siunitx} for a number is controlled by -% two families of options. The first family cover the number of digits -% allowed for in different parts of the number, for example -% \opt{table-figures-integer} controls the space for integer digits in -% the mantissa. If the number of figures is set to \num{0}, then no -% space is reserved and some output will either be out of position -% or not printed at all (although a warning will result). Reserving -% space for a given part of number will automatically include space -% for any associated items (for example the \enquote{\( \times \)} -% symbol for exponents). -%\DescribeOption{table-sign-exponent} -%\DescribeOption{table-sign-mantissa} -% The second family of options are switches which govern whether -% space is reserved for a sign: \opt{table-sign-exponent} and -% \opt{table-sign-mantissa}. The effect of altering some of these -% settings is shown in \cref{tab:S:space}. -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \caption{Reserving space in \texttt{S} columns.} -% \label{tab:S:space} -% \sisetup{ -% table-number-alignment = center, -% table-figures-integer = 2 -% } -% \centering -% \begin{tabular}{ -% S -% S[table-number-alignment = right] -% S[table-figures-uncertainty = 1] -% S[ -% separate-uncertainty, -% table-figures-uncertainty = 1 -% ] -% S[table-sign-mantissa] -% S[table-figures-exponent = 1] -% } -% \toprule -% {Values} -% & {Values} -% & {Values} -% & {Values} -% & {Values} -% & {Values} \\ -% \midrule -% 2.3 & 2.3 & 2.3(5) & 2.3(5) & 2.3 & 2.3e8 \\ -% 34.23 & 34.23 & 34.23(4) & 34.23(4) & 34.23 & 34.23 \\ -% 56.78 & 56.78 & 56.78(3) & 56.78(3) & -56.78 & 56.78e3 \\ -% 3,76 & 3,76 & 3,76(2) & 3.76(2) & +-3.76 & e6 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -%\DescribeOption{table-comparator} -%\changes{v2.1}{2010/10/26}{New \opt{table-comparator} option -% for reserving space for comparators in tables} -% Space can also be reserved in a table for a comparator (greater than, -% less than, and so forth). This is activated using the -% \opt{table-comparator} switch (\cref{tab:S:comparators}). -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \caption{Reserving space for comparators in \texttt{S} columns.} -% \label{tab:S:comparators} -% \sisetup{ -% table-number-alignment = center, -% table-figures-integer = 2, -% table-figures-decimal = 2, -% table-figures-exponent = 2, -% } -% \centering -% \begin{tabular}{ -% S -% S[table-comparator = true] -% } -% \toprule -% {Values} -% & {Values} \\ -% \midrule -% 2.3 & < 2.3e8 \\ -% 34.23 & = 34.23 \\ -% 56.78 & >= 56.78e3 \\ -% 3,76 & \gg e6 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% The table-printing code will omit any part of a number which has no -% space reserved, placing a warning in the \LaTeX{} log. This means that -% uncertainties and exponents will not be printed if no space is -% reserved for them. -% -%\DescribeOption{table-format} -% As a short cut for the preceding options, \pkg{siunitx} also -% provides the \opt{table-format} option. This can be used to give the -% same information about the space to reserve for a number in a -% \enquote{compressed} manner. The input to \opt{table-format} should -% consist of a number showing how many figures to reserve in each part -% of the input. Thus -%\begin{LaTeXdemo}[code only] -% \sisetup{ -% table-format = 3.2 -% } -%\end{LaTeXdemo} -% is equivalent to -%\begin{LaTeXdemo}[code only] -% \sisetup{ -% table-figures-integer = 3, -% table-figures-decimal = 2 -% } -%\end{LaTeXdemo} -% The \opt{table-format} option will also correctly interpret the -% presence of a sign, so that -%\begin{LaTeXdemo}[code only] -% \sisetup{ -% table-format = +3.2e+4 -% } -%\end{LaTeXdemo} -% will have the same effect as -%\begin{LaTeXdemo}[code only] -% \sisetup{ -% table-figures-integer = 3, -% table-figures-decimal = 2, -% table-figures-exponent = 4, -% table-sign-mantissa, -% table-sign-exponent -% } -%\end{LaTeXdemo} -% It is important to note that any parts of a number \emph{not} -% specified in the table format argument are set to be absent (the -% number of figures is set to zero). Setting the \opt{table-format} -% option also resets \opt{table-number-alignment} to \opt{center} -% (\cref{tab:S:format}). -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \caption{Using the \opt{table-format} option.} -% \label{tab:S:format} -% \centering -% \begin{tabular}{ -% S -% S[table-format = 2.2] -% S[table-format = 2.2(1)] -% S[table-format = +2.2] -% S[table-format = 2.2e1] -% } -% \toprule -% {Values} -% & {Values} -% & {Values} -% & {Values} -% & {Values} \\ -% \midrule -% 2.3 & 2.3 & 2.3(5) & 2.3 & 2.3e8 \\ -% 34.23 & 34.23 & 34.23(4) & 34.23 & 34.23 \\ -% 56.78 & 56.78 & 56.78(3) & -56.78 & 56.78e3 \\ -% 3,76 & 3,76 & 3.76(2) & +-3.76 & e6 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\DescribeOption{table-space-text-pre} -%\DescribeOption{table-space-text-post} -% Space for material before and after the \texttt{S} column can -% be reserved by giving model text for the options -% \opt{table-space-text-pre} and \opt{\ldots -post}. -% This is then used to provide the necessary gap while maintaining -% alignment (\cref{tab:S:ends}). -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \caption{Text before and after numbers.} -% \label{tab:S:ends} -% \centering -% \sisetup{ -% table-number-alignment = center, -% table-figures-integer = 2, -% table-figures-decimal = 4, -% table-space-text-pre = now~, -% table-space-text-post = -% \textsuperscript{\emph{a}} -% } -% \begin{tabular}{S} -% \toprule -% {Values} \\ -% \midrule -% 2.3456 \\ -% 34.2345 \textsuperscript{\emph{a}}\\ -% 56.7835 \\ -% now~ 90.473 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\DescribeOption{table-align-comparator} -%\changes{v2.2}{2010/04/04}{New \opt{table-align-comparator} -% option for more control of table formatting} -%\DescribeOption{table-align-exponent} -%\DescribeOption{table-align-uncertainty} -%\changes{v2.1}{2010/10/12}{New \opt{table-align-exponent} and -% \opt{table-align-uncertainty} options for additional choices of -% table formatting} -% When printing exponents in tables, there is a choice of aligning -% the exponent parts or having these close up to the mantissa. This -% is controlled by the \opt{table-align-exponent} option -% (\cref{tab:align:exp}). Similarly, uncertainty parts which are printed -% separately from the mantissa can be aligned or closed up. This is -% set by the \opt{table-align-uncertainty} option -% (\cref{tab:align:uncert}). Finally, the same approach is available -% for the comparator with the \opt{table-align-comparator} option -% (\cref{tab:align:comp}). -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \centering -% \caption{The \opt{table-align-exponent} option} -% \label{tab:align:exp} -% \sisetup{table-format = 1.3e2, table-number-alignment = center} -% \begin{tabular}{SS[table-align-exponent = false]} -% \toprule -% {Header} & {Header} \\ -% \midrule -% 1.2e3 & 1.2e3 \\ -% 1.234e56 & 1.234e56 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \centering -% \caption{The \opt{table-align-uncertainty} option} -% \label{tab:align:uncert} -% \sisetup{ -% separate-uncertainty, -% table-format = 1.3(1), -% } -% \begin{tabular}{SS[table-align-uncertainty = false]} -% \toprule -% {Header} & {Header} \\ -% \midrule -% 1.2(1) & 1.2(3) \\ -% 1.234(5) & 1.234(5) \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \centering -% \caption{The \opt{table-align-comparator} option} -% \label{tab:align:comp} -% \sisetup{table-format = >2.2} -% \begin{tabular}{SS[table-align-comparator = false]} -% \toprule -% {Header} & {Header} \\ -% \midrule -% > 1.2 & > 1.2 \\ -% < 12.34 & < 12.34 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\DescribeOption{table-omit-exponent} -%\changes{v2.1}{2010/10/13}{New \opt{table-omit-exponent} option -% for simplifying tables} -% In cases where data cover a range of values, printing using a fixed -% exponent in a table may make presentation clearer. In these cases, -% omitting the exponent value from the table is useful. The package -% offers the \opt{table-omit-exponent} option to do this -% (\cref{tab:exp:omit}); this automatically sets -% \opt{scientific-notation = fixed} for the table column. -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \centering -% \caption{The \opt{table-omit-exponent} option} -% \label{tab:exp:omit} -% \begin{tabular}{ -% S[table-format = 1.1e1] -% S[ -% fixed-exponent = 3, -% table-format = 2.1, -% table-omit-exponent -% ] -% } -% \toprule -% {Header} & {Header / \num{e3}} \\ -% \midrule -% 1.2e3 & 1.2e3 \\ -% 3e2 & 3e2 \\ -% 1.0e4 & 1.0e4 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\DescribeOption{table-align-text-pre} -% \changes{v2.3}{2011/06/19}{New \opt{table-align-text-pre} option} -%\DescribeOption{table-align-text-post} -% Note markers are often given in tables after the numerical content. It -% may be desirable for these to close up to the numbers. Whether this -% takes place is controlled by the \opt{table-align-text-pre} -% and \opt{\ldots-post} -% option (\cref{tab:S:notes}). -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \caption{Closing notes up to text.} -% \label{tab:S:notes} -% \newrobustcmd\NoteMark[1]{% -% \textsuperscript{\emph{#1}}% -% } -% \centering -% \sisetup{ -% table-number-alignment = center, -% table-figures-integer = 2, -% table-figures-decimal = 4, -% table-space-text-pre = \NoteMark{a} -% } -% \begin{tabular}{ -% S -% S[table-align-text-pre = false] -% } -% \toprule -% {Values} & {Values} \\ -% \midrule -% 2.3456 & 2.3456 \\ -% \NoteMark{a} 4.234 & \NoteMark{a} 4.234 \\ -% \NoteMark{b} .78 & \NoteMark{b} .78 \\ -% \NoteMark{d} 88 & \NoteMark{d} 88 \\ -% \bottomrule -% \end{tabular} -% \hfil -% \sisetup{table-space-text-post = \NoteMark{a}} -% \begin{tabular}{ -% S -% S[table-align-text-post = false] -% } -% \toprule -% {Values} & {Values} \\ -% \midrule -% 2.3456 & 2.3456 \\ -% 34.234 \NoteMark{a} & 34.234 \NoteMark{a} \\ -% 56.78 \NoteMark{b} & 56.78 \NoteMark{b} \\ -% 90.4 \NoteMark{c} & 90.4 \NoteMark{c} \\ -% 88 \NoteMark{d} & 88 \NoteMark{d} \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\DescribeOption{table-auto-round} -% The contents of table cells can automatically be rounded or -% zero-filled to the number of decimal digits given for the -% \opt{table-figures-decimal} option. This mode is activated using -% the \opt{table-auto-round} switch, as illustrated in -% \cref{tab:S:auto}. -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \centering -% \caption{The \opt{table-auto-round} option.} -% \label{tab:S:auto} -% \sisetup{ -% table-number-alignment = center, -% table-figures-integer = 1, -% table-figures-decimal = 3 -% } -% % Notice the overfull hbox which results with -% % the first column -% \begin{tabular}{ -% S -% S[table-auto-round] -% } -% \toprule -% {Header} & {Header} \\ -% \midrule -% 1.2 & 1.2 \\ -% 1.2345 & 1.2345 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\DescribeOption{parse-numbers} -% When the \opt{parse-numbers} option is set to \opt{false}, then -% the alignment code for tables takes a different approach. The -% output is always set in math mode, and alignment takes place -% at the first decimal marker. This is achieved by making it -% active in math mode. When reserving space for content only -% the integer and decimal values for the mantissa are considered -% (\cref{tab:S:nonparsed}). -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \caption{Aligning without parsing.} -% \label{tab:S:nonparsed} -% \sisetup{ -% parse-numbers = false, -% table-figures-integer = 2, -% table-figures-decimal = 3 -% } -% \centering -% \begin{tabular}{ -% S -% S[table-number-alignment = center] -% S[table-number-alignment = right] -% S[table-number-alignment = left] -% } -% \toprule -% {Some values} -% & {Some values} -% & {Some values} -% & {Some values} \\ -% \midrule -% 2.35 & 2.35 & 2.35 & 2.35 \\ -% 34.234 & 34.234 & 34.234 & 34.234 \\ -% 56.783 & 56.783 & 56.783 & 56.783 \\ -% 3,762 & 3,762 & 3,762 & 3.762 \\ -% \sqrt{2} & \sqrt{2} & \sqrt{2} & \sqrt{2} \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\DescribeOption{table-text-alignment} -% Cell contents which are not part of a number can be protected -% using braces, as illustrated. Cells which contain no numerical data -% at all are aligned using the setting specified by the -% \opt{table-text-alignment} option, which recognises the values -% \opt{center}, \opt{left} and \opt{right} (\cref{tab:S:text}). -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \caption{Aligning text in \texttt{S} columns.} -% \label{tab:S:text} -% \sisetup{ -% table-number-alignment = center, -% table-figures-integer = 4, -% table-figures-decimal = 4 -% } -% \centering -% \begin{tabular}{ -% S -% S[table-text-alignment = left] -% S[table-text-alignment = right] -% } -% \toprule -% {Values} -% & {Values} -% & {Values} \\ -% \midrule -% 992.435 & 992.435 & 992.435 \\ -% 7734.2344 & 7734.2344 & 7734.2344 \\ -% 56.7834 & 56.7834 & 56.7834 \\ -% 3,7462 & 3,7462 & 3,7462 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\DescribeOption{table-unit-alignment} -% The contents of \texttt{s} columns can be centred or aligned to the -% left or right using the \opt{table-unit-alignment} option. As for the -% other alignment options, this recognises the choices \opt{center}, -% \opt{left} and \opt{right}. -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \centering -% \caption{Alignment options in \texttt{s} columns.} -% \label{tab:s:align} -% \begin{tabular} -% { -% s[table-unit-alignment = right] -% s -% s[table-unit-alignment = left] -% } -% \toprule -% {Right-aligned} & -% {Centred text} & -% {Left-aligned} \\ -% \midrule -% \metre\per\second & \metre\per\second & \metre\per\second \\ -% \kilogram & \kilogram & \kilogram \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\DescribeOption{table-alignment} -% The three table alignment options (\opt{table-number-alignment}, -% \opt{table-text-alignment} and \opt{table-unit-alignment}) can be set -% to the same value using the \opt{table-alignment} option. This will -% set all three alignment options to the same value (one of -% \opt{center}, \opt{right} or \opt{left}). -% -%\DescribeOption{table-column-width} -%\changes{v2.2}{2011/04/02}{New \opt{table-column-width} option} -%\changes{v2.2f}{2011/05/25}{Fix setting \opt{table-column-width} to -% \opt{0 pt} to restore auto-sizing} -% Usually, the width of the \texttt{S} and \texttt{s} columns is allowed -% to vary depending on the content. However, there are cases where a -% strictly fixed width is desirable. For these cases, the -% \opt{table-column-width} option is available. The standard -% setting, "0 pt", indicates that no fixing takes place. If a value -% is set for this option then the tabular material is typeset to -% the specified width (\cref{tab:width:fixed}). -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \centering -% \caption{Fixed-width columns.} -% \label{tab:width:fixed} -% \begin{tabular} -% { -% s -% s[table-column-width = 2 cm] -% S -% S[table-column-width = 2 cm] -% } -% \toprule -% {Flexible} & -% {Fixed} & -% {Flexible} & -% {Fixed} \\ -% \midrule -% \metre\per\second & \metre\per\second & 1.23 & 1.23 \\ -% \kilogram\candela & \kilogram\candela & 45.6 & 45.6 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -% The \opt{table-column-width} option can also be used to achieve -% special effects. One example is centring a column of numbers under -% a wide heading, with the numbers themselves right-aligned -% (\cref{tab:width:special}). -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \centering -% \caption{Right-aligning under a heading.} -% \label{tab:width:special} -% \settowidth\mylength{Long header} -% \sisetup{ -% table-format = 4 , -% table-number-alignment = center , -% table-column-width = \mylength , -% input-decimal-markers = , -% input-symbols = . , -% } -% \begin{tabular}{S} -% \toprule -% {Long header} \\ -% \midrule -% 12.33 \\ -% 2 \\ -% 1234 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\subsection{Symbols} -% -% Most units use letters as the symbol for the unit, and these are all -% very easy to control. However, a small number of units use other -% symbols, and matching these to the body text requires more work. -% \pkg{siunitx} provides appropriate symbols for commonly-used units, -% but the definitions may need adjustment depending on the body font -% used in a document. -% -%\DescribeOption{redefine-symbols} -% The package provides one general option for the handling of symbols. -% If the packages \pkg{textcomp} or \pkg{upgreek} are loaded, symbols -% can be taken from these for units, rather than using the -% \pkg{siunitx} default values. The switch \opt{redefine-symbols} -% can be used to turn this behaviour on or off: the standard setting -% is \opt{true}. -% -% The individual symbols are set up independently for math and text -% output, and are summarised in \cref{tab:opt:symbols}. Many of -% the definitions are variations using \cs{text} or \cs{ensuremath} to -% produce the correct output, as the symbols available in the document -% may vary considerably. In the case of the micro symbol -% (\SIUnitSymbolMicro), \pkg{siunitx} provides a suitable low-level -% definition for the symbol. Depending on the fonts available, this -% may need to be replaced by an alternative by the user. The -% ohm symbol (\SIUnitSymbolOhm) is usually set to \cs{Omega}, but -% will check that this has not been redefined as a slanted letter. If -% \cs{Omega} has been redefined, an alternative definition is used. -% -%\begin{table} -% \centering -% \caption{Symbol options.} -% \label{tab:opt:symbols} -% \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} -% \toprule -% \multicolumn{1}{l}{Option name} & -% Type & -% \multicolumn{1}{l}{Default} \\ -% \midrule ^^A ( -% math-angstrom & Literal & \verb=\text{\AA}= \\ -% math-arcminute & Literal & \verb={}^{\prime}= \\ -% math-arcsecond & Literal & \verb={}^{\prime\prime}= \\ -% math-celsius & Literal & \meta{see text} \\ -% math-degree & Literal & \verb=\text{\textdegree}= \\ -% math-micro & Literal & \verb=\text{\textmu}= \\ -% math-ohm & Literal & \verb=\text{\ensuremath{\Omega}}= \\ -% redefine-symbols & Switch & true \\ -% text-angstrom & Literal & \cs{AA} \\ -% text-arcminute & Literal & \verb=\ensuremath{{}^{\prime}}= \\ -% text-arcsecond & Literal & -% \verb=\ensuremath{{}^{\prime\prime}}= \\ -% text-celsius & Literal & \verb=\textdegree C= \\ -% text-degree & Literal & \verb=\textdegree= \\ -% text-micro & Literal & \verb=\textmu= \\ -% text-ohm & Literal & \verb=\textohm= \\ -% \bottomrule -% \end{tabular} -%\end{table} -% -%\DescribeMacro{\SIUnitSymbolAngstrom} -%\DescribeMacro{\SIUnitSymbolArcminute} -%\DescribeMacro{\SIUnitSymbolArcsecond} -%\DescribeMacro{\SIUnitSymbolCelsius} -%\DescribeMacro{\SIUnitSymbolDegree} -%\DescribeMacro{\SIUnitSymbolMicro} -%\DescribeMacro{\SIUnitSymbolOhm} -% The math and text symbols defined above are wrapped up into mode -% independent functions with user names. These are then used in the -% definitions of the appropriate units. For example, the micro -% symbol can be accessed using the macro \cs{SIUnitSymbolMicro}. -% Notice that these names capitalise the unit name (to make reading -% the macro name easier!).\footnote{The function -% \cs{SIUnitSymbolAngstrom} uses the name without accents.} -% -%\subsection{Other options} -% -%\DescribeOption{locale} -%\changes{v2.0m}{2010/07/09}{Re-introduce \opt{locale} option} -% \pkg{siunitx} allows the user to switch between the typographic -% conventions of different (geographical) areas by using locales. -% Currently, the package is supplied with configurations for locales -% \opt{UK}, \opt{US}, \opt{DE} (Germany), \opt{FR} (French) and \opt{ZA} -% (South Africa). The \opt{locale} option is used to switch to a -% particular locale. -%\begin{LaTeXdemo} -% \SI{1.234}{\metre}\\ -% \SI[locale = DE]{6.789}{\metre} -%\end{LaTeXdemo} -% -%\DescribeOption{strict} -% Some users will want to stick closely to the official rules for -% typesetting units. This could be made complicated if the options -% for non-standards behaviour could not be turned off. The -% preamble-only option \opt{strict} resets package behaviour to -% follow the rules closely, and disables options which deviate from -% this. If the package is loaded with the \opt{strict} option, all -% output is made using the upright (serif) font. -% -%\subsection{Local configurations} -%\label{sec:config:local} -% -% The \pkg{siunitx} package will check for a local configuration file -% \file{siunitx.cfg} during package loading. This occurs before -% applying any setting given in the optional argument to -% \cs{usepackage}. A typical configuration file may include -% settings (using \cs{sisetup}) and locally-defined units, for -% example -%\begin{LaTeXdemo}[code only] -% \ProvidesFile{siunitx.cfg} -% \sisetup{ -% output-decimal-marker = {,}, -% per-mode = symbol, -% } -% \DeclareSIUnit\torr{torr} -%\end{LaTeXdemo} -% As units are always declared, overwriting any existing definition, -% units may safely be created in the configuration file even when also -% included in individual \LaTeX{} document headers. -% -% Installing a local configuration file on your system is very much like doing -% a local installation of a package. The exact method depends on the \TeX{} -% system in use. For advice on this, a good start is the -% \href{http://tex.stackexchange.com/questions/1137/} -% {TeX.SX question on local installation}. -% -%\section{Localisation} -% -% The \pkg{translator} package provides a structured framework for -% localisation of words and phrases, and is part of the larger -% \pkg{beamer} bundle. The \pkg{translator} package provides the -% \cs{translate} macro, which will provide appropriate translations -% based on the current \pkg{babel} or \pkg{polyglossia} language -% setting. -% -% If \pkg{translator} is available, \pkg{siunitx} will load it and alter -% the standard settings for the \opt{list-final-separator} and -% \opt{range-phrase} options to read: -%\begin{LaTeXdemo}[code only] -% \sisetup{ -% list-final-separator = { \translate{and} }, -% list-pair-separator = { \translate{and} }, -% range-phrase = { \translate{to (numerical range)} }, -% } -%\end{LaTeXdemo} -% If the current language is known to the \pkg{translator} package -% then the result will be localised text. The preamble for this manual -% loads English, French, German and Spanish as options, and also loads the -% \pkg{babel} package: -%\begin{LaTeXdemo} -% % In English by default -% \SIlist{1;2;3}{\metre} \\ -% \SIrange{1}{10}{\degreeCelsius} \\ -% \selectlanguage{french}% -% \SIlist{1;2;3}{\metre} \\ -% \SIrange{1}{10}{\degreeCelsius} \\ -% \selectlanguage{german}% -% \SIlist{1;2;3}{\metre} \\ -% \SIrange{1}{10}{\degreeCelsius} \\ -% \selectlanguage{spanish}% -% \SIlist{1;2;3}{\metre} \\ -% \SIrange{1}{10}{\degreeCelsius} \\ -%\end{LaTeXdemo} -% -% Note that the in order for this to work correctly, languages should -% be given as global (class) options rather than as package options -% for \pkg{babel}. -% -%\section{Hints for using \pkg{siunitx}} -% -%\subsection{Ensuring text or math output} -% -% The macros \cs{ensuremath} and \cs{text} should be used to ensure that -% a particular item is always printed in the desired mode. Some -% mathematical output does not work well in \cs{mathrm} (the standard -% font used by \pkg{siunitx} for printing). The easiest way to solve -% this is to use the construction "\text{\ensuremath{...}}", which will -% print the material in the standard mathematics font without affecting -% the rest of the output. In some cases, simply forcing \cs{mathnormal} -% will suffice, but this is less reliable with non-Latin characters. -% -%\subsection{Expanding content in tables} -%\label{sec:expanding} -% -% When processing tables, \pkg{siunitx} will expand anything stored -% inside a macro, unless it is long or protected. \LaTeXe{} robust -% commands are also detected and are not expanded -% (\cref{tab:xmpl:macro}). Values which would otherwise be expanded -% can be protected by wrapping them in a set of braces. As \TeX{} itself -% will expand the first token in a table cell before \pkg{siunitx} -% can act on it, using the \eTeX{} protected mechanism is the -% recommended course of action to prevent expansion of macros in -% table cells. (As is shown in the table, \TeX's expansion of -% \LaTeXe{} robust commands can lead to unexpected results.) -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \centering -% \caption{Values as macros in \texttt{S} columns.} -% \label{tab:xmpl:macro} -% \newcommand*\myvaluea{1234} -% \newcommand\myvalueb{1234} -% \DeclareRobustCommand*\myvaluec{1234} -% \protected\def\myvalued{1234} -% \begin{tabular}{S} -% \toprule -% {Some Values} \\ -% \midrule -% \myvaluea 8.8 \myvaluea \\ % Both expanded -% \myvalueb 8.8 \myvalueb \\ % First expanded by TeX -% % to numbers -% \myvaluec 8.8 \myvaluec \\ % First expanded by TeX -% % but not to numbers! -% \myvalued 8.8 \myvalued \\ % Neither expanded -% {\myvaluea\ 8.8 \myvaluea} \\ % Neither expanded -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -% It is possible to use calculated values in tables. For this to -% work, the calculation must take place before attempting to parse -% the number. An added complication is that \TeX{} itself will -% expand the first macro in a table cell until it finds -% something unexpandable. The \eTeX{} protected mechanism can be -% used to prevent this; using the \pkg{etoolbox} package provides -% a convenient way to apply this protection to existing functions. -% The general approach is illustrated in \cref{tab:xmpl:calc}. -% The macro \cs{DTLmul} is made robust inside the table using -% the \cs{robustify} command from \pkg{etoolbox}, before -% constructing the table using an extra column to contain the -% calculation. -%\begin{LaTeXdemo}[code and float] -% \DTLnewdb{data} -% \DTLnewrow{data}\DTLnewdbentry{data}{value}{66.7012} -% \DTLnewrow{data}\DTLnewdbentry{data}{value}{66.0212} -% \DTLnewrow{data}\DTLnewdbentry{data}{value}{64.9026} -% \begin{table} -% \caption{Calculated values.} -% \label{tab:xmpl:calc} -% \centering -% \robustify\DTLmul -% \sisetup{ -% table-number-alignment = center, -% table-figures-integer = 2, -% table-figures-decimal = 4 -% } -% \begin{tabular}{ -% S -% S[table-figures-integer = 3] -% @{}l -% } -% \toprule -% {Value} & {Doubled} & -% \DTLforeach{data}{\myvalue=value}{% -% \DTLiffirstrow {\\ \midrule}{\\}% -% \myvalue & % First column -% \DTLmul{\myvalue}{\myvalue}{2} \myvalue % second column -% & }\\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\subsection{Using \pkg{siunitx} with \pkg{datatool}} -% -% As illustrated in \cref{tab:xmpl:calc}, \pkg{siunitx} can be used -% to typeset data stored using \pkg{datatool}. For quickly displaying -% the contents of tables, \pkg{datatool} offers the \cs{DTLshowtable} -% macro. This will only work with \texttt{S} columns if number parsing -% is turned off (\cref{tab:xmpl:datatool}). -%\begin{LaTeXdemo}[code and float] -% \DTLnewdb{moredata} -% \DTLnewrow{moredata}\DTLnewdbentry{moredata}{value}{ 6.7012} -% \DTLnewrow{moredata}\DTLnewdbentry{moredata}{value}{66.0212} -% \DTLnewrow{moredata}\DTLnewdbentry{moredata}{value}{64.902 } -% \begin{table} -% \caption{Displaying a \textsf{datatool} table.} -% \label{tab:xmpl:datatool} -% \centering -% \sisetup{ -% parse-numbers = false, -% table-number-alignment = center, -% table-figures-integer = 2, -% table-figures-decimal = 4 -% } -% \renewcommand*\dtlrealalign{S} -% \DTLdisplaydb{moredata} -% \end{table} -%\end{LaTeXdemo} -% -%\subsection{Using units such as \si{\micro\metre\per\second} in -% headings} -% -% The \pkg{siunitx} code is designed to work correctly with functions -% in headings. They will print correctly in headings and in the table -% of contents. As illustrated here, the standard behaviour is to ignore -% font changes. When the \pkg{hyperref} package is loaded, the -% functions automatically \enquote{degrade gracefully} to produce -% useful information in PDF bookmarks. If you want more control over -% the bookmark text, use the \cs{texorpdfstring} function from -% \pkg{hyperref}, for example: -%\begin{LaTeXdemo}[code only] -% \section{Some text -% \texorpdfstring -% {\si{\joule\per\mole\per\kelvin}} -% {J mol-1 K-1}% -% } -%\end{LaTeXdemo} -% -% \subsection{A left-aligned column visually centred under a heading} -% -% When you have a column of non-related numbers, the usual advice is to -% make these left-aligned and then centre the resulting column under the -% heading. With the \pkg{dcolumn} package, that would be done with -% something like |D{x}{}{5.0}|. This is something of an abuse of the -% nature of a number, but can also be done using \pkg{siunitx} -% (\ref{tbl:xmpl:unrel}). -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \caption{Formatting unrelated numbers} -% \label{tbl:xmpl:unrel} -% \centering -% \begin{tabular} -% { -% S[ -% table-format = 5.0, -% parse-numbers = false, -% input-symbols=., -% input-decimal-markers = x -% ] -% } -% \toprule -% \multicolumn{1}{c}{Header} \\ -% \midrule -% 120 \\ -% 12.3 \\ -% 12340 \\ -% 12.02 \\ -% 123 \\ -% 1 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\subsection{Symbols and \texorpdfstring{\XeTeX}{XeTeX}} -% -% A small number of non-Latin symbols are needed by \pkg{siunitx}, -% notably \SIUnitSymbolOhm\ and \SIUnitSymbolMicro. The package picks -% glyphs for these which are correct in the sense that they are upright -% (not italic) symbols, and match the \LaTeX{} standard Computer Modern -% font. However, this does not make them the best choice if other -% fonts are in use, which is particularly common when \XeTeX{} is -% being used. -% -% \XeTeX{} users will probably need to choose appropriate symbols -% themselves. The correct choice depends on the fonts in use, but many -% system fonts include Greek letters and other symbols (which is not -% the case with most \TeX-specific fonts). An appropriate setting -% could then be to use the text \SIUnitSymbolMicro\ symbol in all -% cases: -%^^A This document cannot be UTF-8, as it has to work correctly with -%^^A pdfLaTeX. So there is a bit of work to do here to get the right -%^^A output. -%\begin{flushleft} -% \ttfamily -% \textbackslash \textcolor{blue}{sisetup}\{\\ -% \ \ math-micro = \textbackslash -% \textcolor{blue}{text}\{\SIUnitSymbolMicro\}, \\ -% \ \ text-micro \ = \SIUnitSymbolMicro \\ -% \} -%\end{flushleft} -% It may also be desirable in these cases to select a fixed font -% using the \pkg{fontspec} package, for example -%\begin{LaTeXdemo}[code only] -% \sisetup{ -% math-micro = \fontspec{Minion Pro} \textmu, -% text-micro = \fontspec{Minion Pro} \textmu -% } -%\end{LaTeXdemo} -% -%\subsection{Scaled document fonts with \texorpdfstring{\XeTeX}{XeTeX}} -% -% The \pkg{fontspec} package makes it possible to scale the document -% body font. This can lead to unexpected problems with printing -% for \pkg{siunitx}, as some symbols will not scale while numbers -% and text will. The problem is best avoided by forcing \pkg{siunitx} -% to use the default math font for all output: -%\begin{LaTeXdemo}[code only] -% \sisetup{ -% mode = math, -% math-rm = \ensuremath -% } -%\end{LaTeXdemo} -% This will cause all \pkg{siunitx} output \emph{not} to scale at all, -% consistent with other mathematical content. -% -% \subsection{Interaction with \pkg{tex4ht}} -% -% \pkg{siunitx} will detect when \pkg{tex4ht} is in use, and makes -% some changes to the way output is printed. Text mode printing is -% automatically selected, and certain items (such as spaces) are -% printed in text mode rather than as math. This is designed to -% reduce the likelihood of spurious formulae appearing in, for -% example, output converted to OpenOffice format. -% -%\subsection{Maximising performance} -% -% Both the number and unit parsers require significant effort in -% terms of \TeX{} programming. For input that does not require -% such processing, the maximum performance for \pkg{siunitx} can -% therefore be obtained by turning off both systems: -%\begin{LaTeXdemo} -% \SI{7.3}{\Hz} \\ -% \SI[parse-units = false]{7.3}{\Hz} \\ -% \SI[ -% parse-numbers = false, -% parse-units = false -% ]{7.3}{\Hz} -%\end{LaTeXdemo} -% -%\subsection{Transferring settings to \pkg{pgf}} -% -%\DescribeMacro{\SendSettingsToPgf} -%\changes{v2.0a}{2010/05/28}{Make \cs{SendSettingsToPgf} available -% in document body} -% The numerical engine in the \pkg{pgf} package has settings similar -% to those in \pkg{siunitx}. To enable working with both packages -% easily, the macro \cs{SendSettingsToPgf} is available. It will -% set some commonly-used numerical formatting options in \pkg{pgf} -% to the current values used by \pkg{siunitx} to make using the -% two packages together more convenient for end users. This -% function can be used at any point after loading both the -% \pkg{pgf} and \pkg{siunitx} packages. -%\begin{LaTeXdemo}[code only] -% \documentclass{article} -% \usepackage{pgf,siunitx} -% \sisetup{...} -% \SendSettingsToPgf -% ... -%\end{LaTeXdemo} -% -%\subsection{Using \pkg{siunitx} with the \pkg{cellspace} package} -% -% Both \pkg{siunitx} and \pkg{cellspace} use the letter \texttt{S} for a -% new column type as standard. If \pkg{cellspace} loaded and is using the -% \texttt{S} column specifier, \pkg{siunitx} will move the -% functionality of \pkg{cellspace} to the letter \texttt{C}, and \texttt{S} -% will be used by \pkg{siunitx}. This -% allows the normal use of \pkg{cellspace} with standard column types: -% it does \emph{not} work with the \pkg{siunitx} \texttt{S} or -% \texttt{s} columns. Note that \pkg{cellspace} can be loaded with a -% user-selectable identifier, for example -%\begin{LaTeXdemo}[code only] -% \usepackage[column=Q]{cellspace} -%\end{LaTeXdemo} -% -%\subsection{Special considerations for the \cs{kWh} unit} -% -% The \file{abbreviations} configuration file provides the unit -% \cs{kWh}, which is set up with no spacing between the -% \enquote{\si{\kilo\watt}} and the \enquote{\si{\hour}} unit to -% give \enquote{\si{\kWh}}. However, this only applies when the unit -% is given on its own: combinations will follow the normal rules -%\begin{LaTeXdemo} -% \si{\kWh} \\ -% \si{\kWh\per\metre} -%\end{LaTeXdemo} -% This is because the unit \cs{kWh} is defined so that it can still be -% varied by altering \cs{kilo}, \cs{watt} and \cs{hour}, and so that -% the prefix can still be turned into a number. However, some users -% may prefer to have a non-flexible macro which never adds a space. -% This can be achieved by redefining \cs{kWh} with \cs{DeclareSIUnit}, -% by added an alternative definition -%\begin{LaTeXdemo}[code only] -% \DeclareSIUnit\kWh{kWh} -% \DeclareSIUnit\KWH{kWh} -%\end{LaTeXdemo} -% or of course by using literal unit input. -%\begin{LaTeXdemo} -% \si{\KWH\per\metre}\\ -% \si{kWh.m^{-1}} -%\end{LaTeXdemo} -% -% Another point to notice is that the \cs{per} macro applies to -% the next unit, and not an entire unit combination. Thus in -%\begin{LaTeXdemo} -% \si{\candela\per\kWh} -%\end{LaTeXdemo} -% \cs{per} applies to the watts but not to the hours. In this case, -% the units need to be written out in full or the \opt{sticky-per} -% option should be used. -%\begin{LaTeXdemo} -% \si{\candela\per\kilo\watt\per\hour} \\ -% \si[sticky-per]{\candela\per\kWh} -%\end{LaTeXdemo} -% -%\subsection{Adding items after the last column of a tabular} -%\changes{v2.0d}{2010/06/10}{Document special case situations for last -% cell in table row} -% -% When using the \pkg{array} package \enquote{\texttt{<}} construct -% to insert material after an \texttt{S} or \texttt{s} column, the -% alignment of the final column may be wrong if the standard tabular row -% terminator |\\| is used. -% This is due to the way that \LaTeX{} constructs -% tables at a low level. The incorrect spacing can be avoided by using -% the \TeX{} \cs{cr} primitive to end the table rows (\cref{tab:cr}). -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \caption{Correcting spacing in last \texttt{S} column} -% \label{tab:cr} -% \hfil -% \begin{tabular}{S<{\,\si{\kg}}S<{\,\si{\kg}}} -% \toprule -% \multicolumn{1}{c}{Long header} & -% \multicolumn{1}{c}{Long header} \\ -% \midrule -% 1.23 & 1.23 \\ -% 4.56 & 4.56 \\ -% 7.8 & 7.8 \\ -% \bottomrule -% \end{tabular} -% \hfil -% \begin{tabular}{S<{\,\si{\kg}}S<{\,\si{\kg}}} -% \toprule -% \multicolumn{1}{c}{Long header} & -% \multicolumn{1}{c}{Long header} \\ -% \midrule -% 1.23 & 1.23 \cr -% 4.56 & 4.56 \cr -% 7.8 & 7.8 \cr -% \bottomrule -% \end{tabular} -% \hfil -% \end{table} -%\end{LaTeXdemo} -% -%\subsection{Creating a column with numbers and units} -% -% Usually, numbers in a table should be given with the units in the -% column heading. However, there are cases where a series of data are -% best presented in a table but have different units. There are two -% ways to do this (\cref{tab:xmpl:mixed}). The first is to place the -% units in the first column of the table, which makes sense if there -% are several related items in the table. The second method is to -% generate two columns, one for numbers and a second for units, and then -% to format these to give the visual effect of a single column. The -% later effect is most appropriate when only one set of numbers are -% presented in a table. -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \caption{Tables where numbers have different units} -% \label{tab:xmpl:mixed} -% \hfil -% \begin{tabular} -% { -% >{$}l<{$} -% S[table-format = 2.3(1)] -% S[table-format = 3.3(1)] -% } -% \toprule -% & {One} & {Two} \\ -% \midrule -% a / \si{\angstrom} & 1.234(2) & 5.678(4) \\ -% \beta / \si{\degree} & 90.34(4) & 104.45(5) \\ -% \mu / \si{\per\mm} & 0.532 & 0.894 \\ -% \bottomrule -% \end{tabular} -% \hfil -% \begin{tabular} -% {S[table-format=1.3]@{\,}s[table-unit-alignment = left]} -% \toprule -% \multicolumn{2}{c}{Heading} \\ -% \midrule -% 1.234 & \metre \\ -% 0.835 & \candela \\ -% 4.23 & \joule\per\mole \\ -% \bottomrule -% \end{tabular} -% \hfil -% \end{table} -%\end{LaTeXdemo} -% -%\subsection{Tables with heading rows} -%\changes{v2.0s}{2010/08/12}{Document how to do mixed bold and normal -% numbers in tables} -% -% A common format for tables is to make the heading row visually -% distinct using a background colour and bold text. If numbers appear -% in such a heading row within an \texttt{S} column then getting the -% appearance right can be challenging. The best approach is to -% make the \cs{bfseries} macro \enquote{robust} (as demonstrated in -% \cref{sec:expanding}), then to use this macro to make the heading -% cells bold. This approach is illustrated in \cref{tab:xmpl:headers}, -% along with the use of \cs{rowcolor} to provide a background colour. -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \caption{Header row in a table} -% \label{tab:xmpl:headers} -% \robustify\bfseries -% \centering -% \begin{tabular} -% {S[detect-weight,table-format = 3.3]} -% \rowcolor[gray]{0.9} -% \bfseries 123.456 \\ -% 23.45 \\ -% 123.4 \\ -% 3.456 \\ -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\subsection{Associating a locale with a \pkg{babel} language} -% -% It is possible to instruct the \pkg{babel} package to switch -% to a particular \pkg{siunitx} locale when changing language. This -% can be done using the \pkg{babel} \cs{extras\meta{language}} -% system. For example, to associate the \texttt{DE} locale with -% the \texttt{german} \pkg{babel} language, the appropriate -% code would be -%\begin{LaTeXdemo}[code only] -% \addto\extrasgerman{\sisetup{locale = DE}} -%\end{LaTeXdemo} -% -%\section{Information for those upgrading} -% -%\subsection{Upgrading from version 1} -%\changes{v2.0a}{2010/05/28}{Fix various errors in \file{version-1} -% configuration file} -%\changes{v2.0a}{2010/05/28}{Detect use of version 1 options and -% automatically load appropriate configuration file} -%\changes{v2.0a}{2010/05/28}{Include high energy physics units in -% discussion of old configurations and in \file{version-1} -% configuration file} -%\changes{v2.0b}{2010/06/01}{Further improvements to \file{version-1} -% configuration file} -%\changes{v2.0r}{2010/08/02}{Error in definition for old -% \opt{decimalsymbol} option corrected} -%\changes{v2.1d}{2010/11/14}{Error with definition of version 1 option -% \opt{xspace} corrected} -% -% The key--value control system of \pkg{siunitx} has been completely -% rewritten for version 2, and at the same time some of the macros -% provided by the package have been renamed and reworked. The package -% can be loaded with a configuration file to provide most of the -% same options and defaults as in version 1: -%\begin{LaTeXdemo}[code only] -% \usepackage[version-1-compatibility]{siunitx} -%\end{LaTeXdemo} -% Many of the options from version 1 map to similar ones in version 2 -% (\cref{tab:opt:map}). The correspondence often includes a syntax -% change: consult details of the new options for the correct syntax for -% the new options. In some cases, the new approach is different to the -% older one, and in these cases the most appropriate option new has been -% listed in the table. -%\begin{center} -% \tablecaption{Mapping of version 1 options to version 2.} -% \label{tab:opt:map} -% \tablefirsthead{^^A -% \toprule -% \multicolumn{1}{l}{Version 1} & -% \multicolumn{1}{l}{See in version 2} \\ -% \midrule -% } -% \tablehead{^^A -% \multicolumn{2}{l}{\emph{Continued from previous page}} \\ -% \toprule -% \multicolumn{1}{l}{Version 1} & -% \multicolumn{1}{l}{See in version 2} \\ -% \midrule -% } -% \tabletail{^^A -% \bottomrule -% \multicolumn{2}{r}{\emph{Continued on next page}} \\ -% } -% \tablelasttail{\bottomrule} -% -% \begin{xtabular}{>{\ttfamily}l>{\ttfamily}l} -% addsign & explicit-sign \\ -% allowlitunits & free-standing-units \\ -% allowoptarg & unit-optional-argument \\ -% allowzeroexp & retain-zero-exponent \\ -% anglesep & arc-separator \\ -% astroang & angle-symbol-over-decimal \\ -% closeerr & close-bracket \\ -% closefrac & close-bracket \\ -% closerange & close-bracket \\ -% colour & color \\ -% colorall & color \\ -% colourall & color \\ -% colorunits & unit-color \\ -% colorneg & negative-color \\ -% colourneg & negative-color \\ -% colourunits & unit-color \\ -% colorvalues & number-color \\ -% colourvalues & number-color \\ -% decimalsymbol & output-decimal-marker \\ -% detectdisplay & detect-display-math \\ -% digitsep & group-separator \\ -% dp & round-mode \\ -% & round-precision \\ -% errspace & uncertainty-separator \\ -% expbase & exponent-base \\ -% expproduct & exponent-product \\ -% fixdp & round-mode \\ -% fixsf & round-mode \\ -% fraction & fraction-function \\ -% inlinebold & detect-inline-weight \\ -% locale & locale \\ -% mathOmega & math-ohm \\ -% mathcelsius & math-celsius \\ -% mathdegree & math-degree \\ -% mathminute & math-arcminute \\ -% mathmu & math-micro \\ -% mathringA & math-angstrom \\ -% mathrm & math-rm \\ -% mathsOmega & math-ohm \\ -% mathscelsius & math-celsius \\ -% mathsdegree & math-degree \\ -% mathsecond & math-arcsecond \\ -% mathsf & math-sf \\ -% mathsminute & math-arcminute \\ -% mathsmu & math-micro \\ -% mathsringA & math-angstrom \\ -% mathsrm & math-rm \\ -% mathssecond & math-arcsecond \\ -% mathssf & math-sf \\ -% mathstt & math-tt \\ -% mathtt & math-tt \\ -% mode & mode \\ -% negcolor & negative-color \\ -% negcolour & negative-color \\ -% numaddn & input-symbols \\ -% numcloseerr & input-close-uncertainty \\ -% numdecimal & input-decimal-markers \\ -% numdigits & input-digits \\ -% numdiv & input-quotient \\ -% numexp & input-exponent-markers \\ -% numgobble & input-ignore \\ -% numopenerr & input-open-uncertainty \\ -% numprod & input-product \\ -% numsign & input-signs \\ -% obeyall & detect-all \\ -% obeybold & detect-weight \\ -% obeyfamily & detect-family \\ -% obeyitalic & detect-shape \\ -% obeymode & detect-mode \\ -% openerr & open-bracket \\ -% openfrac & open-bracket \\ -% openrange & open-bracket \\ -% padangle & add-arc-degree-zero \\ -% & add-arc-minute-zero \\ -% & add-arc-second-zero \\ -% padnumber & add-decimal-zero \\ -% & add-integer-zero \\ -% per & per-mode \\ -% prefixsymbolic & prefixes-as-symbols \\ -% prespace & space-before-unit \\ -% redefsymbols & redefine-symbols \\ -% repeatunits & multi-part-units \\ -% & product-units \\ -% & range-units \\ -% retainplus & retain-explicit-plus \\ -% seperr & separate-uncertainty \\ -% sepfour & group-four-digits \\ -% sf & round-mode \\ -% & round-precision \\ -% sign & explicit-sign \\ -% slash & per-symbol \\ -% stickyper & sticky-per \\ -% strict & strict \\ -% tabalign & table-alignment \\ -% tabalignexp & table-align-exponent \\ -% tabautofit & table-auto-round \\ -% tabformat & table-format \\ -% tabnumalign & table-number-alignment \\ -% tabparseonly & table-parse-only \\ -% tabexpalign & table-align-exponent \\ -% tabtextalign & table-text-alignment \\ -% tabunitalign & table-unit-alignment \\ -% textcelsius & text-celsius \\ -% textdegree & text-degree \\ -% textminute & text-arcminute \\ -% textmode & mode \\ -% textmu & text-micro \\ -% textOmega & text-ohm \\ -% textringA & text-angstrom \\ -% textrm & text-rm \\ -% textsecond & text-arcsecond \\ -% textsf & text-sf \\ -% texttt & text-tt \\ -% tightpm & tight-spacing \\ -% tophrase & range-phrase \\ -% trapambigerr & multi-part-units \\ -% trapambigfrac & bracket-numbers \\ -% trapambigrange & range-units \\ -% unitcolor & unit-color \\ -% unitcolour & unit-color \\ -% unitmathrm & unit-math-rm \\ -% unitmathsf & unit-math-sf \\ -% unitmathsrm & unit-math-rm \\ -% unitmathssf & unit-math-sf \\ -% unitmathstt & unit-math-tt \\ -% unitmathtt & unit-math-tt \\ -% unitmode & unit-mode \\ -% unitsep & inter-unit-product \\ -% unitspace & inter-unit-product \\ -% valuecolor & number-color \\ -% valuecolour & number-color \\ -% valuemathrm & number-math-rm \\ -% valuemathsf & number-math-sf \\ -% valuemathsrm & number-math-rm \\ -% valuemathssf & number-math-sf \\ -% valuemathstt & number-math-tt \\ -% valuemathtt & number-math-tt \\ -% valuemode & value-mode \\ -% valuesep & number-unit-product \\ -% xspace & use-xspace \\ -% \end{xtabular} -%\end{center} -% A small number of the options from version 1 are used unchanged in -% version 2, for example the \opt{mode} setting. These are listed above -% but require no action on the part of the user. There are also a -% few options which are no longer used at all, and are therefore ignored -% by the current code. -% -% Loading configuration files has been completely changed, and this -% means that the options \opt{alsoload}, \opt{load} and \opt{noload} are -% ignored by version 2. In the same way the options \opt{debug} and -% \opt{log} are not used by the current release of \pkg{siunitx}, as -% this information is usually only needed by the package author. -% Emulation of older packages is no longer offered (it was intended -% to help with the transition form earlier packages), and so the -% \opt{emulate} option no longer applies. -% -%\subsection{Upgrading from version 2.0 or 2.1} -% -% User feedback on \pkg{siunitx} means that over time some renaming -% takes place. The following functions and options have been deprecated -% in version 2.2. They are therefore available in version 2.2, but -% should be replaced in new or updated documents with the successor -% names. -% -%\DescribeOption{angle-unit-separator} -%\DescribeOption{inter-unit-separator} -%\DescribeOption{number-unit-separator} -%\changes{v2.2}{2011/03/20}{Renamed \opt{angle-unit-separator} option -% to \opt{angle-unit-product}} -%\changes{v2.2}{2011/03/20}{Renamed \opt{inter-unit-separator} option -% to \opt{inter-unit-product}} -%\changes{v2.2}{2011/03/20}{Renamed \opt{number-unit-separator} option -% to \opt{number-unit-product}} -% These options have been replaced by the options -%\begin{itemize} -% \item \opt{angle-unit-product} -% \item \opt{inter-unit-product} -% \item \opt{number-unit-product} -%\end{itemize} -% as these items are formally products, and the new option names -% emphasise this. -% -%\DescribeMacro{\DeclareSIUnitWithOptions} -%\changes{v2.2}{2011/04/01}{Depreciate \cs{DeclareSIUnitWithOptions}} -% The \cs{DeclareSIUnit} function has been extended to take a -% first optional argument, which removes the need for -% \cs{DeclareSIUnitWithOptions}. This function is therefore depreciated -% but retained for compatibility. -% -% \subsection{Upgrading from version 2.2} -% -% \DescribeOption{load-configurations} -% \changes{v2.3}{2011/03/20}{Load abbreviations as standard} -% \changes{v2.3}{2011/03/20}{Replace \opt{load-configurations} option -% with separate \opt{abbreviations}, \opt{binary-units} and -% \opt{version-1-compatibility} options} -% The option \opt{load-configurations} has been deprecated in favour of the -% three options \opt{abbreviations}, \opt{binary-units} and -% \opt{version-1-compatibility}. At the same time, loading of the abbreviations -% is now the standard behaviour, and so in most cases no -% explicit configuration file loading will be needed. -% -% \DescribeOption{group-decimal-digits} -% \DescribeOption{group-integer-digits} -% The digit grouping options have been revised, and the options -% \opt{group-decimal-digits} and \opt{group-integer-digits} are now -% integrated into \opt{group-digits}. -% \DescribeOption{group-four-digits} -% At the same time, the \opt{group-four-digits} option has been extended -% to the new option \opt{group-minimum-digits}. -% -% \DescribeOption{literal-superscript-as-power} -% The new {literal-superscript-as-power} option means that the standard -% behaviour now uses the current math font for superscripts, even when -% units are printed literally. This will only be obvious in documents such -% as this manual, where the text and math mode numerals are (deliberately) -% different. To restore the previous behaviour, set -% \opt{literal-superscript-as-power = false}. -% -% \subsection{Upgrading from version 2.3} -% -% The number of options which assume that the input is given in math mode -% has been significantly reduced. As most material can be typeset in either -% math or text mode, the \enquote{intrinsic} math mode options could lead to -% inconsistent output. The only options which now force math mode are those -% for products, which will almost always require the use of math mode. -% -% \subsection{Upgrading from version 2.4} -% -% The process of removing options which assume math mode, begun with -% version~2.4, has been taken further, and only \opt{output-product} -% and \opt{exponent-product} now do not require \cs{ensuremath} for material -% which must be in math mode. The standard settings have been altered to take -% account of this, but user-set options for products may need to be updated -% accordingly. -% -% \subsection{Upgrading from version 2.5} -% -% All printing now takes place in math mode (\emph{i.e.}~\opt{mode = math} -% is set). This may alter the appearance of some units, and users may want -% to verify the output is correct. -% -%\section{Correct application of (SI) units} -% -% Consistent and logical units are a necessity for scientific work, -% and have applicability everywhere. Historically, a number of -% systems have been used for physical units. SI units were -% introduced by the \emph{Conf{\'e}rence G{\'e}n{\'e}rale des Poids et -% Mesures} (CGPM) in 1960. SI units are a coherent system based on -% seven base units, from which all other units may be derived. -% -% At the same time, physical quantities with units are mathematical -% entities, and as such way that they are typeset is important. In -% mathematics, changes of type (such as using bold, italic, sans -% serif typeface and so on) convey information. This means that -% rules exist not only for the type of units to be used under the SI -% system, but also the way they should appear in print. Advice on -% best practice has been made available by the \emph{National -% Institute of Standards and Technology} (NIST) \cite{NIST}. -% -% As befits an agreed international standard, the full rules are -% detailed. It is not appropriate to reproduce these in totality -% here; instead, a useful summary of the key points is provided. The -% full details are available from the \emph{Bureau International des -% Poids et Mesures} \cite{BIPM}. -% -% \pkg{siunitx} takes account of the information given here, so far as -% is possible. Thus the package defaults follow the recommendations -% made for typesetting numbers and units. Spacing and so forth is -% handled in such a way as to make implementing the rules -% (relatively) easy. -% -%\subsection{Units} -% -% There are seven base SI units, listed in \cref{tab:unit:base}. -% Apart from the kilogram, these are defined in terms of a measurable -% physical quantity needing the definition alone.\footnote{Some base -% units need others defined first; there is therefore a required -% order of definition.} The base units have been chosen such that -% all physical quantities can be expressed using an appropriative -% combination of these units, needing no others and with no -% redundancy. The kilogram is slightly different from the other base -% units as it is still defined in terms of a \enquote{prototype} held in -% Paris. -% -% All other units within the SI system are regarded as \enquote{derived} -% from the seven base units. At the most basic, all other SI units -% can be expressed as combinations of the base units. However, many -% units (listed in \cref{tab:unit:derived,tab:unit:accepted}) have a -% special name and symbol. Most of these units are simple combinations -% of one or more base units (raised to powers as appropriate). A small -% number of units derived from experimental data are allowed as SI -% units (\cref{tab:unit:physical}). -% -% A series of SI prefixes for decimal multiples and sub-multiples are -% provided, and can be used as modifiers for any SI unit (either base -% or derived units) with the exception of the kilogram. The prefixes -% are listed in \cref{tab:unit:prefix}. No space should be used -% between a prefix and the unit, and only a single prefix should be -% used. Even the degree Celsius can be given a prefix, for example -% \SI{1}{\milli\degreeCelsius}. -% -% It is important to note that the kilogram is the only SI unit with -% a prefix as part of its name and symbol. Only single prefix may -% be used, and so in the case of the kilogram prefix names are used -% with the unit name \enquote{gram} and the prefix symbols are used with -% the unit symbol \si{\gram}. For example -% \( \SI[prefixes-as-symbols = false]{1}{\milli\gram} = -% \SI{1}{\milli\gram} \). -% -% The application of SI units is meant to provide a single set of -% units which ensure consistency and clarity across all areas. -% However, other units are common is many areas, and are not without -% merit. The units provided by \pkg{siunitx} by default do not include -% any of these; only units which are part of the SI set or are -% accepted for use with SI units are defined. However, several other -% sets of units can be loaded as optional modules. The binary -% prefixes and units (\cref{tab:unit:binary}) are the most obvious -% example. These are \emph{not} part of the SI specifications, but the -% prefix names are derived from those in \cref{tab:unit:prefix}. -% -% Other units are normally to be avoided where possible. SI units -% should, in the main, be preferred due to the advantages of clear -% definition and self-consistency this brings. However, there will -% probably always be a place for specialist or non-standard units. -% This is particularly true of units derived from basic physical -% constants. -% -% There are also many areas where non-standard units are used so -% commonly that to do otherwise is difficult or impossible. For -% example, most synthetic chemists measure the pressure inside vacuum -% apparatus in \si{\mmHg}, partly because the most common gauge for -% the task still uses a column of mercury metal. For these reasons, -% \pkg{siunitx} does define non-SI units. -% -%\subsection{Mathematical meaning} -% -% As explained earlier, a number--unit combination is a single -% mathematical entity. This has implications for how both the number -% and the unit should be printed. Firstly, the two parts should not -% be separated: a quantity is a product of the number and the unit. -% With the exception of the symbols for plane angles (\si{\degree}, -% \si{\arcminute} and \si{\arcsecond}), the \textsc{bipm} -% specifies either a space or half-height (centred) dot should be -% used \cite{BIPM}. -%\begin{LaTeXdemo} -% A space for \SI{10}{\percent}\\ -% and also for \SI{100}{\degreeCelsius}\\ -% but not for \ang{1.23}. -%\end{LaTeXdemo} -% -% The mathematical meaning of units also means that the shape, weight -% and family are important. Units are supposed to be typeset in an -% upright, medium weight font. Italic, bold and sans serif are -% all used mathematically to convey other meanings. (In an all -% sans serif document, using sans serif for units is reasonable.) -% The \pkg{siunitx} -% package defaults again follow this convention: any local settings are -% ignored, and uses the current upright math font. However, -% there are occasions where this may not be the most desirable -% behaviour. A classic example would be in an all-bold section -% heading. As the surrounding text is bold, some people feel that -% any units should follow this. -%\begin{LaTeXdemo} -% Units should \textbf{not be bold: \SI{54}{\farad}}\\ -% \textbf{But perhaps in a running block,\\ -% it might look better: \SI[detect-weight]{54}{\farad}} -%\end{LaTeXdemo} -% -% Symbols for units formed from other units by multiplication are -% indicated by means of either a half-height (that is, centred) dot -% or a (thin) space. -%\begin{LaTeXdemo} -% \( \si{\metre\second} = \text{metre second} \) \\ -% \( \si{\milli\second} = \text{millisecond} \) \\ -% \sisetup{inter-unit-product = \ensuremath { { } \cdot { } } } -% \( \si{\metre\second} = \text{metre second} \) \\ -% \( \si{\milli\second} = \text{millisecond} \) -%\end{LaTeXdemo} -% There are some circumstances under which it is common practice to omit -% any spaces. The classic example is \si{\kWh}, where -% \enquote{\si[inter-unit-product = \,]{\kWh}} does not add any -% useful information. If using such a unit repeatedly, users of -% \pkg{siunitx} are advised to create a custom unit to ensure -% consistency. It is important to note that while this is common -% practice, it is \emph{not} allowed by the \textsc{bipm} -% \cite{BIPM}. -% -% Symbols for units formed from other units by division are indicated -% by means of a virgule (oblique stroke, slash, "/"), a horizontal -% line, or negative exponents.\footnote{Notice that a virgule and a -% solidus are not the same symbol.} However, to avoid ambiguity, the -% virgule must not be repeated on the same line unless parentheses -% are used. This is ensured when using named unit macros in -% \pkg{siunitx}, which will \enquote{trap} repeated division and format -% it correctly. In complicated cases, negative exponents are to be -% preferred over other formats. -%\begin{LaTeXdemo} -% \si{\joule\per\mole\per\kelvin}\\ -% \si[per-mode = fraction]{\joule\per\mole\per\kelvin}\\ -% \si[per-mode = symbol]{\joule\per\mole\per\kelvin} -%\end{LaTeXdemo} -% -% Products and errors should show what unit applies to each number -% given. Thus \SI[product-units = brackets]{2x3}{\metre} is an -% ordered set of lengths of a geometric area, whereas -% \SI[product-units = single]{2x3}{\metre} is a length (and equal -% to \SI{6}{\metre}). Thus, \(\times\) is not a product but is a -% mathematical operator; in the same way, a \(2 \times 3\) matrix is not -% a \(6\) matrix! In some areas, areas and volumes are given with -% separated units but a unit raised to the appropriate power: -% \SI[product-units = power]{2 x 3}{\metre}. Although this does -% display the correct overall units, it is potentially-confusing and is -% not encouraged. -% -% Care must be taken when writing ranges of numbers. For purely -% numerical values, it is common to use a en-dash to show a range, for -% example \enquote{see pages 1--5}. On the other hand, physical -% quantities could be misinterpret as negative values if written in this -% way. As the unit--number combination is a single mathematical entity, -% writing the values with an en-dash followed by a single unit is also -% incorrect. As a result, using the word \enquote{to} is strongly -% recommended. -%\begin{LaTeXdemo} -% \SIrange{1}{5}{\metre} long. -%\end{LaTeXdemo} -% -%\subsection{Graphs and tables} -% -% In graphs and tables, repetition of the units following each entry -% or axis mark is confusing and repetitive. It is therefore best to -% place the unit in the label part of the information. Placing the -% unit in square brackets is common but mathematically -% poor.\footnote{For example, for an acceleration \(a\), the expression -% \([a]\) is the dimensions of \(a\), \emph{i.e.}~length per time -% squared in this case.} Much better is to show division of all -% quantities by the unit, which leaves the entries as unitless ratios. -% This is illustrated in \cref{tab:xmpl:unitless} and -% \cref{fig:xmpl:unitless}. -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \centering -% \caption{An example of table labelling.} -% \label{tab:xmpl:unitless} -% \sisetup{ -% table-number-alignment = center, -% table-figures-integer = 1, -% table-figures-decimal = 4 -% } -% \begin{tabular}{cS} -% \toprule -% Entry & {Length/\si{\metre}} \\ -% \midrule -% 1 & 1.1234 \\ -% 2 & 1.1425 \\ -% 3 & 1.7578 \\ -% 4 & 1.9560 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -%\begin{LaTeXdemo}[code and float] -% \begin{figure} -% \centering -% \begin{tikzpicture} -% \begin{axis}[ -% xlabel = \( t/\si{\second} \), -% xmax = 6, -% xmin = 0, -% ylabel = \( d/\si{\metre} \), -% ymin = 0 -% ] -% \addplot[smooth,mark=*] -% plot coordinates { -% (0,0) -% (1,5) -% (2,8) -% (3,9) -% (4,8) -% (5,5) -% (6,0) -% }; -% \end{axis} -% \end{tikzpicture} -% \caption{An example of graph labelling.} -% \label{fig:xmpl:unitless} -% \end{figure} -%\end{LaTeXdemo} -% -% In most cases, adding exponent values in the body of a table is -% less desirable than adding a fixed exponent to column headers. An -% example is shown in \cref{tab:good}. The use of \cs{multicolumn} is -% needed here due to the \enquote{\texttt{<}}; without \cs{multicolumn}, -% the titles are followed by \enquote{\si{\kilo\gram}}! -%\begin{LaTeXdemo}[code and float] -% \begin{table} -% \centering -% \caption{Good and bad columns.} -% \label{tab:good} -% \sisetup{table-number-alignment = center} -% \begin{tabular}{ -% c -% S[ -% table-figures-integer = 1, -% table-figures-decimal = 3, -% table-figures-exponent = 1 -% ] -% @{\,\si{\kilogram}} -% S[ -% table-figures-integer = 2, -% table-figures-decimal = 2 -% ] -% } -% \toprule -% Entry & \multicolumn{1}{c}{Mass} & -% {Mass/\SI{e3}{\kilogram}} \\ -% \midrule -% 1 & 4.56e3 & 4.56 \\ -% 2 & 2.40e3 & 2.40 \\ -% 3 & 1.345e4 & 13.45 \\ -% 4 & 4.5e2 & 0.45 \\ -% \bottomrule -% \end{tabular} -% \end{table} -%\end{LaTeXdemo} -% -%\section{Making suggestions and reporting bugs} -% -% Feedback on \pkg{siunitx} is always welcome, either to make -% suggestions or to report problems. When sending feedback, it is -% always useful if a small example file is included, showing the -% bug being reported or illustrating the desired output. It is -% helpful if a \enquote{reference rendering} is included, showing what -% the output should look like. A typical example file might read -%\begin{LaTeXdemo}[code only] -% \listfiles -% % Use the article class unless the problem is class-dependent -% \documentclass{article} -% \usepackage{siunitx} -% % Other packages loaded as required -% \begin{document} -% Reference output: $ 1.23\,\mathrm{m} $ -% -% siunitx output: \SI{1.23}{\metre} -% \end{document} -%\end{LaTeXdemo} -% As illustrated, it is usually best to use the \texttt{article} -% class and to only load packages which are needed to show the issue. -% It is also useful to include a copy of the log file generate by -% \TeX{} when reporting a bug (as the versions of packages can be -% important to solving the issue). +%<*driver> +\documentclass{l3doc} +% The next line is needed so that \GetFileInfo will be able to pick up +% version data +\usepackage{siunitx} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi % -% Feedback can be sent in a range of ways. The development code -% is hosted by -% \href{https://github.com/josephwright/siunitx/}{GitHub}, -% and the site includes an issue tracker. Adding feedback directly -% to the database means that other users can see it, and also -% ensures that it does not get forgotten. E-mailing directly -% will also definitely get attention: -% \href{mailto:joseph.wright@morningstar2.co.uk} -% {\texttt{joseph.wright@morningstar2.co.uk}}. +% \GetFileInfo{siunitx.sty} % -% \section{Code level interfaces} +% \title{^^A +% \pkg{siunitx} -- Overall set up^^A +% \thanks{This file describes \fileversion, +% last revised \filedate.}^^A +% } % -% At present, most interfaces in \pkg{siunitx} at the code level are internal. -% This largely reflects the parallel between \pkg{siunitx} and core \pkg{expl3} -% development: much of the code here was written whilst the \LaTeX{} team were -% defining how best to handle this area. Development work on the next major -% release of \pkg{siunitx} includes a full set of documented code level -% interfaces. Some of these will be added to this (release) version of the -% package over time, where this is appropriate. +% \author{^^A +% Joseph Wright^^A +% \thanks{^^A +% E-mail: +% \href{mailto:joseph.wright@morningstar2.co.uk} +% {joseph.wright@morningstar2.co.uk}^^A +% }^^A +% } % -% \begin{variable}{\l_siunitx_unit_symbolic_seq} -% This sequence contains all of the symbolic \meta{unit} names defined: -% these will be in the form of control sequences such as |\kilogram|. -% The order of the sequence is unimportant. -% \end{variable} +% \date{Released \filedate} % -%\section{Thanks} +% \maketitle % -% Many users have provided feedback, bug reports and ideas for new -% features for \pkg{siunitx}: thanks to all of them. Particular thanks -% to Stefan Pinnow, who has taken the lead role as beta tester for -% \pkg{siunitx}, finding incorrect output, bad documentation and the -% odd spelling mistake in the documentation. Thanks also to -% Danie Els and Marcel Heldoorn for the \pkg{SIstyle} and \pkg{SIunits} -% packages, respectively, which provided the starting point for the -% development of \pkg{siunitx}. +% \begin{documentation} % -%\end{documentation} +% \end{documentation} % -%\begin{implementation} +% \begin{implementation} % -%\section{Implementation} +% \section{\pkg{siunitx} implementation} % +% Start the \pkg{DocStrip} guards. % \begin{macrocode} %<*package> % \end{macrocode} % +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention). % \begin{macrocode} %<@@=siunitx> % \end{macrocode} % -%\subsection{Preliminaries} -% -% The usual preliminaries. -% \begin{macrocode} -\ProvidesExplPackage {siunitx} {2021-04-17} {2.8e} - {A comprehensive (SI) units package} -% \end{macrocode} +% \subsection{Initial set up} % -% Make sure that the version of \pkg{l3kernel} in use is sufficiently new. -% This will also trap any problems with \pkg{l3packages} (as the two are now -% tied together, version-wise). % \begin{macrocode} -\@ifpackagelater { expl3 } { 2020/01/12 } - { } - { - \PackageError { siunitx } { Support~package~expl3~too~old } - { - You~need~to~update~your~installation~of~the~bundles~'l3kernel'~and~ - 'l3packages'.\MessageBreak - Loading~siunitx~will~abort! - } - \tex_endinput:D - } +%<*init> % \end{macrocode} % -%\begin{macro}{\@@_load_check:} -% There are also a number of packages that are incompatible with -% \pkg{siunitx}. These are all checked for next. Some of the -% incompatible packages will not raise an error if loaded after -% \pkg{siunitx}. So a test is made at the beginning of the -% document as well. The message for this may be needed immediately, so -% it is created here not with the other messages. +% Set up a couple of commands in recent-ish \LaTeXe{} releases. % \begin{macrocode} -\msg_new:nnnn { siunitx } { incompatible-package } - { Package~'#1'~incompatible. } - { The~#1~package~and~siunitx~are~incompatible. } -\cs_new_protected:Npn \@@_load_check:n #1 { - \group_begin: - \@ifpackageloaded {#1} - { \msg_error:nnx { siunitx } { incompatible-package } {#1} } - { } - \group_end: -} -\clist_map_function:nN - { SIunits , sistyle , siunits , SIstyle , unitsdef , fancyunits } - \@@_load_check:n -\AtBeginDocument { - \clist_map_function:nN { SIunits , sistyle , siunits , SIstyle } - \@@_load_check:n -} -% \end{macrocode} -%\end{macro} -% -% Now load the support packages. -% \begin{macrocode} -\RequirePackage{ amstext , array , l3keys2e } -% \end{macrocode} -% -% \begin{macro}{@@_if_hooks:TF} -% To work with updated hooks if available. -% \begin{macrocode} -\@ifl@t@r \fmtversion { 2020-10-01 } - { \cs_new_eq:NN \@@_if_hooks:TF \use_i:nn } - { \cs_new_eq:NN \@@_if_hooks:TF \use_ii:nn } -% \end{macrocode} -% \end{macro} -% -%\begin{macro}{\@@_tmp:w} -% A scratch function. -% \begin{macrocode} -\cs_new:Npn \@@_tmp:w { } -% \end{macrocode} -%\end{macro} -% -% Add some variants. -% \begin{macrocode} -\cs_generate_variant:Nn \clist_map_function:nN { nc } -\cs_generate_variant:Nn \tl_if_blank:nTF { V } -\cs_generate_variant:Nn \tl_replace_all:Nnn { No, NV , Nx } -% \end{macrocode} -% -%\begin{macro}{ -% \l_@@_tmp_bool , -% \l_@@_tmp_box , -% \l_@@_tmp_dim , -% \l_@@_tmp_int , -% \l_@@_tmpa_tl , -% \l_@@_tmpb_tl -%} -% Scratch variables. -% \begin{macrocode} -\bool_new:N \l_@@_tmp_bool -\box_new:N \l_@@_tmp_box -\dim_new:N \l_@@_tmp_dim -\int_new:N \l_@@_tmp_int -\tl_new:N \l_@@_tmpa_tl -\tl_new:N \l_@@_tmpb_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_error:nxx , -% \@@_error:nx , -% \@@_error:n -%} -%\begin{macro}{\l_@@_error_bool} -% General-purpose functions for throwing errors. -% \begin{macrocode} -\cs_new_protected:Npn \@@_error:nxx #1#2#3 { - \bool_set_true:N \l_@@_error_bool - \msg_error:nnxx { siunitx } {#1} {#2} {#3} -} -\cs_new_protected:Npn \@@_error:nx #1#2 { - \@@_error:nxx {#1} {#2} { } -} -\cs_new_protected:Npn \@@_error:n #1 { - \@@_error:nxx {#1} { } { } -} -\bool_new:N \l_@@_error_bool -% \end{macrocode} -%\end{macro} -%\end{macro} -% -% Ensure that the companion font is loaded. -% \begin{macrocode} -\AtBeginDocument { - \cs_if_free:cT { T@TS1 } - { \RequirePackage { textcomp } } -} -% \end{macrocode} -% -% \begin{macro} -% { -% \@@_tl_put_left_math:Nn , -% \@@_tl_put_left_math:NV , -% } -% To add stuff in math mode. -% \begin{macrocode} -\cs_new_protected:Npn \@@_tl_put_left_math:Nn #1#2 - { \tl_put_left:Nn #1 { \ensuremath {#2} } } -\cs_generate_variant:Nn \@@_tl_put_left_math:Nn { NV } -% \end{macrocode} -% \end{macro} -% -%\begin{macro}{\c_@@_old_options_seq} -% To pick up old options, all of the names need to be known. -% \begin{macrocode} -\exp_args:NNx \seq_const_from_clist:Nn \c_@@_old_options_seq - { - \tl_to_str:n - { - addsign , - allowlitunits , - allowoptarg , - allowzeroexp , - alsoload , - angformat , - anglesep , - astroang , - closeerr , - closrfrac , - closerange , - colour , - colorall , - colourall , - colorneg , - colourneg , - colourunits , - colourunits , - colorvalues , - colourvalues , - decimalsymbol , - debug , - detectdisplay , - digitsep , - dp , - emulate , - errspace , - eVcorra , - eVcorrb , - expbase , - expproduct , - fixdp , - fixsf , - fraction , - inlinebold , - loctolang , - log , - load , - mathOmega , - mathcelsius , - mathdegree , - mathminute , - mathmu , - mathringA , - mathrm , - mathsOmega , - mathscelsius , - mathsdegree , - mathsecond , - mathsf , - mathsminute , - mathsmu , - mathsringA , - mathsrm , - mathssecond , - mathssf , - mathstt , - mathtt , - negcolor , - negcolour , - noload , - numaddn , - numcloseerr , - numdecimal , - numdigits , - numdiv , - numexp , - numgobble , - numopenerr , - numprod , - numsign , - obeyall , - obeybold , - obeyfamily , - obeymode , - obeyitalic , - openerr , - openfrac , - openrange , - padangle , - padnumber , - per , - prefixbase , - prefixproduct , - prefixsymbolic , - prespace , - redefsymbols , - repeatunits , - retainplus , - seperr , - sepfour , - sf , - sign , - slash , - stickyper , - strictarc , - tabalign , - tabalignexp , - tabautofit , - tabexpalign , - tabformat , - tabnumalign , - tabparseonly , - tabtextalign , - textOmega , - textcelsius , - textdegree , - textminute , - textmode , - textmu , - textringA , - textrm , - textsecond , - textsf , - texttt , - tightpm , - tophrase , - trapamigerr , - trapambigfrac , - trapambigrange , - unitcolor , - unitcolour , - unitmathrm , - unitmathsf , - unitmathsrm , - unitmathssf , - unitmathstt , - unitmathtt , - unitmode , - unitsep , - unitspace , - valuecolor , - valuecolour , - valuemathrm , - valuemathsf , - valuemathsrm , - valuemathssf , - valuemathstt , - valuemathtt , - valuemode , - valuesep , - xspace - } - } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_key_tl} -% Unknown options should raise an \pkg{siunitx}-specific error message. -% \begin{macrocode} -\tl_new:N \l_@@_key_tl -\keys_define:nn { siunitx } { - unknown .code:n = - { - \seq_if_in:NVTF \c_@@_old_options_seq \l_keys_key_tl - { - \msg_warning:nnx { siunitx } { version-1-option } - { \exp_not:V \l_keys_key_tl } - \tl_set:Nx \l_@@_key_tl - { - \keys_set:nn { siunitx } - { - \exp_not:V \l_keys_key_tl - \tl_if_blank:nF {#1} { = \exp_not:n {#1} } - } - } - \keys_set:nn { siunitx } { version-1-compatibility } - \tl_use:N \l_@@_key_tl - } - { - \msg_error:nnx { siunitx } { unknown-option } - { \exp_not:V \l_keys_key_tl } - } - } -} -\AtBeginDocument { - \keys_define:nn { siunitx } { - unknown .code:n = - { - \seq_if_in:NVTF \c_@@_old_options_seq \l_keys_key_tl - { - \msg_error:nnx { siunitx } { version-1-option } - { \exp_not:V \l_keys_key_tl } - } - { - \msg_error:nnx { siunitx } { unknown-option } - { \exp_not:V \l_keys_key_tl } - } - } -} -} +\providecommand\DeclareRelease[3]{} +\providecommand\DeclareCurrentRelease[2]{} % \end{macrocode} -%\end{macro} % -%\begin{macro}{\@@_option_deactivate:n} -%\begin{macro}{\@@_option_deactivate_aux:n} -%\begin{macro}{\l_@@_option_deactivate_clist} -% Some options need to be deactivated at the start of the document. +% Allow rollback to version~$2$: if we need to, version~$1$ could eventually +% be added here too. % \begin{macrocode} -\cs_new_protected:Npn \@@_option_deactivate:n #1 { - \clist_put_right:Nn \l_@@_option_deactivate_clist {#1} -} -\cs_new_protected:Npn \@@_option_deactivate_aux:n #1 { - \keys_define:nn { siunitx } - { - #1 .code:n = - { \msg_warning:nnx { siunitx } { option-preamble-only } {#1} } - } -} -\AtBeginDocument { - \clist_map_function:NN \l_@@_option_deactivate_clist - \@@_option_deactivate_aux:n -} -\clist_new:N \l_@@_option_deactivate_clist +\DeclareRelease{2}{2010-05-23}{siunitx-v2.sty} +\DeclareRelease{v2}{2010-05-23}{siunitx-v2.sty} +\DeclareCurrentRelease{}{2021-05-17} % \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} % -% \begin{macro}{\@@_option_unchanged:Nnn} -% Needed to allow for altering of options at the start of the document -% only if they are unchanged. This needs to use the low-level implementation -% detail, hence the use of variable name directly. +% Load only the essential support (\pkg{expl3}) \enquote{up-front}, and +% only if required. % \begin{macrocode} -\cs_new_protected:Npn \@@_option_unchanged:Nnn #1#2#3 - { - \str_if_eq:VnT #1 {#2} - { \tl_set:Nn #1 {#3} } - } +\@ifundefined{ExplFileDate} + {\RequirePackage{expl3}} + {} % \end{macrocode} -% \end{macro} % -% Variants needed which are not in \pkg{expl3}. -% \begin{macrocode} -\cs_generate_variant:Nn \tl_if_empty_p:n { f } -\cs_generate_variant:Nn \tl_if_empty:nT { f } -\cs_generate_variant:Nn \tl_if_in:NnTF { NV } -\cs_generate_variant:Nn \tl_replace_all:Nnn { NnV } +% Make sure that the version of \pkg{l3kernel} in use is sufficiently new. +% We use \cs{ExplFileDate} as \cs{@ifpackagelater} doesn't work for pre-loaded +% \pkg{expl3} in the absence of the package. +% \begin{macrocode} +\@ifl@t@r\ExplFileDate{2018-06-01} + {} + {% + \PackageError{siunitx}{Support package expl3 too old} + {% + You need to update your installation of the bundles 'l3kernel' and + 'l3packages'.\MessageBreak + Loading~siunitx~will~abort!% + }% + \endinput + }% % \end{macrocode} % -% \begin{macro}[pTF]{\@@_cs_if_tl:N} -% A test for token lists (more or less). +% Identify the package and give the over all version information. % \begin{macrocode} -\prg_new_conditional:Npnn \@@_cs_if_tl:N #1 { T, F , TF , p } - { - \bool_lazy_and:nnTF - { - \tl_if_empty_p:f - { - \cs_prefix_spec:N #1 - \cs_argument_spec:N #1 - } - } - { \bool_not_p:n { \cs_if_exist_p:c { \cs_to_str:N #1 ~ } } } - { \prg_return_true: } - { \prg_return_false: } - } +\ProvidesExplPackage {siunitx} {2021-05-17} {3.0.0} + {A comprehensive (SI) units package} % \end{macrocode} -% \end{macro} % -% \begin{macro}[EXP] -% {\@@_number_if_zero:nTF, \@@_number_if_zero_p:n \@@_number_if_zero_p:V} -% \begin{macro}[EXP, aux]{\@@_number_if_zero_aux:n} -% A test for all of the input to a function being made up of zeros: -% needed to avoid overflowing \TeX{}'s integer range. -% \begin{macrocode} -\prg_new_conditional:Npnn \@@_number_if_zero:n #1 { p , TF } - { - \tl_map_function:nN {#1} \@@_number_if_zero_aux:n - \prg_return_true: - } -\cs_generate_variant:Nn \@@_number_if_zero_p:n { V } -\cs_new:Npn \@@_number_if_zero_aux:n #1 - { - \token_if_eq_charcode:NNF #1 0 - { \tl_map_break:n { \prg_return_false: \use_none:n } } - } -% \end{macrocode} -% \end{macro} -% \end{macro} +% \subsection{Safety checks} % -% If \pkg{tex4ht} is in use, make a few changes to give nicer looking -% conversion to other formats. +% \begin{macro}{\@@_load_check:} +% There are a number of packages that are incompatible with \pkg{siunitx} +% as they cover the same concepts and in some cases define the same command +% names. These are all tested at the point of loading to try to trap +% issues, and a couple are also tested later as it's possible for them to +% load without an obvious error if \pkg{siunitx} was loaded first. % \begin{macrocode} -\AtBeginDocument +\msg_new:nnnn { siunitx } { incompatible-package } + { Package~'#1'~incompatible. } + { The~#1~package~and~siunitx~are~incompatible. } +\cs_new_protected:Npn \@@_load_check:n #1 { - \@ifpackageloaded { tex4ht } - { - \cs_set_eq:NN \@@_print_text_super:n \textsuperscript - \@@_option_unchanged:Nnn \l_@@_qualifier_mode_tl - { subscript } { brackets } - \keys_set:nn { siunitx } { mode = text } - } + \@ifpackageloaded {#1} + { \msg_error:nnx { siunitx } { incompatible-package } {#1} } { } } -% \end{macrocode} -% -% \begin{macro}{\@@_ensure_ltr:n} -% When the \pkg{bidi} package is loaded with \XeTeX{} we need to make sure -% that \cs{text} is doing the correct thing. The \pkg{bidi} package seems to -% lead to a slightly broken \cs{text}, so this is something of a hack. -% \begin{macrocode} -\cs_new_eq:NN \@@_ensure_ltr:n \use:n +\clist_map_function:nN + { SIunits , sistyle , unitsdef , fancyunits } + \@@_load_check:n \AtBeginDocument { - \@ifpackageloaded { bidi } - { - \sys_if_engine_xetex:T - { \cs_set_protected:Npn \@@_ensure_ltr:n #1 { \LRE {#1} } } - } - { } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_textsuperscript:n} -% This function is set up here so that it can be redefined -% elsewhere as expandable. That is used in the bookmark system so -% that \pkg{hyperref} does not raise any unnecessary warnings. With -% \pkg{fontspec} loaded the kernel defintion for \cs{textsuperscript} -% may get altered so a private copy of the orignal code is used. (Yes, -% this really should be done like Con\TeX{}t -% \begin{macrocode} -\cs_new_protected:Npn \@@_textsuperscript:n #1 - { - \m@th - \ensuremath { ^ { \mbox { \fontsize \sf@size \z@ \selectfont #1 } } } - } -% \end{macrocode} -% \end{macro} -% -%\begin{macro}{\l_@@_display_math_bool} -% To test for display math, a flag is added to the start of every -% display environment. -% \begin{macrocode} -\bool_new:N \l_@@_display_math_bool -\tex_everydisplay:D \exp_after:wN - { - \tex_the:D \tex_everydisplay:D - \bool_set_true:N \l_@@_display_math_bool - } -% \end{macrocode} -%\end{macro} -% -% \begin{macro}[TF]{\prop_get:NVN} -% Missing from \pkg{expl3} at the moment. -% \begin{macrocode} -\cs_generate_variant:Nn \prop_get:NnNT { NV } -\cs_generate_variant:Nn \prop_get:NnNF { NV } -\cs_generate_variant:Nn \prop_get:NnNTF { NV } -% \end{macrocode} -% \end{macro} -% -%\subsection{Font detection} -% -% A number of controls and tests are needed to control the font used -% for output. The detection routines set up various functions which can -% then be used inside the \cs{text} macro from the \pkg{amstext} -% package. By carrying out the changes outside math mode, bold can -% reliably be applied to math output. -% -%\begin{macro}{\@@_set_math_fam:n} -%\begin{macro}{ -% \c_@@_mathsf_int , -% \c_@@_mathtt_int -%} -% The detection routine needs some basic data about the sans serif and -% monospaced fonts in use. This is collected up at the start of the -% document. The families used can change between here and the start of -% the document. This is run as a hook onto \cs{document}, rather than -% using \cs{AtBeginDocument} as it has to come after anything that -% \pkg{fontspec} does (nasty errors arise otherwise). -% \begin{macrocode} -\cs_new_protected:Npn \@@_set_math_fam:n #1 { - \group_begin: - \hbox_set:Nn \l_@@_tmp_box - { - \ensuremath - { - \use:c { math #1 } - { - \int_const:cn { c_@@_math #1 _int } { \fam } - } - } - } - \group_end: -} -\@@_if_hooks:TF - { - \AddToHook { begindocument / end } [ siunitx ] - { - \@@_set_math_fam:n { sf } - \@@_set_math_fam:n { tt } - } - } - { - \tl_put_right:Nn \document - { - \@@_set_math_fam:n { sf } - \@@_set_math_fam:n { tt } - \ignorespaces - } + \clist_map_function:nN { SIunits , sistyle } + \@@_load_check:n } % \end{macrocode} %\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_font_set_text_fam:n} -%\begin{macro}{ -% \c_@@_textsf_tl , -% \c_@@_texttt_tl -%} -% The text families are done in a somewhat different manner: there are -% no issues with \cs{AtBeginDocument}, luckily. The need to define -% new macros here arises as \cs{sfdefault} and \cs{ttdefault} are -% \cs{long}, whereas \cs{f@family} is not. -% \begin{macrocode} -\cs_new_protected:Npn \@@_set_text_fam:n #1 { - \tl_const:cx { c_@@_text #1 _tl } { \use:c { #1 default } } -} -\AtBeginDocument { - \@@_set_text_fam:n { sf } - \@@_set_text_fam:n { tt } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\l_@@_detect_inline_weight_tl} -% Used by the keys, but needs to be created here. -% \begin{macrocode} -\tl_new:N \l_@@_detect_inline_weight_tl -% \end{macrocode} -%\end{macro} -% -% \begin{variable}{\l_@@_detect_inline_family_tl} -% This one is not generated by the keys system. -% \begin{macrocode} -\tl_new:N \l_@@_detect_inline_family_tl -% \end{macrocode} -% \end{variable} % -%\begin{macro}{ -% \l_@@_detect_display_math_bool , -% \l_@@_detect_family_bool , -% \l_@@_detect_inline_family_tl , -% \l_@@_detect_shape_bool , -% \l_@@_detect_mode_bool , -% \l_@@_detect_weight_bool -%} -% Font detection is all about creating switches, with just a little -% gloss for \texttt{detect-all} and \texttt{detect-none}. -% \begin{macrocode} -\keys_define:nn { siunitx } { - detect-all .choice:, - detect-all .default:n = true, - detect-all / false .meta:n = - { - detect-family = false , - detect-mode = false , - detect-shape = false , - detect-weight = false , - }, - detect-all / true .meta:n = - { - detect-family = true , - detect-mode = true , - detect-shape = true , - detect-weight = true , - }, - detect-display-math .bool_set:N = - \l_@@_detect_display_math_bool, - detect-family .bool_set:N = \l_@@_detect_family_bool, - detect-inline-family .choice:, - detect-inline-family .value_required:n = true, - detect-inline-family / - math .code:n = - { \tl_set:Nn \l_@@_detect_inline_family_tl { math } }, - detect-inline-family / - text .code:n = - { \tl_set:Nn \l_@@_detect_inline_family_tl { text } }, - detect-inline-weight .choice:, - detect-inline-weight .value_required:n = true, - detect-inline-weight / - math .code:n = - { \tl_set:Nn \l_@@_detect_inline_weight_tl { math } }, - detect-inline-weight / - text .code:n = - { \tl_set:Nn \l_@@_detect_inline_weight_tl { text } }, - detect-italic .bool_set:N = \l_@@_detect_shape_bool, - detect-mode .bool_set:N = \l_@@_detect_mode_bool, - detect-none .choice:, - detect-none .default:n = true, - detect-none / false .meta:n = - { - detect-family = true, - detect-mode = true, - detect-shape = true, - detect-weight = true - }, - detect-none / true .meta:n = - { - detect-family = false, - detect-mode = false, - detect-shape = false, - detect-weight = false - }, - detect-shape .bool_set:N = \l_@@_detect_shape_bool, - detect-weight .bool_set:N = \l_@@_detect_weight_bool -} -\keys_set:nn { siunitx } { - detect-inline-family = text , - detect-inline-weight = text , -} -% \end{macrocode} -%\end{macro} +% \subsection{Provide a kernel command} % -%\begin{macro}{ -% \l_@@_font_set_bool , -% \l_@@_font_math_mode_bool -%} -% The internals of the package need a number of switches to track what -% is happening. +% \begin{macro}{\IfFormatAtLeastTF} +% Not present in older kernels: use the \LaTeXe{} mechanism as this is correct +% for this case. % \begin{macrocode} -\bool_new:N \l_@@_font_set_bool -\bool_new:N \l_@@_font_math_mode_bool +\providecommand \IfFormatAtLeastTF { \@ifl@t@r \fmtversion } % \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_font_family_tl} -% Also some token storage. -% \begin{macrocode} -\tl_new:N \l_@@_font_family_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_font_shape: , -% \@@_font_weight: -%} -% These could be token lists or functions! -% \begin{macrocode} -\cs_new:Npn \@@_font_shape: { } -\cs_new:Npn \@@_font_weight: { } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_detect_font:} -% The main font-setting macro is a control point for the other -% functions. Nesting font-control should not happen, so the first -% test is to ensure this is not happening. -% \begin{macrocode} -\cs_new_protected:Npn \@@_detect_font: { - \bool_if:NF \l_@@_font_set_bool - { - \@@_detect_font_init: - \bool_if:NT \l_@@_detect_weight_bool - { \@@_detect_font_weight: } - \bool_if:NT \l_@@_detect_family_bool - { \@@_detect_font_family: } - \bool_if:NT \l_@@_detect_shape_bool - { \@@_detect_font_shape: } - \bool_if:NT \l_@@_detect_mode_bool - { \@@_detect_font_mode: } - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_detect_font_init:} -% Set up the basic macros on the assumption nothing happens. -% \begin{macrocode} -\cs_new_protected:Npn \@@_detect_font_init: { - \bool_set_true:N \l_@@_font_set_bool - \cs_set:Npn \@@_font_weight: - { - \unboldmath - \mdseries - } - \cs_set:Npn \@@_font_shape: { \upshape } - \tl_set:Nn \l_@@_font_family_tl { rm } - \bool_set_true:N \l_@@_font_math_mode_bool -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_detect_font_weight:} -% The font weight detection code depends on whether the current text is -% math or text, and also the type of math (if appropriate). For -% inline math, there is a choice of what test to apply. -% \begin{macrocode} -\cs_new_protected:Npn \@@_detect_font_weight: { - \mode_if_math:TF - { - \bool_if:NTF \l_@@_display_math_bool - { - \bool_if:NTF \l_@@_detect_display_math_bool - { \@@_detect_font_weight_math: } - { \@@_detect_font_weight_text: } - } - { - \use:c - { - @@_detect_font_weight_ - \l_@@_detect_inline_weight_tl - : - } - } - } - { \@@_detect_font_weight_text: } -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{ -% \@@_detect_font_weight_math: , -% \@@_detect_font_weight_text: -%} -% The tests for font weight depend on whether the module is testing -% text or math content. -% \begin{macrocode} -\cs_new_protected:Npn \@@_detect_font_weight_math: { - \str_if_eq:VnT \math@version { bold } - { - \cs_set:Npn \@@_font_weight: - { - \boldmath - \bfseries - } - } - \str_if_eq:VnT \math@version { light } - { \cs_set:Npn \@@_font_weight: { \lseries } } -} -\cs_new_protected:Npn \@@_detect_font_weight_text: { - \tl_set:Nx \l_@@_tmpa_tl { \tl_head:N \f@series } - \str_if_eq:VnT \l_@@_tmpa_tl { b } - { - \cs_set:Npn \@@_font_weight: - { - \boldmath - \bfseries - } - } - \str_if_eq:VnT \l_@@_tmpa_tl { l } - { \cs_set:Npn \@@_font_weight: { \lseries } } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_detect_font_family:} -% Family detection usually picks up the surrounding text. However, for -% display math there are two options, and so a second test may be made. -% \begin{macrocode} -\cs_new_protected:Npn \@@_detect_font_family: { - \mode_if_math:TF - { - \bool_if:NTF \l_@@_display_math_bool - { - \bool_if:NTF \l_@@_detect_display_math_bool - { \@@_detect_font_family_math: } - { \@@_detect_font_family_text: } - } - { - \use:c - { - @@_detect_font_family_ - \l_@@_detect_inline_family_tl - : - } - } - } - { \@@_detect_font_family_text: } -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{ -% \@@_detect_font_family_math: , -% \@@_detect_font_family_text: -%} -% The two detections routines check if the current font is sans serif or -% monospaced. The method used depends on whether the current math or -% text font is of interest. The math detection routine re-applies the -% default (\texttt{rm}), as the text function is always called and may -% have changed things. -% \begin{macrocode} -\cs_new_protected:Npn \@@_detect_font_family_math: { - \tl_set:Nn \l_@@_font_family_tl { rm } - \int_compare:nNnT { \fam } = { \c_@@_mathsf_int } - { \tl_set:Nn \l_@@_font_family_tl { sf } } - \int_compare:nNnT { \fam } = { \c_@@_mathtt_int } - { \tl_set:Nn \l_@@_font_family_tl { tt } } -} -\cs_new_protected:Npn \@@_detect_font_family_text: { - \tl_if_eq:NNT \f@family \c_@@_textsf_tl - { \tl_set:Nn \l_@@_font_family_tl { sf } } - \tl_if_eq:NNT \f@family \c_@@_texttt_tl - { \tl_set:Nn \l_@@_font_family_tl { tt } } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_detect_font_shape:} -% The shape test uses \cs{f@shape} as a handy indicator. -% \begin{macrocode} -\cs_new_protected:Npn \@@_detect_font_shape: - { - \cs_if_exist:cT { \f@shape shape } - { - \cs_set:Npx \@@_font_shape: { \exp_not:c { \f@shape shape } } - } - } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_detect_font_mode:} -% The mode switch works from the fact that math mode output it the -% standard. -% \begin{macrocode} -\cs_new_protected:Npn \@@_detect_font_mode: { - \mode_if_math:F - { - \bool_set_false:N \l_@@_font_math_mode_bool - \bool_set_false:N \l_@@_number_math_mode_bool - \bool_set_false:N \l_@@_unit_math_mode_bool - } -} -% \end{macrocode} -%\end{macro} -% -%\subsection{Font macros} -% -% With the detection routines in place, the module can apply the result -% to control the font used for output. This requires a series of font -% names to be available. The appropriate storage areas will be selected -% by name, based on output type (\texttt{unit} or \texttt{value}) and -% the family selected by the detector. -% -%\begin{macro}{ -% \l_@@_number_math_mode_bool , -% \l_@@_unit_math_mode_bool -%} -% Most of the variables are created by the keys system: these are not. -% \begin{macrocode} -\bool_new:N \l_@@_number_math_mode_bool -\bool_new:N \l_@@_unit_math_mode_bool -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_number_mathrm:n , -% \@@_number_mathsf:n , -% \@@_number_mathtt:n , -% \@@_number_textrm: , -% \@@_number_textsf: , -% \@@_number_texttt: -%} -% Functions for number-mode fonts. -% \begin{macrocode} -\cs_new:Npn \@@_number_mathrm:n #1 { } -\cs_new:Npn \@@_number_mathsf:n #1 { } -\cs_new:Npn \@@_number_mathtt:n #1 { } -\cs_new:Npn \@@_number_textrm: { } -\cs_new:Npn \@@_number_textsf: { } -\cs_new:Npn \@@_number_texttt: { } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_number_color_tl} -% The settings are actually created separately for numbers and units: -% numbers first. -% \begin{macrocode} -\keys_define:nn { siunitx } { - number-color .tl_set:N = \l_@@_number_color_tl, - number-math-rm .code:n = - { \cs_set:Npn \@@_number_mathrm:n ##1 { #1 {##1} } }, - number-math-sf .code:n = - { \cs_set:Npn \@@_number_mathsf:n ##1 { #1 {##1} } }, - number-math-tt .code:n = - { \cs_set:Npn \@@_number_mathtt:n ##1 { #1 {##1} } }, - number-mode .choice:, - number-mode / math .code:n = - { \bool_set_true:N \l_@@_number_math_mode_bool }, - number-mode / text .code:n = - { \bool_set_false:N \l_@@_number_math_mode_bool }, - number-text-rm .code:n = - { \cs_set:Npn \@@_number_textrm: {#1} }, - number-text-sf .code:n = - { \cs_set:Npn \@@_number_textsf: {#1} }, - number-text-tt .code:n = - { \cs_set:Npn \@@_number_texttt: {#1} } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_unit_mathrm:n , -% \@@_unit_mathsf:n , -% \@@_unit_mathtt:n , -% \@@_unit_textrm: , -% \@@_unit_textsf: , -% \@@_unit_texttt: -%} -% The same storage for unit-mode fonts. -% \begin{macrocode} -\cs_new:Npn \@@_unit_mathrm: { } -\cs_new:Npn \@@_unit_mathsf: { } -\cs_new:Npn \@@_unit_mathtt: { } -\cs_new:Npn \@@_unit_textrm: { } -\cs_new:Npn \@@_unit_textsf: { } -\cs_new:Npn \@@_unit_texttt: { } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_unit_color_tl} -% Units look exactly the same. -% \begin{macrocode} -\keys_define:nn { siunitx } { - unit-color .tl_set:N = \l_@@_unit_color_tl, - unit-math-rm .code:n = - { \cs_set:Npn \@@_unit_mathrm:n ##1 { #1 {##1} } }, - unit-math-sf .code:n = - { \cs_set:Npn \@@_unit_mathsf:n ##1 { #1 {##1} } }, - unit-math-tt .code:n = - { \cs_set:Npn \@@_unit_mathtt:n ##1 { #1 {##1} } }, - unit-mode .choice:, - unit-mode / math .code:n = - { \bool_set_true:N \l_@@_unit_math_mode_bool }, - unit-mode / text .code:n = - { \bool_set_false:N \l_@@_unit_math_mode_bool }, - unit-text-rm .code:n = - { \cs_set:Npn \@@_unit_textrm: {#1} }, - unit-text-sf .code:n = - { \cs_set:Npn \@@_unit_textsf: {#1} }, - unit-text-tt .code:n = - { \cs_set:Npn \@@_unit_texttt: {#1} } -} -% \end{macrocode} -%\end{macro} -% -% The general settings are all meta-keys. A few initial values are set -% here as they are needed for everything to work. -% \begin{macrocode} -\keys_define:nn { siunitx } { - color .meta:n = - { - number-color = #1, - unit-color = #1 - }, - math-rm .meta:n = - { - number-math-rm = #1, - unit-math-rm = #1 - }, - math-sf .meta:n = - { - number-math-sf = #1, - unit-math-sf = #1 - }, - math-tt .meta:n = - { - number-math-tt = #1, - unit-math-tt = #1 - }, - mode .choice:, - mode / math .meta:n = - { - number-mode = math, - unit-mode = math - }, - mode / text .meta:n = - { - number-mode = text, - unit-mode = text - }, - text-rm .meta:n = - { - number-text-rm = #1, - unit-text-rm = #1 - }, - text-sf .meta:n = - { - number-text-sf = #1, - unit-text-sf = #1 - }, - text-tt .meta:n = - { - number-text-tt = #1, - unit-text-tt = #1 - } -} -\keys_set:nn { siunitx } { - math-rm = \mathrm, - math-sf = \mathsf, - math-tt = \mathtt, - mode = math, - text-rm = \rmfamily, - text-sf = \sffamily, - text-tt = \ttfamily, -} -% \end{macrocode} -% -% Some packages and classes (for example \pkg{beamer}) set the default -% family to be something other than serif family. A one-off detection -% will make life easier -% all round. -% \begin{macrocode} -\AtBeginDocument { - \tl_set:Nx \l_@@_tmpa_tl { \familydefault } - \@ifpackageloaded { eulervm } - { - \cs_set:Npn \@@_tmp:w #1 { \mathrm {#1} } - \cs_if_eq:NNT \@@_number_mathrm:n \@@_tmp:w - { \keys_set:nn { siunitx } { number-math-rm = \mathnormal } } - \cs_if_eq:NNT \@@_unit_mathrm:n \@@_tmp:w - { \keys_set:nn { siunitx } { unit-math-rm = \mathnormal } } - } - { } - \tl_if_eq:NNT \l_@@_tmpa_tl \c_@@_textsf_tl - { - \@ifpackageloaded { arev } - { } - { - \@ifpackageloaded { cmbright } - { } - { - \cs_set:Npn \@@_tmp:w #1 { \mathrm {#1} } - \cs_if_eq:NNT \@@_number_mathrm:n \@@_tmp:w - { \keys_set:nn { siunitx } { number-math-rm = \mathsf } } - \cs_if_eq:NNT \@@_unit_mathrm:n \@@_tmp:w - { \keys_set:nn { siunitx } { unit-math-rm = \mathsf } } - } - } - \cs_set:Npn \@@_tmp:w { \rmfamily } - \cs_if_eq:NNT \@@_number_textrm: \@@_tmp:w - { \keys_set:nn { siunitx } { number-text-rm = \sffamily } } - \cs_if_eq:NNT \@@_unit_textrm: \@@_tmp:w - { \keys_set:nn { siunitx } { unit-text-rm = \sffamily } } - } - \tl_if_eq:NNT \l_@@_tmpa_tl \c_@@_texttt_tl - { - \cs_set:Npn \@@_tmp:w #1 { \mathrm {#1} } - \cs_if_eq:NNT \@@_number_mathrm:n \@@_tmp:w - { \keys_set:nn { siunitx } { number-math-rm = \mathtt } } - \cs_if_eq:NNT \@@_unit_mathrm:n \@@_tmp:w - { \keys_set:nn { siunitx } { unit-math-rm = \mathtt } } - \cs_set:Npn \@@_tmp:w { \rmfamily } - \cs_if_eq:NNT \@@_number_textrm: \@@_tmp:w - { \keys_set:nn { siunitx } { number-text-rm = \ttfamily } } - \cs_if_eq:NNT \@@_unit_textrm: \@@_tmp:w - { \keys_set:nn { siunitx } { unit-text-rm = \ttfamily } } - } -} -% \end{macrocode} -% -%\subsection{Output control} -% -% The \pkg{siunitx} output routine uses all of the font information -% gathered earlier to print the text given in whatever font is required. -% The low-level stuff is done here, with the calling routines expected -% to have taken some steps first (this is to allow line breaks in the -% appropriate places). -% -%\begin{macro}{\l_@@_print_arg_tl} -% The text to print. -% \begin{macrocode} -\tl_new:N \l_@@_print_arg_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_print_type_tl} -% The type of output (\texttt{number} or \texttt{unit}) is always -% needed. -% \begin{macrocode} -\tl_new:N \l_@@_print_type_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_print:nn , -% \@@_print:nV -%} -%\begin{macro}{\@@_print_aux:} -% The main printing function does everything inside a group, as -% there are category code and definition changes to make. First, set -% the fonts. Then move on to printing mode, before moving to actual -% printing. -% \begin{macrocode} -\cs_new_protected:Npn \@@_print:nn #1#2 { - \group_begin: - \tl_set:Nn \l_@@_print_type_tl {#1} - \tl_set:Nn \l_@@_print_arg_tl {#2} - \@@_detect_font: - \bool_if:NF \l_@@_detect_mode_bool - { - \bool_if:cTF { l_@@_ #1 _math_mode_bool } - { \bool_set_true:N \l_@@_font_math_mode_bool } - { \bool_set_false:N \l_@@_font_math_mode_bool } - } - \@@_print_aux: - \group_end: -} -\cs_generate_variant:Nn \@@_print:nn { nV } -% \end{macrocode} -% The various font changes are set up, then the correct printing -% function is called. Everything is inside \cs{text} as this allows -% proper setting of the various mode settings. -% \begin{macrocode} -\cs_new_protected:Npn \@@_print_aux: - { - \text - { - \@@_ensure_ltr:n - { - \color@begingroup - \@@_print_color: - \@@_font_shape: - \@@_font_weight: - \use:c - { - @@_ \l_@@_print_type_tl _ - text \l_@@_font_family_tl : - } - \bool_if:NTF \l_@@_font_math_mode_bool - { \@@_print_math: } - { \@@_print_text: } - \color@endgroup - } - } - } -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{ -% \@@_print_color: , -% \@@_textcolor:n -%} -% The colour system checks if \pkg{color} is loaded, and only does -% anything if it is. This will change when \LaTeX3 proper is available: -% there will be colour out of the box! -% \begin{macrocode} -\cs_new_protected:Npn \@@_print_color: { - \tl_if_empty:cF { l_@@_ \l_@@_print_type_tl _color_tl } - { - \color - { - \tl_use:c { l_@@_ \l_@@_print_type_tl _color_tl } - } - } -} -\AtBeginDocument { - \@ifpackageloaded { color } - { \cs_new_eq:NN \@@_textcolor:n \textcolor } - { - \cs_set_protected:Npn \@@_print_color: - { - \tl_if_empty:cF { l_@@_ \l_@@_print_type_tl _color_tl } - { - \cs_gset_eq:NN \@@_print_color: \scan_stop: - \msg_warning:nn { siunitx } { color-not-loaded } - } - } - \cs_new_protected:Npn \@@_textcolor:n #1 - { - \cs_gset_eq:NN \@@_textcolor:n \use_none:n - \msg_warning:nn { siunitx } { color-not-loaded } - } - } -} -% \end{macrocode} -%\end{macro} -% -% \begin{macro}{\@@_print_math:, \@@_print_text:} -% \begin{macro}{\@@_print_text_aux:} -% \begin{macro}{\@@_print_text_aux:NnN} -% Printing the text means replacing any awkward characters, which is -% dependent on the output mode. The rest of the package uses "_" and -% "^" to represent sub- and superscripts, respectively. In this way, -% mode decisions can be delayed as long as possible. The -% \pkg{underscore} package may make "_" active, or more likely -% it will be a superscript character. Both are tested for here. -% \begin{macrocode} -\cs_new_protected:Npn \@@_print_math: - { - \cs_set_eq:NN \PrintSubscript \sb - \cs_set_eq:NN \PrintSuperscript \sp - \ensuremath - { - \use:c - { - @@_ \l_@@_print_type_tl _ - math \l_@@_font_family_tl :n - } - { \l_@@_print_arg_tl } - } - } -\cs_new_protected:Npn \@@_print_text: - { - \tl_replace_all:Nnn \l_@@_print_arg_tl { - } - { \textminus } - \@@_print_text_aux: - \tl_replace_all:Nnn \l_@@_print_arg_tl { \mp } - { \ensuremath { \mp } } - \tl_remove_all:Nn \l_@@_print_arg_tl { \mathord } - \cs_set_eq:NN \PrintSubscript \@@_print_text_sub:n - \cs_set_eq:NN \PrintSuperscript \@@_print_text_super:n - \__siunitx_print_text_aux:NnN - _ { math_subscript } \@@_print_text_sub:n - _ { active } \@@_print_text_sub:n - ^ { math_superscript } \@@_print_text_super:n - ^ { active } \@@_print_text_super:n - \q_recursion_tail ? ? - \q_recursion_stop - \l_@@_print_arg_tl - } -\cs_new_protected:Npn \@@_print_text_aux: - { - \tl_replace_all:Nnn \l_@@_print_arg_tl { \pm } - { \ensuremath { \pm } } - } -\cs_new_protected:Npn \@@_print_text_aux:NnN #1#2#3 - { - \quark_if_recursion_tail_stop:N #1 - \tl_set_rescan:Nnn \l_@@_tmpa_tl - { \use:c { char_set_catcode_ #2 :N } #1 } - {#1} - \tl_replace_all:NVn \l_@@_print_arg_tl \l_@@_tmpa_tl {#3} - \_@@_print_text_aux:NnN - } -\AtBeginDocument - { - \@ifpackageloaded { textcomp } - { - \cs_set_protected:Npn \@@_print_text_aux: - { - \tl_replace_all:Nnn \l_@@_print_arg_tl { \pm } - { \textpm } - } - } - { } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -%\begin{macro}{ -% \@@_print_text_sub:n , -% \@@_print_text_super:n -%} -%\begin{macro}{\@@_print_text_sub_super:n} -% \begin{macro}{\@@_print_text_sub_peek:} -% \begin{macro}{\@@_peek_true:, \@@_peek_false:} -% The appropriate macros for sub- and superscript in text mode ensure -% the appearance is the same as math mode. The search and replace -% code for superscripts deals with the case where a literal number has -% been given with text mode printing. There is currently an issue with -% \pkg{expl3}'s \cs{peek_\ldots} functions, which means that the peek -% code is written out here in full. -% \begin{macrocode} -\cs_new_protected:Npn \@@_print_text_sub:n #1 - { - \cs_set:Npn \@@_print_text_sub_super:n ##1 - { - \ensuremath - { - \sb { \text {#1} } - \sp { \text {##1} } - } - } - \cs_set_protected:Npn \@@_peek_true: - { - \tex_afterassignment:D \@@_print_text_sub_super:n - \cs_set_eq:NN \@@_tmp:w - } - \cs_set_protected:Npn \@@_peek_false: - { \ensuremath { \sb { \text {#1} } } } - \peek_after:Nw \@@_print_text_sub_peek: - } -\cs_new_protected:Npn \@@_print_text_sub_peek: - { - \if_meaning:w \l_peek_token \@@_print_text_super:n - \exp_after:wN \@@_peek_true: - \else: - \exp_after:wN \@@_peek_false: - \fi: - } -\cs_new_protected:Npn \@@_peek_true: { } -\cs_new_protected:Npn \@@_peek_false: { } -\cs_new_protected:Npn \@@_print_text_sub_super:n { } -\cs_new_protected:Npn \@@_print_text_super:n #1 { - \tl_set:Nn \l_@@_tmpa_tl {#1} - \tl_replace_all:Nnn \l_@@_tmpa_tl { - } - { \textminus } - \tl_set:Nx \l_@@_tmpa_tl - { - \exp_not:N \ensuremath - { \sp { \exp_not:N \text { \exp_not:V \l_@@_tmpa_tl } } } - } - \l_@@_tmpa_tl -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% \end{macro} % \end{macro} % -%\begin{macro}{ -% \PrintSubscript , -% \PrintSuperscript -%} -% In the unit-construction code, there are places where it cannot -% be guarenteed that the search-and-replace approach will work. -% Instead, two user-space functions are needed. These are only -% defined within the above code: the names are not needed elsewhere. -%\end{macro} -% -%\subsection{Pre-processing numbers} -% -% Before the main parsing routine can be called, there is a need to -% pre-process the input. The possibility that the data in can contain -% more than one number needs to be handled. -% -%\begin{macro}{\l_@@_input_product_tl} -%\begin{macro}{\l_@@_input_quotient_tl} -% There are a couple of settings which are created here as they are used -% only for pre-processing. -% \begin{macrocode} -\keys_define:nn { siunitx } { - input-product .tl_set:N = \l_@@_input_product_tl, - input-quotient .tl_set:N = \l_@@_input_quotient_tl, -} -\keys_set:nn { siunitx } { - input-product = x, - input-quotient = / -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{ -% \l_@@_number_arg_tl , -% \l_@@_number_next_tl -%} -% Storage for the pre-parsed material. The \texttt{arg} variable -% contains the current argument, the \texttt{next} variable contains -% anything held-over for the next round. -% \begin{macrocode} -\tl_new:N \l_@@_number_arg_tl -\tl_new:N \l_@@_number_next_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_number_multi_tl} -% For products and quotients, a way of feeding information back. -% \begin{macrocode} -\tl_new:N \l_@@_number_multi_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \l_@@_number_denominator_tl , -% \l_@@_number_numerator_tl -%} -% When searching for quotients, some more storage is needed. -% \begin{macrocode} -\tl_new:N \l_@@_number_denominator_tl -\tl_new:N \l_@@_number_numerator_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_number_preprocess:n , -% \@@_number_preprocess:V -%} -% The pre-processor starts with the obvious: the most likely outcome is -% that all of the argument is passed through unchanged. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_preprocess:n #1 { - \@@_number_preprocess_init: - \tl_set:Nn \l_@@_number_arg_tl {#1} - \@@_number_preprocess_product: - \tl_if_empty:NT \l_@@_number_multi_tl - { \@@_number_preprocess_quotient: } -} -\cs_generate_variant:Nn \@@_number_preprocess:n { V } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_preprocess_init:} -% A little initialisation as normal. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_preprocess_init: { - \bool_set_false:N \l_@@_error_bool - \tl_clear:N \l_@@_number_multi_tl -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_preprocess_product:} -%\begin{macro}{\@@_number_preprocess_product_aux:N} -% Rather than search through the entire argument, we use the -% delimited-argument trick. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_preprocess_product: { - \tl_map_function:NN \l_@@_input_product_tl - \@@_number_preprocess_product_aux:N -} -\cs_new_protected:Npn \@@_number_preprocess_product_aux:N #1 { - \tl_if_in:NnT \l_@@_number_arg_tl {#1} - { - \cs_set:Npn \@@_tmp:w ##1 #1 ##2 \q_stop - { - \tl_set:Nn \l_@@_number_arg_tl {##1} - \tl_set:Nn \l_@@_number_next_tl {##2} - \tl_set:Nn \l_@@_number_multi_tl { product } - } - \exp_after:wN \@@_tmp:w \l_@@_number_arg_tl \q_stop - \tl_if_empty:NT \l_@@_number_arg_tl - { \@@_error:n { starting-product-token } } - \tl_if_empty:NT \l_@@_number_next_tl - { \@@_error:n { ending-product-token } } - \tl_map_break: - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_number_preprocess_quotient:} -%\begin{macro}{\@@_number_preprocess_quotient_aux:N} -% For the quotient, only one token can appear in each part. So there -% is an additional error check. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_preprocess_quotient: { - \tl_map_function:NN \l_@@_input_quotient_tl - \@@_number_preprocess_quotient_aux:N -} -\cs_new_protected:Npn \@@_number_preprocess_quotient_aux:N #1 { - \tl_if_in:NnT \l_@@_number_arg_tl {#1} - { - \cs_set:Npn \@@_tmp:w ##1 #1 ##2 \q_stop - { - \tl_set:Nn \l_@@_number_numerator_tl {##1} - \tl_set:Nn \l_@@_number_denominator_tl {##2} - \tl_set:Nn \l_@@_number_multi_tl { quotient } - } - \exp_after:wN \@@_tmp:w \l_@@_number_arg_tl \q_stop - \tl_if_empty:NT \l_@@_number_numerator_tl - { \@@_error:n { starting-quotient-token } } - \tl_if_empty:NT \l_@@_number_denominator_tl - { \@@_error:n { ending-quotient-token } } - \tl_if_in:NnT \l_@@_number_denominator_tl {#1} - { \@@_error:n { duplicate-quotient-token } } - \tl_map_break: - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\subsection{Parsing numbers} -% -% The parser is designed to be relativity fast, which means some code is -% more or less duplicated to gain more speed. It is also loaded so -% that simple numbers (such as \num{-1.23}) are parsed particularly -% quickly. For most documents, this gain more than offsets any slight -% losses with more complicated numbers. -% -%\begin{macro}{\c_@@_number_part_complex_tl} -% A couple of the comparisons needed for checking complex numbers -% are done using stored text. To make them a little quicker, a -% pre-stored version of the text is stored here. -% \begin{macrocode} -\tl_const:Nn \c_@@_number_part_complex_tl { complex } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \l_@@_number_in_complex_bool , -% \l_@@_number_in_complex_root_bool , -% \l_@@_number_in_decimal_bool , -% \l_@@_number_in_exponent_bool , -% \l_@@_number_in_first_bool , -% \l_@@_number_in_sign_bool , -% \l_@@_number_in_uncert_bool , -% \l_@@_number_in_value_bool -%} -% \begin{macrocode} -\bool_new:N \l_@@_number_in_complex_bool -\bool_new:N \l_@@_number_in_complex_root_bool -\bool_new:N \l_@@_number_in_decimal_bool -\bool_new:N \l_@@_number_in_exponent_bool -\bool_new:N \l_@@_number_in_first_bool -\bool_new:N \l_@@_number_in_sign_bool -\bool_new:N \l_@@_number_in_uncert_bool -\bool_new:N \l_@@_number_in_value_bool -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_number_in_prop} -% The parsed number is stored in a property list as its constituent -% parts. -% \begin{macrocode} -\prop_new:N \l_@@_number_in_prop -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_number_parsed_tl} -% Each part of the number parsed has to be built up in a token list. -% \begin{macrocode} -\tl_new:N \l_@@_number_parsed_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \l_@@_number_part_tl , -% \l_@@_number_part_decimal_tl , -% \l_@@_number_part_decimal_marker_tl , -% \l_@@_number_part_integer_tl , -% \l_@@_number_part_sign_tl , -% \l_@@_number_part_uncert_tl -%} -% The names of various parts of a number are set up as stored values. -% This lets some code be used for different parts of a number, while -% pre-storing everything brings a performance (and clarity) benefit. -% \begin{macrocode} -\tl_new:N \l_@@_number_part_tl -\tl_new:N \l_@@_number_part_decimal_tl -\tl_new:N \l_@@_number_part_decimal_marker_tl -\tl_new:N \l_@@_number_part_integer_tl -\tl_new:N \l_@@_number_part_sign_tl -\tl_new:N \l_@@_number_part_uncert_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \l_@@_number_mantissa_length_int -% \l_@@_number_uncert_tl -% \l_@@_number_uncert_length_int -%} -% Conversion of uncertainty forms requires some storage, mainly for -% performance reasons. -% \begin{macrocode} -\int_new:N \l_@@_number_mantissa_length_int -\tl_new:N \l_@@_number_uncert_tl -\int_new:N \l_@@_number_uncert_length_int -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_input_uncert_sign_tl} -% This one is stored by some low-level code, so is declared explicitly. -% \begin{macrocode} -\tl_new:N \l_@@_input_uncert_sign_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \l_@@_input_uncert_close_tl , -% \l_@@_input_complex_tl , -% \l_@@_input_comparator_tl , -% \l_@@_input_decimal_tl , -% \l_@@_input_digit_tl , -% \l_@@_input_exponent_tl , -% \l_@@_input_ignore_tl , -% \l_@@_input_uncert_open_tl , -% \l_@@_input_protect_tl , -% \l_@@_input_sign_tl , -% \l_@@_input_symbol_tl , -% \l_@@_input_uncert_sign_tl -%} -% The various tokens to check against when parsing are all set up here. -% These are valid inside a single number: the pre-processor has already -% set up the appropriate things for products and quotients. -% \begin{macrocode} -\keys_define:nn { siunitx } { - input-close-uncertainty .tl_set:N = \l_@@_input_uncert_close_tl , - input-complex-roots .tl_set:N = \l_@@_input_complex_tl , - input-comparators .tl_set:N = \l_@@_input_comparator_tl , - input-decimal-markers .tl_set:N = \l_@@_input_decimal_tl , - input-digits .tl_set:N = \l_@@_input_digit_tl , - input-exponent-markers .tl_set:N = \l_@@_input_exponent_tl , - input-ignore .tl_set:N = \l_@@_input_ignore_tl , - input-open-uncertainty .tl_set:N = \l_@@_input_uncert_open_tl , - input-protect-tokens .tl_set:N = \l_@@_input_protect_tl , - input-signs .tl_set:N = \l_@@_input_sign_tl , - input-symbols .tl_set:N = \l_@@_input_symbol_tl , - input-uncertainty-signs .code:n = - { - \tl_set:Nn \l_@@_input_uncert_sign_tl {#1} - \tl_map_inline:nn {#1} - { - \tl_if_in:NnF \l_@@_input_sign_tl {##1} - { \tl_put_right:Nn \l_@@_input_sign_tl {##1} } - } - } , -} -\keys_set:nn { siunitx } { % ( - input-close-uncertainty = ), - input-complex-roots = ij, - input-comparators = {<=>\approx\ge\geq\gg\le\leq\ll\sim}, - input-decimal-markers = {.,}, - input-digits = 0123456789, - input-exponent-markers = dDeE, - input-open-uncertainty = (, % ) - input-protect-tokens = \approx\dots\ge\geq\gg\le\leq\ll\mp\pi\pm\sim, - input-signs = +-\mp\pm, - input-symbols = \dots\pi, - input-uncertainty-signs = \pm, -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_number_in_parse:n , -% \@@_number_in_parse:V -%} -%\begin{macro}{\@@_number_in_parse_aux:n} -% The parsing routine starts by replacing any formatting in the input -% using \cs{tl_set_rescan:Nnx}. Next, there is a quick routine to -% ensure that all signs are single tokens. The main loop then takes -% place, which will parse the input into the property list and also -% set up the flags. There are then some checks and possible corrections. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_parse:n #1 { - \tl_if_empty:nF {#1} - { - \@@_number_in_init: - \cs_set_eq:NN \@@_number_in_parse_more:N - \@@_number_in_parse_mantissa_aux:N - \@@_number_in_parse_aux:n {#1} - } -} -\cs_generate_variant:Nn \@@_number_in_parse:n { V } -\group_begin: - \char_set_catcode_active:N \~ - \char_set_catcode_space:N \ % - \cs_new_protected:Npn \@@_number_in_parse_aux:n#1% - {% - \group_begin: - \@@_number_in_protect: - \cs_set_eq:NN\,\prg_do_nothing: - \cs_set_eq:NN~\prg_do_nothing: - \tl_set_rescan:Nnx\l_@@_number_arg_tl - {% - \char_set_catcode_ignore:N\ % - \char_set_catcode_other:N\,% - \char_set_catcode_other:N\.% - }% - {#1}% - \exp_args:NNNV\group_end: - \tl_set:Nn\l_@@_number_arg_tl\l_@@_number_arg_tl - \@@_number_in_sign_replace:N\l_@@_number_arg_tl - \@@_number_in_parse_relation:N\l_@@_number_arg_tl - \tl_map_function:NN\l_@@_number_arg_tl - \@@_number_in_parse_loop:N - \tl_if_empty:NF\l_@@_number_parsed_tl - {% - \bool_if:NTF\l_@@_number_in_uncert_bool - {\@@_error:nx{invalid-number}{#1}}% - {% - \prop_put:NVn \l_@@_number_in_prop - \l_@@_number_part_tl {true}% - \bool_if:NTF\l_@@_number_in_decimal_bool - {% - \prop_put:NVV\l_@@_number_in_prop - \l_@@_number_part_decimal_tl - \l_@@_number_parsed_tl - }% - {% - \prop_put:NVV\l_@@_number_in_prop - \l_@@_number_part_integer_tl - \l_@@_number_parsed_tl - }% - }% - }% - \@@_number_in_check:n {#1}% - } -\group_end: -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{ -% \@@_number_in_init: , -% \@@_number_in_init_part:n -%} -% The set up code is divided into to parts. First, code only needed -% once to start the entire parser. Then a second group, which is -% carried out at the start of each part of a number, and so is called -% from a few places. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_init: { - \cs_set_eq:NN \@@_number_in_parse_loop:N - \@@_number_in_parse_mantissa:N - \cs_set_eq:NN \@@_number_in_check:n - \@@_number_in_check_short:n - \tl_clear:N \l_@@_number_parsed_tl - \prop_clear:N \l_@@_number_in_prop - \bool_set_false:N \l_@@_error_bool - \bool_set_false:N \l_@@_number_in_complex_bool - \bool_set_false:N \l_@@_number_in_complex_root_bool - \bool_set_false:N \l_@@_number_in_exponent_bool - \bool_set_false:N \l_@@_number_in_uncert_bool - \@@_number_in_init_part:n { mantissa } -} -\cs_new_protected:Npn \@@_number_in_init_part:n #1 { - \bool_set_false:N \l_@@_number_in_decimal_bool - \bool_set_true:N \l_@@_number_in_first_bool - \bool_set_false:N \l_@@_number_in_sign_bool - \bool_set_false:N \l_@@_number_in_value_bool - \tl_set:Nn \l_@@_number_part_tl {#1} - \tl_set:Nn \l_@@_number_part_decimal_tl { #1 -decimal } - \tl_set:Nn \l_@@_number_part_decimal_marker_tl - { #1 -decimal-marker } - \tl_set:Nn \l_@@_number_part_integer_tl { #1 -integer } - \tl_set:Nn \l_@@_number_part_sign_tl { #1 -sign } - \tl_set:Nn \l_@@_number_part_uncert_tl { #1 -uncertainty } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_in_protect:} -%\begin{macro}{\@@_number_in_protect_aux:N} -% Under some circumstances (for example when loading \pkg{breqn}) -% some tokens do not behave safely under \texttt{x} expansion (at the -% moment). To get round this, they are redefined here. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_protect: { - \tl_map_function:NN \l_@@_input_protect_tl - \@@_number_in_protect_aux:N -} -\cs_new_protected:Npn \@@_number_in_protect_aux:N #1 { - \cs_set_eq:NN #1 \scan_stop: -} -% \end{macrocode} -%\end{macro} -%\end{macro} +% \subsection{Top-level scratch space} % -% \begin{macro}[int]{\@@_number_in_sign_replace:N} -% \begin{macro}{\@@_number_in_sign_replace_aux:N} -% \begin{macro}{\@@_number_in_sign_replace_aux:NnN} -% A short spin-out to keep the replacement of tokens clear. -% The case where |-| is active needs special treatment and -% needs to come first. +% \begin{macro}{\l_@@_tmp_tl} +% Scratch space for the interfaces. % \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_sign_replace:N #1 - { - \@@_number_in_sign_replace_aux:N #1 - \@@_number_in_sign_replace_aux:NnN #1 - { -+ } \mp - { +- } \pm - { << } \ll - { <= } \le - { >> } \gg - { >= } \ge - { ?? } \q_recursion_tail - \q_recursion_stop - } -\group_begin: - \char_set_catcode_active:N - - \cs_new_protected:Npx \_@@_number_in_sign_replace_aux:N #1 - { \tl_replace_all:Nnn #1 { \exp_not:N - } { \token_to_str:N - } } -\group_end: -\cs_new_protected:Npn \@@_number_in_sign_replace_aux:NnN #1#2#3 - { - \quark_if_recursion_tail_stop:N #3 - \tl_replace_all:Nnn #1 {#2} {#3} - \@@_number_in_sign_replace_aux:NnN #1 - } +\tl_new:N \l_@@_tmp_tl % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} % -%\begin{macro}{ -% \@@_number_in_parse_error:nn , -% \@@_number_in_parse_error:nV -%} -% There are lots of rather similar errors in the parser, all of which -% require a \cs{tl_map_break:}. To keep life simple, this is set up -% here. % \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_parse_error:nn #1#2 { - \@@_error:nx {#1} { \exp_not:n {#2} } - \tl_map_break: -} -\cs_generate_variant:Nn \@@_number_in_parse_error:nn { nV } +%</init> % \end{macrocode} -%\end{macro} % -%\begin{macro}{ -% \@@_number_in_parse_loop:N , -% \@@_number_in_parse_more:N -%} -% The main loop is set up as a place holder, as the definition is -% varied to keep things fast. There is also a place holder for the -% extended routing for normal mantissas. % \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_parse_loop:N #1 { } -\cs_new_protected:Npn \@@_number_in_parse_more:N #1 { } +%<*options> % \end{macrocode} -%\end{macro} % -%\begin{macro}{\@@_number_in_parse_relation:N} -%\begin{macro}{\@@_number_in_parse_relation:w} -% The idea here is that a relation with be the very first token in the -% input, or it is not valid. So the test for a relation can be very -% simple and hopefully efficient. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_parse_relation:N #1 { - \exp_after:wN \@@_number_in_parse_relation:w #1 \q_stop #1 -} -\cs_new_protected:Npn \@@_number_in_parse_relation:w - #1#2 \q_stop #3 { - \tl_if_in:NnT \l_@@_input_comparator_tl {#1} - { - \prop_put:Nnn \l_@@_number_in_prop { comparator } {#1} - \tl_set:Nn #3 {#2} - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_number_in_parse_restricted:N} -% When parsing numbers for the \cs{ang} function, no extended input -% is permitted at all. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_parse_restricted:N #1 { - \tl_if_in:NnTF \l_@@_input_exponent_tl {#1} - { - \@@_number_in_parse_error:nn - { restricted-number } {#1} - } - { - \tl_if_in:NnTF \l_@@_input_uncert_open_tl {#1} - { - \@@_number_in_parse_error:nV - { restricted-number } \l_@@_number_arg_tl - } - { - \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#1} - { - \@@_number_in_parse_error:nV - { restricted-number } \l_@@_number_arg_tl - } - { - \tl_if_in:NnTF \l_@@_input_complex_tl {#1} - { - \@@_number_in_parse_error:nV - { restricted-number } \l_@@_number_arg_tl - } - { - \@@_number_in_parse_error:nn - { restricted-number } {#1} - } - } - } - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_in_parse_complex:N} -% After a complex root when the root is \emph{after} the number, there -% are a very limited range of legitimate tokens. Thus most cases can be -% trapped with a modified parser. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_parse_complex:N #1 { - \tl_if_in:NnTF \l_@@_input_exponent_tl {#1} - { - \cs_set_eq:NN \@@_number_in_parse_loop:N - \@@_number_in_parse_mantissa:N - \@@_number_in_exponent:N #1 - } - { - \tl_if_in:NnF \l_@@_input_ignore_tl {#1} - { - \@@_number_in_parse_error:nV - { misplaced-complex-root-token } - \l_@@_number_arg_tl - } - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_in_parse_exponent:N} -% When processing an exponent, the \enquote{extended} part of the -% number which is valid in a mantissa is no longer needed. So the -% auxiliary function is pointed to a series of errors instead. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_parse_exponent:N #1 { - \tl_if_in:NnTF \l_@@_input_exponent_tl {#1} - { - \@@_number_in_parse_error:nn - { duplicate-exponent-token } { \token_to_str:N #1 } - } - { - \tl_if_in:NnTF \l_@@_input_uncert_open_tl {#1} - { - \@@_number_in_parse_error:nV - { invalid-token-in-exponent } \l_@@_number_arg_tl - } - { - \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#1} - { - \@@_number_in_parse_error:nV - { invalid-token-in-exponent } \l_@@_number_arg_tl - } - { - \tl_if_in:NnTF \l_@@_input_complex_tl {#1} - { - \@@_number_in_parse_error:nV - { invalid-token-in-exponent } - \l_@@_number_arg_tl - } - { - \@@_number_in_parse_error:nn - { invalid-token-in-number } {#1} - } - } - } - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_in_parse_mantissa:N} -%\begin{macro}{\@@_number_in_parse_mantissa_aux:N} -% For the mantissa, most things are valid. The procedure is split -% into two parts, with the simple symbols handled here and the more -% complex ones in a second part(which needs to be varied). Essentially -% everything here is a comparison, done so that the code is a fast as -% possible. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_parse_mantissa:N #1 { - \tl_if_in:NnTF \l_@@_input_digit_tl {#1} - { \@@_number_in_digit:n {#1} } - { - \tl_if_in:NnTF \l_@@_input_decimal_tl {#1} - { \@@_number_in_decimal:N #1 } - { - \tl_if_in:NnTF \l_@@_input_sign_tl {#1} - { \@@_number_in_sign:N #1 } - { - \tl_if_in:NnTF \l_@@_input_symbol_tl {#1} - { - \prop_put:Nnn \l_@@_number_in_prop { symbolic } - { true } - \@@_number_in_digit:n {#1} - } - { - \tl_if_in:NnF \l_@@_input_ignore_tl {#1} - { \@@_number_in_parse_more:N #1 } - } - } - } - } -} -\cs_new_protected:Npn \@@_number_in_parse_mantissa_aux:N #1 { - \tl_if_in:NnTF \l_@@_input_exponent_tl {#1} - { \@@_number_in_exponent:N #1 } - { - \tl_if_in:NnTF \l_@@_input_uncert_open_tl {#1} - { \@@_number_in_uncert_open:N #1 } - { - \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#1} - { - \@@_number_in_parse_error:nn - { misplaced-uncertainty-token } {#1} - } - { - \tl_if_in:NnTF \l_@@_input_complex_tl {#1} - { \@@_number_in_complex:N #1 } - { - \@@_number_in_parse_error:nn - { invalid-token-in-number } {#1} - } - } - } - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_number_in_parse_uncert:N} -% Within uncertainties, the range of tokens is limited. An alternative -% parsing system can therefore be used. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_parse_uncert:N #1 { - \tl_if_in:NnTF \l_@@_input_digit_tl {#1} - { \@@_number_in_digit:n {#1} } - { - \tl_if_in:NnTF \l_@@_input_decimal_tl {#1} - { - \@@_number_in_parse_error:nV - { invalid-token-in-uncertainty } - \l_@@_number_arg_tl - } - { - \tl_if_in:NnTF \l_@@_input_sign_tl {#1} - { - \@@_number_in_parse_error:nV - { invalid-token-in-uncertainty } - \l_@@_number_arg_tl - } - { - \tl_if_in:NnTF \l_@@_input_symbol_tl {#1} - { - \prop_put:Nnn \l_@@_number_in_prop { symbolic } - { true } - \@@_number_in_digit:n {#1} - } - { - \tl_if_in:NnF \l_@@_input_ignore_tl {#1} - { - \tl_if_in:NnTF \l_@@_input_uncert_close_tl - {#1} - { \@@_number_in_uncert_close:N #1 } - { - \@@_number_in_parse_error:nV - { invalid-token-in-uncertainty } - \l_@@_number_arg_tl - } - } - } - } - } - } -} -% \end{macrocode} -%\end{macro} +% \subsection{Load time options} % -%\begin{macro}{\@@_number_in_parse_uncert_after:N} -% After an uncertainty, there is once again a very limited range of -% tokens that can be present in a valid number. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_parse_uncert_after:N #1 { - \tl_if_in:NnTF \l_@@_input_exponent_tl {#1} - { - \cs_set_eq:NN \@@_number_in_parse_loop:N - \@@_number_in_parse_mantissa:N - \@@_number_in_exponent:N #1 - } - { - \tl_if_in:NnTF \l_@@_input_sign_tl {#1} - { - \cs_set_eq:NN \@@_number_in_parse_loop:N - \@@_number_in_parse_mantissa:N - \@@_number_in_sign:N #1 - } - { - \tl_if_in:NnF \l_@@_input_ignore_tl {#1} - { - \tl_if_in:NnTF \l_@@_input_complex_tl {#1} - { - \cs_set_eq:NN \@@_number_in_parse_loop:N - \@@_number_in_parse_mantissa:N - \@@_number_in_complex:N #1 - } - { - \@@_number_in_parse_error:nV { invalid-number } - \l_@@_number_arg_tl - } - } - } - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_in_complex:N} -%\begin{macro}{\@@_number_in_complex_aux:nn} -% Only one complex root token can be give, hence the initial test. -% More tests are needed for complex numbers than other systems, so -% the additional ones are turned on, followed by some flag setting. -% The complex root is stored, then there is a check to see if the -% root is at the end of the number: if it is, prevent any more tokens -% being added. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_complex:N #1 { - \bool_set_false:N \l_@@_number_in_first_bool - \bool_if:NTF \l_@@_number_in_complex_root_bool - { - \@@_number_in_parse_error:nn - { duplicate-complex-root-token } { \token_to_str:N #1 } - } - { - \cs_set_eq:NN \@@_number_in_check:n - \@@_number_in_check_full:n - \bool_set_true:N \l_@@_number_in_complex_root_bool - \prop_put:Nnn \l_@@_number_in_prop { complex-root } {#1} - \tl_if_empty:NF \l_@@_number_parsed_tl - { - \cs_set_eq:NN \@@_number_in_parse_loop:N - \@@_number_in_parse_complex:N - } - \bool_if:NT \l_@@_number_in_decimal_bool - { - \bool_if:NF \l_@@_number_in_complex_bool - { - \prop_if_in:NnT \l_@@_number_in_prop - { mantissa-uncertainty } - { - \@@_number_in_complex_aux:nn - { mantissa-decimal } { complex-decimal } - \@@_number_in_complex_aux:nn - { mantissa-uncertainty } { complex-uncertainty } - } - \@@_number_in_complex_aux:nn { mantissa-integer } - { complex-integer } - \@@_number_in_complex_aux:nn - { mantissa-decimal-marker } { complex-decimal-marker } - \prop_remove:Nn \l_@@_number_in_prop { mantissa } - \prop_put:Nnn \l_@@_number_in_prop { complex } - { true } - } - } - \prop_if_in:NnF \l_@@_number_in_prop { mantissa } - { - \prop_if_in:NnT \l_@@_number_in_prop { mantissa-sign } - { - \@@_number_in_complex_aux:nn { mantissa-sign } - { complex-sign } - } - } - \bool_set_true:N \l_@@_number_in_complex_bool - \bool_set_false:N \l_@@_number_in_first_bool - \@@_number_in_init_part:n { complex } - \prop_if_in:NnT \l_@@_number_in_prop - { complex-decimal-marker } - { \bool_set_true:N \l_@@_number_in_decimal_bool } - \prop_if_in:NnTF \l_@@_number_in_prop - { complex-sign } - { \bool_set_true:N \l_@@_number_in_sign_bool } - { \prop_remove:Nn \l_@@_number_in_prop { mantissa } } - } -} -\cs_new_protected:Npn \@@_number_in_complex_aux:nn #1#2 { - \prop_get:NnNT \l_@@_number_in_prop {#1} \l_@@_tmpa_tl - { - \prop_remove:Nn \l_@@_number_in_prop {#1} - \prop_put:NnV \l_@@_number_in_prop {#2} \l_@@_tmpa_tl - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_number_in_decimal:N} -% Only one decimal marker allowed, so a test for this. If an integer -% part has been found, it is saved. The flag for the number being -% found is not set unless there is an integer, to watch for the case -% of invalid numbers. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_decimal:N #1 { - \bool_set_false:N \l_@@_number_in_first_bool - \bool_if:NTF \l_@@_number_in_decimal_bool - { - \@@_number_in_parse_error:nn { duplicate-decimal-token } - {#1} - } - { - \bool_set_true:N \l_@@_number_in_decimal_bool - \tl_if_empty:NF \l_@@_number_parsed_tl - { - \prop_put:NVn \l_@@_number_in_prop - \l_@@_number_part_tl { true } - \prop_put:NVV \l_@@_number_in_prop - \l_@@_number_part_integer_tl - \l_@@_number_parsed_tl - \tl_clear:N \l_@@_number_parsed_tl - } - \prop_put:NVn \l_@@_number_in_prop - \l_@@_number_part_decimal_marker_tl {#1} - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_in_digit:n} -% For digits, only in an uncertainty can the value be stored -% directly. Otherwise, there is a need to see if the value is non-zero. -% This is used to drop leading zeros and to validate any sign (as zero -% is unsigned). -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_digit:n #1 { - \bool_set_false:N \l_@@_number_in_first_bool - \bool_if:NTF \l_@@_number_in_uncert_bool - { \tl_put_right:Nn \l_@@_number_parsed_tl {#1} } - { - \bool_if:NTF \l_@@_number_in_decimal_bool - { - \tl_put_right:Nn \l_@@_number_parsed_tl {#1} - \str_if_eq:nnF {#1} { 0 } - { \bool_set_true:N \l_@@_number_in_value_bool } - } - { - \str_if_eq:nnTF {#1} { 0 } - { - \prop_put:NVn \l_@@_number_in_prop - \l_@@_number_part_tl { true } - \prop_put:NVn \l_@@_number_in_prop - \l_@@_number_part_integer_tl { 0 } - } - { \bool_set_true:N \l_@@_number_in_value_bool } - \bool_if:NT \l_@@_number_in_value_bool - { \tl_put_right:Nn \l_@@_number_parsed_tl {#1} } - } - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_in_exponent:N} -% A duplicate token test starts off the code, which if passed -% leads to some simple storage manipulation. As exponents are -% more simple than the mantissa, the extra processing is swapped for -% some that only raises errors. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_exponent:N #1 { - \bool_if:NTF \l_@@_number_in_exponent_bool - { - \@@_number_in_parse_error:nn { duplicate-exponent-token } - { \token_to_str:N #1 } - } - { - \cs_set_eq:NN \@@_number_in_parse_more:N - \@@_number_in_parse_exponent:N - \tl_if_empty:NF \l_@@_number_parsed_tl - { \@@_number_in_store: } - \bool_set_true:N \l_@@_number_in_exponent_bool - \@@_number_in_init_part:n { exponent } - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_in_sign:N} -% The code for signs is complicated by complex numbers. A sign token -% must be the fist thing in a number, but after the real part of the -% mantissa a second sign token can appear to start a complex number. -% So most of the code here is to detect that case. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_sign:N #1 { - \bool_if:NTF \l_@@_number_in_first_bool - { - \bool_set_false:N \l_@@_number_in_first_bool - \bool_set_true:N \l_@@_number_in_sign_bool - \prop_put:NVn \l_@@_number_in_prop - \l_@@_number_part_sign_tl {#1} - } - { - \bool_if:NTF \l_@@_number_in_exponent_bool - { - \@@_number_in_parse_error:nn { misplaced-sign-token } - {#1} - } - { - \bool_if:NTF \l_@@_number_in_complex_bool - { - \@@_number_in_parse_error:nn - { misplaced-sign-token } {#1} - } - { - \tl_if_empty:NF \l_@@_number_parsed_tl - { \@@_number_in_store: } - \cs_set_eq:NN \@@_number_in_check:n - \@@_number_in_check_full:n - \@@_number_in_init_part:n { complex } - \prop_put:Nnn \l_@@_number_in_prop - { complex-sign } {#1} - \bool_set_true:N \l_@@_number_in_complex_bool - } - } - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_number_in_uncert_open:N , -% \@@_number_in_uncert_close:N -%} -% Opening and closing uncertainty tokens are handled separately. For -% opening tokens, a check is made that there is something else to the -% number before collecting material up. For the closing token, the -% uncertainty must contain some numbers. A special loop function is then -% set up to prevent any additional digits after the closing token. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_uncert_open:N #1 { - \bool_set_false:N \l_@@_number_in_first_bool - \cs_set_eq:NN \@@_number_in_parse_loop:N - \@@_number_in_parse_uncert:N - \bool_set_true:N \l_@@_number_in_uncert_bool - \tl_if_empty:NTF \l_@@_number_parsed_tl - { - \prop_if_in:NVF \l_@@_number_in_prop - \l_@@_number_part_integer_tl - { - \@@_number_in_parse_error:nV { invalid-number } - \l_@@_number_arg_tl - } - } - { \@@_number_in_store: } -} -\cs_new_protected:Npn \@@_number_in_uncert_close:N #1 { - \bool_set_false:N \l_@@_number_in_uncert_bool - \tl_if_empty:NTF \l_@@_number_parsed_tl - { - \@@_number_in_parse_error:nV { empty-uncertainty } - \l_@@_number_arg_tl - } - { - \prop_put:NVV \l_@@_number_in_prop - \l_@@_number_part_uncert_tl \l_@@_number_parsed_tl - \prop_put:Nnn \l_@@_number_in_prop - { uncertainty } { true } - \tl_clear:N \l_@@_number_parsed_tl - \cs_set_eq:NN \@@_number_in_parse_loop:N - \@@_number_in_parse_uncert_after:N - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_in_store:} -% A short auxiliary function needed in various places for storing -% either the integer or decimal part of a number, as appropriate. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_store: { - \prop_put:NVn \l_@@_number_in_prop \l_@@_number_part_tl - { true } - \bool_if:NTF \l_@@_number_in_decimal_bool - { - \prop_put:NVV \l_@@_number_in_prop - \l_@@_number_part_decimal_tl \l_@@_number_parsed_tl - } - { - \prop_put:NVV \l_@@_number_in_prop - \l_@@_number_part_integer_tl \l_@@_number_parsed_tl - } - \tl_clear:N \l_@@_number_parsed_tl -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_number_in_check:n , -% \@@_number_in_check_short:n , -% \@@_number_in_check_full:n -%} -% The checks needed for a number depend on whether there is a complex -% part. In all cases, there must be some digits, as well as a sign or -% decimal marker. There is also a check for a zero-valued input, which -% has any sign deleted. For complex numbers, the check is needed in -% case there was no real part. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_check:n #1 { } -\cs_new_protected:Npn \@@_number_in_check_short:n #1 { - \prop_if_in:NVF \l_@@_number_in_prop - \l_@@_number_part_integer_tl - { - \prop_if_in:NVF \l_@@_number_in_prop - \l_@@_number_part_decimal_tl - { \@@_error:nx { invalid-number } {#1} } - } - \bool_if:NF \l_@@_number_in_value_bool - { - \tl_if_eq:NNF \l_@@_number_part_tl - \c_@@_number_part_complex_tl - { - \prop_get:NVNT \l_@@_number_in_prop - \l_@@_number_part_sign_tl \l_@@_tmpa_tl - { - \tl_set:Nx \l_@@_tmpb_tl - { \l_@@_number_part_sign_tl -deleted } - \prop_put:NVV \l_@@_number_in_prop - \l_@@_tmpb_tl \l_@@_tmpa_tl - } - \prop_remove:NV \l_@@_number_in_prop - \l_@@_number_part_sign_tl - } - } -} -\cs_new_protected:Npn \@@_number_in_check_full:n #1 { - \tl_if_eq:NNF \l_@@_number_part_tl - \c_@@_number_part_complex_tl - { \@@_number_in_check_short:n {#1} } - \bool_if:NF \l_@@_number_in_complex_root_bool - { - \prop_get:NnN \l_@@_number_in_prop { complex-sign } - \l_@@_tmpa_tl - \tl_if_in:NVTF \l_@@_input_uncert_sign_tl \l_@@_tmpa_tl - { - \prop_if_in:NnTF \l_@@_number_in_prop { uncertainty } - { - \@@_error:nx { misplaced-sign-token } - { \exp_not:n {#1} } - } - { \@@_number_in_complex_to_uncert:n {#1} } - } - { - \@@_error:nx { misplaced-sign-token } - { \exp_not:n {#1} } - } - } - \prop_get:NnNT \l_@@_number_in_prop { mantissa-sign } - \l_@@_tmpa_tl - { - \prop_if_in:NnF \l_@@_number_in_prop { mantissa } - { - \prop_remove:Nn \l_@@_number_in_prop { mantissa-sign } - \prop_put:NnV \l_@@_number_in_prop { complex-sign } - \l_@@_tmpa_tl - } - } -} -% \end{macrocode} -%\end{macro} -% -% -%\begin{macro}{\@@_number_in_complex_to_uncert:n} -%\begin{macro}{ -% \@@_number_in_complex_to_uncert_int: , -% \@@_number_in_complex_to_uncert_dec: -%} -% Internally, uncertainties are stored in \enquote{compact} form. -% The code here takes a putative complex part and converts it to -% a compact uncertainty, with checks for the cases where things look -% wrong. The method needed depends on whether there is an integer -% part. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_complex_to_uncert:n #1 { - \prop_remove:Nn \l_@@_number_in_prop { complex } - \prop_remove:Nn \l_@@_number_in_prop { complex-decimal-marker } - \prop_remove:Nn \l_@@_number_in_prop { complex-sign } - \prop_put:Nnn \l_@@_number_in_prop { uncertainty } { true } - \prop_get:NnNTF \l_@@_number_in_prop { complex-integer } - \l_@@_number_uncert_tl - { - \tl_if_single:NTF \l_@@_number_uncert_tl - { - \int_compare:nNnTF \l_@@_number_uncert_tl = 0 - { \@@_number_in_complex_to_uncert_dec:n {#1} } - { \@@_number_in_complex_to_uncert_int: } - } - { \@@_number_in_complex_to_uncert_int: } - } - { \@@_number_in_complex_to_uncert_dec:n {#1} } - \prop_remove:Nn \l_@@_number_in_prop { complex-integer } - \prop_remove:Nn \l_@@_number_in_prop { complex-decimal } -} -% \end{macrocode} -% When the input has an integer part to the uncertainty, the -% conversion is easy as all of the decimal part can be copied -% across. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_complex_to_uncert_int: { - \prop_get:NnNF \l_@@_number_in_prop { complex-decimal } - \l_@@_tmpa_tl - { \tl_clear:N \l_@@_tmpa_tl } - \prop_get:NnNF \l_@@_number_in_prop { mantissa-decimal } - \l_@@_tmpb_tl - { \tl_clear:N \l_@@_tmpb_tl } - \@@_number_in_complex_to_uncert_pad: -} -% \end{macrocode} -% For a number in which all of the uncertainty is in the decimal part, -% only the significant digits are needed. This means that a loop is -% needed to drop non-significant ones. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_complex_to_uncert_dec:n - #1 - { - \tl_clear:N \l_@@_number_uncert_tl - \prop_get:NnNTF \l_@@_number_in_prop { complex-decimal } - \l_@@_tmpa_tl - { - \prop_get:NnN \l_@@_number_in_prop { mantissa-decimal } - \l_@@_tmpb_tl - \quark_if_no_value:NT \l_@@_tmpb_tl - { \tl_clear:N \l_@@_tmpb_tl } - \tl_map_function:NN - \l_@@_tmpa_tl - \@@_number_in_complex_to_uncert_dec_loop:N - \@@_number_in_complex_to_uncert_pad: - } - { \@@_error:nx { misplaced-sign-token } { \exp_not:n {#1} } } - } -\cs_new_protected:Npn - \@@_number_in_complex_to_uncert_dec_loop:N #1 +% \begin{variable}{\l_@@_column_type_tl} +% \begin{macrocode} +\keys_define:nn { siunitx } { - \str_if_eq:nnTF {#1} { 0 } - { - \tl_set:Nx \l_@@_tmpa_tl - { \tl_tail:N \l_@@_tmpa_tl } - \tl_if_empty:NF \l_@@_tmpb_tl - { - \tl_set:Nx \l_@@_tmpb_tl - { \tl_tail:N \l_@@_tmpb_tl } - } - } - { \tl_map_break: } + table-column-type .tl_set:N = + \l_@@_column_type_tl } -% \end{macrocode} -% In all cases, there is a need to pad out either the uncertainty or -% the decimal part so the places agree. To allow the two branches to -% share code, some of the order here is slightly odd. The code -% also re-obtains the decimal part from the mantissa, as the stored -% value may have been trimmed to drop non-significant zeros. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_in_complex_to_uncert_pad: +\keys_set:nn { siunitx } { - \int_set:Nn \l_@@_number_uncert_length_int - { \tl_count:N \l_@@_tmpa_tl } - \int_set:Nn \l_@@_number_mantissa_length_int - { \tl_count:N \l_@@_tmpb_tl } - \int_compare:nNnTF - { \l_@@_number_mantissa_length_int } - > { \l_@@_number_uncert_length_int } - { - \tl_set:Nx \l_@@_tmpa_tl - { - \exp_not:V \l_@@_tmpa_tl - \prg_replicate:nn - { - \l_@@_number_mantissa_length_int - - \l_@@_number_uncert_length_int - } - { 0 } - } - } - { - \prop_get:NnNF \l_@@_number_in_prop { mantissa-decimal } - \l_@@_tmpb_tl - { \tl_clear:N \l_@@_tmpb_tl } - \tl_set:Nx \l_@@_tmpb_tl - { - \exp_not:V \l_@@_tmpb_tl - \prg_replicate:nn - { - \l_@@_number_uncert_length_int - - \l_@@_number_mantissa_length_int - } - { 0 } - } - \tl_if_empty:NF \l_@@_tmpb_tl - { - \prop_put:NnV \l_@@_number_in_prop { mantissa-decimal } - \l_@@_tmpb_tl - \prop_if_in:NnF \l_@@_number_in_prop - { mantissa-decimal-marker } - { - \prop_put:Nnn \l_@@_number_in_prop - { mantissa-decimal-marker } { . } - } - } - } - \tl_put_right:NV \l_@@_number_uncert_tl \l_@@_tmpa_tl - \prop_put:NnV \l_@@_number_in_prop { mantissa-uncertainty } - \l_@@_number_uncert_tl + table-column-type = S } % \end{macrocode} -%\end{macro} -%\end{macro} -% -%\subsection{Post-processing numbers} -% -% After finding the basic number in the code above, there may be some -% manipulation to do. This covers things such as tidying up excess -% information and rounding numbers. Nothing is added here that is -% for \enquote{formatting}: this is left for the output part of the -% system. -% -% \begin{variable} -% { -% \l_@@_round_int , -% \l_@@_round_tl , -% \l_@@_round_bool , -% \l_@@_round_decimal_in_tl , -% \l_@@_round_decimal_out_tl , -% \l_@@_round_discard_tl , -% \l_@@_round_even_bool , -% \l_@@_round_integer_in_tl , -% \l_@@_round_integer_out_tl , -% \l_@@_round_half_up_bool -% } -% The rounding system needs a number of variables. -% \begin{macrocode} -\int_new:N \l_@@_round_int -\tl_new:N \l_@@_round_tl -\bool_new:N \l_@@_round_bool -\tl_new:N \l_@@_round_decimal_in_tl -\tl_new:N \l_@@_round_decimal_out_tl -\tl_new:N \l_@@_round_discard_tl -\tl_new:N \l_@@_round_even_bool -\tl_new:N \l_@@_round_integer_in_tl -\tl_new:N \l_@@_round_integer_out_tl -\bool_new:N \l_@@_round_half_up_bool -% \end{macrocode} % \end{variable} % -%\begin{macro}{ -% \l_@@_process_decimal_int , -% \l_@@_process_uncertainty_int , -% \l_@@_uncertainty_decimal_tl , -% \l_@@_uncertainty_integer_tl -%} -% The code to expand uncertainties needs to know numbers of digits, and -% to store various data. -% \begin{macrocode} -\int_new:N \l_@@_process_decimal_int -\int_new:N \l_@@_process_uncertainty_int -\tl_new:N \l_@@_uncertainty_decimal_tl -\tl_new:N \l_@@_uncertainty_integer_tl -% \end{macrocode} -%\end{macro} +% \subsection{Option handling} % -%\begin{macro}{ -% \l_@@_process_fixed_bool , -% \l_@@_process_engineering_bool , -% \l_@@_process_scientific_bool -%} -% Settings for the scientific notation system. -% \begin{macrocode} -\bool_new:N \l_@@_process_fixed_bool -\bool_new:N \l_@@_process_engineering_bool -\bool_new:N \l_@@_process_scientific_bool +% \begin{macrocode} +\RequirePackage { l3keys2e } % \end{macrocode} -%\end{macro} % -% \begin{variable}{\l_@@_process_drop_exponent_bool} -% Used to drop the exponent when this is necessary. -% \begin{macrocode} -\bool_new:N \l_@@_process_drop_exponent_bool +% \begin{macrocode} +\ProcessKeysOptions { siunitx } % \end{macrocode} -% \end{variable} % -% \begin{variable} -% { -% \l_@@_process_decimal_zero_bool , -% \l_@@_process_integer_zero_bool , -% \l_@@_process_sign_tl , -% \l_@@_process_fixed_int , -% \l_@@_process_integer_min_int , -% \l_@@_process_plus_bool , -% \l_@@_omit_uncert_bool , -% \l_@@_process_unity_mantissa_tl , -% \l_@@_process_zero_exponent_bool , -% \l_@@_process_int_to_dec_bool , -% \l_@@_process_round_min_tl , -% \l_@@_process_precision_int , -% \l_@@_zero_decimal_to_integer_bool -% } -% First, the options are set up. % \begin{macrocode} -\keys_define:nn { siunitx } - { - add-decimal-zero .bool_set:N = \l_@@_process_decimal_zero_bool, - add-integer-zero .bool_set:N = \l_@@_process_integer_zero_bool, - explicit-sign .tl_set:N = \l_@@_process_sign_tl, - fixed-exponent .int_set:N = \l_@@_process_fixed_int, - minimum-integer-digits .int_set:N = - \l_@@_process_integer_min_int, - retain-explicit-plus .bool_set:N = \l_@@_process_plus_bool, - omit-uncertainty .bool_set:N = \l_@@_omit_uncert_bool, - retain-unity-mantissa .bool_set:N = - \l_@@_process_unity_mantissa_bool, - retain-zero-exponent .bool_set:N = - \l_@@_process_zero_exponent_bool, - round-half .choice:, - round-half / even .code:n = - { \bool_set_false:N \l_@@_round_half_up_bool }, - round-half / up .code:n = - { \bool_set_true:N \l_@@_round_half_up_bool }, - round-integer-to-decimal .bool_set:N = - \l_@@_process_int_to_dec_bool, - round-minimum .tl_set:N = \l_@@_process_round_min_tl, - round-mode .choice: , - round-mode / figures .code:n = - { \tl_set:Nn \l_@@_round_tl { figures } }, - round-mode / off .code:n = { \tl_clear:N \l_@@_round_tl }, - round-mode / places .code:n = - { \tl_set:Nn \l_@@_round_tl { places } }, - round-precision .int_set:N = \l_@@_process_precision_int, - scientific-notation .choice: , - scientific-notation - / false .code:n = - { - \bool_set_false:N \l_@@_process_fixed_bool - \bool_set_false:N \l_@@_process_engineering_bool - \bool_set_false:N \l_@@_process_scientific_bool - }, - scientific-notation - / engineering .code:n = - { - \bool_set_false:N \l_@@_process_fixed_bool - \bool_set_true:N \l_@@_process_engineering_bool - \bool_set_true:N \l_@@_process_scientific_bool - }, - scientific-notation - / fixed .code:n = - { - \bool_set_true:N \l_@@_process_fixed_bool - \bool_set_false:N \l_@@_process_engineering_bool - \bool_set_false:N \l_@@_process_scientific_bool - }, - scientific-notation - / true .code:n = - { - \bool_set_false:N \l_@@_process_fixed_bool - \bool_set_false:N \l_@@_process_engineering_bool - \bool_set_true:N \l_@@_process_scientific_bool - }, - zero-decimal-to-integer .bool_set:N = - \l_@@_zero_decimal_to_integer_bool - } -\keys_set:nn { siunitx } - { - add-decimal-zero = true, - add-integer-zero = true, - retain-unity-mantissa = true, - round-half = up, - round-minimum = 0, - round-precision = 2 - } +%</options> % \end{macrocode} -% \end{variable} % -% \begin{macro}{\@@_number_process:} -% Post-processing is a series of small tasks. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process: - { - \@@_number_process_sign: - \@@_number_process_zero_fill: - \@@_number_process_mantissa: - \prop_if_in:NnF \l_@@_number_in_prop { symbolic } - { - \bool_if:NTF \l_@@_process_fixed_bool - { \@@_number_process_fixed: } - { - \bool_if:NT \l_@@_process_scientific_bool - { \@@_number_process_scientific: } - } - \@@_number_process_exponent: - \@@_number_process_uncertainty: - \bool_if:NT \l_@@_exp_to_prefix_bool - { - \tl_if_empty:NF \l_@@_unit_tl - { \@@_number_exp_to_prefix: } - } - \prop_if_in:NnTF \l_@@_number_in_prop { uncertainty } - { - \bool_if:NT \l_@@_omit_uncert_bool - { - \prop_remove:Nn \l_@@_number_in_prop { uncertainty } - \prop_remove:Nn \l_@@_number_in_prop { mantissa-uncertainty } - } - } - { \@@_number_process_round: } - } - \@@_number_process_zero_to_integer: - \@@_number_process_integer_digits: - \bool_if:NT \l_@@_process_drop_exponent_bool - { - \prop_remove:Nn \l_@@_number_in_prop { exponent } - \prop_remove:Nn \l_@@_number_in_prop { exponent-integer } - } - } -% \end{macrocode} -% \end{macro} +% \subsection{User interfaces} % -%\begin{macro}{\@@_number_process_exponent:} -%\begin{macro}{\@@_number_process_exponent_aux:n} -% To check for a totally zero exponent, the possibility that one or more -% of the exponent storage areas is zero needs to be considered. % \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_exponent: { - \bool_if:NF \l_@@_process_zero_exponent_bool - { - \prop_if_in:NnT \l_@@_number_in_prop { exponent } - { - \bool_set_false:N \l_@@_tmp_bool - \@@_number_process_exponent_aux:n { integer } - \bool_if:NF \l_@@_tmp_bool - { \@@_number_process_exponent_aux:n { decimal } } - \bool_if:NF \l_@@_tmp_bool - { - \prop_remove:Nn \l_@@_number_in_prop { exponent } - \prop_remove:Nn \l_@@_number_in_prop - { exponent-integer } - \prop_remove:Nn \l_@@_number_in_prop - { exponent-decimal } - \prop_if_in:NnF \l_@@_number_in_prop { mantissa } - { - \prop_put:Nnn \l_@@_number_in_prop { mantissa } { true } - \prop_put:Nnn \l_@@_number_in_prop { mantissa-integer } { 1 } - } - } - } - } -} -\cs_new_protected:Npn \@@_number_process_exponent_aux:n #1 { - \prop_get:NnNT \l_@@_number_in_prop { exponent- #1 } - \l_@@_tmpa_tl - { - \int_compare:nNnF { \l_@@_tmpa_tl } = { 0 } - { \bool_set_true:N \l_@@_tmp_bool } - } -} +%<*interfaces> % \end{macrocode} -%\end{macro} -%\end{macro} % -% \begin{macro}{\@@_number_process_figures:n} -% \begin{macro} -% { -% \@@_number_process_figures_aux:n , -% \@@_number_process_figures_init:n -% } -% The approach here is to find how many digits there are in each part -% of the number, working out which are significant. The next stage is -% reconstruction of the number. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_figures:n #1 - { - \int_compare:nNnTF \l_@@_process_precision_int > 0 - { - \prop_if_in:NnT \l_@@_number_in_prop {#1} - { \@@_number_process_figures_aux:n {#1} } - } - { - \prop_remove:Nn \l_@@_number_in_prop { #1 -sign } - \prop_put:Nnn \l_@@_number_in_prop { #1 -integer } { 0 } - \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal } - \bool_if:NF \l_@@_process_int_to_dec_bool - { \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal-marker } } - } - } -\cs_new_protected:Npn \@@_number_process_figures_aux:n #1 - { - \@@_number_process_figures_init:n {#1} - \@@_number_process_figures_count:n { integer } - \@@_number_process_figures_count:n { decimal } - \bool_if:NTF \l_@@_round_bool - { - \bool_set_false:N \l_@@_round_bool - \int_compare:nNnTF - \l_@@_round_int > \l_@@_process_precision_int - { - \@@_number_process_figures_round: - \@@_number_process_round_tidy:n {#1} - } - { \@@_number_process_figures_pad:n {#1} } - } - { - \prop_put:Nnn \l_@@_number_in_prop { #1 -integer } { 0 } - \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal } - } - } -\cs_new_protected:Npn \@@_number_process_figures_init:n #1 - { - \int_zero:N \l_@@_round_int - \bool_set_false:N \l_@@_round_bool - \bool_set_false:N \l_@@_round_even_bool - \prop_get:NnNF \l_@@_number_in_prop { #1 -decimal } - \l_@@_round_decimal_in_tl - { \tl_clear:N \l_@@_round_decimal_in_tl } - \prop_get:NnNF \l_@@_number_in_prop { #1 -integer } - \l_@@_round_integer_in_tl - { \tl_clear:N \l_@@_round_integer_in_tl } - \tl_clear:N \l_@@_round_decimal_out_tl - \tl_clear:N \l_@@_round_integer_out_tl - \tl_clear:N \l_@@_round_discard_tl - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \begin{macro}{\@@_number_process_figures_count:n} -% \begin{macro}{\@@_number_process_figures_count_aux:n} -% The counting code has to check that characters are actually -% significant. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_figures_count:n #1 - { - \tl_if_empty:cF { l_@@_round_ #1 _in_tl } - { - \prop_if_in:NnF \l_@@_number_in_prop { #1 -uncertainty } - { \@@_number_process_figures_count_aux:n {#1} } - } - } -\cs_new_protected:Npn \@@_number_process_figures_count_aux:n #1 - { - \int_set:Nn \l_@@_tmp_int - { \tl_head:v { l_@@_round_ #1 _in_tl } } - \tl_set:cx { l_@@_round_ #1 _in_tl } - { \tl_tail:v { l_@@_round_ #1 _in_tl } } - \tl_put_left:cV { l_@@_round_ #1 _out_tl } \l_@@_tmp_int - \bool_if:NF \l_@@_round_bool - { - \int_compare:nNnF \l_@@_tmp_int = 0 - { \bool_set_true:N \l_@@_round_bool } - } - \bool_if:NT \l_@@_round_bool - { \int_incr:N \l_@@_round_int } - \tl_if_empty:cTF { l_@@_round_ #1 _in_tl } - { - \tl_set_eq:cc { l_@@_round_ #1 _in_tl } - { l_@@_round_ #1 _out_tl } - \tl_clear:c { l_@@_round_ #1 _out_tl } - } - { \@@_number_process_figures_count_aux:n {#1} } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \begin{macro}{\@@_number_process_figures_round:} -% \begin{macro}{\@@_number_process_figures_round_loop:} -% The control macro for rounding to figures does the decimal part -% then the integer part as loops. There is then some tidying up if a -% digit is carried at the end. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_figures_round: - { - \int_set:Nn \l_@@_round_int - { \l_@@_round_int - \l_@@_process_precision_int } - \tl_if_empty:NF \l_@@_round_decimal_in_tl - { \@@_number_process_figures_round_loop: } - \tl_if_empty:NF \l_@@_round_integer_in_tl - { \@@_number_process_figures_integer: } - \bool_if:NT \l_@@_round_bool - { \tl_put_left:Nn \l_@@_round_integer_out_tl { 1 } } - } -\cs_new_protected:Npn \@@_number_process_figures_round_loop: - { - \@@_number_process_round_decimal: - \tl_if_empty:NF \l_@@_round_decimal_in_tl - { \@@_number_process_figures_round_loop: } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \begin{macro}{\@@_number_process_figures_integer:} -% For figures, the integer part is a little complicated as zeros need -% to be included. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_figures_integer: - { - \int_compare:nNnT \l_@@_round_int > 0 - { \tl_put_left:Nn \l_@@_round_integer_out_tl { 0 } } - \int_compare:nNnF \l_@@_round_int > 1 - { - \int_set:Nn \l_@@_tmp_int - { \tl_head:N \l_@@_round_integer_in_tl } - \@@_number_process_round_up: - \int_compare:nNnTF \l_@@_round_int = 1 - { - \int_compare:nNnT \l_@@_tmp_int > 4 - { \bool_set_true:N \l_@@_round_bool } - } - { - \int_compare:nNnT \l_@@_tmp_int = { 10 } - { - \bool_set_true:N \l_@@_round_bool - \int_zero:N \l_@@_tmp_int - } - \tl_put_left:NV \l_@@_round_integer_out_tl - \l_@@_tmp_int - } - } - \int_decr:N \l_@@_round_int - \tl_set:Nx \l_@@_round_integer_in_tl - { \tl_tail:N \l_@@_round_integer_in_tl } - \tl_if_empty:NF \l_@@_round_integer_in_tl - { \@@_number_process_figures_integer: } - } -% \end{macrocode} -%\end{macro} -%\begin{macro}{\@@_number_process_figures_pad:n} -% If the number is too short, then the reversal is undone and the -% padding routine is called. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_figures_pad:n #1 { - \prop_get:NnN \l_@@_number_in_prop { #1 -integer } - \l_@@_round_integer_in_tl - \prop_get:NnN \l_@@_number_in_prop { #1 -decimal } - \l_@@_round_decimal_in_tl - \int_set:Nn \l_@@_round_int - { \l_@@_process_precision_int - \l_@@_round_int } - \@@_number_process_pad:n {#1} -} -% \end{macrocode} -%\end{macro} +% The user interfaces are defined in terms of documented code-level ones. +% This is all done here, and will appear in the \file{.sty} file before the +% relevant code. Things could be re-arranged by \pkg{DocStrip} but there is no +% advantage. % -%\begin{macro}{\@@_number_process_fixed:} -%\begin{macro}{ -% \@@_number_process_fixed_aux_i:nnn , -% \@@_number_process_fixed_aux_ii:nnn , -% \@@_number_process_fixed_aux_iii:nnn , -% \@@_number_process_fixed_large:nnn , -% \@@_number_process_fixed_large_aux:w , -% \@@_number_process_fixed_small:nnn , -% \@@_number_process_fixed_small_aux:w -%} -% When working to a fixed exponent value, the idea is to use the stack -% to do the work. First, there is some set up to do. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_fixed: { - \prop_if_in:NnF \l_@@_number_in_prop { complex } - { - \prop_get:NnNF \l_@@_number_in_prop { mantissa-integer } - \l_@@_tmpa_tl - { \tl_set:Nn \l_@@_tmpa_tl { 0 } } - \prop_get:NnNF \l_@@_number_in_prop { mantissa-decimal } - \l_@@_tmpb_tl - { \tl_clear:N \l_@@_tmpb_tl } - \tl_set:Nx \l_@@_tmpa_tl - { { \l_@@_tmpa_tl } { \l_@@_tmpb_tl } } - \prop_get:NnNF \l_@@_number_in_prop { exponent-integer } - \l_@@_tmpb_tl - { \tl_set:Nn \l_@@_tmpb_tl { 0 } } - \group_begin: - \prop_get:NnNT \l_@@_number_in_prop { exponent-sign } - \l_@@_tmpa_tl - { - \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpa_tl - } - \exp_args:NNNV \group_end: - \tl_set:Nn \l_@@_tmpb_tl \l_@@_tmpb_tl - \tl_set:Nx \l_@@_tmpa_tl - { \l_@@_tmpa_tl { \l_@@_tmpb_tl } } - \exp_after:wN \@@_number_process_fixed_aux_i:nnn - \l_@@_tmpa_tl - } -} -% \end{macrocode} -% The main loop checks to see which way to adjust the exponent then -% does the work. +% User level interfaces are all created by \pkg{xparse} % \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_fixed_aux_i:nnn #1#2#3 - { - \prop_put:Nnn \l_@@_number_in_prop { exponent } { true } - \int_compare:nNnTF \l_@@_process_fixed_int > 0 - { - \prop_put:NnV \l_@@_number_in_prop { exponent-integer } - \l_@@_process_fixed_int - \prop_remove:Nn \l_@@_number_in_prop { exponent-sign } - } - { - \prop_put:Nnx \l_@@_number_in_prop { exponent-integer } - { \int_eval:n { - \l_@@_process_fixed_int } } - \prop_put:Nnn \l_@@_number_in_prop { exponent-sign } { - } - } - \@@_number_process_fixed_aux_ii:nnn {#1} {#2} {#3} - } -\cs_new_protected:Npn \@@_number_process_fixed_aux_ii:nnn #1#2#3 - { - \bool_set_true:N \l_@@_tmp_bool - \tl_map_inline:nn {#1#2} - { - \str_if_eq:nnF {##1} { 0 } - { - \bool_set_false:N \l_@@_tmp_bool - \tl_map_break: - } - } - \bool_if:NF \l_@@_tmp_bool - { \@@_number_process_fixed_aux_iii:nnn {#1} {#2} {#3} } - } -\cs_new_protected:Npn - \@@_number_process_fixed_aux_iii:nnn #1#2#3 { - \int_compare:nNnTF {#3} > { \l_@@_process_fixed_int } - { \@@_number_process_fixed_large:nnn {#1} {#2} {#3} } - { - \int_compare:nNnTF {#3} < { \l_@@_process_fixed_int } - { \@@_number_process_fixed_small:nnn {#1} {#2} {#3} } - { - \prop_put:Nnn \l_@@_number_in_prop - { mantissa-integer } {#1} - \tl_if_empty:nTF {#2} - { - \prop_remove:Nn \l_@@_number_in_prop - { mantissa-decimal } - \prop_remove:Nn \l_@@_number_in_prop - { mantissa-decimal-marker } - } - { - \prop_put:Nnn \l_@@_number_in_prop - { mantissa-decimal } {#2} - \prop_if_in:NnF \l_@@_number_in_prop - { mantissa-decimal-marker } - { - \prop_put:Nnn \l_@@_number_in_prop - { mantissa-decimal-marker } { . } - } - } - } - } -} -% \end{macrocode} -% Simple stack-based manipulation of the input for number which are -% either too big or too small. There are a couple of checks needed to -% deal with cases where there is no decimal part and where there are -% leading zeros to dispose of. There is also a check to avoid adding -% an additional zero to the decimal part of the number. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_fixed_large:nnn #1 - { - \@@_number_if_zero:nTF {#1} - { \@@_number_process_fixed_large_aux:nnn { } } - { \@@_number_process_fixed_large_aux:nnn {#1} } - } -\cs_new_protected:Npn \@@_number_process_fixed_large_aux:nnn #1#2#3 - { - \cs_set_protected:Npn - \@@_number_process_fixed_large_aux:w ##1##2 \q_stop - { - \tl_if_empty:nTF {##2} - { - \int_compare:nNnTF - { #3 - 1 } = { \l_@@_process_fixed_int } - { - \@@_number_process_fixed_aux_ii:nnn { #1 ##1 } - { } { #3 - 1 } - } - { - \@@_number_process_fixed_aux_ii:nnn { #1 ##1 } - { 0 } { #3 - 1 } - } - } - { - \@@_number_if_zero:nTF {#1} - { - \@@_number_process_fixed_aux_ii:nnn {##1} {##2} - { #3 - 1 } - } - { - \@@_number_process_fixed_aux_ii:nnn { #1 ##1 } - {##2} { #3 - 1 } - } - } - } - \tl_if_empty:nTF {#2} - { \@@_number_process_fixed_aux_ii:nnn { #1 0 } { } { #3 - 1 } } - { \@@_number_process_fixed_large_aux:w #2 \q_stop } -} -\cs_new_protected:Npn \@@_number_process_fixed_large_aux:w +\IfFormatAtLeastTF { 2020-10-01 } { } -\cs_new_protected:Npn - \@@_number_process_fixed_small:nnn #1#2#3 { - \cs_set_protected:Npn - \@@_number_process_fixed_small_aux:w ##1##2 \q_stop ##3 - { - \tl_if_empty:nTF {##2} - { - \tl_if_empty:nTF {##3} - { - \@@_number_process_fixed_aux_ii:nnn { 0 } - { ##1 #2 } { #3 + 1 } - } - { - \@@_number_process_fixed_aux_ii:nnn {##3} - { ##1 #2 } { #3 + 1 } - } - } - { - \@@_number_process_fixed_small_aux:w ##2 \q_stop - { ##3 ##1 } - } - } - \@@_number_process_fixed_small_aux:w #1 \q_stop { } -} -\cs_new_protected:Npn \@@_number_process_fixed_small_aux:w - { } -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_number_process_integer_digits:} -% Producing extra digits for the integer part is a simple process -% once the target is known. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_integer_digits: { - \int_compare:nNnT \l_@@_process_integer_min_int > 0 - { - \prop_get:NnNT \l_@@_number_in_prop { mantissa-integer } - \l_@@_tmpa_tl - { - \int_set:Nn \l_@@_tmp_int - { - \l_@@_process_integer_min_int - - \tl_count:N \l_@@_tmpa_tl - } - \int_compare:nNnT \l_@@_tmp_int > 0 - { - \tl_set:Nx \l_@@_tmpa_tl - { - \prg_replicate:nn { \l_@@_tmp_int } { 0 } - \exp_not:V \l_@@_tmpa_tl - } - \prop_put:NnV \l_@@_number_in_prop - { mantissa-integer } \l_@@_tmpa_tl - } - } - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_process_mantissa:} -%\begin{macro}{\c_@@_unity_tl} -% A check for the mantissa consisting only of the token \texttt{1}, when -% an exponent is also available. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_mantissa: { - \bool_if:NF \l_@@_process_unity_mantissa_bool - { - \prop_if_in:NnT \l_@@_number_in_prop { exponent } - { - \prop_get:NnNT \l_@@_number_in_prop { mantissa-integer } - \l_@@_tmpa_tl - { - \tl_if_eq:NNT \c_@@_unity_tl \l_@@_tmpa_tl - { - \prop_if_in:NnF \l_@@_number_in_prop - { mantissa-decimal-marker } - { - \prop_remove:Nn \l_@@_number_in_prop - { mantissa } - \prop_remove:Nn \l_@@_number_in_prop - { mantissa-integer } - } - } - } - } - } -} -\tl_const:Nn \c_@@_unity_tl { 1 } + { \RequirePackage { xparse } } % \end{macrocode} -%\end{macro} -%\end{macro} % -%\begin{macro}{\@@_number_process_pad:n} -% For padding a number by adding zero to the end repeatedly. This can -% happen if the input was zero or if the number is too short. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_pad:n #1 { - \prop_get:NnNT \l_@@_number_in_prop { #1 -decimal } - \l_@@_tmpa_tl - { - \int_while_do:nNnn { \l_@@_round_int } > { 0 } - { - \tl_put_right:Nn \l_@@_tmpa_tl { 0 } - \int_decr:N \l_@@_round_int - } - \prop_put:NnV \l_@@_number_in_prop { #1 -decimal } - \l_@@_tmpa_tl - } -} -% \end{macrocode} -%\end{macro} +% \subsubsection{Preamble commands} % -% \begin{macro}{\@@_number_process_places:n} % \begin{macro} % { -% \@@_number_process_places_init:n , -% \@@_number_process_places_aux_i:n , -% \@@_number_process_places_aux_i:TF , -% \@@_number_process_places_none: , -% \@@_number_process_places_aux_ii:n , -% \@@_number_process_places_loop:n , -% \@@_number_process_places_integer:n -% } -% For rounding to a fixed number of places, a check is made to see if -% the decimal part is exactly zero. If it is, just create the -% appropriate number of zeros in the padding routine. Otherwise, do the -% real work. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_places:n #1 - { - \prop_if_in:NnT \l_@@_number_in_prop {#1} - { - \prop_if_in:NnF \l_@@_number_in_prop { #1 -uncertainty } - { \@@_number_process_places_aux_i:n {#1} } - } - } -\cs_new_protected:Npn \@@_number_process_places_aux_i:n #1 - { - \int_compare:nNnTF \l_@@_process_precision_int = 0 - { \@@_number_process_places_none:n {#1} } - { - \prop_get:NnNT \l_@@_number_in_prop { #1 -decimal } - \l_@@_tmpa_tl - { - \tl_if_empty:NT \l_@@_tmpa_tl - { \tl_set:Nn \l_@@_tmpa_tl { 0 } } - \@@_number_process_places_aux_i:TF - { - \prop_put:Nnn \l_@@_number_in_prop { #1 -decimal } { } - \int_set:Nn \l_@@_round_int - { \l_@@_process_precision_int } - \@@_number_process_pad:n {#1} - } - { - \int_set:Nn \l_@@_round_int - { \tl_count:N \l_@@_tmpa_tl } - \@@_number_process_places_aux_ii:n {#1} - } - } - } - } -% \end{macrocode} -% The number of digits in the decimal part could be more that \TeX{} can -% handle, so a slow loop is used to see if we need to round. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_places_aux_i:TF - { - \bool_set_true:N \l_@@_tmp_bool - \tl_map_inline:Nn \l_@@_tmpa_tl - { - \int_compare:nNnF {##1} = 0 - { - \bool_set_false:N \l_@@_tmp_bool - \tl_map_break: - } - } - \bool_if:NTF \l_@@_tmp_bool - } -% \end{macrocode} -% Rounding to no places at all requires a few checks to see if there is any -% work to do. That includes a check for rounding half to even, where if -% the decimal part is exactly half then special action is required. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_places_none:n #1 - { - \prop_get:NnNT \l_@@_number_in_prop { #1 -decimal } \l_@@_tmpa_tl - { - \int_compare:nNnTF { \tl_head:N \l_@@_tmpa_tl } > 4 - { - \prop_get:NnNTF \l_@@_number_in_prop { #1 -integer } - \l_@@_tmpb_tl - { - \tl_set:Nx \l_@@_tmpb_tl - { \int_eval:n { \l_@@_tmpb_tl + 1 } } - \bool_if:NF \l_@@_round_half_up_bool - { - \bool_lazy_and:nnT - { - \int_compare_p:nNn - { 0 \tl_head:N \l_@@_tmpa_tl } = 5 - } - { - \int_compare_p:nNn - { 0 \tl_tail:N \l_@@_tmpa_tl } = 0 - } - { - \int_if_odd:nT \l_@@_tmpb_tl - { - \tl_set:Nx \l_@@_tmpb_tl - { \int_eval:n { \l_@@_tmpb_tl - 1 } } - } - } - } - } - { \tl_set:Nn \l_@@_tmpb_tl { 1 } } - \prop_put:NnV \l_@@_number_in_prop - { #1 -integer } \l_@@_tmpb_tl - } - { - \prop_if_in:NnF \l_@@_number_in_prop { #1 -integer } - { - \prop_put:Nnn \l_@@_number_in_prop - { #1 -integer } { 0 } - } - } - } - \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal } - \bool_if:NF \l_@@_process_int_to_dec_bool - { \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal-marker } } - } -% \end{macrocode} -% For rounding to a fixed number of places, the package finds the -% difference in length between what is present and what is required. -% If the number is too short, there is some simple padding to do. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_places_aux_ii:n #1 - { - \int_sub:Nn \l_@@_round_int - { \l_@@_process_precision_int } - \int_compare:nNnTF \l_@@_round_int < 0 - { - \int_set:Nn \l_@@_round_int { - \l_@@_round_int } - \@@_number_process_pad:n {#1} - } - { - \@@_number_process_places_init:n {#1} - \@@_number_process_places_loop:n {#1} - \@@_number_process_round_tidy:n {#1} - } - } -% \end{macrocode} -% To keep the code a little clearer. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_places_init:n #1 - { - \prop_get:NnNF \l_@@_number_in_prop { #1 -integer } - \l_@@_round_integer_in_tl - { \tl_clear:N \l_@@_round_integer_in_tl } - \prop_get:NnN \l_@@_number_in_prop { #1 -decimal } - \l_@@_round_decimal_in_tl - \tl_reverse:N \l_@@_round_integer_in_tl - \tl_reverse:N \l_@@_round_decimal_in_tl - \tl_clear:N \l_@@_round_integer_out_tl - \tl_clear:N \l_@@_round_decimal_out_tl - \tl_clear:N \l_@@_round_discard_tl - \bool_set_false:N \l_@@_round_bool - \bool_set_false:N \l_@@_round_even_bool - } -% \end{macrocode} -% If there is a decimal, do the decimal processing then come back here. -% If there is an integer, do the same. Only if both are empty does the -% loop stop. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_places_loop:n #1 - { - \tl_if_empty:NTF \l_@@_round_decimal_in_tl - { - \tl_if_empty:NF \l_@@_round_integer_in_tl - { - \@@_number_process_places_integer:n {#1} - \@@_number_process_places_loop:n {#1} - } - \bool_if:NT \l_@@_round_bool - { - \tl_put_left:Nn \l_@@_round_integer_out_tl { 1 } - \bool_set_false:N \l_@@_round_bool - } - } - { - \@@_number_process_round_decimal: - \@@_number_process_places_loop:n {#1} - } - } -% \end{macrocode} -% Rounding for integers is just a case of carrying digits. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_places_integer:n #1 - { - \int_set:Nn \l_@@_tmp_int - { \tl_head:N \l_@@_round_integer_in_tl } - \tl_set:Nx \l_@@_round_integer_in_tl - { \tl_tail:N \l_@@_round_integer_in_tl } - \@@_number_process_round_up: - \bool_set_false:N \l_@@_round_bool - \int_compare:nNnT \l_@@_tmp_int = { 10 } - { - \int_zero:N \l_@@_tmp_int - \bool_set_true:N \l_@@_round_bool - } - \tl_put_left:NV \l_@@_round_integer_out_tl \l_@@_tmp_int - } -% \end{macrocode} -%\end{macro} -%\end{macro} -% -% \begin{macro}{\@@_number_process_round:} -% The lead-off for rounding is the same for decimal places and -% significant figures. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_round: - { - \tl_if_empty:NF \l_@@_round_tl - { - \bool_if:NT \l_@@_process_int_to_dec_bool - { - \prop_if_in:NnF \l_@@_number_in_prop { mantissa-decimal } - { - \prop_put:Nnn \l_@@_number_in_prop { mantissa-decimal } - { 0 } - } - \prop_if_in:NnF \l_@@_number_in_prop - { mantissa-decimal-marker } - { - \prop_put:Nnn \l_@@_number_in_prop - { mantissa-decimal-marker } { . } - } - } - \clist_map_function:nc { mantissa , complex } - { @@_number_process_ \l_@@_round_tl :n } - } - } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\@@_number_process_round_decimal:} -% \begin{macro}{\@@_number_process_round_decimal_aux:} -% The rounding routine for decimals is the same for figures and places, -% so there is a generalised function here. Unfortunately, it is also -% complicated! +% \DeclareSIPower , +% \DeclareSIPrefix , +% \DeclareSIQualifier , +% \DeclareSIUnit +% } +% Pass data to the code layer. % \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_round_decimal: +\NewDocumentCommand \DeclareSIPower { +m +m m } { - \int_compare:nNnF \l_@@_round_int > 1 - { \@@_number_process_round_decimal_aux: } - \tl_put_right:Nx \l_@@_round_discard_tl - { \tl_head:N \l_@@_round_decimal_in_tl } - \tl_set:Nx \l_@@_round_decimal_in_tl - { \tl_tail:N \l_@@_round_decimal_in_tl } - \int_decr:N \l_@@_round_int + \siunitx_declare_power:NNn #1 #2 {#3} } -% \end{macrocode} -% The logic here has to deal with the (simpler) rounding up method and the -% case where there is a need to check for rounding to an even number. The -% later is only required when the discarded part is exactly equal to -% half of the least-significant digit. So there is a somewhat complex check -% for that, along with a somewhat simpler check when carrying out the -% rounding. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_round_decimal_aux: +\NewDocumentCommand \DeclareSIPrefix { +m m m } { - \int_set:Nn \l_@@_tmp_int - { \tl_head:N \l_@@_round_decimal_in_tl } - \@@_number_process_round_up: - \int_compare:nNnTF \l_@@_round_int = 1 - { - \int_compare:nNnT \l_@@_tmp_int > 4 - { - \bool_set_true:N \l_@@_round_bool - \bool_if:NF \l_@@_round_half_up_bool - { - \int_compare:nNnT - { \l_@@_round_discard_tl \int_use:N \l_@@_tmp_int } = 5 - { \bool_set_true:N \l_@@_round_even_bool } - } - } - } - { - \int_compare:nNnT \l_@@_tmp_int = { 10 } - { - \bool_set_true:N \l_@@_round_bool - \int_zero:N \l_@@_tmp_int - } - \tl_put_left:NV \l_@@_round_decimal_out_tl - \l_@@_tmp_int - } + \siunitx_declare_prefix:Nnn #1 {#2} {#3} } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \begin{macro}{\@@_number_process_round_up:} -% This is needed a few times, to round up the current digit unless -% it is even and \enquote{half to even} is active. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_round_up: +\NewDocumentCommand \DeclareSIQualifier { +m m } { - \bool_if:NT \l_@@_round_bool - { - \bool_if:NTF \l_@@_round_even_bool - { - \bool_set_false:N \l_@@_round_even_bool - \int_if_even:nF \l_@@_tmp_int - { \int_incr:N \l_@@_tmp_int } - } - { \int_incr:N \l_@@_tmp_int } - } - \bool_set_false:N \l_@@_round_bool + \siunitx_declare_qualifier:Nn #1 {#2} } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\@@_number_process_round_tidy:n} -% \begin{macro}{\@@_number_process_round_tidy_aux:w} -% To put data back again: there is a check to see if the number has been -% r ounded to zero and a minimal value has been requested. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_round_tidy:n #1 +\NewDocumentCommand \DeclareSIUnit { o +m m } { - \bool_lazy_and:nnTF - { \@@_number_if_zero_p:V \l_@@_round_integer_out_tl } - { \@@_number_if_zero_p:V \l_@@_round_decimal_out_tl } - { - \str_if_eq:VnTF \l_@@_process_round_min_tl { 0 } - { - \prop_put:Nnn \l_@@_number_in_prop { #1 -integer } { 0 } - \prop_put:NnV \l_@@_number_in_prop { #1 -decimal } - \l_@@_round_decimal_out_tl - } - { - \exp_after:wN \@@_number_process_round_tidy_aux:w - \l_@@_process_round_min_tl . . \q_stop {#1} - } - } - { - \prop_put:NnV \l_@@_number_in_prop { #1 -integer } - \l_@@_round_integer_out_tl - \tl_if_empty:NTF \l_@@_round_decimal_out_tl - { - \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal } - \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal-marker } - } - { - \prop_put:NnV \l_@@_number_in_prop { #1 -decimal } - \l_@@_round_decimal_out_tl - } - } - } -\cs_new_protected:Npn \@@_number_process_round_tidy_aux:w - #1 . #2 . #3 \q_stop #4 - { - \prop_put:Nnn \l_@@_number_in_prop { comparator } { < } - \prop_put:Nnn \l_@@_number_in_prop { #4 -integer } {#1} - \tl_if_empty:nTF {#2} - { \prop_remove:Nn \l_@@_number_in_prop { #4 -decimal } } - { \prop_put:Nnn \l_@@_number_in_prop { #4 -decimal } {#2} } + \IfNoValueTF {#1} + { \siunitx_declare_unit:Nn #2 {#3} } + { \siunitx_declare_unit:Nnn #2 {#3} {#1} } } % \end{macrocode} % \end{macro} -% \end{macro} % -%\begin{macro}{\@@_number_process_scientific:} -%\begin{macro}{ -% \@@_number_process_scientific_aux_i:nnn , -% \@@_number_process_scientific_aux_ii:nnn , -% \@@_number_process_scientific_large:nnn , -% \@@_number_process_scientific_large_loop:nNN , -% \@@_number_process_scientific_small:wn , -% \@@_number_process_scientific_store:nnn , -% \@@_number_process_scientific_engineering:nnn , -% \@@_number_process_scientific_engineering_0:nnn , -% \@@_number_process_scientific_engineering_1:nnn , -% \@@_number_process_scientific_engineering_1:nw , -% \@@_number_process_scientific_engineering_2:nnn , -% \@@_number_process_scientific_engineering_2_i:nw , -% \@@_number_process_scientific_engineering_2_ii:nw -%} -% Converting a number to scientific form is done such that the number -% of places involved is unchanged. The first step is to skip any -% complex-number containing input and to recover the stored data. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_scientific: { - \prop_if_in:NnF \l_@@_number_in_prop { complex } - { - \prop_get:NnNF \l_@@_number_in_prop { mantissa-integer } - \l_@@_tmpa_tl - { \tl_set:Nn \l_@@_tmpa_tl { 0 } } - \prop_get:NnNF \l_@@_number_in_prop { mantissa-decimal } - \l_@@_tmpb_tl - { \tl_clear:N \l_@@_tmpb_tl } - \tl_set:Nx \l_@@_tmpa_tl - { { \l_@@_tmpa_tl } { \l_@@_tmpb_tl } } - \prop_get:NnNF \l_@@_number_in_prop { exponent-integer } - \l_@@_tmpb_tl - { \tl_set:Nn \l_@@_tmpb_tl { 0 } } - \group_begin: - \prop_get:NnNT \l_@@_number_in_prop { exponent-sign } - \l_@@_tmpa_tl - { \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpa_tl } - \exp_args:NNNV \group_end: - \tl_set:Nn \l_@@_tmpb_tl \l_@@_tmpb_tl - \tl_set:Nx \l_@@_tmpa_tl - { \l_@@_tmpa_tl { \l_@@_tmpb_tl } } - \exp_after:wN \@@_number_process_scientific_aux_i:nnn - \l_@@_tmpa_tl - } -} -\cs_new_protected:Npn \@@_number_process_scientific_aux_i:nnn #1#2#3 - { - \bool_set_true:N \l_@@_tmp_bool - \tl_map_inline:nn {#1#2} - { - \str_if_eq:nnF {##1} { 0 } - { - \bool_set_false:N \l_@@_tmp_bool - \tl_map_break: - } - } - \bool_if:NF \l_@@_tmp_bool - { \@@_number_process_scientific_aux_ii:nnn {#1} {#2} {#3} } - } -% \end{macrocode} -% The code here works on a loop, standardising the mantissa into the -% range \( 1 \le x < 10 \). -% \begin{macrocode} -\cs_new_protected:Npn - \@@_number_process_scientific_aux_ii:nnn #1#2#3 { - \int_compare:nNnTF { \tl_count:n {#1} } > 1 - { \@@_number_process_scientific_large:nnn {#1} {#2} {#3} } - { - \@@_number_if_zero:nTF {#1} - { - \@@_number_process_scientific_small:wn - #2 \q_stop {#3} - } - { - \bool_if:NTF \l_@@_process_engineering_bool - { \@@_number_process_scientific_engineering:nnn } - { \@@_number_process_scientific_store:nnn } - {#1} {#2} {#3} - } - - } -} -% \end{macrocode} -% A faster approach here is to use integer maths to do the digit move, -% but that runs into problems with the range available for the input. -% Instead, we use a loop to find the last digit. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_scientific_large:nnn #1#2#3 - { - \cs_set_protected:Npn \@@_number_process_scientific_large_loop:nNN - ##1##2##3 - { - \quark_if_recursion_tail_stop_do:Nn ##3 - { - \@@_number_process_scientific_aux_ii:nnn {##1} { ##2 #2 } - { #3 + 1 } - } - \@@_number_process_scientific_large_loop:nNN { ##1 ##2 } ##3 - } - \@@_number_process_scientific_large_loop:nNN { } #1 - \q_recursion_tail \q_recursion_stop - } -% \end{macrocode} -% For small numbers, the important digit is easy to find. -% \begin{macrocode} -\cs_new_protected:Npn - \@@_number_process_scientific_small:wn #1#2 \q_stop #3 - { \@@_number_process_scientific_aux_ii:nnn {#1} {#2} { #3 - 1 } } -% \end{macrocode} -% A tidy-up and store routine. -% \begin{macrocode} -\cs_new_protected:Npn - \@@_number_process_scientific_store:nnn #1#2#3 - { - \prop_put:Nnn \l_@@_number_in_prop { mantissa-integer } {#1} - \tl_if_empty:nTF {#2} - { - \prop_remove:Nn \l_@@_number_in_prop { mantissa-decimal } - \prop_remove:Nn \l_@@_number_in_prop - { mantissa-decimal-marker } - } - { - \prop_put:Nnn \l_@@_number_in_prop - { mantissa-decimal } {#2} - \prop_if_in:NnF \l_@@_number_in_prop - { mantissa-decimal-marker } - { - \prop_put:Nnn \l_@@_number_in_prop - { mantissa-decimal-marker } { . } - } - } - \int_compare:nNnTF {#3} = { 0 } - { - \prop_remove:Nn \l_@@_number_in_prop { exponent } - \prop_remove:Nn \l_@@_number_in_prop { exponent-sign } - \prop_remove:Nn \l_@@_number_in_prop { exponent-integer } - } - { - \prop_put:Nnn \l_@@_number_in_prop { exponent } { true } - \int_compare:nNnTF {#3} > { 0 } - { - \int_set:Nn \l_@@_tmp_int {#3} - \prop_put:NnV \l_@@_number_in_prop - { exponent-integer } \l_@@_tmp_int - \prop_remove:Nn \l_@@_number_in_prop { exponent-sign } - } - { - \int_set:Nn \l_@@_tmp_int { 0 - (#3) } - \prop_put:NnV \l_@@_number_in_prop - { exponent-integer } \l_@@_tmp_int - \prop_put:Nnn \l_@@_number_in_prop { exponent-sign } - { - } - } - } - } -% \end{macrocode} -% For engineering style, the exponent has to be a power of three. -% The fastest way to do this is by expansion, as the number of tokens -% is known. -% \begin{macrocode} -\cs_new_protected:Npn - \@@_number_process_scientific_engineering:nnn #1#2#3 - { - \use:c - { - @@_number_process_scientific_engineering_ - \int_compare:nNnTF {#3} < { 0 } - { - \int_case:nnF { \int_mod:nn { 0 - (#3) } { 3 } } - { - { 1 } { 2 } - { 2 } { 1 } - } - { 0 } - } - { \int_mod:nn {#3} { 3 } } - :nnn - } - {#1} {#2} {#3} - } -\cs_new_eq:cN - { @@_number_process_scientific_engineering_0:nnn } - \@@_number_process_scientific_store:nnn -\cs_new_protected:cpn - { @@_number_process_scientific_engineering_1:nnn } #1#2#3 - { - \tl_if_empty:nTF {#2} - { - \@@_number_process_scientific_store:nnn { #1 0 } { } - { #3 - 1 } - } - { - \use:c - { @@_number_process_scientific_engineering_1:nw } - {#1} #2 \q_stop {#3} - } - } -\cs_new_protected:cpn - { @@_number_process_scientific_engineering_1:nw } - #1#2#3 \q_stop #4 - { - \@@_number_process_scientific_store:nnn - {#1#2} {#3} { #4 - 1 } - } -\cs_new_protected:cpn - { @@_number_process_scientific_engineering_2:nnn } #1#2#3 - { - \tl_if_empty:nTF {#2} - { - \@@_number_process_scientific_store:nnn { #1 00 } { } - { #3 - 2 } - } - { - \use:c - { @@_number_process_scientific_engineering_2_i:nw } - {#1} #2 \q_stop {#3} - } - } -\cs_new_protected:cpn - { @@_number_process_scientific_engineering_2_i:nw } - #1#2#3 \q_stop #4 - { - \tl_if_empty:nTF {#3} - { - \@@_number_process_scientific_store:nnn { #1#2 0 } { } - { #4 - 2 } - } - { - \use:c - { @@_number_process_scientific_engineering_2_ii:nw } - {#1#2} #3 \q_stop {#4} - } - } -\cs_new_protected:cpn - { @@_number_process_scientific_engineering_2_ii:nw } - #1#2#3 \q_stop #4 - { - \@@_number_process_scientific_store:nnn { #1#2 } {#3} - { #4 - 2 } - } -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_number_process_sign:} -%\begin{macro}{ -% \@@_number_process_sign_add:n , -% \@@_number_process_sign_plus:n -%} -%\begin{macro}{\c_@@_plus_tl} -% Sorting out signs consists of two parts: retaining a plus if necessary -% and adding an explicit sign. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_sign: { - \bool_if:NF \l_@@_process_plus_bool - { - \prop_if_in:NnTF \l_@@_number_in_prop { mantissa-sign } - { \@@_number_process_sign_plus:n { mantissa } } - { - \prop_if_in:NnT \l_@@_number_in_prop { complex-sign } - { - \prop_if_in:NnF \l_@@_number_in_prop { mantissa } - { \@@_number_process_sign_plus:n { complex } } - } - } - \prop_if_in:NnT \l_@@_number_in_prop { exponent-sign } - { \@@_number_process_sign_plus:n { exponent } } - } - \tl_if_empty:NF \l_@@_process_sign_tl - { - \@@_number_process_sign_add:n { mantissa } - \prop_if_in:NnTF \l_@@_number_in_prop { complex } - { \@@_number_process_sign_add:n { complex } } - } -} -% \end{macrocode} -% Adding a sign to an existing number needs a couple of to make sure -% there is a number to add to, and to see if there is a sign already. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_sign_add:n #1 { - \prop_if_in:NnF \l_@@_number_in_prop { #1 -sign } - { - \prop_if_in:NnF \l_@@_number_in_prop { #1 -had-sign } - { - \prop_get:NnN \l_@@_number_in_prop {#1} - \l_@@_tmpa_tl - \tl_if_empty:NTF \l_@@_tmpa_tl - { - \prop_put:NnV \l_@@_number_in_prop { sign } - \l_@@_process_sign_tl - } - { - \prop_put:NnV \l_@@_number_in_prop { #1 -sign } - \l_@@_process_sign_tl - } - } - } -} -% \end{macrocode} -% Holding onto a plus works very much in the same way as adding a sign: -% some quick tests and an assignment. Using a pre-defined token list is -% a speed-related choice: very slightly faster comparison. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_sign_plus:n #1 { - \prop_get:NnN \l_@@_number_in_prop { #1 -sign } - \l_@@_tmpa_tl - \tl_if_eq:NNT \c_@@_plus_tl \l_@@_tmpa_tl - { - \prop_remove:Nn \l_@@_number_in_prop { #1 -sign } - \prop_put:Nnn \l_@@_number_in_prop { #1 -had-sign } { true } - } -} -\tl_const:Nn \c_@@_plus_tl { + } -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} +% \subsubsection{Document commands} % -%\begin{macro}{\@@_number_process_uncertainty:} -%\begin{macro}{\@@_number_process_uncertainty_aux:n} -% There may be a need to expand uncertainties into a decimal and integer -% part. This is done here so that the core \texttt{in} code is faster. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_uncertainty: { - \clist_map_function:nN { mantissa , complex } - \@@_number_process_uncertainty_aux:n -} -\cs_new_protected:Npn - \@@_number_process_uncertainty_aux:n #1 { - \prop_if_in:NnT \l_@@_number_in_prop { #1 -uncertainty } - { - \prop_if_in:NnTF \l_@@_number_in_prop { #1 -decimal-marker } - { \@@_number_process_uncertainty_decimal:n {#1} } - { \@@_number_process_uncertainty_integer:n {#1} } - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -%\begin{macro}{\@@_number_process_uncertainty_decimal:n} -%\begin{macro}{\@@_number_process_uncertainty_count:nn} -% To deal with an error in the decimal part, care needs to be taken to -% correctly pad with zeros and also to allow for the possibility that -% the error crosses the decimal--integer boundary. -% \begin{macrocode} -\cs_new_protected:Npn - \@@_number_process_uncertainty_decimal:n #1 { - \@@_number_process_uncertainty_count:nn {#1} { decimal } - \@@_number_process_uncertainty_count:nn {#1} { uncertainty } - \tl_clear:N \l_@@_uncertainty_decimal_tl - \tl_clear:N \l_@@_uncertainty_integer_tl - \int_compare:nNnTF - { \l_@@_process_uncertainty_int } > - { \l_@@_process_decimal_int } - { \@@_number_process_uncertainty_separate: } - { \@@_number_process_uncertainty_pad: } - \tl_if_empty:NF \l_@@_uncertainty_integer_tl - { - \prop_put:NnV \l_@@_number_in_prop - { #1 -uncertainty-integer } - \l_@@_uncertainty_integer_tl - } - \prop_put:NnV \l_@@_number_in_prop { #1 -uncertainty-decimal } - \l_@@_uncertainty_decimal_tl - \prop_get:NnN \l_@@_number_in_prop { #1 -decimal-marker } - \l_@@_tmpa_tl - \prop_put:NnV \l_@@_number_in_prop - { #1 -uncertainty-decimal-marker } \l_@@_tmpa_tl -} -\cs_new_protected:Npn - \@@_number_process_uncertainty_count:nn #1#2 { - \prop_get:NnN \l_@@_number_in_prop { #1 - #2 } - \l_@@_tmpa_tl - \int_set:cn { l_@@_process_ #2 _int } - { \tl_count:N \l_@@_tmpa_tl } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -%\begin{macro}{\@@_number_process_uncertainty_pad:} -% Uncertainty is short: add zeros. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_uncertainty_pad: { - \int_while_do:nNnn - { \l_@@_process_uncertainty_int } < - { \l_@@_process_decimal_int } - { - \tl_put_right:Nn \l_@@_uncertainty_decimal_tl {0} - \int_incr:N \l_@@_process_uncertainty_int - } - \tl_put_right:NV \l_@@_uncertainty_decimal_tl - \l_@@_tmpa_tl -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\@@_number_process_uncertainty_separate:} -%\begin{macro}{\@@_number_process_uncertainty_separate_aux:N} -% Find the integer--decimal boundary and work appropriately. +% \begin{macro}{\qty} % \begin{macrocode} -\cs_new_protected:Npn - \@@_number_process_uncertainty_separate: { - \tl_map_function:NN \l_@@_tmpa_tl - \@@_number_process_uncertainty_separate_aux:N -} -\cs_new_protected:Npn - \@@_number_process_uncertainty_separate_aux:N #1 { - \int_compare:nNnTF - { \l_@@_process_uncertainty_int } > - { \l_@@_process_decimal_int } - { \tl_put_right:Nn \l_@@_uncertainty_integer_tl {#1} } - { \tl_put_right:Nn \l_@@_uncertainty_decimal_tl {#1} } - \int_decr:N \l_@@_process_uncertainty_int -} -% \end{macrocode} -%\end{macro} -%\end{macro} -%\begin{macro}{\@@_number_process_uncertainty_integer:n} -% Relatively easy: the uncertainty is in the integer part of the number, -% and so there is no need to generate zeros. -% \begin{macrocode} -\cs_new_protected:Npn - \@@_number_process_uncertainty_integer:n #1 { - \prop_get:NnN \l_@@_number_in_prop { #1 -uncertainty } - \l_@@_tmpa_tl - \prop_put:NnV \l_@@_number_in_prop { #1 -uncertainty-integer } - \l_@@_tmpa_tl -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_process_zero_fill:} -%\begin{macro}{ -% \@@_number_process_zero_fill_aux:n , -% \@@_number_process_zero_fill_aux:nn -%} -% Checks for adding zeros to each component are carried out. The nesting -% here makes checking the appropriate flag a little more efficient. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_zero_fill: { - \@@_number_process_zero_fill_aux:n { integer } - \@@_number_process_zero_fill_aux:n { decimal } -} -\cs_new:Npn \@@_number_process_zero_fill_aux:n #1 { - \bool_if:cT { l_@@_process_ #1 _zero_bool } - { - \@@_number_process_zero_fill_aux:nn { mantissa } {#1} - \@@_number_process_zero_fill_aux:nn { complex } {#1} - \@@_number_process_zero_fill_aux:nn { exponent } {#1} - } -} -\cs_new_protected:Npn - \@@_number_process_zero_fill_aux:nn #1#2 { - \prop_if_in:NnT \l_@@_number_in_prop { #1 -decimal-marker } - { - \prop_if_in:NnF \l_@@_number_in_prop { #1 - #2 } - { \prop_put:Nnn \l_@@_number_in_prop { #1 - #2 } { 0 } } - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -% \begin{macro}{\@@_number_process_zero_to_integer:} -% \begin{macro}{\@@_number_process_zero_to_integer_aux:n} -% Look for a decimal part which is simply zero, and if found delete it. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_process_zero_to_integer: - { - \bool_if:NT \l_@@_zero_decimal_to_integer_bool - { - \@@_number_process_zero_to_integer_aux:n { mantissa } - \@@_number_process_zero_to_integer_aux:n { complex } - } - } -\cs_new_protected:Npn \@@_number_process_zero_to_integer_aux:n #1 +\@ifpackageloaded { physics } { - \prop_get:NnNT \l_@@_number_in_prop { #1 -decimal } \l_@@_tmpa_tl + \msg_new:nnn { siunitx } { physics-pkg } { - \bool_set_true:N \l_@@_tmp_bool - \tl_map_inline:Nn \l_@@_tmpa_tl - { - \str_if_eq:nnF {##1} { 0 } - { - \bool_set_false:N \l_@@_tmp_bool - \tl_map_break: - } - } - \bool_if:NT \l_@@_tmp_bool - { - \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal } - \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal-marker } - } + Detected~the~"physics"~package: \\ + Omitting~definition~of~\token_to_str:N \qty. } + \msg_warning:nn { siunitx } { physics-pkg } + \use_none:nnnn } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}{\@@_number_exp_to_prefix:} -% This function is a bit awkward, as it essentially cuts across the -% unit processor. The idea here is first to recover the numerical exponent, -% and sign if there is one. The earlier formatting run will have reset the -% total number of units to zero, so that has to be recovered before -% doing the format a second time. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_exp_to_prefix: - { - \prop_set_eq:NN \l_@@_unit_prop \l_@@_unit_saved_prop - \prop_get:NnNT \l_@@_number_in_prop { exponent-integer } - \l_@@_tmpa_tl - { - \prop_get:NnNT \l_@@_number_in_prop { exponent-sign } - \l_@@_tmpb_tl - { \tl_put_left:NV \l_@@_tmpa_tl \l_@@_tmpb_tl } - \prop_if_in:NnT \l_@@_unit_prop { per-1 } - { - \tl_set:Nx \l_@@_tmpa_tl - { \int_eval:n { - \l_@@_tmpa_tl } } - } - \prop_get:NnNT \l_@@_unit_prop { prefix-1 } \l_@@_tmpb_tl - { - \prop_remove:Nn \l_@@_unit_prop { prefix-1 } - \prop_remove:Nn \l_@@_unit_prop { prefix-symbol-1 } - \prop_get:NVN \l_@@_prefix_forward_prop \l_@@_tmpb_tl - \l_@@_tmpb_tl - \tl_set:Nx \l_@@_tmpa_tl - { \int_eval:n { \l_@@_tmpa_tl + \l_@@_tmpb_tl } } - } - \prop_get:NnNT \l_@@_unit_prop { power-1 } \l_@@_tmpb_tl - { - \tl_set:Nx \l_@@_tmpa_tl - { \int_eval:n { \l_@@_tmpa_tl / \l_@@_tmpb_tl } } - } - \prop_get:NVNTF \l_@@_prefix_reverse_prop \l_@@_tmpa_tl - \l_@@_tmpb_tl - { - \prop_remove:Nn \l_@@_number_in_prop { exponent } - \use:c - { - @@_ \exp_after:wN \token_to_str:N \l_@@_tmpb_tl - _function:w - } - \prop_get:NnN \l_@@_unit_prop { total-units } \l_@@_tmpa_tl - \int_set:Nn \l_@@_unit_int \l_@@_tmpa_tl - \cs_set_eq:NN \@@_pm: \pm - \@@_unit_format: - \cs_set_eq:NN \pm \@@_pm: - } - { - \msg_error:nnx { siunitx } { non-convertible-exponent } - { \l_@@_tmpa_tl } - } - } - } -% \end{macrocode} -% \end{macro} -% -%\subsection{Formatting numbers for output} -% -% Getting numbers ready for printing requires the reconstruction of the -% number from the various parts processed earlier. Spaces and brackets -% are added back into the main numbers, as the various parts are also -% correctly formatted. The difference between the \texttt{in} and -% \texttt{out} store is that the later can include formatting such as -% hard spaces. -% -%\begin{macro}{\l_@@_number_out_prop} -% Like the \texttt{in} version! -% \begin{macrocode} -\prop_new:N \l_@@_number_out_prop -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \l_@@_group_sep_tl , -% \l_@@_output_decimal_tl -%} -% A couple of variables are declared here, as they need a little more -% work than just storage. -% \begin{macrocode} -\tl_new:N \l_@@_group_sep_tl -\tl_new:N \l_@@_output_decimal_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_complex_after_bool} -% A setting for where complex numbers go. -% \begin{macrocode} -\bool_new:N \l_@@_complex_after_bool -% \end{macrocode} -%\end{macro} -% -% \begin{variable} -% {\l_@@_group_decimal_bool, \l_@@_group_integer_bool} -% Used for grouping digits. -% \begin{macrocode} -\bool_new:N \l_@@_group_decimal_bool -\bool_new:N \l_@@_group_integer_bool -% \end{macrocode} -% \end{variable} -% -%\begin{macro}{ -% \l_@@_negative_bracket_bool , -% \l_@@_brackets_bool , -% \l_@@_bracket_close_tl , -% \l_@@_output_complex_copy_bool , -% \l_@@_output_decimal_copy_bool , -% \l_@@_exponent_base_tl , -% \l_@@_exponent_product_tl , -% \l_@@_group_min_int , -% \l_@@_negative_color_tl , -% \l_@@_bracket_open_tl , -% \l_@@_output_uncert_close_tl , -% \l_@@_output_complex_tl , -% \l_@@_output_exponent_tl , -% \l_@@_output_uncert_open_tl , -% \l_@@_uncert_sep_bool , -% \l_@@_tight_bool , -% \l_@@_uncert_sep_tl -%} -% Lots of settings, some used only for numbers, some more widely. -% \begin{macrocode} -\keys_define:nn { siunitx } { - bracket-negative-numbers .bool_set:N = - \l_@@_negative_bracket_bool , - bracket-numbers .bool_set:N = \l_@@_brackets_bool, - close-bracket .tl_set:N = \l_@@_bracket_close_tl, - complex-root-position .choice:, - complex-root-position - / after-number .code:n = - { \bool_set_true:N \l_@@_complex_after_bool } , - complex-root-position - / before-number .code:n = - { \bool_set_false:N \l_@@_complex_after_bool } , - copy-complex-root .bool_set:N = - \l_@@_output_complex_copy_bool, - copy-decimal-marker .bool_set:N = - \l_@@_output_decimal_copy_bool, - exponent-base .tl_set:N = \l_@@_exponent_base_tl, - exponent-product .tl_set:N = - \l_@@_exponent_product_tl, - group-decimal-digits .meta:n = { group-digits = decimal }, - group-digits .choice: , - group-digits / - decimal .code:n = - { - \bool_set_true:N \l_@@_group_decimal_bool - \bool_set_false:N \l_@@_group_integer_bool - }, - group-digits / - false .code:n = - { - \bool_set_false:N \l_@@_group_decimal_bool - \bool_set_false:N \l_@@_group_integer_bool - }, - group-digits / - integer .code:n = - { - \bool_set_false:N \l_@@_group_decimal_bool - \bool_set_true:N \l_@@_group_integer_bool - }, - group-digits / - true .code:n = - { - \bool_set_true:N \l_@@_group_decimal_bool - \bool_set_true:N \l_@@_group_integer_bool - }, - group-digits .default:n = true , - group-four-digits .choice:, - group-four-digits / - false .meta:n = { group-minimum-digits = 5 }, - group-four-digits / - true .meta:n = { group-minimum-digits = 4 }, - group-four-digits .default:n = true, - group-integer-digits .meta:n = { group-digits = integer }, - group-minimum-digits .int_set:N = \l_@@_group_min_int, - group-separator .code:n = - { \tl_set:Nn \l_@@_group_sep_tl { {#1} } }, - negative-color .tl_set:N = \l_@@_negative_color_tl, - open-bracket .tl_set:N = \l_@@_bracket_open_tl, - output-close-uncertainty .tl_set:N = - \l_@@_output_uncert_close_tl, - output-complex-root .tl_set:N = \l_@@_output_complex_tl , - output-decimal-marker .code:n = - { \tl_set:Nn \l_@@_output_decimal_tl { {#1} } }, - output-exponent-marker .tl_set:N = \l_@@_output_exponent_tl, - output-open-uncertainty .tl_set:N = - \l_@@_output_uncert_open_tl, - separate-uncertainty .bool_set:N = \l_@@_uncert_sep_bool, - tight-spacing .bool_set:N = \l_@@_tight_bool, - uncertainty-separator .tl_set:N = \l_@@_uncert_sep_tl, -} -\keys_set:nn { siunitx } - { - bracket-numbers = true , % ( - close-bracket = ) , - complex-root-position = after-number , - copy-decimal-marker = false , - exponent-base = 10 , - exponent-product = \times , - group-digits = true , - group-minimum-digits = 5 , - group-separator = \, , - open-bracket = ( , % ) ( - output-close-uncertainty = ) , - output-complex-root = \ensuremath { \mathrm { i } } , - output-decimal-marker = . , - output-open-uncertainty = ( % ) - } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_format:} -% The master control function for formatting output: the usual set up. -% The number is put back together in stages. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format: { - \prop_if_empty:NF \l_@@_number_in_prop - { - \prop_clear:N \l_@@_number_out_prop - \@@_number_format_reassemble: - \@@_number_format_complex: - \@@_number_format_sign:n { mantissa } - \@@_number_format_sign:n { exponent } - \@@_number_format_relation: - \@@_number_format_color: - \@@_number_format_final: - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_format_brackets:n} -%\begin{macro}{\@@_number_format_brackets_aux:n} -% There are various points at which brackets might be added to -% avoid ambiguity. The function here adds the appropriate tokens -% around whatever is in the supplied named store. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_brackets:n #1 { - \bool_if:NT \l_@@_brackets_bool - { - \prop_if_in:NnT \l_@@_number_out_prop { #1 -bracket } - { - \@@_number_format_brackets_aux:n {#1} - \prop_remove:Nn \l_@@_number_out_prop { #1 -bracket } - } - } -} -\cs_new_protected:Npn \@@_number_format_brackets_aux:n #1 { - \prop_get:NnNF \l_@@_number_out_prop { #1 -result } - \l_@@_tmpa_tl - { - \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpa_tl - } - \tl_put_left:NV \l_@@_tmpa_tl \l_@@_bracket_open_tl - \tl_put_right:NV \l_@@_tmpa_tl \l_@@_bracket_close_tl - \str_if_eq:nnTF {#1} { result } - { \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpa_tl } - { - \prop_put:NnV \l_@@_number_out_prop { #1 -result } - \l_@@_tmpa_tl - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_number_format_color:} -%\begin{macro}{\@@_number_format_color_aux:n} -% If the mantissa is negative, then any colour for output might change. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_color: { - \tl_if_empty:NF \l_@@_negative_color_tl - { - \@@_number_format_color_aux:n { mantissa-sign } - \@@_number_format_color_aux:n { sign } - } -} -\cs_new_protected:Npn \@@_number_format_color_aux:n #1 { - \prop_get:NnNT \l_@@_number_in_prop {#1} \l_@@_tmpa_tl - { - \str_if_eq:VnT \l_@@_tmpa_tl { - } - { - \prop_put:NnV \l_@@_number_out_prop { color } - \l_@@_negative_color_tl - } - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_number_format_complex:} -%\begin{macro}{ -% \@@_number_format_complex_aux:n , -% \@@_number_format_complex_aux: -%} -% The real and complex parts of each number are reassembled, with -% brackets if needed. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_complex: { - \prop_if_in:NnT \l_@@_number_in_prop { complex-root } - { - \prop_if_in:NnTF \l_@@_number_out_prop { complex } - { - \@@_number_format_brackets:n { complex } - \@@_number_format_complex_aux:n { complex } - \@@_number_format_complex_aux:n { complex-result } - \prop_if_in:NnT \l_@@_number_out_prop - { complex-uncertainty } - { - \@@_number_format_complex_aux:n - { complex-uncertainty } - } - } - { - \prop_put:NnV \l_@@_number_out_prop { complex } - \l_@@_output_complex_tl - } - \@@_number_format_join_complex: - } -} -\cs_new_protected:Npn \@@_number_format_complex_aux:n #1 { - \bool_if:NTF \l_@@_output_complex_copy_bool - { - \prop_get:NnN \l_@@_number_in_prop { complex-root } - \l_@@_tmpa_tl - } - { \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_output_complex_tl } - \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpb_tl - \bool_if:NTF \l_@@_complex_after_bool - { \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpa_tl } - { \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpa_tl } - \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpb_tl -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{ -% \@@_number_format_copy:n , -% \@@_number_format_copy:nn -%} -% Just copy across. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_copy:n #1 { - \prop_get:NnN \l_@@_number_in_prop {#1} \l_@@_tmpa_tl - \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpa_tl -} -\cs_new_protected:Npn \@@_number_format_copy:nn #1#2 { - \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpa_tl - \prop_put:NnV \l_@@_number_out_prop {#2} \l_@@_tmpa_tl -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_format_final:} -% For numbers which do not contain an exponent, the mantissa result is -% simply copied to the final output position. On the other hand, for -% exponents there are further checks, which are handed off to dedicated -% functions. There is also a check for complex numbers with no real -% part, which needs to be \enquote{copied} to the standard result -% slot. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_final: { - \prop_if_in:NnT \l_@@_number_out_prop { complex } - { - \prop_if_in:NnF \l_@@_number_out_prop { mantissa-result } - { - \@@_number_format_copy:nn { complex } - { mantissa-result } - } - } - \prop_if_in:NnTF \l_@@_number_out_prop { exponent } - { - \@@_number_format_final_exponent: - \prop_if_in:NnTF \l_@@_number_out_prop { mantissa-result } - { \@@_number_format_final_combined: } - { \@@_number_format_final_exponent_only: } - } - { \@@_number_format_copy:nn { mantissa-result } { result } } - \prop_if_in:NnT \l_@@_number_out_prop { mantissa-bracket } - { - \prop_put:Nnn \l_@@_number_out_prop { result-bracket } - { true } - \prop_remove:Nn \l_@@_number_out_prop { mantissa-bracket } - } - \prop_if_in:NnT \l_@@_number_out_prop { comparator } - { - \@@_number_format_brackets:n { result } - \prop_get:NnN \l_@@_number_out_prop { comparator } - \l_@@_tmpa_tl - \prop_get:NnN \l_@@_number_out_prop { result } - \l_@@_tmpb_tl - \tl_set:Nx \l_@@_tmpa_tl - { - \exp_not:N \mathord - \exp_not:V \l_@@_tmpa_tl - \exp_not:V \l_@@_tmpb_tl - } - \prop_put:NnV \l_@@_number_out_prop { result } - \l_@@_tmpa_tl - } -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\@@_number_format_final_combined:} -% When there is both a mantissa and an exponent, the mantissa is -% combined with the product sign before adding the exponent part on. -% The combined result is then stored. The marker -% \texttt{result-bracket-exponent} indicates that the number needs -% brackets due to the exponent part, but not in other cases. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_final_combined: { - \@@_number_format_brackets:n { mantissa } - \prop_get:NnN \l_@@_number_out_prop { mantissa-result } - \l_@@_tmpa_tl - \tl_if_empty:NT \l_@@_output_exponent_tl - { - \tl_put_right:Nx \l_@@_tmpa_tl - { - \exp_not:N \ensuremath - { - \bool_if:NTF \l_@@_tight_bool - { { \exp_not:V \l_@@_exponent_product_tl } } - { { } \exp_not:V \l_@@_exponent_product_tl { } } - } - } - } - \prop_get:NnN \l_@@_number_out_prop { exponent-result } - \l_@@_tmpb_tl - \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl - \prop_put:NnV \l_@@_number_out_prop { result } - \l_@@_tmpa_tl - \prop_put:Nnn \l_@@_number_out_prop - { result-bracket-exponent } { true } -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\@@_number_format_final_exponent:} -% When there is an exponent, the base always needs to be added to the -% front of the number itself. The number must be superscripted, of -% course. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_final_exponent: { - \prop_get:NnN \l_@@_number_out_prop { exponent } - \l_@@_tmpa_tl - \tl_if_empty:NTF \l_@@_output_exponent_tl - { - \tl_set:Nx \l_@@_tmpa_tl - { ^ { \exp_not:V \l_@@_tmpa_tl } } - \tl_put_left:NV \l_@@_tmpa_tl \l_@@_exponent_base_tl - } - { - \tl_set:Nx \l_@@_tmpa_tl - { - \exp_not:V \l_@@_output_exponent_tl - \exp_not:N \mathord - \exp_not:V \l_@@_tmpa_tl - } - } - \prop_put:NnV \l_@@_number_out_prop { exponent-result } - \l_@@_tmpa_tl -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\@@_number_format_final_exponent_only:} -% When there is only an exponent, a check must be made for a -% sign in the mantissa part. If there is one, it is copied across. -% \begin{macrocode} -\cs_new_protected:Npn - \@@_number_format_final_exponent_only: { - \prop_get:NnNT \l_@@_number_in_prop { mantissa-sign } - \l_@@_tmpa_tl - { - \prop_get:NnN \l_@@_number_out_prop { exponent-result } - \l_@@_tmpb_tl - \@@_tl_put_left_math:NV \l_@@_tmpb_tl - \l_@@_tmpa_tl - \prop_put:NnV \l_@@_number_out_prop { exponent-result } - \l_@@_tmpb_tl - } - \@@_number_format_copy:nn { exponent-result } { result } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_format_group:n} -%\begin{macro}{\@@_number_format_group_aux:nn} -% Grouping digits only happens if there are no symbols in the input, and -% of course if grouping has been requested. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_group:n #1 { - \@@_number_format_group_aux:nn {#1} { integer } - \@@_number_format_group_aux:nn {#1} { decimal } - \prop_if_in:NnTF \l_@@_number_out_prop { #1 -integer } - { \@@_number_format_copy:nn { #1 -integer } {#1} } - { \tl_clear:N \l_@@_tmpa_tl } - \prop_get:NnNT \l_@@_number_in_prop { #1 -decimal-marker } - \l_@@_tmpb_tl - { - \bool_if:NTF \l_@@_output_decimal_copy_bool - { \tl_set:Nx \l_@@_tmpb_tl { { \l_@@_tmpb_tl } } } - { - \tl_set_eq:NN \l_@@_tmpb_tl - \l_@@_output_decimal_tl - } - \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl - \prop_put:NnV \l_@@_number_out_prop { #1 -decimal-marker } - \l_@@_tmpb_tl - \prop_get:NnNF \l_@@_number_out_prop { #1 -decimal } - \l_@@_tmpb_tl - { \tl_clear:N \l_@@_tmpb_tl } - \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl - \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpa_tl - } -} -\cs_new_protected:Npn \@@_number_format_group_aux:nn #1#2 { - \prop_if_in:NnT \l_@@_number_in_prop { #1 - #2 } - { - \bool_if:cTF { l_@@_group_ #2 _bool } - { \@@_number_format_group:nn {#1} {#2} } - { \@@_number_format_copy:n { #1 - #2 } } - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% \begin{macro}{\@@_number_format_group:nn} -% The idea here is that grouping is only needed for numbers with sufficient -% digits: this is done simply by counting up all of the digits. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_group:nn #1#2 + { } +\NewDocumentCommand \qty { O { } m > { \TrimSpaces } m } { - \prop_get:NnN \l_@@_number_in_prop { #1 - #2 } \l_@@_tmpa_tl - \int_compare:nNnTF - { \tl_count:N \l_@@_tmpa_tl } < \l_@@_group_min_int - { \@@_number_format_copy:n { #1 - #2 } } - { - \tl_clear:N \l_@@_tmpb_tl - \use:c { @@_number_format_group_ #2 : } - \prop_put:NnV \l_@@_number_out_prop { #1 - #2 } \l_@@_tmpb_tl - } + \mode_leave_vertical: + \group_begin: + \siunitx_unit_options_apply:n {#3} + \keys_set:nn { siunitx } {#1} + \siunitx_quantity:nn {#2} {#3} + \group_end: } % \end{macrocode} % \end{macro} -%\begin{macro}{\@@_number_format_group_decimal:} -%\begin{macro}{\@@_number_format_group_decimal_aux:} -% Using the \enquote{keep everything on the stack} approach, relatively -% simple recursion is needed. This trick is taken more or less directly -% from \pkg{numprint}. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_group_decimal: { - \tl_if_empty:NF \l_@@_tmpa_tl - { - \exp_after:wN \@@_number_format_group_decimal_aux:NNNN - \l_@@_tmpa_tl { } { } { } - } -} -\cs_new_protected:Npn \@@_number_format_group_decimal_aux:NNNN - #1#2#3#4 { - \tl_if_empty:nTF {#2} - { \tl_put_right:Nn \l_@@_tmpb_tl {#1} } - { - \tl_if_empty:nTF {#3} - { \tl_put_right:Nn \l_@@_tmpb_tl { #1 #2 } } - { - \tl_put_right:Nn \l_@@_tmpb_tl { #1 #2 #3 } - \tl_if_empty:nF {#4} - { - \tl_put_right:NV \l_@@_tmpb_tl \l_@@_group_sep_tl - \@@_number_format_group_decimal_aux:NNNN #4 - } - } - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -%\begin{macro}{\@@_number_format_group_integer:} -%\begin{macro}{ -% \@@_number_format_group_integer_setup:n , -% \@@_number_format_group_integer_setup:V , -% \@@_number_format_group_integer_setup_aux:NNNN , -% \@@_number_format_group_integer_aux:NNNN -%} -% By keeping everything on the stack, recursion can occur quite -% efficiently here. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_group_integer: { - \tl_if_empty:NF \l_@@_tmpa_tl - { - \@@_number_format_group_integer_setup:V \l_@@_tmpa_tl - } -} -\cs_new_protected:Npn \@@_number_format_group_integer_setup:n #1 { - \@@_number_format_group_integer_setup_aux:NNNN - { } #1 { } { } { } -} -\cs_generate_variant:Nn \@@_number_format_group_integer_setup:n - { V } -\cs_new_protected:Npn - \@@_number_format_group_integer_setup_aux:NNNN #1#2#3#4 { - \tl_if_empty:nTF {#2} - { \@@_number_format_group_integer_aux:NNNN #1 \q_nil } - { - \tl_if_empty:nTF {#3} - { - \@@_number_format_group_integer_aux:NNNN { } { } #1#2 - \q_nil - } - { - \tl_if_empty:nTF {#4} - { - \@@_number_format_group_integer_aux:NNNN { } #1#2#3 - \q_nil - } - { - \@@_number_format_group_integer_setup_aux:NNNN - {#1#2#3#4} - } - } - } -} -\cs_new_protected:Npn - \@@_number_format_group_integer_aux:NNNN #1#2#3#4 { - \tl_put_right:Nn \l_@@_tmpb_tl {#1#2#3} - \quark_if_nil:nF {#4} - { - \tl_put_right:NV \l_@@_tmpb_tl \l_@@_group_sep_tl - \@@_number_format_group_integer_aux:NNNN #4 - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_number_format_join_complex:} -% For adding the complex part to the main part of a number. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_join_complex: { - \@@_number_format_sign_complex: - \prop_if_in:NnT \l_@@_number_out_prop { mantissa } - { - \@@_number_format_brackets:n { mantissa } - \prop_get:NnN \l_@@_number_out_prop { mantissa-result } - \l_@@_tmpa_tl - \prop_get:NnNF \l_@@_number_out_prop { complex-result } - \l_@@_tmpb_tl - { - \prop_get:NnN \l_@@_number_out_prop { complex } - \l_@@_tmpb_tl - } - \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl - \prop_put:NnV \l_@@_number_out_prop { mantissa-result } - \l_@@_tmpa_tl - \prop_put:Nnn \l_@@_number_out_prop { mantissa-bracket } - { true } - } -} -% \end{macrocode} -%\end{macro} % -%\begin{macro}{ -% \@@_number_format_join_uncert: , -% \@@_number_format_join_uncert:n -%} -%\begin{macro}{\@@_number_format_join_uncert_pm:N} -% For adding separated uncertainties to the main part of a number. +% \begin{macro}{\ang, \num, \unit} +% All of a standard form: start a paragraph (if required), set local +% key values, do the formatting, print the result. % \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_join_uncert: { - \@@_number_format_join_uncert:n { mantissa } - \@@_number_format_join_uncert:n { complex } -} -\cs_new_protected:Npn \@@_number_format_join_uncert:n #1 { - \prop_get:NnNT \l_@@_number_out_prop {#1} - \l_@@_tmpa_tl - { - \prop_get:NnNTF \l_@@_number_out_prop { #1 -uncertainty } - \l_@@_tmpb_tl - { - \bool_if:NT \l_@@_uncert_sep_bool - { \@@_number_format_join_uncert_pm:N \l_@@_tmpb_tl } - \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl - \prop_put:NnV \l_@@_number_out_prop { #1 -result } - \l_@@_tmpa_tl - \prop_put:Nnn \l_@@_number_out_prop { #1 -bracket } - { true } - } - { \@@_number_format_copy:nn {#1} { #1 -result } } - } -} -\cs_new_protected:Npn \@@_number_format_join_uncert_pm:N #1 +\NewDocumentCommand \ang { O { } > { \SplitArgument { 2 } { ; } } m } { - \bool_if:NTF \l_@@_tight_bool - { \tl_put_left:Nn #1 { \ensuremath { { \pm } } } } - { \tl_put_left:Nn #1 { \ensuremath { { } \pm { } } } } + \mode_leave_vertical: + \group_begin: + \keys_set:nn { siunitx } {#1} + \@@_angle:nnn #2 + \group_end: } -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_number_format_reassemble:} -% The integer, decimal and any non-separated uncertainty parts are -% put back together. This gives a \enquote{minimal} unit which cannot -% need any brackets or repeated units (if applicable). If the -% uncertainty is separate, it is stored at this stage pending later -% re-attachment. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_reassemble: { - \prop_if_in:NnT \l_@@_number_in_prop { mantissa } - { - \@@_number_format_group:n { mantissa } - \@@_number_format_uncertainty:n { mantissa } - } - \prop_if_in:NnT \l_@@_number_in_prop { complex } - { - \@@_number_format_group:n { complex } - \@@_number_format_uncertainty:n { complex } - } - \prop_if_in:NnT \l_@@_number_in_prop { exponent } - { \@@_number_format_group:n { exponent } } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_format_relation:} -% A simple check and copy operation for a relation: this will still need -% to be added to the result, of course. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_relation: { - \prop_get:NnNT \l_@@_number_in_prop { comparator } - \l_@@_tmpa_tl - { - \tl_set:Nx \l_@@_tmpa_tl - { - \exp_not:N \ensuremath - { \exp_not:V \l_@@_tmpa_tl } - } - \prop_put:NnV \l_@@_number_out_prop { comparator } - \l_@@_tmpa_tl - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_number_format_sign:n , -% \@@_number_format_sign_complex: -%} -%\begin{macro}{ -% \@@_number_format_sign_aux:n , -% \@@_number_format_sign_negative_brackets:n , -% \@@_number_format_sign_complex:n -%} -% Some simple sign manipulation: for tight signs, a little shuffling. -% In the complex number case, there is a need for a correction to get -% the right formatting in text mode. For speed reasons, this is done in -% a separate function. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_sign:n #1 { - \prop_if_in:NnT \l_@@_number_out_prop {#1} - { - \prop_get:NnNT \l_@@_number_in_prop { #1 -sign } - \l_@@_tmpa_tl - { - \bool_if:NTF \l_@@_negative_bracket_bool - { - \str_if_eq:VnTF \l_@@_tmpa_tl { - } - { \@@_number_format_sign_negative_brackets:n {#1} } - { \@@_number_format_sign_aux:n {#1} } - } - { \@@_number_format_sign_aux:n {#1} } - } - } -} -\cs_new_protected:Npn \@@_number_format_sign_aux:n #1 { - \tl_clear:N \l_@@_tmpb_tl - \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpa_tl - \prop_put:NnV \l_@@_number_out_prop { #1 -sign } - \l_@@_tmpb_tl - \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpa_tl - \tl_put_left:NV \l_@@_tmpa_tl \l_@@_tmpb_tl - \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpa_tl - \prop_get:NnNT \l_@@_number_out_prop { #1 -result } - \l_@@_tmpa_tl - { - \tl_put_left:NV \l_@@_tmpa_tl \l_@@_tmpb_tl - \prop_put:NnV \l_@@_number_out_prop { #1 -result } - \l_@@_tmpa_tl - } -} -\cs_new_protected:Npn - \@@_number_format_sign_negative_brackets:n #1 +\NewDocumentCommand \num { O { } m } { - \@@_number_format_brackets_aux:n {#1} - \prop_get:NnNT \l_@@_number_out_prop { #1 } - \l_@@_tmpa_tl - { - \tl_put_left:NV \l_@@_tmpa_tl \l_@@_bracket_open_tl - \tl_put_right:NV \l_@@_tmpa_tl \l_@@_bracket_close_tl - \prop_put:NnV \l_@@_number_out_prop { #1 } - \l_@@_tmpa_tl - } + \mode_leave_vertical: + \group_begin: + \keys_set:nn { siunitx } {#1} + \siunitx_number_format:nN {#2} \l_@@_tmp_tl + \siunitx_print_number:V \l_@@_tmp_tl + \group_end: } -\cs_new_protected:Npn \@@_number_format_sign_complex: { - \@@_number_format_sign_complex:n { complex } - \@@_number_format_sign_complex:n { complex-result } -} -\cs_new_protected:Npn \@@_number_format_sign_complex:n #1 { - \prop_if_in:NnT \l_@@_number_out_prop {#1} - { - \prop_get:NnNT \l_@@_number_in_prop { complex-sign } - \l_@@_tmpa_tl - { - \bool_if:NTF \l_@@_tight_bool - { - \tl_set:Nx \l_@@_tmpa_tl - { \exp_not:N \mathord \exp_not:V \l_@@_tmpa_tl } - } - { - \prop_if_in:NnT \l_@@_number_out_prop { mantissa } - { - \tl_set:Nx \l_@@_tmpa_tl - { { } \exp_not:V \l_@@_tmpa_tl { } } - } - } - \tl_clear:N \l_@@_tmpb_tl - \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpa_tl - \prop_put:NnV \l_@@_number_out_prop { complex-sign } - \l_@@_tmpb_tl - \prop_get:NnN \l_@@_number_out_prop {#1} - \l_@@_tmpa_tl - \tl_put_left:NV \l_@@_tmpa_tl \l_@@_tmpb_tl - \prop_put:NnV \l_@@_number_out_prop {#1} - \l_@@_tmpa_tl - } - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_number_format_uncertainty:n} -%\begin{macro}{ -% \@@_number_format_uncertainty_joined:n , -% \@@_number_format_uncertainty_sep:n -%} -% Uncertainty output varies depending on whether there is a need to -% separate the error form the number in the output. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_format_uncertainty:n #1 { - \prop_if_in:NnTF \l_@@_number_in_prop { #1 -uncertainty } - { - \bool_if:NTF \l_@@_uncert_sep_bool - { \@@_number_format_uncertainty_sep:n {#1} } - { \@@_number_format_uncertainty_joined:n {#1} } - \@@_number_format_join_uncert: - } - { \@@_number_format_copy:nn {#1} { #1 -result } } -} -\cs_new_protected:Npn - \@@_number_format_uncertainty_joined:n #1 { - \prop_get:NnN \l_@@_number_in_prop { #1 -uncertainty } - \l_@@_tmpa_tl - \prop_remove:Nn \l_@@_number_in_prop { #1 -uncertainty } - \tl_put_left:NV \l_@@_tmpa_tl \l_@@_output_uncert_open_tl - \tl_put_left:NV \l_@@_tmpa_tl \l_@@_uncert_sep_tl - \tl_put_right:NV \l_@@_tmpa_tl \l_@@_output_uncert_close_tl - \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpb_tl - \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpa_tl - \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpb_tl -} -\cs_new_protected:Npn - \@@_number_format_uncertainty_sep:n #1 { - \prop_if_in:NnT \l_@@_number_out_prop { #1 -integer } - { - \prop_if_in:NnF \l_@@_number_out_prop - { #1 -uncertainty-integer } - { - \prop_put:Nnn \l_@@_number_out_prop - { #1 -uncertainty-integer } { 0 } - } - } - \@@_number_format_group:n { #1 -uncertainty } - \prop_put:NnV \l_@@_number_out_prop { #1 -uncertainty } - \l_@@_tmpa_tl -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\subsection{Numerical output} -% -% The outer level of number processing for actually printing things. -% -%\begin{macro}{ -% \l_@@_number_out_tl , -% \l_@@_number_out_saved_tl -%} -% The final result, plus a version for loops. -% \begin{macrocode} -\tl_new:N \l_@@_number_out_tl -\tl_new:N \l_@@_number_out_saved_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_number_fraction_tl} -% Fractions need to be build separately, so that there is no problem -% with stack order. -% \begin{macrocode} -\tl_new:N \l_@@_number_fraction_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_number_compound_bool} -% To help with brackets. -% \begin{macrocode} -\bool_new:N \l_@@_number_compound_bool -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_quotient_mode_tl} -% The action for quotients is stored as a token list variable. -% \begin{macrocode} -\tl_new:N \l_@@_quotient_mode_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_fraction:nn} -% The function used for fractions should be stored here. -% \begin{macrocode} -\cs_new_protected:Npn \@@_fraction:nn { } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \l_@@_output_quotient_tl , -% \l_siunix_number_parse_bool -%} -% Some options related to numbers at the output stage. -% \begin{macrocode} -\keys_define:nn { siunitx } { - fraction-function .code:n = - { \cs_set_protected:Npn \@@_fraction:nn {#1} }, - output-product .tl_set:N = \l_@@_output_product_tl, - output-quotient .tl_set:N = \l_@@_output_quotient_tl, - parse-numbers .bool_set:N = \l_@@_number_parse_bool, - quotient-mode .choice:, - quotient-mode / fraction .code:n = - { \tl_set:Nn \l_@@_quotient_mode_tl { fraction } }, - quotient-mode / symbol .code:n = - { \tl_set:Nn \l_@@_quotient_mode_tl { symbol } }, -} -\keys_set:nn { siunitx } { - fraction-function = \frac , - output-product = \times , - output-quotient = / , - parse-numbers = true , - quotient-mode = symbol -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_number_output:n , -% \@@_number_output:V -%} -% The number output system simply sets up for the combined number and -% unit system. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_output:n #1 { - \tl_clear:N \l_@@_unit_tl - \tl_clear:N \l_@@_preunit_tl - \@@_combined_output:n {#1} -} -\cs_generate_variant:Nn \@@_number_output:n { V } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_output_bracket:} -% Compound numbers may need brackets adding. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_output_bracket: { - \bool_if:NF \l_@@_error_bool - { - \bool_if:NT \l_@@_number_compound_bool - { \@@_number_format_brackets:n { result } } - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_output_color:} -% If a colour needs to be set, it is recovered here and put into the -% appropriate place. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_output_color: { - \prop_if_in:NnT \l_@@_number_out_prop { color } - { - \prop_get:NnN \l_@@_number_out_prop { color } - \l_@@_number_color_tl - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_number_output_parse:n , -% \@@_number_output_parse:V -%} -%\begin{macro}{\@@_number_output_parse_aux:} -% The parsing system just has to check if there are multiple parts to -% worry about. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_output_parse:n #1 { - \@@_number_preprocess:n {#1} - \bool_if:NF \l_@@_error_bool - { - \tl_if_empty:NTF \l_@@_number_multi_tl - { \@@_number_output_parse_aux: } - { - \use:c - { @@_number_output_ \l_@@_number_multi_tl : } - } - } -} -\cs_generate_variant:Nn \@@_number_output_parse:n { V } -% \end{macrocode} -% There are a few additional tests for printing partwise, as this is -% only needed if there are brackets to add and these are not due to -% an exponent. The test for an exponent is needed as this must force -% the units to come at the end of the number, and there then have to -% be brackets in the output if there are any separate parts. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_output_parse_aux: { - \@@_number_in_parse:V \l_@@_number_arg_tl - \bool_if:NF \l_@@_error_bool - { - \@@_number_process: - \@@_number_format: - \@@_number_output_color: - \bool_if:NTF \l_@@_brackets_bool - { \@@_number_output_single: } - { - \prop_if_in:NnTF \l_@@_number_out_prop - { result-bracket } - { \@@_number_output_parts: } - { \@@_number_output_single: } - } - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_number_output_parts:} -%\begin{macro}{ -% \@@_number_output_parts_aux: , -% \@@_number_output_parts_aux:n , -% \@@_number_output_parts_print:n -%} -% Printing numbers by parts is necessary when there are units to -% repeat. That means doing things that have already been done by the -% number formatter again. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_output_parts: { - \bool_lazy_and:nnTF - { \tl_if_empty_p:N \l_@@_pre_unit_tl } - { \tl_if_empty_p:N \l_@@_unit_tl } - { \@@_number_output_single: } - { \@@_number_output_parts_aux: } -} -\cs_new_protected:Npn \@@_number_output_parts_aux: { - \bool_if:NTF \l_@@_multi_repeat_bool - { - \prop_if_in:NnT \l_@@_number_out_prop { mantissa-result } - { - \@@_number_output_parts_aux:n { mantissa } - \@@_number_output_parts_aux:n { complex } - } - \prop_get:NnNT \l_@@_number_out_prop { exponent-result } - \l_@@_tmpa_tl - { - \prop_if_in:NnT \l_@@_number_out_prop { mantissa-result } - { - \tl_put_left:Nx \l_@@_tmpa_tl - { - \exp_not:N \ensuremath - { - \bool_if:NTF \l_@@_tight_bool - { { \exp_not:V \l_@@_exponent_product_tl } } - { { } \exp_not:V \l_@@_exponent_product_tl { } } - } - } - \prop_put:NnV \l_@@_number_out_prop { exponent } - \l_@@_tmpa_tl - } - \@@_number_output_parts_print:n { exponent } - } - } - { \@@_number_output_single: } -} -\cs_new_protected:Npn \@@_number_output_parts_aux:n #1 { - \prop_if_in:NnT \l_@@_number_out_prop {#1} - { \@@_number_output_parts_print:n {#1} } - \prop_if_in:NnT \l_@@_number_out_prop { #1 -uncertainty } - { - \bool_if:NTF \l_@@_tight_bool - { \@@_print:nn { number } { \ensuremath { { \pm } } } } - { \@@_print:nn { number } { \ensuremath { { } \pm { } } } } - \@@_number_output_parts_print:n { #1 -uncertainty } - } -} -\cs_new_protected:Npn \@@_number_output_parts_print:n #1 { - \@@_unit_output_pre_print: - \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpa_tl - \@@_print:nV { number } \l_@@_tmpa_tl - \@@_unit_output_print: -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_number_output_product:} -% For products, there may need to be the addition of brackets if there -% are units about. When not repeating units, some work has to be done to -% print everything correctly. The extra group here is necessary -% otherwise looping will delete the units entirely! -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_output_product: { - \bool_if:NTF \l_@@_product_brackets_bool - { - \bool_lazy_and:nnTF - { \tl_if_empty_p:N \l_@@_pre_unit_tl } - { \tl_if_empty_p:N \l_@@_unit_tl } - { \@@_number_output_product_aux: } - { \@@_number_output_product_brackets: } - } - { - \bool_if:NTF \l_@@_product_repeat_bool - { \@@_number_output_product_aux: } - { - \@@_unit_output_pre_print: - \tl_set_eq:NN \l_@@_unit_saved_tl \l_@@_unit_tl - \tl_clear:N \l_@@_pre_unit_tl - \tl_clear:N \l_@@_unit_tl - \group_begin: - \@@_number_output_product_aux: - \group_end: - \tl_set_eq:NN \l_@@_unit_tl \l_@@_unit_saved_tl - \@@_unit_output_print: - } - } -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\@@_number_output_product_brackets:} -% When printing products that have to be bracketed, there is a need to -% shuffle the units about a bit. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_output_product_brackets: { - \@@_unit_output_pre_print: - \@@_print:nV { number } \l_@@_bracket_open_tl - \nobreak - \tl_set_eq:NN \l_@@_unit_saved_tl \l_@@_unit_tl - \tl_clear:N \l_@@_pre_unit_tl - \tl_clear:N \l_@@_unit_tl - \@@_number_output_product_aux: - \nobreak - \tl_set_eq:NN \l_@@_unit_tl \l_@@_unit_saved_tl - \@@_print:nV { number } \l_@@_bracket_close_tl - \@@_unit_output_print: -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\@@_number_output_product_aux:} -% Printing the products needs a looping function. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_output_product_aux: { - \bool_set_true:N \l_@@_number_compound_bool - \@@_number_preprocess:V \l_@@_number_arg_tl - \bool_if:NF \l_@@_error_bool - { - \tl_if_empty:NTF \l_@@_number_multi_tl - { \@@_number_output_parse_aux: } - { \@@_number_output_quotient: } - \tl_if_empty:NF \l_@@_number_next_tl - { - \bool_if:NTF \l_@@_tight_bool - { - \@@_print:nn { number } - { \ensuremath { \l_@@_output_product_tl } } - } - { - \@@_print:nn { number } - { \ensuremath { { } \l_@@_output_product_tl { } } } - } - \@@_number_output_parse:V \l_@@_number_next_tl - } - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_output_quotient:} -% For quotients, there are two options. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_output_quotient: { - \use:c - { @@_number_output_quotient_ \l_@@_quotient_mode_tl : } -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\@@_number_output_quotient_fraction:} -% For fraction output, there are quite a lot of braces to construct, -% unfortunately. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_output_quotient_fraction: { - \bool_set_false:N \l_@@_number_compound_bool - \@@_number_output_quotient_aux_i: - \tl_set:Nx \l_@@_number_out_tl - { { \exp_not:V \l_@@_number_numerator_tl } } - \tl_set:Nx \l_@@_tmpa_tl - { { \exp_not:V \l_@@_number_denominator_tl } } - \tl_put_right:NV \l_@@_number_out_tl \l_@@_tmpa_tl - \tl_put_left:Nn \l_@@_number_out_tl { \@@_fraction:nn } - \tl_set:Nx \l_@@_number_out_tl - { - \exp_not:N \ensuremath - { \exp_not:V \l_@@_number_out_tl } - } - \@@_number_output_single_aux: -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\@@_number_output_quotient_symbol:} -% If a symbol is used for the division, the build process is less -% complex. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_output_quotient_symbol: { - \bool_set_true:N \l_@@_number_compound_bool - \@@_number_output_quotient_aux_i: - \tl_set_eq:NN \l_@@_number_out_tl - \l_@@_number_numerator_tl - \tl_put_right:NV \l_@@_number_out_tl \l_@@_output_quotient_tl - \tl_put_right:NV \l_@@_number_out_tl - \l_@@_number_denominator_tl - \@@_number_output_single_aux: -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{ -% \@@_number_output_quotient_aux_i: , -% \@@_number_output_quotient_aux_ii: -%} -% The two parts of the number are parsed and formatted. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_output_quotient_aux_i: { - \@@_number_in_parse:V \l_@@_number_numerator_tl - \@@_number_output_quotient_aux_ii: - \@@_number_output_color: - \prop_if_in:NnT \l_@@_number_out_prop { complex } - { - \prop_if_in:NnT \l_@@_number_out_prop { mantissa } - { - \prop_put:Nnn \l_@@_number_out_prop - { result-bracket } { true } - \@@_number_format_brackets:n { result } - } - } - \prop_get:NnN \l_@@_number_out_prop { result } - \l_@@_number_numerator_tl - \@@_number_in_parse:V \l_@@_number_denominator_tl - \@@_number_output_quotient_aux_ii: - \prop_if_in:NnT \l_@@_number_out_prop - { result-bracket-exponent } - { - \prop_put:Nnn \l_@@_number_out_prop { result-bracket } - { true } - } - \@@_number_output_bracket: - \prop_get:NnN \l_@@_number_out_prop { result } - \l_@@_number_denominator_tl -} -\cs_new_protected:Npn \@@_number_output_quotient_aux_ii: { - \@@_number_process: - \@@_number_format: -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_number_output_single:} -%\begin{macro}{\@@_number_output_single_aux:} -% Printing a number with no multiple parts is easy. There is a check for -% any units, which if present may force the number to have brackets -% added. there is then simply a short run to print the units and number. -% The test for bracketing numbers does not happen if there is an -% exponent: if there is, any other parts will already be bracketed and -% mathematically there is no need for brackets at this point. -% \begin{macrocode} -\cs_new_protected:Npn \@@_number_output_single: { - \bool_lazy_and:nnF - { \tl_if_empty_p:N \l_@@_pre_unit_tl } - { \tl_if_empty_p:N \l_@@_unit_tl } - { - \prop_if_in:NnF \l_@@_number_out_prop { exponent } - { \@@_number_format_brackets:n { result } } - } - \@@_number_output_bracket: - \prop_get:NnN \l_@@_number_out_prop { result } - \l_@@_number_out_tl - \@@_number_output_single_aux: -} -\cs_new_protected:Npn \@@_number_output_single_aux: { - \@@_unit_output_pre_print: - \quark_if_no_value:NTF \l_@@_number_out_tl - { \tl_clear:N \l_@@_number_unit_product_tl } - { \@@_print:nV { number } \l_@@_number_out_tl } - \@@_unit_output_print: -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\subsection{Angles} -% -% Angles are a special case of numbers for two reasons. First, there -% is always a unit, which is known in advance. Second, there are two -% possible input syntaxes, "\ang{1.23}" and "\ang{1;2;3}". Both need -% to be handled correctly. -% -%\begin{macro}{ -% \l_@@_angle_degree_space_bool , -% \l_@@_angle_minute_space_bool -%} -% The need for spaces between parts of an arc needs to be accommodated: -% this is achieved by flagging up the need for such spaces using two -% switches. -% \begin{macrocode} -\bool_new:N \l_@@_angle_degree_space_bool -\bool_new:N \l_@@_angle_minute_space_bool -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \l_@@_angle_marker_box , -% \l_@@_angle_unit_box , -% \l_@@_angle_marker_dim , -% \l_@@_angle_unit_dim -%} -% When creating astronomy-style angles, the decimal marker and angle -% symbol have to be boxed up and measured. -% \begin{macrocode} -\box_new:N \l_@@_angle_marker_box -\box_new:N \l_@@_angle_unit_box -\dim_new:N \l_@@_angle_marker_dim -\dim_new:N \l_@@_angle_unit_dim -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \l_@@_angle_degree_prop , -% \l_@@_angle_minute_prop , -% \l_@@_angle_second_prop -%} -% As there are potentially three numbers to parse, three properly lists -% are made available to hold the results. This allows the code to be -% generalised, with only the name of the storage area varying. -% \begin{macrocode} -\prop_new:N \l_@@_angle_degree_prop -\prop_new:N \l_@@_angle_minute_prop -\prop_new:N \l_@@_angle_second_prop -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \l_@@_angle_degree_zero_bool , -% \l_@@_angle_minute_zero_bool , -% \l_@@_angle_second_zero_bool , -% \l_@@_angle_arc_separator_tl , -% \l_@@_angle_astronomy_bool , -% \l_@@_angle_unit_product_tl -%} -% The angle-specific options are created here. -% \begin{macrocode} -\keys_define:nn { siunitx } { - add-arc-degree-zero .bool_set:N = - \l_@@_angle_degree_zero_bool , - add-arc-minute-zero .bool_set:N = - \l_@@_angle_minute_zero_bool , - add-arc-second-zero .bool_set:N = - \l_@@_angle_second_zero_bool , - angle-symbol-over-decimal .bool_set:N = - \l_@@_angle_astronomy_bool , - arc-separator .tl_set:N = - \l_@@_angle_arc_separator_tl , - number-angle-product .tl_set:N = - \l_@@_angle_unit_product_tl , - number-angle-separator .tl_set:N = - \l_@@_angle_unit_product_tl , -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_angle_output:nnn} -%\begin{macro}{\@@_angle_output_aux:nnn} -% The input will have been split up by \pkg{xparse}, and so the various -% possible inputs can be picked up. To keep to a minimal route through -% the code, a decimal angle is simply treated like an arc, but with -% any zero-filling disabled. -% \begin{macrocode} -\cs_new_protected:Npn \@@_angle_output:nnn #1#2#3 { - \@@_angle_init: - \IfNoValueTF {#2} - { - \bool_set_false:N \l_@@_angle_minute_zero_bool - \bool_set_false:N \l_@@_angle_second_zero_bool - \@@_angle_output_aux:nnn {#1} { } { } - } - { - \IfNoValueTF {#3} - { \@@_error:nx { invalid-arc-format } { #1 ; #2 } } - { \@@_angle_output_aux:nnn {#1} {#2} {#3} } - } -} -\cs_new_protected:Npn \@@_angle_output_aux:nnn #1#2#3 { - \tl_if_empty:nTF { #1#2#3 } - { \@@_error:n { empty-arc } } - { - \bool_if:NTF \l_@@_number_parse_bool - { \@@_angle_parse:nnn {#1} {#2} {#3} } - { \@@_angle_direct:nnn {#1} {#2} {#3} } - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_angle_init:} -% The usual separation of initial storage resets. -% \begin{macrocode} -\cs_new_protected:Npn \@@_angle_init: { - \bool_set_false:N \l_@@_angle_degree_space_bool - \bool_set_false:N \l_@@_angle_minute_space_bool - \prop_clear:N \l_@@_angle_degree_prop - \prop_clear:N \l_@@_angle_minute_prop - \prop_clear:N \l_@@_angle_second_prop - \tl_clear:N \l_@@_preunit_tl - \tl_set_eq:NN \l_@@_number_unit_product_tl - \l_@@_angle_unit_product_tl - \cs_set_eq:NN \@@_number_in_parse_more:N - \@@_number_in_parse_restricted:N -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_angle_direct:nnn} -%\begin{macro}{ -% \@@_angle_direct_aux_i:nnn , -% \@@_angle_direct_aux_ii:nnn , -% \@@_angle_direct_aux_iii:nnn -%} -% When printing an arc directly, there is still the need to fill in -% any zero values required and to check the spacing is correct. That -% is done using a chain approach, which is easy to implement and -% reasonably clear. -% \begin{macrocode} -\cs_new_protected:Npn \@@_angle_direct:nnn #1 { - \tl_if_empty:nTF {#1} - { - \bool_if:NTF \l_@@_angle_degree_zero_bool - { \@@_angle_direct_aux_i:nnn { 0 } } - { \@@_angle_direct_aux_i:nnn { } } - } - { \@@_angle_direct_aux_i:nnn {#1} } -} -\cs_new_protected:Npn \@@_angle_direct_aux_i:nnn #1#2 { - \tl_if_empty:nTF {#2} - { - \bool_if:NTF \l_@@_angle_minute_zero_bool - { \@@_angle_direct_aux_ii:nnn {#1} { 0 } } - { \@@_angle_direct_aux_ii:nnn {#1} { } } - } - { \@@_angle_direct_aux_ii:nnn {#1} {#2} } -} -\cs_new_protected:Npn \@@_angle_direct_aux_ii:nnn #1#2#3 { - \tl_if_empty:nTF {#3} - { - \bool_if:NTF \l_@@_angle_second_zero_bool - { \@@_angle_direct_aux_iii:nnn {#1} {#2} { 0 } } - { \@@_angle_direct_aux_iii:nnn {#1} {#2} { } } - } - { \@@_angle_direct_aux_iii:nnn {#1} {#2} {#3} } -} -\cs_new_protected:Npn \@@_angle_direct_aux_iii:nnn #1#2#3 { - \tl_if_empty:nF {#1} - { - \tl_if_empty:nF {#2#3} - { \bool_set_true:N \l_@@_angle_degree_space_bool } - } - \tl_if_empty:nF {#2} - { - \tl_if_empty:nF {#3} - { \bool_set_true:N \l_@@_angle_minute_space_bool } - } - \@@_angle_print_direct:nnn {#1} {#2} {#3} -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{ -% \@@_angle_parse:nnn , -% \@@_angle_check_sign: , -% \@@_angle_zero_fill: , -% \@@_angle_sign_shuffle:nn -%} -%\begin{macro}{ -% \@@_angle_parse_aux:nnn , -% \@@_angle_check_sign:n , -% \@@_angle_sign_shuffle_aux:nnn -%} -% Parsing an arc requires a number of stages. First, there is the -% basic conversion of the input numbers into three property lists, -% which will contain the data required. There is then a zero-filling -% step, done here so that signs can be shuffled into the correct places. -% After that, a check to make sure there is only one sign for an arc -% before setting up the inter-part spacing and actually printing. -% \begin{macrocode} -\cs_new_protected:Npn \@@_angle_parse:nnn #1#2#3 { - \@@_angle_parse_aux:nn {#1} { degree } - \@@_angle_parse_aux:nn {#2} { minute } - \@@_angle_parse_aux:nn {#3} { second } - \@@_angle_check_sign: - \@@_angle_zero_fill: - \prop_if_empty:NF \l_@@_angle_degree_prop - { - \prop_if_empty:NF \l_@@_angle_minute_prop - { \bool_set_true:N \l_@@_angle_degree_space_bool } - \prop_if_empty:NF \l_@@_angle_second_prop - { \bool_set_true:N \l_@@_angle_degree_space_bool } - } - \prop_if_empty:NF \l_@@_angle_minute_prop - { - \prop_if_empty:NF \l_@@_angle_second_prop - { \bool_set_true:N \l_@@_angle_minute_space_bool } - } - \@@_angle_print: -} -\cs_new_protected:Npn \@@_angle_parse_aux:nn #1#2 { - \prop_clear:N \l_@@_number_in_prop - \tl_if_empty:nF {#1} - { - \@@_number_in_init: - \@@_number_in_parse_aux:n {#1} - } - \prop_get:NnNT \l_@@_number_in_prop { mantissa-sign-deleted } - \l_@@_tmpa_tl - { - \prop_put:NnV \l_@@_number_in_prop { mantissa-sign } - \l_@@_tmpa_tl - } - \@@_number_process: - \prop_set_eq:cN { l_@@_angle_ #2 _prop } - \l_@@_number_in_prop -} -% \end{macrocode} -% Only the highest-order part of an arc can have a sign. This is checked -% now so that the shuffling code is easier to write. -% \begin{macrocode} -\cs_new_protected:Npn \@@_angle_check_sign: { - \prop_if_empty:NTF \l_@@_angle_degree_prop - { - \prop_if_empty:NF \l_@@_angle_minute_prop - { \@@_angle_check_sign_aux:n { second } } - } - { - \@@_angle_check_sign_aux:n { minute } - \@@_angle_check_sign_aux:n { second } - } -} -\cs_new_protected:Npn \@@_angle_check_sign_aux:n #1 { - \prop_if_in:cnTF { l_@@_angle_ #1 _prop } - { mantissa-sign } - { \msg_error:nn { siunitx } { bad-arc-sign } } - { - \prop_if_in:cnT { l_@@_angle_ #1 _prop } - { mantissa-sign-deleted } - { \msg_error:nn { siunitx } { bad-arc-sign } } - } -} -% \end{macrocode} -% Filling in the zero values is rather awkward as there are signs -% to worry about. There is therefore a shuffle to move them into the -% correct places. -% \begin{macrocode} -\cs_new_protected:Npn \@@_angle_zero_fill: { - \bool_lazy_and:nnT - { \l_@@_angle_second_zero_bool } - { \prop_if_empty_p:N \l_@@_angle_second_prop } - { - \prop_put:Nnn \l_@@_angle_second_prop { mantissa } - { true } - \prop_put:Nnn \l_@@_angle_second_prop { mantissa-integer } - { 0 } - } - \bool_lazy_and:nnT - { \l_@@_angle_minute_zero_bool } - { \prop_if_empty_p:N \l_@@_angle_minute_prop } - { - \prop_put:Nnn \l_@@_angle_minute_prop { mantissa } - { true } - \prop_put:Nnn \l_@@_angle_minute_prop { mantissa-integer } - { 0 } - \@@_angle_sign_shuffle:nn { second } { minute } - } - \bool_lazy_and:nnT - { \l_@@_angle_degree_zero_bool } - { \prop_if_empty_p:N \l_@@_angle_degree_prop } - { - \prop_put:Nnn \l_@@_angle_degree_prop { mantissa } - { true } - \prop_put:Nnn \l_@@_angle_degree_prop { mantissa-integer } - { 0 } - \@@_angle_sign_shuffle:nn { second } { degree } - \@@_angle_sign_shuffle:nn { minute } { degree } - } -} -\cs_new_protected:Npn \@@_angle_sign_shuffle:nn #1#2 { - \@@_angle_sign_shuffle_aux:nnn {#1} {#2} { } - \@@_angle_sign_shuffle_aux:nnn {#1} {#2} { -deleted } -} -\cs_new_protected:Npn \@@_angle_sign_shuffle_aux:nnn - #1#2#3 { - \prop_get:cnN { l_@@_angle_ #1 _prop } { mantissa-sign #3 } - \l_@@_tmpa_tl - \prop_remove:cn { l_@@_angle_ #1 _prop } { mantissa-sign #3 } - \quark_if_no_value:NF \l_@@_tmpa_tl - { - \prop_put:cnV { l_@@_angle_ #2 _prop } { mantissa-sign #3 } - \l_@@_tmpa_tl - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_angle_print:} -%\begin{macro}{\@@_angle_print:nn} -% The standard printing routine examines each part of the arc in turn -% and either does a standard format or calls the special astronomy-style -% routine. There may also be some spaces to add. -% \begin{macrocode} -\cs_new_protected:Npn \@@_angle_print: { - \@@_angle_print_aux:nn { degree } { \SIUnitSymbolDegree } - \bool_if:NT \l_@@_angle_degree_space_bool - { - \nobreak - \l_@@_angle_arc_separator_tl - } - \@@_angle_print_aux:nn { minute } { \SIUnitSymbolArcminute } - \bool_if:NT \l_@@_angle_minute_space_bool - { - \nobreak - \l_@@_angle_arc_separator_tl - } - \@@_angle_print_aux:nn { second } { \SIUnitSymbolArcsecond } -} -\cs_new_protected:Npn \@@_angle_print_aux:nn #1#2 { - \prop_if_empty:cF { l_@@_angle_ #1 _prop } - { - \prop_set_eq:Nc \l_@@_number_in_prop - { l_@@_angle_ #1 _prop } - \tl_set:Nn \l_@@_unit_tl {#2} - \tl_clear:N \l_@@_number_out_tl - \@@_number_format: - \@@_number_output_color: - \bool_if:NTF \l_@@_angle_astronomy_bool - { \@@_angle_print_astronomy: } - { \@@_number_output_single: } - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_angle_print_astronomy:} -%\begin{macro}{ -% \@@_angle_print_astronomy_aux: , -% \@@_angle_print_astronomy_aux:n , -% \@@_angle_print_astronomy_marker: , -% \@@_angle_print_astronomy_unit: -%} -% The first check for astronomy-style angles is that there is a decimal -% marker in the current input: if not, the standard method can be used. -% The method for the astronomy-style angle is not straight-forward, so -% needs a little explanation. The integer and decimal parts of the -% number are printed at each end of the function. In the middle is a -% method to centre the unit symbol on the decimal marker. This is done -% by typesetting the two symbols and measuring their respective widths. -% The two are then put into zero-width boxes, which allows them to be -% aligned horizontally centred with no vertical change. The larger -% dimension is then used to reconstruct the appropriate width for the -% final output. There is also a need to allow for the \cs{scriptspace} -% added in after superscripts, which otherwise messes up the -% calculation. -% \begin{macrocode} -\cs_new_protected:Npn \@@_angle_print_astronomy: { - \prop_if_in:NnTF \l_@@_number_in_prop - { mantissa-decimal-marker } - { \@@_angle_print_astronomy_aux: } - { \@@_number_output_single: } -} -\cs_new_protected:Npn \@@_angle_print_astronomy_aux: { - \prop_get:NnNF \l_@@_number_out_prop { mantissa-sign } - \l_@@_tmpa_tl - { \tl_clear:N \l_@@_tmpa_tl } - \prop_get:NnNT \l_@@_number_out_prop { mantissa-integer } - \l_@@_tmpb_tl - { - \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl - \@@_print:nV { number } \l_@@_tmpa_tl - } - \hbox_set:Nn \l_@@_angle_marker_box - { - \@@_print:nn { number } { { \l_@@_output_decimal_tl } } - } - \hbox_set:Nn \l_@@_angle_unit_box - { - \@@_print:nV { unit } \l_@@_unit_tl - \skip_horizontal:n { -\scriptspace } - } - \@@_angle_print_astronomy_aux:n { marker } - \@@_angle_print_astronomy_aux:n { unit } - \hbox_set:Nn \l_@@_angle_marker_box - { - \box_use:N \l_@@_angle_marker_box - \box_use:N \l_@@_angle_unit_box - } - \dim_compare:nNnTF - { \l_@@_angle_marker_dim } > { \l_@@_angle_unit_dim } - { \@@_angle_print_astronomy_marker: } - { \@@_angle_print_astronomy_unit: } - \prop_get:NnNT \l_@@_number_out_prop { mantissa-decimal } - \l_@@_tmpa_tl - { \@@_print:nV { number } \l_@@_tmpa_tl } -} -\cs_new_protected:Npn \@@_angle_print_astronomy_aux:n #1 { - \dim_set:cn { l_@@_angle_ #1 _dim } - { \box_wd:c { l_@@_angle_ #1 _box } } - \hbox_set_to_wd:cnn { l_@@_angle_ #1 _box } { \c_zero_skip } - { - \tex_hss:D - \hbox_unpack:c { l_@@_angle_ #1_box } - \tex_hss:D - } -} -\cs_new_protected:Npn \@@_angle_print_astronomy_marker: { - \hbox_set_to_wd:Nnn \l_@@_angle_marker_box - { \l_@@_angle_marker_dim } - { - \tex_hss:D - \hbox_unpack:N \l_@@_angle_marker_box - \tex_hss:D - } - \box_use:N \l_@@_angle_marker_box -} -\cs_new_protected:Npn \@@_angle_print_astronomy_unit: { - \hbox_set_to_wd:Nnn \l_@@_angle_marker_box - { \l_@@_angle_unit_dim } - { - \tex_hss:D - \hbox_unpack:N \l_@@_angle_marker_box - \tex_hss:D - } - \box_use:N \l_@@_angle_marker_box - \skip_horizontal:N \scriptspace -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_angle_print_direct:nnn} -%\begin{macro}{\@@_angle_print_direct_aux:nn} -% The direct printing routine is rather similar to the standard -% one, with just a modified final step. -% \begin{macrocode} -\cs_new_protected:Npn \@@_angle_print_direct:nnn #1#2#3 { - \@@_angle_print_direct_aux:nn {#1} { \SIUnitSymbolDegree } - \bool_if:NT \l_@@_angle_degree_space_bool - { - \nobreak - \l_@@_angle_arc_separator_tl - } - \@@_angle_print_direct_aux:nn {#2} { \SIUnitSymbolArcminute } - \bool_if:NT \l_@@_angle_minute_space_bool - { - \nobreak - \l_@@_angle_arc_separator_tl - } - \@@_angle_print_direct_aux:nn {#3} { \SIUnitSymbolArcsecond } -} -\cs_new_protected:Npn \@@_angle_print_direct_aux:nn #1#2 { - \tl_if_empty:nF {#1} - { - \tl_set:Nn \l_@@_unit_tl {#2} - \@@_print:nn { number } { \ensuremath {#1} } - \@@_unit_output_print: - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\subsection{Creating unit macros} -% -% Unit macros and related support are created here. To avoid cluttering -% up the user name-space with a lot of short macro names, the standard -% method only makes these available inside the unit-processing functions -% (\cs{SI}, \cs{si} and the \texttt{S} column). -% -%\begin{macro}{\l_siunitx_unit_symbolic_seq} -% A list of all unit and related functions. -% \begin{macrocode} -\seq_new:N \l_siunitx_unit_symbolic_seq -\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \of } -\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \highlight } -\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \per } -\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \raiseto } -\seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \tothe } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_declare_power_after:Nn , -% \@@_declare_power_before:Nn -%} -% Creating powers is all about storing values. -% \begin{macrocode} -\cs_new_protected:Npn \@@_declare_power_after:Nn #1#2 { - \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} - \cs_set:cpn { @@_ \token_to_str:N #1 _literal:w } - { \@@_textsuperscript:n {#2} } - \cs_set:cpn { @@_ \token_to_str:N #1 _function:w } - { \@@_unit_parse_power_after:n {#2} } -} -\cs_new_protected:Npn \@@_declare_power_before:Nn #1#2 { - \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} - \cs_set:cpn { @@_ \token_to_str:N #1 _literal:w } ##1 - { ##1 \@@_textsuperscript:n {#2} } - \cs_set:cpn { @@_ \token_to_str:N #1 _function:w } - { \@@_unit_parse_power_before:n {#2} } -} -% \end{macrocode} -%\end{macro} -% -% \begin{macro}{\@@_declare_prefix:Nnnn} -% \begin{variable} -% {\l_@@_prefix_forward_prop, \l_@@_prefix_reverse_prop} -% Prefixes need to store both the symbol and the power they represent. -% A reverse system is also set up, to allow powers to be converted to -% prefixes. -% \begin{macrocode} -\cs_new_protected:Npn \@@_declare_prefix:Nnnn #1#2#3#4 +\NewDocumentCommand \unit { O { } > { \TrimSpaces } m } { - \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} - \prop_put:Nnn \l_@@_prefix_forward_prop {#1} {#4} - \prop_put:Nnn \l_@@_prefix_reverse_prop {#4} {#1} - \cs_set:cpn { @@_ \token_to_str:N #1 _literal:w } {#2} - \cs_set:cpn { @@_ \token_to_str:N #1 _function:w } - { - \bool_if:NTF \l_@@_prefix_symbols_bool - { \@@_unit_parse_prefix:Nn #1 {#2} } - { \@@_unit_parse_prefix:nn {#3} {#4} } - } + \mode_leave_vertical: + \group_begin: + \siunitx_unit_options_apply:n {#2} + \keys_set:nn { siunitx } {#1} + \siunitx_unit_format:nN {#2} \l_@@_tmp_tl + \siunitx_print_unit:V \l_@@_tmp_tl + \group_end: } -\prop_new:N \l_@@_prefix_forward_prop -\prop_new:N \l_@@_prefix_reverse_prop % \end{macrocode} -% \end{variable} % \end{macro} % -%\begin{macro}{\@@_declare_qualifier:Nn} -% Qualifiers just need storing. -% \begin{macrocode} -\cs_new_protected:Npn \@@_declare_qualifier:Nn #1#2 { - \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} - \cs_set:cpn { @@_ \token_to_str:N #1 _literal:w } - { \text { ~ } ( #2 ) } - \cs_set:cpn { @@_ \token_to_str:N #1 _function:w } - { \@@_unit_parse_qualifier:n {#2} } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_declare_unit:Nnn} -%\begin{macro}{\@@_unit_first_token:n} -% Creating units requires various things to be stored. This is done -% with several storage bins to keep the code clear. For the -% \texttt{macro} definition, the test occurs at use so that there is no -% problem with the creation order for units. -% \begin{macrocode} -\cs_new_protected:Npn \@@_declare_unit:Nnn #1#2#3 { - \seq_put_right:Nn \l_siunitx_unit_symbolic_seq {#1} - \cs_set:cpn { @@_ \token_to_str:N #1 _literal:w } {#2} - \cs_set_protected:cpn { @@_ \token_to_str:N #1 _function:w } - { - \@@_unit_if_literal:nTF {#2} - { \@@_unit_parse_unit:Nn #1 {#2} } - {#2} - } - \tl_if_empty:nTF {#3} - { \cs_undefine:c { l_@@_ \token_to_str:N #1 _options_tl } } - { - \tl_clear_new:c { l_@@_ \token_to_str:N #1 _options_tl } - \tl_set:cn { l_@@_ \token_to_str:N #1 _options_tl } {#3} - } -} -\cs_new_protected:Npn \@@_unit_first_token:n #1 { - \exp_last_unbraced:No \token_to_str:N { \tl_head:w #1 \q_stop } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\per} -% The \cs{per} function is pretty simple. -% \begin{macrocode} -\cs_new:cpn { @@_ \token_to_str:N \per _literal:w } { / } -\cs_new_protected:cpn { @@_ \token_to_str:N \per _function:w } { - \bool_set_true:N \l_@@_per_bool - \@@_unit_parse_per: -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \raiseto , -% \tothe -%} -% Generic versions of the pre-set powers. -% \begin{macrocode} -\cs_new:cpn { @@_ \token_to_str:N \raiseto _literal:w } #1#2 { - #2 - \@@_textsuperscript:n {#1} -} -\cs_new_protected:cpn { @@_ \token_to_str:N \raiseto _function:w } - #1 { - \@@_unit_parse_power_before:n {#1} -} -\cs_new:cpn { @@_ \token_to_str:N \tothe _literal:w } #1 { - \@@_textsuperscript:n {#1} -} -\cs_new_protected:cpn { @@_ \token_to_str:N \tothe _function:w } - #1 { - \@@_unit_parse_power_after:n {#1} -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\of} -% A flexible qualifier as well. -% \begin{macrocode} -\cs_new:cpn { @@_ \token_to_str:N \of _literal:w } #1 { - \text { ~ } ( #1 ) -} -\cs_new_protected:cpn { @@_ \token_to_str:N \of _function:w } #1 { - \@@_unit_parse_qualifier:n {#1} -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\cancel} -%\begin{macro}{\@@_real_cancel:n} -%\begin{macro}{\@@_cancel:n} -% The \cs{cancel} macro is odd as it is only defined if the appropriate -% package is loaded. -% \begin{macrocode} -\AtBeginDocument { - \cs_if_exist:NT \cancel - { - \cs_set_protected:Npn \@@_cancel:n #1 - { \@@__real_cancel:n { \@@_print:nn { unit } {#1} } } - \cs_set_eq:NN \@@__real_cancel:n \cancel - \seq_put_right:Nn \l_siunitx_unit_symbolic_seq { \cancel } - \cs_new_protected:cpn - { @@_ \token_to_str:N \cancel _function:w } - { \@@_unit_parse_special:n { \@@_cancel:n } } - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\highlight} -% Another special function: selective colour. -% \begin{macrocode} -\cs_new:cpn - { @@_ \token_to_str:N \highlight _literal:w } #1 - { \@@_textcolor:n {#1} } -\cs_new_protected:cpn - { @@_ \token_to_str:N \highlight _function:w } #1 - { \@@_unit_parse_special:n { \@@_textcolor:n {#1} } } -% \end{macrocode} -%\end{macro} -% -%\subsection{Creating body unit macros} -% -% The user might have asked for the unit macros to be available in the -% document body. If so, then these are created at the start of the -% document body. -% -%\begin{macro}{ -% \l_@@_create_free_bool , -% \l_@@_create_overwrite_bool , -% \l_@@_create_prespace_bool , -% \l_@@_create_optional_bool , -% \l_@@_create_xspace_bool -%} -% There are a few options which control this behaviour: these are all -% preamble-only. -% \begin{macrocode} -\keys_define:nn { siunitx } { - free-standing-units .bool_set:N = \l_@@_create_free_bool , - overwrite-functions .bool_set:N = \l_@@_create_overwrite_bool, - space-before-unit .bool_set:N = \l_@@_create_prespace_bool , - unit-optional-argument .bool_set:N = \l_@@_create_optional_bool , - use-xspace .bool_set:N = \l_@@_create_xspace_bool , -} -\@@_option_deactivate:n { - free-standing-units , - overwrite-functions , - space-before-unit , - unit-optional-argument , - use-xspace , -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_unit_create_empty_functions:} -%\begin{macro}{\@@_unit_create_empty_functions_aux:N} -% Without this, horrible things happen with \pkg{memoir} and -% \pkg{hyperref}. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_create_empty_functions: - { - \@@_unit_create_functions_aux_i: - \seq_map_function:NN \l_siunitx_unit_symbolic_seq - \@@_unit_create_empty_functions_aux:N - \@@_unit_create_functions_aux_ii: - } -\cs_new_protected:Npn \@@_unit_create_empty_functions_aux:N #1 - { - \cs_if_free:NT #1 - { \cs_set_protected:Npn #1 { \ERROR } } - } -% \end{macrocode} -%\end{macro} -%\end{macro} -% -% \begin{macro}{\@@_unit_create_functions:} % \begin{macro} -% { -% \@@_unit_create_functions_aux_i:, -% \@@_unit_create_functions_aux_ii: -% } -% Creation of macros essentially involves picking up a couple of loops. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_create_functions: - { - \@@_unit_create_functions_aux_i: - \bool_if:NT \l_@@_create_overwrite_bool - { \seq_map_function:NN \l_siunitx_unit_symbolic_seq \cs_undefine:N } - \bool_if:NTF \l_@@_create_optional_bool - { - \seq_map_function:NN \l_siunitx_unit_symbolic_seq - \@@_unit_create_with_arg:N - } - { - \seq_map_function:NN \l_siunitx_unit_symbolic_seq - \@@_unit_create:N - } - \@@_unit_create_functions_aux_ii: - \bool_if:NT \l_@@_create_xspace_bool - { \RequirePackage { xspace } } - } -\cs_new_protected:Npn \@@_unit_create_functions_aux_i: - { - \@ifpackageloaded { soulpos } - { - \@ifpackageloaded { soul } - { } - { - \cs_set_protected:Npn \@@_unit_create_functions_aux_ii: - { - \cs_undefine:N \hl - \cs_undefine:N \ul - } - } - } - { } - } -\cs_new_protected:Npn \@@_unit_create_functions_aux_ii: { } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -%\begin{macro}{ -% \@@_unit_create:N , -% \@@_unit_create_with_arg:N -%} -% The creation functions expand everything as far as possible so that -% there is less to do in the document. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_create:N #1 { - \cs_if_free:NT #1 - { - \cs_set:Npx \@@_tmp:w - { - \ProvideDocumentCommand \exp_not:N #1 { } - { - \group_begin: - \exp_not:N \cs_if_free:NF - \exp_not:c - { l_@@_ \token_to_str:N #1 _options_tl } - { - \keys_set:nV { siunitx } - \exp_not:c - { l_@@_ \token_to_str:N #1 _options_tl } - } - \bool_if:NT \l_@@_create_prespace_bool - { \exp_not:N \l_@@_number_unit_product_tl } - \exp_not:n { \@@_unit_output:nn {#1} { } } - \group_end: - \bool_if:NT \l_@@_create_xspace_bool - { \exp_not:N \xspace } - } - } - \@@_tmp:w - } -} -\cs_new_protected:Npn \@@_unit_create_with_arg:N #1 { - \cs_if_free:NT #1 - { - \cs_set:Npx \@@_tmp:w - { - \ProvideDocumentCommand \exp_not:N #1 { o } - { - \group_begin: - \exp_not:N \cs_if_free:NF - \exp_not:c - { l_@@_ \token_to_str:N #1 _options_tl } - { - \keys_set:nV { siunitx } - \exp_not:c - { - l_@@_ \token_to_str:N #1 _options_tl - } - } - \exp_not:N \IfNoValueTF {####1} - { - \bool_if:NT \l_@@_create_prespace_bool - { \exp_not:N \l_@@_number_unit_product_tl } - \exp_not:n { \@@_unit_output:nn {#1} { } } - } - { \SI {####1} { \exp_not:N #1 } } - \group_end: - \bool_if:NT \l_@@_create_xspace_bool - { \exp_not:N \xspace } - } - } - \@@_tmp:w - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_protect_symbols:N} -% There are a few unit names which may be defined by other parts of -% \LaTeX. They need to be unexpandable, as in an \texttt{S} column -% \TeX{} will look for \cs{omit} \emph{before} starting the internal -% version of \cs{si} and doing a redefinition. The same is true -% for the \cs{color} function, which may well be the first thing in -% a table cell. The same is true for \cs{array@row@rst}, from REV\TeX, -% which otherwise gives an error. -% \begin{macrocode} -\AtBeginDocument { - \cs_if_eq:NNT \color \use_none:n - { \cs_set_protected:Npn \color #1 { } } - \cs_set:Npn \@@_tmp:w #1 { } - \cs_if_eq:NNT \color \@@_tmp:w - { \cs_set_protected:Npn \color #1 { } } - \tl_map_function:nN { \bar \color \ng \pm \array@row@rst } - \@@_protect_symbols:N -} -\@@_if_hooks:TF - { - \AddToHook { begindocument / end } [ siunitx ] - { \@@_protect_symbols:N \fg } - } - { - \tl_put_right:Nn \document - { - \@@_protect_symbols:N \fg - \ignorespaces - } - } -\cs_new_protected:Npn \@@_protect_symbols:N #1 { - \cs_if_exist:NT #1 - { - \tl_if_empty:fT { \cs_prefix_spec:N #1 } - { \cs_set_protected:Npx #1 { \exp_not:V #1 } } - } -} -% \end{macrocode} -%\end{macro} -% -%\subsection{Initial unit processing} -% -% The unit processor has to convert the input (which may be all macros -% or may contain literal input) into formatted text for output. The -% input part of the process is used to sort out parsed or literal units. -% -%\begin{macro}{ -% \l_@@_unit_forbid_literal_bool , -% \l_@@_unit_parse_bool -%} -% One option is related to how units are pre-processed. -% \begin{macrocode} -\keys_define:nn { siunitx } { - forbid-literal-units .bool_set:N = - \l_@@_unit_forbid_literal_bool, - parse-units .bool_set:N = \l_@@_unit_parse_bool -} -\keys_set:nn { siunitx } { - forbid-literal-units = false, - parse-units = true -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_unit_in:nn , -% \@@_unit_in:Vn , -% \@@_pm: -%} -% The master function does a very simple checks then hands off. -% The definition of \cs{pm} needs to be saved here so that it can -% safely be used as an abbreviation for picometre and also in numbers -% for \( \pm \). -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_in:nn #1#2 { - \bool_if:NTF \l_@@_unit_parse_bool - { - \tl_if_empty:nF {#1} - { - \@@_unit_if_literal:nTF {#1} - { - \tl_clear:N \l_@@_per_mode_tl - \bool_if:NTF \l_@@_unit_forbid_literal_bool - { - \msg_error:nnx { siunitx } { literal-unit } - { \exp_not:n {#1} } - } - { - \cs_set_eq:NN \@@_pm: \pm - \@@_unit_format_literal:n {#1} - \cs_set_eq:NN \pm \@@_pm: - } - } - { - \cs_set_eq:NN \@@_pm: \pm - \@@_unit_parse:nn {#1} {#2} - \@@_unit_format: - \prop_set_eq:NN \l_@@_unit_saved_prop \l_@@_unit_prop - \cs_set_eq:NN \pm \@@_pm: - } - } - } - { \@@_unit_format_literal:n {#1} } -} -\cs_generate_variant:Nn \@@_unit_in:nn { V } -\cs_new:Npn \@@_pm: { } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_unit_if_literal:nTF} -%\begin{macro}{\@@_unit_if_literal_aux:N} -% A test is needed to see if the input only contains unit macros. This -% is done by altering setting all of the unit macros to expand to -% nothing at all. Thus there will only be anything left if there is -% a literal in the unit. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_if_literal:nTF #1#2#3 { - \group_begin: - \seq_map_function:NN \l_siunitx_unit_symbolic_seq - \@@_unit_if_literal_aux:N - \cs_set_eq:NN \of \use_none:n - \cs_set_eq:NN \highlight \use_none:n - \cs_set_eq:NN \raiseto \use_none:n - \cs_set_eq:NN \tothe \use_none:n - \protected@edef \l_@@_tmpa_tl {#1} - \exp_args:NNNV \group_end: - \tl_set:Nn \l_@@_tmpa_tl \l_@@_tmpa_tl - \tl_if_blank:VTF \l_@@_tmpa_tl {#3} {#2} -} -\cs_new_protected:Npn \@@_unit_if_literal_aux:N #1 { - \cs_set_eq:NN #1 \prg_do_nothing: -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\subsection{Parsing macro units} -% -% For macro-based units, the macros are converted into literal text, -% which is then passed on for printing. The code reads through the -% input to collect up the units, before re-combining everything into -% a single block at the end of the process. -% -% \begin{variable} -% { -% \l_@@_unit_int , -% \l_@@_unit_prop , -% \l_@@_unit_saved_prop -% } -% Parsed units are stored in a property list, to keep things compact. -% An integer is also needed to count up units. -% \begin{macrocode} -\int_new:N \l_@@_unit_int -\prop_new:N \l_@@_unit_prop -\prop_new:N \l_@@_unit_saved_prop -% \end{macrocode} -% \end{variable} -% -%\begin{macro}{\l_@@_per_bool} -% To allow \cs{per} to be \enquote{sticky}. -% \begin{macrocode} -\bool_new:N \l_@@_per_bool -% \end{macrocode} -%\end{macro} -% -% \begin{variable} -% { -% \l_@@_exp_to_prefix_bool , -% \l_@@_prefix_symbols_bool , -% \l_@@_sticky_per_bool -% } -% Some options are directly related to how units are handled at this -% stage, so need be created before the reconstruction part of the code. +% {\qtylist, \numlist, \qtyproduct, \numproduct, \qtyrange, \numproduct} +% Interfaces for compound values. % \begin{macrocode} -\keys_define:nn { siunitx } +\NewDocumentCommand \qtylist + { O { } > { \SplitList { ; } } m > { \TrimSpaces } m } { - exponent-to-prefix .bool_set:N = \l_@@_exp_to_prefix_bool , - prefixes-as-symbols .bool_set:N = \l_@@_prefix_symbols_bool , - sticky-per .bool_set:N = \l_@@_sticky_per_bool + \mode_leave_vertical: + \group_begin: + \siunitx_unit_options_apply:n {#3} + \keys_set:nn { siunitx } {#1} + \siunitx_quantity_list:nn {#2} {#3} + \group_end: } -\keys_set:nn { siunitx } { prefixes-as-symbols = true } -% \end{macrocode} -% \end{variable} -% -%\begin{macro}{\@@_unit_parse:nn} -% The unit to be parsed is received here along with any options given. -% The later are needed so that the user can override any saved options -% on a one-off basis. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_parse:nn #1#2 { - \@@_unit_parse_init: - \@@_unit_parse_options:nn {#1} {#2} - #1 -} -% \end{macrocode} -%\end{macro} -% -% \begin{macro}{\@@_unit_parse_init:} -% As always, the initialisation is a separate routine to make life a -% little clearer. The definition of \cs{pm} is saved here as it -% is used by units and numbers. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_parse_init: +\NewDocumentCommand \numlist { O { } > { \SplitList { ; } } m } { - \prop_clear:N \l_@@_unit_prop - \int_zero:N \l_@@_unit_int - \bool_set_false:N \l_@@_per_bool - \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq - { \cs_set_eq:Nc ##1 { @@_ \token_to_str:N ##1 _function:w } } - } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_unit_parse_options:n} -% Any unit-specific options are loaded, followed by re-applying any -% options given for this particular macro. The second call to -% \cs{keys_set:nn} is needed to allow the local overriding of settings. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_parse_options:nn #1#2 { - \tl_if_single:nT {#1} - { - \cs_if_free:cF - { l_@@_ \@@_unit_first_token:n {#1} _options_tl } - { - \keys_set:nv { siunitx } - { l_@@_ \@@_unit_first_token:n {#1} _options_tl } - \keys_set:nn { siunitx } {#2} - } + \mode_leave_vertical: + \group_begin: + \keys_set:nn { siunitx } {#1} + \siunitx_number_list:nn {#2} + \group_end: } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_unit_parse_power_before:n , -% \@@_unit_parse_power_after:n -%} -% Storing powers depends on whether they are given before or after -% the unit. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_parse_power_before:n #1 { - \tl_set:Nx \l_@@_tmpa_tl - { power- \int_eval:n { \l_@@_unit_int + 1 } } - \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#1} -} -\cs_new_protected:Npn \@@_unit_parse_power_after:n #1 { - \tl_set:Nx \l_@@_tmpa_tl - { power- \int_use:N \l_@@_unit_int } - \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#1} -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \@@_unit_parse_prefix:Nn , -% \@@_unit_parse_prefix:nn -%} -% Saving prefixes always increments the counter. For non-symbolic -% mode, the base needs to be saved along with the power. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_parse_prefix:Nn #1#2 +\NewDocumentCommand \qtyproduct + { O { } > { \SplitList { x } } m > { \TrimSpaces } m } { - \int_incr:N \l_@@_unit_int - \tl_set:Nx \l_@@_tmpa_tl - { prefix- \int_use:N \l_@@_unit_int } - \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#1} - \tl_set:Nx \l_@@_tmpa_tl - { prefix-symbol- \int_use:N \l_@@_unit_int } - \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#2} + \mode_leave_vertical: + \group_begin: + \siunitx_unit_options_apply:n {#3} + \keys_set:nn { siunitx } {#1} + \siunitx_quantity_product:nn {#2} {#3} + \group_end: } -\cs_new_protected:Npn \@@_unit_parse_prefix:nn #1#2 +\NewDocumentCommand \numproduct + { O { } > { \SplitList { x } } > { \TrimSpaces } m } { - \@@_unit_parse_prefix:Nn \ERROR {#2} - \tl_set:Nx \l_@@_tmpa_tl - { prefix-base- \int_use:N \l_@@_unit_int } - \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#1} + \mode_leave_vertical: + \group_begin: + \keys_set:nn { siunitx } {#1} + \siunitx_number_product:n {#2} + \group_end: } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_unit_parse_per:} -% The \cs{per} function always applies to the next unit seen, so -% the counter has to be advanced by one. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_parse_per: { - \tl_set:Nx \l_@@_tmpa_tl - { per- \int_eval:n { \l_@@_unit_int + 1 } } - \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl { true } - \bool_if:NT \l_@@_sticky_per_bool - { \cs_set_eq:NN \per \@@_unit_parse_per_error: } -} -\cs_new_protected:Npn \@@_unit_parse_per_error: { - \msg_error:nn { siunitx } { duplicate-sticky-per } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_unit_parse_qualifier:n} -% Qualifiers never alter the number of units. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_parse_qualifier:n #1 { - \tl_set:Nx \l_@@_tmpa_tl - { symbol- \int_use:N \l_@@_unit_int } - \prop_if_in:NVF \l_@@_unit_prop \l_@@_tmpa_tl - { \msg_error:nn { siunitx } { qualifier-before-unit } } - \tl_set:Nx \l_@@_tmpa_tl - { qualifier- \int_use:N \l_@@_unit_int } - \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#1} -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_unit_parse_special:n} -% Special effects are possible by adding code to the unit property -% list here: this is pretty much arbitrary, so there is no real -% processing done. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_parse_special:n #1 { - \tl_set:Nx \l_@@_tmpa_tl - { special- \int_eval:n { \l_@@_unit_int + 1 } } - \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#1} -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_unit_parse_unit:Nn} -%\begin{macro}{\@@_unit_parse_unit_per:} -% For units, there is a check in case a prefix is present (which will -% have incremented the counter). With the counter correct, simply add -% the literal to the property list. There is also a check to see if -% there is a \enquote{sticky} \cs{per} to think about. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_parse_unit:Nn #1#2 { - \tl_set:Nx \l_@@_tmpa_tl - { prefix-symbol- \int_use:N \l_@@_unit_int } - \prop_if_in:NVTF \l_@@_unit_prop \l_@@_tmpa_tl - { - \tl_set:Nx \l_@@_tmpa_tl - { symbol- \int_use:N \l_@@_unit_int } - \prop_if_in:NVT \l_@@_unit_prop \l_@@_tmpa_tl - { \int_incr:N \l_@@_unit_int } - } - { \int_incr:N \l_@@_unit_int } - \tl_set:Nx \l_@@_tmpa_tl - { unit- \int_use:N \l_@@_unit_int } - \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#1} - \tl_set:Nx \l_@@_tmpa_tl - { symbol- \int_use:N \l_@@_unit_int } - \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#2} - \@@_unit_parse_unit_per: -} -\cs_new_protected:Npn \@@_unit_parse_unit_per: { - \bool_if:NT \l_@@_sticky_per_bool - { - \bool_if:NT \l_@@_per_bool - { - \tl_set:Nx \l_@@_tmpa_tl - { per- \int_use:N \l_@@_unit_int } - \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl - { true } - } - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\subsection{Unit formatting} -% -%\begin{macro}{ -% \l_@@_preunit_tl , -% \l_@@_unit_tl , -% \l_@@_unit_current_tl , -% \l_@@_unit_denominator_tl , -% \l_@@_unit_numerator_tl , -% \l_@@_unit_saved_tl -%} -% Storage space for creating unit output. -% \begin{macrocode} -\tl_new:N \l_@@_preunit_tl -\tl_new:N \l_@@_unit_tl -\tl_new:N \l_@@_unit_current_tl -\tl_new:N \l_@@_unit_denominator_tl -\tl_new:N \l_@@_unit_numerator_tl -\tl_new:N \l_@@_unit_saved_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \l_@@_unit_denominator_int , -% \l_@@_unit_numerator_int -%} -% For tracking in case brackets are needed. -% \begin{macrocode} -\int_new:N \l_@@_unit_denominator_int -\int_new:N \l_@@_unit_numerator_int -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \l_@@_unit_prefix_int , -% \l_@@_unit_prefix_base_int , -% \l_@@_unit_prefix_current_tl -%} -% Used to calculate the overall prefix value. -% \begin{macrocode} -\int_new:N \l_@@_unit_prefix_int -\int_new:N \l_@@_unit_prefix_base_int -\tl_new:N \l_@@_unit_prefix_current_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_unit_prefix_gram_int} -% Formatting units is complicated by the fact that the kilogram is a -% base unit, making conversions a little more awkward. -% \begin{macrocode} -\int_new:N \l_@@_unit_prefix_gram_int -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_omit_unit_space_bool} -% Needed to omit the space between a number an a unit when printing -% symbols and when there is no numerator unit. -% \begin{macrocode} -\bool_new:N \l_@@_omit_unit_space_bool -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \l_@@_per_auto_bool , -% \l_@@_per_fraction_bool , -% \l_@@_per_mode_tl , -% \l_@@_power_number_bool , -% \l_@@_qualifier_mode_tl , -% \l_@@_per_two_parts_bool -%} -% For saving settings. -% \begin{macrocode} -\bool_new:N \l_@@_per_auto_bool -\bool_new:N \l_@@_per_fraction_bool -\tl_new:N \l_@@_per_mode_tl -\bool_new:N \l_@@_power_number_bool -\bool_new:N \l_@@_per_two_parts_bool -\tl_new:N \l_@@_qualifier_mode_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \l_@@_unit_denominator_bracket_bool , -% \l_@@_unit_product_tl , -% \l_@@_literal_power_bool , -% \l_@@_per_symbol_tl , -% \l_@@_qualifier_phrase_tl -%} -% At this stage, output formatting options are created. -% \begin{macrocode} -\keys_define:nn { siunitx } { - bracket-unit-denominator .bool_set:N - = \l_@@_unit_denominator_bracket_bool, - inter-unit-product .tl_set:N = \l_@@_unit_product_tl , - inter-unit-separator .tl_set:N = \l_@@_unit_product_tl , - literal-superscript-as-power - .bool_set:N = \l_@@_literal_power_bool, - per-mode .choice:, - per-mode / fraction .code:n = - { - \bool_set_false:N \l_@@_per_auto_bool - \bool_set_true:N \l_@@_per_fraction_bool - \bool_set_true:N \l_@@_per_two_parts_bool - \tl_set:Nn \l_@@_per_mode_tl { fraction } - }, - per-mode / power .meta:n = { per-mode = reciprocal } , - per-mode / power-positive-first .meta:n = - { per-mode = reciprocal-positive-first } , - per-mode / reciprocal .code:n = - { - \bool_set_false:N \l_@@_per_auto_bool - \bool_set_false:N \l_@@_per_fraction_bool - \bool_set_false:N \l_@@_per_two_parts_bool - \tl_clear:N \l_@@_per_mode_tl - }, - per-mode / reciprocal-positive-first .code:n = - { - \bool_set_false:N \l_@@_per_auto_bool - \bool_set_false:N \l_@@_per_fraction_bool - \bool_set_true:N \l_@@_per_two_parts_bool - \tl_clear:N \l_@@_per_mode_tl - }, - per-mode / repeated-symbol .code:n = - { - \bool_set_false:N \l_@@_per_auto_bool - \bool_set_false:N \l_@@_per_fraction_bool - \bool_set_false:N \l_@@_per_two_parts_bool - \tl_set:Nn \l_@@_per_mode_tl { repeat } - }, - per-mode / symbol .code:n = - { - \bool_set_false:N \l_@@_per_auto_bool - \bool_set_true:N \l_@@_per_fraction_bool - \bool_set_true:N \l_@@_per_two_parts_bool - \tl_set:Nn \l_@@_per_mode_tl { symbol } - }, - per-mode / symbol-or-fraction .code:n = - { - \bool_set_true:N \l_@@_per_auto_bool - \bool_set_true:N \l_@@_per_fraction_bool - \bool_set_true:N \l_@@_per_two_parts_bool - \tl_set:Nn \l_@@_per_mode_tl { symbol } - }, - per-symbol .tl_set:N = \l_@@_per_symbol_tl, - power-font .choice:, - power-font / number .code:n = - { \bool_set_true:N \l_@@_power_number_bool }, - power-font / unit .code:n = - { \bool_set_false:N \l_@@_power_number_bool }, - qualifier-mode .choice:, - qualifier-mode / brackets .code:n = - { \tl_set:Nn \l_@@_qualifier_mode_tl { brackets } }, - qualifier-mode / phrase .code:n = - { \tl_set:Nn \l_@@_qualifier_mode_tl { phrase } }, - qualifier-mode / space .code:n = - { \tl_set:Nn \l_@@_qualifier_mode_tl { space } }, - qualifier-mode / subscript .code:n = - { \tl_set:Nn \l_@@_qualifier_mode_tl { subscript } }, - qualifier-mode / text .code:n = - { \tl_set:Nn \l_@@_qualifier_mode_tl { text } }, - qualifier-phrase .tl_set:N = \l_@@_qualifier_phrase_tl -} -\keys_set:nn { siunitx } { - bracket-unit-denominator = true, - inter-unit-product = \,, - literal-superscript-as-power = true, - per-mode = reciprocal, - per-symbol = /, - power-font = number, - qualifier-mode = subscript, - qualifier-phrase = { ~ of ~ } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_unit_format:} -% Most of the work is done by the loop, with a little tidying up for -% fraction-like output. Before starting the loop, there is a check for -% the case of a single reciprocal unit when per is set up to create a -% symbol. In that special case, the space between a number and a unit -% has to be removed. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format: { - \prop_put:Nnx \l_@@_unit_prop { total-units } - { \int_use:N \l_@@_unit_int } - \@@_unit_format_init: - \int_while_do:nNnn { \l_@@_unit_int } > { 0 } - { - \@@_unit_format_prefix: - \@@_unit_format_symbol: - \@@_unit_format_qualifier: - \@@_unit_format_power: - \@@_unit_format_add: - \int_decr:N \l_@@_unit_int - } - \bool_if:NT \l_@@_per_two_parts_bool - { - \bool_if:NTF \l_@@_per_fraction_bool - { \@@_unit_format_fraction: } - { \@@_unit_format_sorted: } - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_unit_format_add:} -%\begin{macro}{\@@_unit_format_add_aux:n} -% Adding the current unit to the output means checking where it goes. -% The odd code when adding a space is to pick up repeated per symbols, -% which need to suppress the space. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format_add: { - \bool_if:NTF \l_@@_per_two_parts_bool - { - \tl_set:Nx \l_@@_tmpb_tl - { per- \int_use:N \l_@@_unit_int } - \prop_if_in:NVTF \l_@@_unit_prop \l_@@_tmpb_tl - { - \@@_unit_format_add_aux:n { _denominator } - \int_incr:N \l_@@_unit_denominator_int - } - { - \@@_unit_format_add_aux:n { _numerator } - \int_incr:N \l_@@_unit_numerator_int - } - } - { \@@_unit_format_add_aux:n { } } - \tl_clear:N \l_@@_unit_current_tl -} -\cs_new_protected:Npn \@@_unit_format_add_aux:n #1 { - \tl_if_empty:cF { l_@@_unit #1 _tl } - { - \str_if_eq:VnTF \l_@@_per_mode_tl { repeat } - { - \tl_set:Nx \l_@@_tmpa_tl - { per- \int_eval:n { \l_@@_unit_int + 1 } } - \prop_if_in:NVF \l_@@_unit_prop \l_@@_tmpa_tl - { - \tl_put_right:NV \l_@@_unit_current_tl - \l_@@_unit_product_tl - } - } - { - \tl_put_right:NV \l_@@_unit_current_tl - \l_@@_unit_product_tl - } - } - \tl_set:Nx \l_@@_tmpa_tl - { special- \int_use:N \l_@@_unit_int } - \prop_get:NVNTF \l_@@_unit_prop \l_@@_tmpa_tl - \l_@@_tmpa_tl +\NewDocumentCommand \qtyrange { O { } m m > { \TrimSpaces } m } { - \tl_put_left:cx { l_@@_unit #1 _tl } - { - \exp_not:V \l_@@_tmpa_tl - { \exp_not:V \l_@@_unit_current_tl } - } + \mode_leave_vertical: + \group_begin: + \siunitx_unit_options_apply:n {#4} + \keys_set:nn { siunitx } {#1} + \siunitx_quantity_range:nnn {#2} {#3} {#4} + \group_end: } +\NewDocumentCommand \numrange { O { } m m } { - \tl_put_left:cV { l_@@_unit #1 _tl } - \l_@@_unit_current_tl + \mode_leave_vertical: + \group_begin: + \keys_set:nn { siunitx } {#1} + \siunitx_number_range:nn {#2} {#3} + \group_end: } -} % \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_unit_format_fraction:} -%\begin{macro}{ -% \@@_unit_format_fraction: , -% \@@_unit_format_auto: , -% \@@_unit_format_symbol: , -% \@@_unit_format_symbol_aux: , -% \@@_unit_format_symbol_aux_alt: -%} -% When making (\emph{psuedo}-)fractions there is a check to place a -% \( 1 \) in the numerator is it's blank. For symbol mode, this is -% only done if there is no number. Then some construction work. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format_fraction: { - \int_compare:nNnT { \l_@@_unit_numerator_int } = { 0 } - { - \str_if_eq:VnT \l_@@_per_mode_tl { symbol } - { \bool_set_true:N \l_@@_omit_unit_space_bool } - } - \int_compare:nNnTF { \l_@@_unit_denominator_int } > { 0 } - { - \bool_if:NTF \l_@@_per_auto_bool - { \@@_unit_format_fraction_auto: } - { - \use:c - { @@_unit_format_fraction_ \l_@@_per_mode_tl : } - } - } - { \tl_set_eq:NN \l_@@_unit_tl \l_@@_unit_numerator_tl } -} -\cs_new_protected:Npn \@@_unit_format_fraction_fraction: { - \tl_if_empty:NT \l_@@_unit_numerator_tl - { \tl_set:Nn \l_@@_unit_numerator_tl { 1 } } - \tl_set:Nx \l_@@_unit_numerator_tl - { { \exp_not:V \l_@@_unit_numerator_tl } } - \tl_put_left:Nn \l_@@_unit_numerator_tl - { \@@_print:nn { unit } } - \tl_set:Nx \l_@@_unit_numerator_tl - { { \exp_not:V \l_@@_unit_numerator_tl } } - \tl_set:Nx \l_@@_unit_denominator_tl - { { \exp_not:V \l_@@_unit_denominator_tl } } - \tl_put_left:Nn \l_@@_unit_denominator_tl - { \@@_print:nn { unit } } - \tl_set:Nx \l_@@_unit_denominator_tl - { { \exp_not:V \l_@@_unit_denominator_tl } } - \tl_set:Nn \l_@@_unit_tl { \@@_fraction:nn } - \tl_put_right:NV \l_@@_unit_tl \l_@@_unit_numerator_tl - \tl_put_right:NV \l_@@_unit_tl \l_@@_unit_denominator_tl - \tl_set:Nx \l_@@_unit_tl - { \exp_not:N \ensuremath { \exp_not:V \l_@@_unit_tl } } -} -% \end{macrocode} -% For the \opt{symbol} setting, there is a need to deal with the -% possible \opt{symbol-or-fraction} choice. That is achieved by -% setting up both the \opt{fraction} and \opt{symbol} output. -% In the automatic mode, both cases are combined inside a -% \cs{tex_mathchoice:D}, with appropriate protection, before sending -% everything through for printing. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format_fraction_auto: { - \mode_if_math:TF - { - \group_begin: - \@@_unit_format_fraction_fraction: - \exp_args:NNNV \group_end: - \tl_set:Nn \l_@@_tmpa_tl \l_@@_unit_tl - \group_begin: - \@@_unit_format_fraction_symbol: - \exp_args:NNNV \group_end: - \tl_set:Nn \l_@@_tmpb_tl \l_@@_unit_tl - \tl_set:Nx \l_@@_tmpb_tl - { - \@@_print:nn { unit } - { \exp_not:V \l_@@_tmpb_tl } - } - \tl_set:Nx \l_@@_unit_tl - { - \exp_not:N \ensuremath { - \tex_mathchoice:D - { \exp_not:V \l_@@_tmpa_tl } - { \exp_not:V \l_@@_tmpb_tl } - { \exp_not:V \l_@@_tmpb_tl } - { \exp_not:V \l_@@_tmpb_tl } - } - } - } - { \@@_unit_format_fraction_symbol: } -} -% \end{macrocode} -% For a normal symbol, the two parts of the input are arranged either -% side of the symbol itself in math mode. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format_fraction_symbol: { - \@@_unit_format_fraction_symbol_aux: - \int_compare:nNnT { \l_@@_unit_denominator_int } > { 1 } - { - \bool_if:NT \l_@@_unit_denominator_bracket_bool - { - \tl_put_left:NV \l_@@_unit_denominator_tl \l_@@_bracket_open_tl - \tl_put_right:NV \l_@@_unit_denominator_tl \l_@@_bracket_close_tl - } - } - \tl_set_eq:NN \l_@@_unit_tl \l_@@_unit_numerator_tl - \tl_put_right:NV \l_@@_unit_tl \l_@@_per_symbol_tl - \tl_put_right:NV \l_@@_unit_tl \l_@@_unit_denominator_tl -} -\cs_new_protected:Npn - \@@_unit_format_fraction_symbol_aux: { } -\cs_new_protected:Npn - \@@_unit_format_fraction_symbol_aux_alt: { - \tl_if_empty:NT \l_@@_unit_numerator_tl - { \tl_set:Nn \l_@@_unit_numerator_tl { 1 } } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_unit_format_init:} -% The normal initialisation stuff. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format_init: { - \bool_set_false:N \l_@@_omit_unit_space_bool - \tl_clear:N \l_@@_unit_tl - \tl_clear:N \l_@@_unit_current_tl - \tl_clear:N \l_@@_unit_denominator_tl - \int_zero:N \l_@@_unit_prefix_gram_int - \tl_clear:N \l_@@_unit_numerator_tl - \int_zero:N \l_@@_unit_prefix_base_int - \int_zero:N \l_@@_unit_prefix_int - \int_zero:N \l_@@_unit_denominator_int - \int_zero:N \l_@@_unit_numerator_int - \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq - { \@@_unit_print_literal_aux:N ##1 } -} -% \end{macrocode} -%\end{macro} -% -% \begin{macro}{\@@_unit_format_literal:n} -% \begin{macro}{\@@_unit_format_literal_aux:N} -% \begin{macro}{\@@_unit_format_literal_power:n} -% If the unit given contains anything which is not a unit macro, then -% any unit macros that are there simply dump literal meanings. There is -% then a little work to do sorting out |~| and |.| characters at -% the outer level. -% \begin{macrocode} -\group_begin: - \char_set_catcode_active:N \~ - \cs_new_protected:Npn \@@_unit_format_literal:n #1 - { - \int_zero:N \l_@@_unit_prefix_int - \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq - { \@@_unit_print_literal_aux:N ##1 } - \tl_set:Nn \l_@@_unit_tl {#1} - \tl_replace_all:NnV \l_@@_unit_tl { . } - \l_@@_unit_product_tl - \tl_replace_all:NnV \l_@@_unit_tl { ~ } - \l_@@_unit_product_tl - \bool_if:NT \l_@@_literal_power_bool - { - \tl_replace_all:Nnn \l_@@_unit_tl { ^ } - { \@@_unit_format_literal_power:n } - \tl_replace_all:Non \l_@@_unit_tl { \token_to_str:N ^ } - { \@@_unit_format_literal_power:n } - } - \@@_unit_format_literal_extras: - } -\group_end: -\cs_new_protected:Npn \@@_unit_print_literal_aux:N #1 - { \cs_set_eq:Nc #1 { @@_ \token_to_str:N #1 _literal:w } } -\cs_new_protected:Npn \@@_unit_format_literal_power:n #1 - { \PrintSuperscript { \@@_unit_format_power_aux:n {#1} } } -% \end{macrocode} -% \end{macro} % \end{macro} - %\end{macro} -% -%\begin{macro}{\@@_unit_format_literal_extras:} -%\begin{macro}{\@@_unit_format_literal_extras_aux:nN} -% The code here deals with characters outside the normal range that -% can appear in units in UTF-8 and related encodings. The idea is to -% do a search and replace, thus avoiding any active characters. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format_literal_extras: - { - \@@_unit_format_literal_extras_aux:nN { 176 } - \SIUnitSymbolDegree - \@@_unit_format_literal_extras_aux:nN { 181 } - \SIUnitSymbolMicro - \@@_unit_format_literal_extras_aux:nN { 197 } - \SIUnitSymbolAngstrom - } -\cs_new_protected:Npn \@@_unit_format_literal_extras_aux:nN #1#2 - { - \tl_replace_all:Nxn \l_@@_unit_tl - { \char_generate:nn { #1 } { 12 } } - {#2} - } -\bool_lazy_or:nnF { \sys_if_engine_luatex_p: } { \sys_if_engine_xetex_p: } - { - \AtBeginDocument - { - \cs_if_exist:NTF \inputencodingname - { - \tl_set:Nn \l_@@_tmpa_tl { latin1 , latin5 , latin9 } - \clist_if_in:NVF \l_@@_tmpa_tl \inputencodingname - { - \cs_set_eq:NN \@@_unit_format_literal_extras: - \scan_stop: - } - } - { - \cs_set_eq:NN \@@_unit_format_literal_extras: - \scan_stop: - } - } - } -% \end{macrocode} -%\end{macro} -%\end{macro} % -%\begin{macro}{\@@_unit_format_power:} -%\begin{macro}{ -% \@@_unit_format_power_aux: , -% \@@_unit_format_power_aux:n , -% \@@_unit_format_power_aux:nn , -% \@@_unit_format_power_aux:w , -% \@@_unit_format_power_brackets: , -% \@@_unit_format_power_per: , -% \@@_unit_format_power_repeat: -%} -% To format powers, there are a few issues: are brackets needed, is -% the power reciprocal and is fraction-formatting in operation. Repeated -% per symbols make life a little more complex, as they have to be -% handled here as well. +% \begin{macro}{\complexnum, \complexqty} +% Interfaces for complex numbers. % \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format_power: { - \tl_set:Nx \l_@@_tmpa_tl - { power- \int_use:N \l_@@_unit_int } - \prop_get:NVNTF \l_@@_unit_prop \l_@@_tmpa_tl - \l_@@_tmpa_tl - { \@@_unit_format_power_aux: } - { - \tl_set:Nx \l_@@_tmpa_tl - { per- \int_use:N \l_@@_unit_int } - \prop_if_in:NVT \l_@@_unit_prop \l_@@_tmpa_tl - { - \tl_set:Nn \l_@@_tmpa_tl { 1 } - \@@_unit_format_power_aux: - } - } -} -% \end{macrocode} -% The auxiliary function needs to make sure that the printing routine -% prints the power as a number, not as text: the two modes may be -% different. A search and replace function is needed for superscripts -% in text mode so that negative signs get printed correctly. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format_power_aux: { - \str_if_eq:VnTF \l_@@_per_mode_tl { repeat } - { \@@_unit_format_power_repeat: } - { \@@_unit_format_power_per: } - \str_if_eq:VnF \l_@@_tmpa_tl { 1 } - { - \@@_unit_format_power_brackets: - \tl_put_right:Nx \l_@@_unit_current_tl - { - \exp_not:N \PrintSuperscript - { - \@@_unit_format_power_aux:n - { - \exp_after:wN \@@_unit_format_power:w - \l_@@_tmpa_tl . . \q_stop - } - } - } - } -} -\cs_new_protected:Npn \@@_unit_format_power_aux:n #1 { - \bool_if:NTF \l_@@_power_number_bool - { \@@_unit_format_power_aux:nn { number } {#1} } - { \@@_unit_format_power_aux:nn { unit } {#1} } -} -\cs_new_protected:Npn \@@_unit_format_power_aux:nn #1#2 { - \bool_if:cTF { l_@@_ #1 _math_mode_bool } - { \@@_print:nn {#1} {#2} } - { - \tl_set:Nn \l_@@_tmpa_tl {#2} - \tl_replace_all:Nnn \l_@@_tmpa_tl { - } - { \text { \textminus } } - \@@_print:nV {#1} \l_@@_tmpa_tl - } -} -\cs_new:Npn \@@_unit_format_power:w #1 . #2 . #3 \q_stop +\NewDocumentCommand \complexnum { O { } m } { - \exp_not:n {#1} - \tl_if_blank:nF {#2} - { - \exp_not:V \l_@@_output_decimal_tl - \exp_not:n {#2} - } + \mode_leave_vertical: + \group_begin: + \keys_set:nn { siunitx } {#1} + \siunitx_complex_number:n {#2} \l_@@_tmp_tl + \group_end: } -% \end{macrocode} -% A check is made for a qualifier with a space, which needs brackets -% if there is also a power. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format_power_brackets: { - \tl_set:Nx \l_@@_tmpb_tl - { bracket- \int_use:N \l_@@_unit_int } - \prop_if_in:NVT \l_@@_unit_prop \l_@@_tmpb_tl - { - \tl_put_left:NV \l_@@_unit_current_tl \l_@@_bracket_open_tl - \tl_put_right:NV \l_@@_unit_current_tl \l_@@_bracket_close_tl - } -} -% \end{macrocode} -% For dealing with \cs{per} and repeated \cs{per} symbols. The sign -% change does not use any numbers, as this makes life easier with -% non-integer values. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format_power_per: { - \tl_set:Nx \l_@@_tmpb_tl - { per- \int_use:N \l_@@_unit_int } - \prop_if_in:NVT \l_@@_unit_prop \l_@@_tmpb_tl - { - \bool_if:NF \l_@@_per_fraction_bool - { - \tl_if_in:NnTF \l_@@_tmpa_tl { - } - { - \cs_set:Npn \@@_tmp:w ##1 - ##2 \q_stop - { \tl_set:Nn \l_@@_tmpa_tl {##2} } - \exp_after:wN \@@_tmp:w \l_@@_tmpa_tl \q_stop - } - { \tl_put_left:Nn \l_@@_tmpa_tl { - } } - } - } -} -\cs_new_protected:Npn \@@_unit_format_power_repeat: { - \tl_set:Nx \l_@@_tmpb_tl - { per- \int_use:N \l_@@_unit_int } - \prop_if_in:NVT \l_@@_unit_prop \l_@@_tmpb_tl - { - \tl_put_left:NV \l_@@_unit_current_tl \l_@@_per_symbol_tl - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_unit_format_prefix:} -%\begin{macro}{ -% \@@_unit_format_prefix_number: , -% \@@_unit_format_prefix_number_calc: , -% \@@_unit_format_prefix_symbol: -%} -% If there is a prefix, it is added to the output. When using numerical -% output, some conversion is needed instead. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format_prefix: { - \tl_set:Nx \l_@@_tmpa_tl - { prefix-symbol- \int_use:N \l_@@_unit_int } - \prop_if_in:NVT \l_@@_unit_prop \l_@@_tmpa_tl - { - \prop_get:NVN \l_@@_unit_prop \l_@@_tmpa_tl - \l_@@_unit_prefix_current_tl - \bool_if:NTF \l_@@_prefix_symbols_bool - { \@@_unit_format_prefix_symbol: } - { \@@_unit_format_prefix_number: } - } -} -\cs_new_protected:Npn \@@_unit_format_prefix_number: { - \tl_set:Nx \l_@@_tmpa_tl - { prefix-base- \int_use:N \l_@@_unit_int } - \prop_get:NVN \l_@@_unit_prop \l_@@_tmpa_tl - \l_@@_tmpa_tl - \int_compare:nNnT { \l_@@_unit_prefix_base_int } = { 0 } - { - \int_set:Nn \l_@@_unit_prefix_base_int - { \l_@@_tmpa_tl } - } - \int_compare:nNnTF - { \l_@@_unit_prefix_base_int } = { \l_@@_tmpa_tl } - { \@@_unit_format_prefix_number_calc: } - { \msg_error:nn { siunitx } { prefix-base-mismatch } } -} -% \end{macrocode} -% The calculation for converting a unit prefix into a number is -% simple unless there are grammes involved. In that case, the base unit -% is the kilogram and so there is some code to convert the number -% back correctly. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format_prefix_number_calc: { - \tl_set:Nx \l_@@_tmpa_tl - { power- \int_use:N \l_@@_unit_int } - \prop_get:NVNF \l_@@_unit_prop \l_@@_tmpa_tl - \l_@@_tmpa_tl - { \tl_set:Nn \l_@@_tmpa_tl { 1 } } - \tl_set:Nx \l_@@_tmpb_tl - { unit- \int_use:N \l_@@_unit_int } - \prop_get:NVN \l_@@_unit_prop \l_@@_tmpb_tl - \l_@@_tmpb_tl - \str_if_eq:VnT \l_@@_tmpb_tl { \gram } - { - \tl_set:Nx \l_@@_unit_prefix_current_tl - { \int_eval:n { \l_@@_unit_prefix_current_tl - 3 } } - \tl_set:Nx \l_@@_tmpb_tl - { symbol- \int_use:N \l_@@_unit_int } - \prop_put:NVn \l_@@_unit_prop \l_@@_tmpb_tl { kg } - } - \tl_set:Nx \l_@@_unit_prefix_current_tl - { - \int_eval:n - { \l_@@_unit_prefix_current_tl * \l_@@_tmpa_tl } - } - \tl_set:Nx \l_@@_tmpa_tl - { per- \int_use:N \l_@@_unit_int } - \prop_if_in:NVTF \l_@@_unit_prop \l_@@_tmpa_tl - { - \int_set:Nn \l_@@_unit_prefix_int - { - \l_@@_unit_prefix_int - - \l_@@_unit_prefix_current_tl - } - } - { - \int_set:Nn \l_@@_unit_prefix_int - { - \l_@@_unit_prefix_int - + \l_@@_unit_prefix_current_tl - } - } -} -\cs_new_protected:Npn \@@_unit_format_prefix_symbol: { - \tl_set_eq:NN \l_@@_unit_current_tl - \l_@@_unit_prefix_current_tl -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_unit_format_qualifier:} -%\begin{macro}{ -% \@@_unit_format_qualifier_brackets: , -% \@@_unit_format_qualifier_phrase: , -% \@@_unit_format_qualifier_space: , -% \@@_unit_format_qualifier_subscript: , -% \@@_unit_format_qualifier_text: -%} -% Four methods for showing qualifiers, each with its own sub-function. -% For the \texttt{space} methods, a warning is set in the property list -% as if there is a power then some brackets will be needed. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format_qualifier: { - \tl_set:Nx \l_@@_tmpa_tl - { qualifier- \int_use:N \l_@@_unit_int } - \prop_get:NVNT \l_@@_unit_prop \l_@@_tmpa_tl - \l_@@_tmpa_tl - { - \use:c - { - @@_unit_format_qualifier_ - \l_@@_qualifier_mode_tl : - } - } -} -\cs_new_protected:Npn \@@_unit_format_qualifier_brackets: { - \tl_put_right:NV \l_@@_unit_current_tl \l_@@_bracket_open_tl - \tl_put_right:NV \l_@@_unit_current_tl \l_@@_tmpa_tl - \tl_put_right:NV \l_@@_unit_current_tl \l_@@_bracket_close_tl -} -\cs_new_protected:Npn \@@_unit_format_qualifier_phrase: +\NewDocumentCommand \complexqty { O { } m m } { - \tl_put_right:NV \l_@@_unit_current_tl \l_@@_qualifier_phrase_tl - \tl_put_right:NV \l_@@_unit_current_tl \l_@@_tmpa_tl - \tl_set:Nx \l_@@_tmpa_tl - { bracket- \int_use:N \l_@@_unit_int } - \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl { true } - } -\char_set_catcode_active:N \~ -\cs_new_protected:Npn \@@_unit_format_qualifier_space: { - \tl_put_right:Nn \l_@@_unit_current_tl { \text { ~ } } - \tl_put_right:NV \l_@@_unit_current_tl \l_@@_tmpa_tl - \tl_set:Nx \l_@@_tmpa_tl - { bracket- \int_use:N \l_@@_unit_int } - \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl { true } -} -\char_set_catcode_space:N \~ -\cs_new_protected:Npn \@@_unit_format_qualifier_subscript: { - \tl_put_right:Nx \l_@@_unit_current_tl - { \exp_not:N \PrintSubscript { \exp_not:V \l_@@_tmpa_tl } } -} -\cs_new_protected:Npn \@@_unit_format_qualifier_text: { - \tl_put_right:NV \l_@@_unit_current_tl \l_@@_tmpa_tl -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -% \begin{macro}{\@@_unit_format_sorted:} -% For when the powers are sorted with the positive ones first. The only -% slight issue is making sure that the additional space is included -% between the two units, if needed. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format_sorted: - { - \tl_set:Nx \l_@@_unit_tl - { - \exp_not:V \l_@@_unit_numerator_tl - \bool_lazy_or:nnF - { \tl_if_empty_p:N \l_@@_unit_numerator_tl } - { \tl_if_empty_p:N \l_@@_unit_denominator_tl } - { - \exp_not:N \l_@@_unit_product_tl - } - \exp_not:V \l_@@_unit_denominator_tl - } + \mode_leave_vertical: + \group_begin: + \siunitx_unit_options_apply:n {#3} + \keys_set:nn { siunitx } {#1} + \siunitx_complex_quantity:nn {#2} {#3} + \group_end: } % \end{macrocode} % \end{macro} % -%\begin{macro}{\@@_unit_format_symbol:} -%\begin{macro}{ -% \@@_unit_format_symbol_aux: , -% \@@_unit_format_symbol_aux_alt: -%} -% If there is no symbol, something is wrong! The only exception is -% when the code is inside the \cs{si} function (or similar) and there -% is only a prefix with nothing else present at all. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_format_symbol: { - \tl_set:Nx \l_@@_tmpa_tl - { symbol- \int_use:N \l_@@_unit_int } - \prop_get:NVNTF \l_@@_unit_prop \l_@@_tmpa_tl - \l_@@_tmpa_tl - { - \tl_put_right:NV \l_@@_unit_current_tl \l_@@_tmpa_tl - } - { \@@_unit_format_symbol_aux: } -} -\cs_new_protected:Npn \@@_unit_format_symbol_aux: { - \msg_error:nn { siunitx } { prefix-only } -} -\cs_new_protected:Npn \@@_unit_format_symbol_aux_alt: { - \int_compare:nNnTF { \l_@@_unit_int } = { 1 } - { - \prop_remove:Nn \l_@@_unit_prop { prefix-1 } - \prop_remove:Nn \l_@@_unit_prop { prefix-symbol-1 } - \prop_remove:Nn \l_@@_unit_prop { prefix-base-1 } - \prop_remove:Nn \l_@@_unit_prop { total-units } - \prop_if_empty:NF \l_@@_unit_prop - { \msg_error:nn { siunitx } { prefix-only } } - } - { \msg_error:nn { siunitx } { prefix-only } } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\subsection{Unit output} -% -% A collection of the internal parts of various user functions. -% -%\begin{macro}{\l_@@_multi_brackets_bool} -%\begin{macro}{\l_@@_multi_repeat_bool} -% Flags for multi-part numbers. -% \begin{macrocode} -\bool_new:N \l_@@_multi_brackets_bool -\bool_new:N \l_@@_multi_repeat_bool -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\l_@@_product_brackets_bool} -%\begin{macro}{\l_@@_product_power_bool} -%\begin{macro}{\l_@@_number_unit_repeat_bool} -% Flags for product units. -% \begin{macrocode} -\bool_new:N \l_@@_product_brackets_bool -\bool_new:N \l_@@_product_power_bool -\bool_new:N \l_@@_product_repeat_bool -\bool_new:N \l_@@_number_unit_repeat_bool -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\l_@@_number_unit_breaks_bool} -%\begin{macro}{\l_@@_number_unit_product_tl} -% Options for printing units or units with numbers. -% \begin{macrocode} -\keys_define:nn { siunitx } { - allow-number-unit-breaks .bool_set:N = - \l_@@_number_unit_breaks_bool, - multi-part-units .choice:, - multi-part-units - / brackets .code:n = - { - \bool_set_true:N \l_@@_multi_brackets_bool - \bool_set_false:N \l_@@_multi_repeat_bool - }, - multi-part-units - / repeat .code:n = - { - \bool_set_false:N \l_@@_multi_brackets_bool - \bool_set_true:N \l_@@_multi_repeat_bool - }, - multi-part-units - / single .code:n = - { - \bool_set_false:N \l_@@_multi_brackets_bool - \bool_set_false:N \l_@@_multi_repeat_bool - }, - number-unit-product .tl_set:N = - \l_@@_number_unit_product_tl, - number-unit-separator .tl_set:N = - \l_@@_number_unit_product_tl, - product-units .choice:, - product-units - / brackets .code:n = - { - \bool_set_true:N \l_@@_product_brackets_bool - \bool_set_false:N \l_@@_product_power_bool - \bool_set_false:N \l_@@_product_repeat_bool - }, - product-units - / brackets-power .code:n = - { - \bool_set_true:N \l_@@_product_brackets_bool - \bool_set_true:N \l_@@_product_power_bool - \bool_set_false:N \l_@@_product_repeat_bool - }, - product-units - / power .code:n = - { - \bool_set_false:N \l_@@_product_brackets_bool - \bool_set_true:N \l_@@_product_power_bool - \bool_set_false:N \l_@@_product_repeat_bool - }, - product-units - / repeat .code:n = - { - \bool_set_false:N \l_@@_product_brackets_bool - \bool_set_false:N \l_@@_product_power_bool - \bool_set_true:N \l_@@_product_repeat_bool - }, - product-units - / single .code:n = - { - \bool_set_false:N \l_@@_product_brackets_bool - \bool_set_false:N \l_@@_product_power_bool - \bool_set_false:N \l_@@_product_repeat_bool - }, -} -\keys_set:nn { siunitx } { - multi-part-units = brackets, - number-unit-product = \, , - product-units = repeat -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_unit_output:nn} -%\begin{macro}{\@@_unit_output:Vn} -% For typesetting a unit directly: used by \cs{si} and the \texttt{s} -% column. The second argument is any options to set locally. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_output:nn #1#2 { - \cs_set_eq:NN \@@_unit_format_symbol_aux: - \@@_unit_format_symbol_aux_alt: - \cs_set_eq:NN \@@_unit_format_fraction_symbol_aux_ii: - \@@_unit_format_fraction_symbol_aux_alt: - \@@_unit_in:nn {#1} {#2} - \int_compare:nNnTF { \l_@@_unit_prefix_int } = { 0 } - { - \str_if_eq:VnT \l_@@_per_mode_tl { symbol } - { - \int_compare:nNnT { \l_@@_unit_numerator_int } = { 0 } - { - \bool_if:NT \l_@@_unit_parse_bool - { \@@_print:nn { unit } { 1 } } - } - } - } - { - \tl_set:Nx \l_@@_tmpa_tl - { - \int_use:N \l_@@_unit_prefix_base_int - \exp_not:N \PrintSuperscript - { \int_use:N \l_@@_unit_prefix_int } - } - \@@_print:nV { number } \l_@@_tmpa_tl - \@@_unit_output_number_sep: - } - \@@_print:nV { unit } \l_@@_unit_tl -} -\cs_generate_variant:Nn \@@_unit_output:nn { V } -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_unit_output_number_sep:} -%\begin{macro}{\@@_unit_output_number_sep_aux:} -% For printing the number separator. The \cs{tex_mathchoice:D} code -% deals with the \opt{symbol-or-fraction} setting for \opt{per-mode}, -% as in that case omission of the space between a number and unit -% depends on the current math style. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_output_number_sep: { - \bool_if:NTF \l_@@_number_unit_breaks_bool - { \penalty \binoppenalty } { \nobreak } - \bool_if:NTF \l_@@_per_auto_bool - { - \mode_if_math:TF - { - \tex_mathchoice:D - { \l_@@_number_unit_product_tl } - { \@@_unit_output_number_sep_aux: } - { \@@_unit_output_number_sep_aux: } - { \@@_unit_output_number_sep_aux: } - } - { \@@_unit_output_number_sep_aux: } - } - { \@@_unit_output_number_sep_aux: } -} -\cs_new_protected:Npn \@@_unit_output_number_sep_aux: { - \bool_if:NF \l_@@_omit_unit_space_bool - { \l_@@_number_unit_product_tl } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_unit_output_pre_print:} -%\begin{macro}{\@@_unit_output_print:} -% The printing functions for units do some simple tests then -% actually print there output. -% \begin{macrocode} -\cs_new_protected:Npn \@@_unit_output_pre_print: { - \tl_if_empty:NF \l_@@_pre_unit_tl - { - \nobreak - \@@_print:nV { unit } \l_@@_pre_unit_tl - } -} -\cs_new_protected:Npn \@@_unit_output_print: { - \int_compare:nNnF { \l_@@_unit_prefix_int } = { 0 } - { - \tl_set:Nx \l_@@_tmpa_tl - { - \bool_if:NTF \l_@@_tight_bool - { - \exp_not:N \ensuremath - { { \exp_not:V \l_@@_exponent_product_tl } } - } - { - \exp_not:N \ensuremath - { { } \exp_not:V \l_@@_exponent_product_tl { } } - } - \int_use:N \l_@@_unit_prefix_base_int - ^ { \int_use:N \l_@@_unit_prefix_int } - } - \@@_print:nV { number } \l_@@_tmpa_tl - } - \tl_if_empty:NF \l_@@_unit_tl - { - \@@_unit_output_number_sep: - \@@_print:nV { unit } \l_@@_unit_tl - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\subsection{Numbers with units} -% -% Numbers with units have to be formatted in a more complex way than -% simply sticking the two together. -% -%\begin{macro}{\l_@@_preunit_tl} -% A pre-unit is optional, so can be handled using the setting system. -% \begin{macrocode} -\keys_define:nn { siunitx } { - preunit .tl_set:N = \l_@@_preunit_tl , -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_pre_unit_tl} -% When there is a pre-unit, it gets stored here. -% \begin{macrocode} -\tl_new:N \l_@@_pre_unit_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_number_product_int} -% Used to count up the number of product tokens in a number. -% \begin{macrocode} -\int_new:N \l_@@_number_product_int -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_combined:nnnn} -% Printing numbers and units means first processing the units, then -% handing off this information to the combined number and unit -% processor. -% \begin{macrocode} -\cs_new_protected:Npn \@@_combined:nnnn #1#2#3#4 { - \IfNoValueTF {#3} - { \tl_clear:N \l_@@_pre_unit_tl } - { - \group_begin: - \@@_unit_in:nn {#3} {#1} - \cs_set_eq:NN \l_@@_pre_unit_tl \l_@@_unit_tl - \exp_args:NNNo \group_end: - \tl_set:Nn \l_@@_pre_unit_tl { \l_@@_unit_tl } - } - \cs_set_eq:NN \l_@@_brackets_bool - \l_@@_multi_brackets_bool - \@@_combined_unit:nnn {#2} {#4} {#1} - \@@_combined_output:n {#2} -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_combined_output:n} -% Printing the combination of a number and a unit means checking for -% parsing then parsing the number part. +% \begin{macro}{\tablenum} +% Slightly odd set up at present: we have to have the |\ignorespaces|. % \begin{macrocode} -\cs_new_protected:Npn \@@_combined_output:n #1 { - \bool_if:NTF \l_@@_number_parse_bool - { - \tl_clear:N \l_@@_number_out_tl - \bool_set_false:N \l_@@_number_compound_bool - \@@_number_output_parse:n {#1} - } - { - \@@_unit_output_pre_print: - \@@_print:nn { number } { \ensuremath {#1} } - \@@_unit_output_print: - } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_combined_unit:nnn} -% In most cases, sorting out the main unit is easy: simply set up for -% printing using \cs{@@_unit_in:nn}. However, if there are multiple -% parts to the number, and they are to be combined into the unit, then -% there is more work to do. In either case, the result is the -% correctly-prepared unit stored in \cs{l_@@_unit_tl}. -% \begin{macrocode} -\cs_new_protected:Npn \@@_combined_unit:nnn #1#2#3 { - \bool_if:NTF \l_@@_product_power_bool - { - \@@_combined_product_count:n {#1} - \int_compare:nNnTF { \l_@@_number_product_int } > { 0 } - { - \int_incr:N \l_@@_number_product_int - \tl_set:Nn \l_@@_tmpa_tl {#2} - \tl_set:Nx \l_@@_tmpb_tl - { \tothe { \exp_not:V \l_@@_number_product_int } } - \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl - \@@_unit_in:Vn \l_@@_tmpa_tl {#3} - } - { \@@_unit_in:nn {#2} {#3} } - } - { \@@_unit_in:nn {#2} {#3} } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_combined_product_count:n} -%\begin{macro}{\@@_combined_product_count_aux:n} -% For counting how many products are in a number, so that the unit -% can be adjusted if needed. -% \begin{macrocode} -\cs_new_protected:Npn \@@_combined_product_count:n #1 { - \int_zero:N \l_@@_number_product_int - \tl_set:Nn \l_@@_tmpa_tl {#1} - \tl_map_function:NN \l_@@_input_product_tl - \@@_combined_product_count_aux:N -} -\cs_new_protected:Npn \@@_combined_product_count_aux:N #1 { - \tl_if_in:NnT \l_@@_tmpa_tl {#1} - { - \int_incr:N \l_@@_number_product_int - \tl_remove_once:Nn \l_@@_tmpa_tl {#1} - \@@_combined_product_count_aux:N #1 - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\subsection{Lists of numbers} -% -%\begin{macro}{\l_@@_list_brackets_bool} -%\begin{macro}{\l_@@_list_repeat_bool} -% For storing the behaviour of list items with respect to units. -% \begin{macrocode} -\bool_new:N \l_@@_list_brackets_bool -\bool_new:N \l_@@_list_repeat_bool -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\l_@@_list_current_tl} -%\begin{macro}{\l_@@_list_tl} -% Two token list variables used to store the list for output. -% \begin{macrocode} -\tl_new:N \l_@@_list_current_tl -\tl_new:N \l_@@_list_tl -% \end{macrocode} -%\end{macro} -%\end{macro} -% -% \begin{variable} -% { -% \l_@@_list_separator_pair_tl , -% \l_@@_list_separator_final_tl , -% \l_@@_list_separator_tl, -% } -% Settings for lists. -% \begin{macrocode} -\keys_define:nn { siunitx } +\NewDocumentCommand \tablenum { O { } m } { - list-final-separator .tl_set:N = \l_@@_list_separator_final_tl , - list-pair-separator .tl_set:N = \l_@@_list_separator_pair_tl , - list-separator .tl_set:N = \l_@@_list_separator_tl , - list-units .choice:, - list-units - / brackets .code:n = - { - \bool_set_true:N \l_@@_list_brackets_bool - \bool_set_false:N \l_@@_list_repeat_bool - }, - list-units - / repeat .code:n = - { - \bool_set_false:N \l_@@_list_brackets_bool - \bool_set_true:N \l_@@_list_repeat_bool - }, - list-units - / single .code:n = - { - \bool_set_false:N \l_@@_list_brackets_bool - \bool_set_false:N \l_@@_list_repeat_bool - } + \mode_leave_vertical: + \group_begin: + \keys_set:nn { siunitx } {#1} + \siunitx_cell_begin:w + \ignorespaces #2 + \siunitx_cell_end: + \group_end: } -\keys_set:nn { siunitx } - { - list-final-separator = { ~ and ~ } , - list-pair-separator = { ~ and ~ } , - list-separator = { , ~ } , - list-units = repeat -} % \end{macrocode} -% \end{variable} +% \end{macro} % -% \begin{macro}{\@@_list_numbers:n} -% \begin{macro} -% {\@@_list_numbers_aux_i:n, \@@_list_numbers_aux_ii:n} -% \begin{macro}{\@@_list_numbers_aux:nn} -% Setting up lists is made slightly complicated by the need to handle the -% case of exactly two items and the case of the very last separator -% differently from everything else. Beyond that, there is not too much -% to any of this code. +% \begin{macro}{\sisetup} +% A very thin wrapper. % \begin{macrocode} -\cs_new_protected:Npn \@@_list_numbers:n #1 - { - \tl_clear:N \l_@@_unit_tl - \tl_clear:N \l_@@_preunit_tl - \@@_list_numbers_aux_i:n {#1} - } -\cs_new_protected:Npn \@@_list_numbers_aux_i:n #1 - { - \bool_set_true:N \l_@@_list_first_bool - \tl_clear:N \l_@@_list_current_tl - \int_compare:nNnTF { \tl_count:n {#1} } > 2 - { - \tl_map_function:nN {#1} \@@_list_numbers_aux_ii:n - \l_@@_list_tl - \l_@@_list_separator_final_tl - \l_@@_list_current_tl - } - { - \int_compare:nNnTF { \tl_count:n {#1} } = 2 - { \@@_list_numbers_aux:nn #1 } - { \@@_combined_output:n #1 } - } - } -\cs_new_protected:Npn \@@_list_numbers_aux_ii:n #1 - { - \tl_if_empty:NTF \l_@@_list_tl - { \tl_set_eq:NN \l_@@_list_tl \l_@@_list_current_tl } - { - \tl_put_right:NV \l_@@_list_tl \l_@@_list_separator_tl - \tl_put_right:NV \l_@@_list_tl \l_@@_list_current_tl - } - \tl_set:Nn \l_@@_list_current_tl { \@@_combined_output:n {#1} } - } -\cs_new_protected:Npn \@@_list_numbers_aux:nn #1#2 - { - \@@_combined_output:n {#1} - \l_@@_list_separator_pair_tl - \@@_combined_output:n {#2} - } +\NewDocumentCommand \sisetup { m } + { \keys_set:nn { siunitx } {#1} } % \end{macrocode} % \end{macro} -% \end{macro} -% \end{macro} % -% \begin{macro}{\@@_list_units:nnn} -% For a list of items with units, the method is to first parse the -% unit when repeating (to save time), then to use the number loop above -% for the actual work. On the other hand, when the unit is only printed -% once life is easier as the normal unit printer can operate. +% \subsection{\enquote{Glue} commands} +% +% \begin{macro}{\@@_angle:nnn} +% The document level interface for \cs{ang} needs some \enquote{glue} to +% work with the code-level API. % \begin{macrocode} -\cs_new_protected:Npn \@@_list_units:nnn #1#2#3 +\cs_new_protected:Npn \@@_angle:nnn #1#2#3 { - \@@_unit_parse_options:nn {#2} {#3} - \bool_if:NTF \l_@@_list_repeat_bool - { - \@@_unit_in:nn {#2} {#3} - \@@_list_numbers_aux_i:n {#1} - } + \tl_if_novalue:nTF {#2} + { \siunitx_angle:n {#1} } { - \bool_if:NT \l_@@_process_fixed_bool - { \bool_set_true:N \l_@@_process_drop_exponent_bool } - \bool_if:NT \l_@@_list_brackets_bool - { \@@_print:nV { number } \l_@@_bracket_open_tl } - \@@_list_numbers:n {#1} - \bool_if:NT \l_@@_list_brackets_bool - { \@@_print:nV { number } \l_@@_bracket_close_tl } - \@@_range_exponent: - \@@_unit_output_number_sep: - \@@_unit_output:nn {#2} {#3} + \tl_if_novalue:nTF {#3} + { \siunitx_angle:nnn {#1} {#2} { } } + { \siunitx_angle:nnn {#1} {#2} {#3} } } } % \end{macrocode} % \end{macro} % -%\subsection{Ranges} +% \subsection{Table column} % -%\begin{macro}{\l_@@_range_brackets_bool} -%\begin{macro}{\l_@@_range_repeat_bool} -% Settings for ranges with units. +% User interfaces in tabular constructs are provided using the mechanisms from +% the \pkg{array} package. % \begin{macrocode} -\bool_new:N \l_@@_range_brackets_bool -\bool_new:N \l_@@_range_repeat_bool +\RequirePackage { array } % \end{macrocode} -%\end{macro} -%\end{macro} % -%\begin{macro}{\l_@@_range_phrase_tl} -% Simple settings for ranges. +% \begin{macro}{\@@_declare_column:Nnn} +% Creating numerical columns requires that these are declared before anything +% else in \cs{NC@list}: this is necessary to work with optional arguments. +% This means a bit of manual effort after the simple declaration of a new +% column type. The token assigned to the column type is not fixed as this +% allows the same code to be used in compatibility with version~$2$. % \begin{macrocode} -\keys_define:nn { siunitx } { - range-phrase .tl_set:N = \l_@@_range_phrase_tl, - range-units .choice:, - range-units - / brackets .code:n = - { - \bool_set_true:N \l_@@_range_brackets_bool - \bool_set_false:N \l_@@_range_repeat_bool - }, - range-units - / repeat .code:n = - { - \bool_set_false:N \l_@@_range_brackets_bool - \bool_set_true:N \l_@@_range_repeat_bool - }, - range-units - / single .code:n = - { - \bool_set_false:N \l_@@_range_brackets_bool - \bool_set_false:N \l_@@_range_repeat_bool - }, -} -\keys_set:nn { siunitx } { - range-phrase = { ~ to ~ }, - range-units = repeat, -} -% \end{macrocode} -%\end{macro} -% -% \begin{macro}{\@@_range_numbers:nn} -% \begin{macro}{\@@_range_numbers_core:nn} -% \begin{macro}{\@@_range_numbers_aux:n} -% A range of numbers. This is more restrictive than the \cs{num} -% function: nothing compound. -% \begin{macrocode} -\cs_new_protected:Npn \@@_range_numbers:nn #1#2 - { - \@@_range_numbers_aux:n {#1} - \l_@@_range_phrase_tl - \@@_range_numbers_aux:n {#2} - } -\cs_new_protected:Npn \@@_range_numbers_aux:n #1 +\cs_new_protected:Npn \@@_declare_column:Nnn #1#2#3 { - \bool_if:NTF \l_@@_number_parse_bool + \cs_if_exist:cT { NC@find@ #1 } { - \tl_clear:N \l_@@_number_out_tl - \tl_clear:N \l_@@_number_out_saved_tl - \bool_set_false:N \l_@@_number_compound_bool - \@@_number_output_parse:n {#1} - \bool_if:NT \l_@@_number_compound_bool - { \msg_error:nnx { siunitx } { multi-part-range } {#1} } + \cs_undefine:c { NC@find@ #1 } + \msg_warning:nnn { siunitx } { column-overwritten } {#1} } + \newcolumntype {#1} { } + \cs_set_protected:Npn \@@_tmp:w \NC@do ##1##2 \NC@do #1 + { \NC@list { \NC@do ##1 \NC@do #1 ##2 } } + \exp_after:wN \@@_tmp:w \the \NC@list + \exp_args:NNc \renewcommand * { NC@rewrite@ #1 } [ 1 ] [ ] { - \@@_unit_output_pre_print: - \@@_print:nn { number } {#1} - \@@_unit_output_print: - } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% \end{macro} -% -%\begin{macro}{\@@_range_unit:nnnn} -% Unit printing is also simple: basically a past-up job. The only compl -% \begin{macrocode} -\cs_new_protected:Npn \@@_range_unit:nnnn #1#2#3#4 { - \@@_unit_parse_options:nn {#1} {#2} - \bool_if:NTF \l_@@_range_repeat_bool - { - \@@_unit_in:nn {#1} {#2} - \@@_range_numbers_aux:n {#3} - \l_@@_range_phrase_tl - \@@_range_numbers_aux:n {#4} - } - { - \bool_if:NT \l_@@_process_fixed_bool - { \bool_set_true:N \l_@@_process_drop_exponent_bool } - \bool_if:NT \l_@@_range_brackets_bool - { \@@_print:nV { number } \l_@@_bracket_open_tl } - \@@_range_numbers:nn {#3} {#4} - \bool_if:NT \l_@@_range_brackets_bool - { \@@_print:nV { number } \l_@@_bracket_close_tl } - \@@_range_exponent: - \@@_unit_output_number_sep: - \@@_unit_output:nn {#1} {#2} - } -} -% \end{macrocode} -%\end{macro} -% -% \begin{macro}{\@@_range_exponent:} -% The idea here is to construct and print an exponent if this is fixed, -% and thus removed from the range. This function is also used by the -% related list concept. -% \begin{macrocode} -\cs_new_protected:Npn \@@_range_exponent: - { - \bool_if:NT \l_@@_process_fixed_bool - { - \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_exponent_product_tl - \bool_if:NT \l_@@_tight_bool + \@temptokena \expandafter { - \tl_set:Nx \l_@@_tmpa_tl - { \exp_not:N \mathord \exp_not:o \l_@@_tmpa_tl } + \the \@temptokena + > {#2} c < {#3} } - \tl_set:Nx \l_@@_tmpa_tl - { - \exp_not:N \ensuremath { { } \exp_not:o \l_@@_tmpa_tl { } } - 10 \exp_not:N \PrintSuperscript - { \int_use:N \l_@@_process_fixed_int } - } - \@@_print:nV { number } \l_@@_tmpa_tl + \NC@find } } +\msg_new:nnn { siunitx } { column-overwritten } + { Tabular~column~type~"#1"~overwritten~with~siunitx~definition. } % \end{macrocode} -% \end{macro} -% -%\subsection{Setting up tables} -% -% There is a slight problem with the \pkg{cellspace} package: it also -% uses \texttt{S} for a column type Here, \texttt{S} seems to make -% more sense for \pkg{siunitx}, with \texttt{C} used for -% \pkg{cellspace}. To enable this to work well, the column -% rewriting code happens \cs{AtBeginDocument}. The \texttt{S} column -% is deleted from \cs{NC@list} so that no warning appears. -% \begin{macrocode} -\AtBeginDocument { - \@ifpackageloaded { cellspace } - { - \cs_if_exist:NT \NC@find@S - { - \newcolumntype { C } [1] - { > { \bcolumn #1 \@nil } #1 < { \ecolumn } } - \cs_set:Npn \@@_tmp:w #1 \NC@do S #2 \q_stop - { \NC@list { #1 #2 } } - \exp_after:wN \@@_tmp:w \tex_the:D \NC@list \q_stop - \cs_undefine:N \NC@find@S - \msg_new:nnn { siunitx } { moved-cellspace-column } - { Column~type~for~cellspace~package~moved~to~'#1'. } - \msg_warning:nnn { siunitx } { moved-cellspace-column } { C } - \ifcellspace@m - \def \env@matrix - { - \hskip -\arraycolsep - \let \@ifnextchar \new@ifnextchar - \array - { - * { \c@MaxMatrixCols } - { > { \bcolumn c \@nil $ } c < { $ \ecolumn } } @ { } - } - } - \fi - } - } - { } -} -% \end{macrocode} -% -%\begin{macro}{\@@_table_rewrite_create:N} -%\begin{macro}{\@@_table_rewrite_create_aux:w} -% The \texttt{s} and \texttt{S} column types are both created using -% the \pkg{array} package, but with the internal macros redefined -% to work with optional argument. First, there is a need to do a -% quick shuffle with the \cs{NC@list} macro. The \pkg{siunitx} -% columns have to be listed first, as otherwise the optional -% arguments do not work correctly. So they are added \enquote{by hand} -% to the appropriate macro. +% When \pkg{mdwtab} is loaded the syntax required is slightly different. % \begin{macrocode} -\cs_new_protected:Npn \@@_table_rewrite_create:N #1 { - \newcolumntype {#1} { } - \cs_set_protected:Npn - \@@_table_rewrite_create_aux:w \NC@do ##1##2 \NC@do #1 - { \NC@list { \NC@do ##1 \NC@do #1 ##2 } } - \exp_after:wN \@@_table_rewrite_create_aux:w \tex_the:D \NC@list - \exp_args:NNc \renewcommand * { NC@rewrite@ #1 } [1] [ ] - { - \@temptokena \exp_after:wN - { - \tex_the:D \@temptokena - > { \@@_table_collect_begin:Nn #1 {##1} } - c - < { \@@_table_print: } - } - \NC@find - } -} \AtBeginDocument { \@ifpackageloaded { mdwtab } { - \cs_set_protected:Npn \@@_table_rewrite_create:N #1 + \cs_set_protected:Npn \@@_declare_column:Nnn #1#2#3 { - \newcolumntype {#1} [1] [] - { - > { \@@_table_collect_begin:Nn #1 {##1} } - c - < { \@@_table_print: } - } + \cs_if_exist:cT { NC@find@ #1 } + { + \cs_undefine:c { NC@find@ #1 } + \msg_warning:nnn { siunitx } { column-overwritten } {#1} + } + \newcolumntype {#1} [ 1 ] [ ] + { > {#2} c < {#3} } } } { } - } -\cs_new_protected:Npn \@@_table_rewrite_create_aux:w { } -\AtBeginDocument { \@@_table_rewrite_create:N s } -\AtBeginDocument { \@@_table_rewrite_create:N S } -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\subsection{Collecting tokens in tables} -% -% The table system is in two parts, collecting tokens and typesetting -% the result. The collection routine tries to ensure that the -% typesetting part only receives real cell contents. -% -%\begin{macro}{\l_@@_table_collect_tl} -%\begin{macro}{\l_@@_table_collect_pre_tl} -%\begin{macro}{\l_@@_table_collect_post_tl} -% Three storage areas. -% \begin{macrocode} -\tl_new:N \l_@@_table_collect_tl -\tl_new:N \l_@@_table_collect_pre_tl -\tl_new:N \l_@@_table_collect_post_tl -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\l_@@_number_valid_tl} -% As the \texttt{S} column has to make a judgement about tokens which -% can be part of a number, there is a need to have a list of valid -% tokens. -% \begin{macrocode} -\tl_new:N \l_@@_number_valid_tl -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_table_math_bool} -% A flag used inside the table cell to track math mode: there is -% a need to do things by hand as otherwise the grouping goes -% wrong. -% \begin{macrocode} -\bool_new:N \l_@@_table_math_bool -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\l_@@_table_collect_pre_bool} -%\begin{macro}{\l_@@_table_collect_post_bool} -% Flags for having found a number in an \texttt{S} column. -% \begin{macrocode} -\bool_new:N \l_@@_table_collect_pre_bool -\bool_new:N \l_@@_table_collect_post_bool -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_table_collect_begin:Nn} -%\begin{macro}{\@@_table_collect_begin:Nw} -%\begin{macro}{\@@_table_collect_begin_s:} -%\begin{macro}{\@@_table_collect_begin_S:} -% The collector starts by setting up local options, then clears and -% initialises the storage and testing system. Font detection for the -% \texttt{S} column happens here as this ensures that it is not inside -% a box, which will give the wrong result for \opt{detect-mode}. The -% |\use_i:nn| removes the |\ignorespaces| from the cell preamble. -% In the basic \LaTeXe{} template there is only an |\ignorespaces| -% before the content, but to deal with any other material we use -% a delimited approach. It's important to grab everything up to the -% end of the template-before-|#| to allow the Appendix~D trick to work -% inside the |peek| code. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_collect_begin:Nn #1#2 - { - \keys_set:nn { siunitx } {#2} - \@@_table_collect_begin:Nw #1 - } -\cs_new_protected:Npn \@@_table_collect_begin:Nw #1#2 \ignorespaces - { \use:c { @@_table_collect_begin_ #1 : } #2 } -\cs_new_protected:Npn \@@_table_collect_begin_s: { - \cs_set_eq:NN \@@_table_collect_token:N - \@@_table_collect_token_s:N - \cs_set_eq:NN \@@_table_print: \@@_table_print_s: - \@@_table_collect_init_s: - \@@_table_collect_get: -} -\cs_new_protected:Npn \@@_table_collect_begin_S: { - \cs_set_eq:NN \@@_table_collect_token:N - \@@_table_collect_token_S:N - \cs_set_eq:NN \@@_table_print: \@@_table_print_S: - \@@_table_collect_init_S: - \@@_detect_font: - \bool_if:NTF \l_@@_number_parse_bool - { \@@_table_collect_get: } - { \@@_table_print_S_direct: } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_table_collect_braced:n} -% The collection of braced items depends on the column type. So we -% start of with an empty definition. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_collect_braced:n #1 { } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_table_collect_expand:N} -%\begin{macro}{\@@_table_collect_expand_math:N} -% The idea here is to expand content if possible. There are a few -% things to note. Only macros which are not long or protected are -% expanded. There is the possibility that the macro may need the -% contents of the pre-numeral part to be executed, for example see -% \cref{tab:xmpl:calc} in the user part of the documentation. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_collect_expand:N #1 { - \cs_if_eq:NNTF #1 \color - { - \bool_if:NTF \l_@@_table_collect_pre_bool - { - \tl_clear:N \l_@@_number_color_tl - \tl_clear:N \l_@@_unit_color_tl - \tl_put_right:Nn \l_@@_table_collect_pre_tl {#1} - } - { - \bool_set_true:N \l_@@_table_collect_post_bool - \tl_put_right:Nn \l_@@_table_collect_post_tl {#1} - } - } - { - \@@_cs_if_tl:NTF #1 - { - \tl_use:N \l_@@_table_collect_pre_tl - \tl_clear:N \l_@@_table_collect_pre_tl - \cs_set:Npn \@@_table_collect_next: - { \exp_after:wN \@@_table_collect_get: #1 } - } - { - \bool_if:NTF \l_@@_table_collect_pre_bool - { - \tl_put_right:Nn \l_@@_table_collect_pre_tl {#1} - \@@_table_collect_expand_math:N #1 - } - { - \bool_set_true:N \l_@@_table_collect_post_bool - \tl_put_right:Nn \l_@@_table_collect_post_tl {#1} - } - } - } -} -% \end{macrocode} -% There is a need to keep a track of math mode, so that there are no -% disasters when the tokens are boxed up later. The ideal is to know -% the math state of the collected tokens so that appropriate -% steps can be taken to insert math shift tokens later. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_collect_expand_math:N #1 { - \token_if_math_toggle:NTF #1 - { - \bool_if:NTF \l_@@_table_math_bool - { \bool_set_false:N \l_@@_table_math_bool } - { \bool_set_true:N \l_@@_table_math_bool } - } - { - \cs_if_eq:NNTF #1 \( % \) - { \bool_set_true:N \l_@@_table_math_bool } - { % \( - \cs_if_eq:NNT #1 \) - { \bool_set_false:N \l_@@_table_math_bool } - } - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_table_collect_get:} -% The token collection system first has to check that the next argument -% does not start with an opening-brace character. If it does, the -% testing is skipped and the braced token is stored. Otherwise, a check -% is made against various ignored tokens. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_collect_get: - { - \cs_set_eq:NN \@@_table_collect_next: - \@@_table_collect_get: - \peek_catcode_ignore_spaces:NTF \c_group_begin_token - { \@@_table_collect_braced:n } - { \@@_table_collect_not_braced:N } - } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_table_collect_init:} -% The usual spin-out of basics. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_collect_init: { - \tl_clear:N \l_@@_table_collect_tl - \tl_clear:N \l_@@_table_collect_pre_tl - \tl_clear:N \l_@@_table_collect_post_tl - \bool_set_false:N \l_@@_table_collect_post_bool - \bool_set_false:N \l_@@_table_math_bool -} -% \end{macrocode} -%\end{macro} -%\begin{macro}{\@@_table_collect_init_s:} -%\begin{macro}{\@@_table_collect_init_S:} -% Some type-specific definitions. In the \texttt{S} case, the -% initialisation function for numbers is used to set -% \cs{l_@@_number_valid_tl} correctly. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_collect_init_s: { - \@@_table_collect_init: - \bool_set_false:N \l_@@_table_collect_pre_bool - \cs_set_protected:Npn \@@_table_collect_braced:n ##1 - { - \tl_put_right:Nn \l_@@_table_collect_tl { {##1} } - \@@_table_collect_next: - } -} -\cs_new_protected:Npn \@@_table_collect_init_S: { - \@@_number_in_init: - \tl_set:Nx \l_@@_number_valid_tl - { - \exp_not:V \l_@@_input_complex_tl - \exp_not:V \l_@@_input_decimal_tl - \exp_not:V \l_@@_input_digit_tl - \exp_not:V \l_@@_input_exponent_tl - \exp_not:V \l_@@_input_ignore_tl - \exp_not:V \l_@@_input_comparator_tl - \exp_not:V \l_@@_input_uncert_close_tl - \exp_not:V \l_@@_input_uncert_open_tl - \exp_not:V \l_@@_input_sign_tl - \exp_not:V \l_@@_input_symbol_tl - } - \bool_set_true:N \l_@@_table_collect_pre_bool - \cs_set_protected:Npn \@@_table_collect_braced:n ##1 - { - \bool_if:NTF \l_@@_table_collect_pre_bool - { \tl_put_right:Nn \l_@@_table_collect_pre_tl { {##1} } } - { - \bool_set_true:N \l_@@_table_collect_post_bool - \tl_put_right:Nn \l_@@_table_collect_post_tl { {##1} } - } - \@@_table_collect_next: - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_table_collect_next:} -% A holder for the next thing to do. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_collect_next: { } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_table_collect_newline:} -% The end macro needs to come before the new line is called. The -% print function is redefined so that it only actually does stuff once. -% As each cell is a group anyway, there is no need to save the -% definition of \cs{@@_table_print:}, as it will re-appear on its -% own. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_collect_newline: { - \@@_table_print: - \cs_set_eq:NN \@@_table_print: \prg_do_nothing: - \tabularnewline -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_table_collect_end:} -% The same concept applies to the \cs{end} macro. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_collect_end: { - \@@_table_print: - \cs_set_eq:NN \@@_table_print: \prg_do_nothing: - \end -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\@@_table_collect_not_braced:N} -%\begin{macro}{\@@_table_collect_not_braced_aux_i:N} -%\begin{macro}{\@@_table_collect_not_braced_aux_ii:N} -% A few macros are simply passed through to be executed; this is mainly -% so that the table actually works. The newline function needs its own -% function, which is picked up by hand. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_collect_not_braced:N #1 - { - \token_if_eq_meaning:NNF #1 \tex_ignorespaces:D - { - \token_if_eq_meaning:NNF #1 \tex_unskip:D - { \@@_table_collect_not_braced_aux_i:N #1 } - } - \@@_table_collect_next: - } -\AtBeginDocument - { - \@ifpackageloaded { mdwtab } + \tl_map_inline:Nn \l_@@_column_type_tl { - \cs_set_protected:Npn \@@_table_collect_not_braced:N #1 + \@@_declare_column:Nnn #1 { - \token_if_eq_meaning:NNF #1 \tex_ignorespaces:D - { - \token_if_eq_meaning:NNF #1 \tex_unskip:D - { - \token_if_eq_meaning:NNF #1 \tab@setcr - { - \token_if_eq_meaning:NNF #1 \@maybe@unskip - { \@@_table_collect_not_braced_aux_i:N #1 } - } - } - } - \@@_table_collect_next: + \keys_set:nn { siunitx } {##1} + \siunitx_cell_begin:w } + { \siunitx_cell_end: } } - { } } -\cs_new_protected:Npn \@@_table_collect_not_braced_aux_i:N #1 { - \cs_set:Npn \@@_table_collect_not_braced_aux_ii:N ##1 - { - \token_if_eq_meaning:NNT #1 ##1 - { \cs_set_eq:NN \@@_table_collect_next: ##1 } - } - \tl_map_function:nN - { \cs:w \scan_stop: \@@_table_print: } - \@@_table_collect_not_braced_aux_ii:N - \token_if_eq_meaning:NNT \@@_table_collect_next: - \@@_table_collect_get: - { - \token_if_eq_meaning:NNTF #1 \tabularnewline - { - \cs_set_eq:NN \@@_table_collect_next: - \@@_table_collect_newline: - } - { - \token_if_eq_meaning:NNTF #1 \end - { - \cs_set_eq:NN \@@_table_collect_next: - \@@_table_collect_end: - } - { \@@_table_collect_token:N #1 } - } - } -} -\cs_new_protected:Npn \@@_table_collect_not_braced_aux_ii:N #1 { } -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\@@_table_collect_token:N} -%\begin{macro}{\@@_table_collect_token_s:N} -% For the \texttt{s} column, every token is added to the same storage -% area, so life is simple. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_collect_token:N #1 { } -\cs_new_protected:Npn \@@_table_collect_token_s:N #1 { - \tl_put_right:Nn \l_@@_table_collect_tl {#1} -} -% \end{macrocode} -%\end{macro} -%\end{macro} -%\begin{macro}{\@@_table_collect_token_S:N} -% Not so easy for the \texttt{S} column type. If the content is after -% a number, things are easy. On the other hand, if the token might be -% a number, then a check is made. It the token is still unmatched, then -% it is passed on to the expansion handler. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_collect_token_S:N #1 { - \bool_if:NTF \l_@@_table_collect_post_bool - { \tl_put_right:Nn \l_@@_table_collect_post_tl {#1} } - { - \tl_if_in:NnTF \l_@@_number_valid_tl {#1} - { - \bool_set_false:N \l_@@_table_collect_pre_bool - \tl_put_right:Nn \l_@@_table_collect_tl {#1} - } - { \@@_table_collect_expand:N #1 } - } -} % \end{macrocode} -%\end{macro} -% -% \subsection{Table printing: general code} +% \end{macro} % -% Getting the general alignment correct in tables is made more -% complex than one would like by the \pkg{colortbl} package. In the -% original \LaTeXe{} definition, cell material is centred by a -% construction of the (primitive) form -% \begin{verbatim} -% \hfil -% # -% \hfil -% \end{verbatim} -% which only uses \texttt{fil} stretch. That is altered by -% \pkg{colortbl} to broadly -% \begin{verbatim} -% \hskip 0 pt plus 0.5 fill -% \kern 0 pt -% # -% \hskip 0 pt plus 0.5 fill -% \end{verbatim} -% which means there is \texttt{fill} stretch to worry about and -% the kern as well. +% \subsection{Document commands in bookmarks} % -% \begin{variable}{\c_@@_one_fill_skip} -% A fixed skip of one \texttt{fill}. -% \begin{macrocode} -\skip_const:Nn \c_@@_one_fill_skip { 0pt plus 1fill } -% \end{macrocode} -% \end{variable} +% In bookmarks, the \pkg{siunitx} document commands need to produce simple +% strings that represent their input as far a possible. % -% \begin{macro}{\@@_table_colortbl_correction:} -% If the package \pkg{colortbl} is loaded, there is a need to allow -% that it changes how centring is carried out. +% \begin{macro}{\@@_bookmark_cmd:Nn} +% To keep things fast, expandable versions of the document command are +% created only once. As here we are at the top-level for internal names, +% we can use the various parts of \pkg{siunitx-compound} that would otherwise +% be inaccessible. % \begin{macrocode} -\AtBeginDocument +\cs_new_protected:Npn \@@_bookmark_cmd:Nnn #1#2#3 { - \@ifpackageloaded { colortbl } - { - \cs_new_protected:Npn \@@_table_colortbl_correction: - { - \skip_horizontal:n { 0pt plus -0.5fill } - \tex_kern:D \c_zero_skip - } - } - { \cs_new_protected:Npn \@@_table_colortbl_correction: { } } + \exp_args:Nc \DeclareExpandableDocumentCommand + { \cs_to_str:N #1 \c_space_tl ( pdfstring ~ context ) } + {#2} {#3} } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_table_align_left:n} -% \begin{macro}{\@@_table_align_right:n} -% These are simple shortcuts to keep life clearer in the rest of the -% code. The idea is that the kern acts as a \enquote{stop} for the -% horizontal skip. The correction for \pkg{colortbl} is separate as the -% spacing needs to be explicitly deleted. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_align_left:n #1 +\@@_bookmark_cmd:Nnn \qty { o m m } { #2 ~ #3 } +\@@_bookmark_cmd:Nnn \ang { m } { \@@_angle:n {#1} } +\@@_bookmark_cmd:Nnn \num { o m } { #2 } +\@@_bookmark_cmd:Nnn \unit { o m } { #2 } +\@@_bookmark_cmd:Nnn \numlist { o m } { - \@@_table_colortbl_correction: - \skip_horizontal:n {#1} - \tex_kern:D \c_zero_skip + \@@_list_use:nnVVV {#2} { } + \l_siunitx_list_separator_pair_tl + \l_siunitx_list_separator_tl + \l_siunitx_list_separator_final_tl } -\cs_new_protected:Npn \@@_table_align_right:n #1 +\@@_bookmark_cmd:Nnn \qtylist { o m m } { - \skip_horizontal:n { \c_@@_one_fill_skip - #1 } - \tex_kern:D \c_zero_skip - \@@_table_colortbl_correction: + \@@_list_use:nnVVV {#2} {#3} + \l_siunitx_list_separator_pair_tl + \l_siunitx_list_separator_tl + \l_siunitx_list_separator_final_tl } +\@@_bookmark_cmd:Nnn \numproduct { o m } { } +\@@_bookmark_cmd:Nnn \qtyproduct { o m m } { } +\@@_bookmark_cmd:Nnn \numrange { o m m } + { #2 \tl_use:N \l_siunitx_range_phrase_tl #3 } +\@@_bookmark_cmd:Nnn \qtyrange { o m m m } + { #2 ~ #4 \tl_use:N \l_siunitx_range_phrase_tl #3 ~ #4 } % \end{macrocode} % \end{macro} -% \end{macro} -% -% \begin{macro}{\@@_table_column_begin:} -% \begin{macro}{\@@_table_column_end:} -% \begin{macrocode} -\cs_new_eq:NN \@@_table_column_begin:n \@@_table_align_left:n -\cs_new_eq:NN \@@_table_column_end:n \@@_table_align_right:n -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% Setting up for a fixed column width is done so that the check is -% made at the key-setting stage. In that way, there will be some -% speed gained if the key is set before the table, as the comparison -% is not made for every cell. +% We also need the v2 names. % \begin{macrocode} -\keys_define:nn { siunitx } +\@@_bookmark_cmd:Nnn \si { o m } { #2 } +\@@_bookmark_cmd:Nnn \SI { o m O { } m } { #3 #2 ~ #4 } +\@@_bookmark_cmd:Nnn \SIlist { o m m } { - table-column-width .code:n = - { - \dim_compare:nNnTF {#1} = { \c_zero_dim } - { - \cs_set_eq:NN \@@_table_column_begin:n - \@@_table_align_left:n - \cs_set_eq:NN \@@_table_column_end:n - \@@_table_align_right:n - } - { - \cs_set_protected:Npn \@@_table_column_begin:n ##1 - { - \@@_table_colortbl_correction: - \tex_hbox:D to \dim_eval:n {#1} - \c_group_begin_token - \skip_horizontal:n {##1} - \tex_kern:D \c_zero_skip - } - \cs_set_protected:Npn \@@_table_column_end:n ##1 - { - \skip_horizontal:n { \c_@@_one_fill_skip - ##1 } - \tex_kern:D \c_zero_skip - \c_group_end_token - \@@_table_colortbl_correction: - } - } - } - } -% \end{macrocode} -% -% \subsection{Printing units in \texttt{s} columns} -% -% The easiest type of printing is the \texttt{s} column. Here, there is -% no real problem with alignment. All that has to happen is to print the -% collected input as the argument to the internal part of an \cs{si} -% function. -% -% \begin{variable}{\l_@@_table_unit_align_skip} -% The spacing used is stored as a skip, which needs to be set up first. -% \begin{macrocode} -\skip_new:N \l_@@_table_unit_align_skip -% \end{macrocode} -% \end{variable} -% -% \begin{macrocode} -\keys_define:nn { siunitx } - { - table-unit-alignment .choice:, - table-unit-alignment / - center .code:n = - { - \skip_set:Nn \l_@@_table_unit_align_skip - { 0pt plus 0.5fill } - }, - table-unit-alignment / - left .code:n = - { \skip_set:Nn \l_@@_table_unit_align_skip { \c_zero_skip } }, - table-unit-alignment / - right .code:n = - { - \skip_set:Nn \l_@@_table_unit_align_skip - { 0pt plus 1fill } - } + \@@_list_use:nnVVV {#2} {#3} + \l_siunitx_list_separator_pair_tl + \l_siunitx_list_separator_tl + \l_siunitx_list_separator_final_tl } -\keys_set:nn { siunitx } { table-unit-alignment = center } +\@@_bookmark_cmd:Nnn \SIrange { o m m m } + { #2 ~ #4 \tl_use:N \l_siunitx_range_phrase_tl #3 ~ #4 } % \end{macrocode} % -% \begin{macro}{\@@_table_print_s:} -% Actually printing an \texttt{s} column is not very complex. There is -% some spacing to do at each side, with the main part of the job being -% to print the material using the internal version of \cs{si}. +% \begin{variable}{\c_@@_bookmark_seq} +% Commands usable in bookmarks % \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_s: +\seq_const_from_clist:Nn \c_@@_bookmark_seq { - \@@_table_column_begin:n { \l_@@_table_unit_align_skip } - \tl_if_empty:NF \l_@@_table_collect_tl - { \@@_unit_output:Vn \l_@@_table_collect_tl { } } - \@@_table_column_end:n { \l_@@_table_unit_align_skip } + \ang , \qty , \num , \unit , + \numlist , \qtylist , + \numrange , \qtyrange , + \si , \SI , \SIlist , \SIrange } % \end{macrocode} -% \end{macro} -% -% \subsection{Formatting and printing in tables} -% -% With the content grabbed, the next stage is to turn it into formatted -% output then print it. Most of the formatting is done elsewhere, so -% most of the work here is in printing. -% -% \begin{variable}{\l_@@_table_model_prop} -% A place to store the model for reserved-space table columns. -% \begin{macrocode} -\prop_new:N \l_@@_table_model_prop -% \end{macrocode} -% \end{variable} -% -% \begin{variable} -% { -% \l_@@_table_exponent_dim , -% \l_@@_table_integer_dim , -% \l_@@_table_mantissa_dim , -% \l_@@_table_marker_dim , -% \l_@@_table_result_dim , -% \l_@@_table_uncert_dim -% } -% Dimensions to track the various spaces needed. -% \begin{macrocode} -\dim_new:N \l_@@_table_exponent_dim -\dim_new:N \l_@@_table_integer_dim -\dim_new:N \l_@@_table_mantissa_dim -\dim_new:N \l_@@_table_marker_dim -\dim_new:N \l_@@_table_result_dim -\dim_new:N \l_@@_table_uncert_dim -% \end{macrocode} -%\end{variable} -% -% \begin{variable} -% {\l_@@_table_fill_pre_dim, \l_@@_table_fill_post_dim} -% Calculating the fill needed can be a bit complicated, so is best -% done using a dedicated dimension. There is a second one for cases dealing -% with fill at the end of a number, where there may be some rearrangement. -% \begin{macrocode} -\dim_new:N \l_@@_table_fill_pre_dim -\dim_new:N \l_@@_table_fill_post_dim -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\l_@@_table_fill_mid_dim} -% For the reserved space approach there is also the need for a third -% piece of fill, which may or may not be used. -% \begin{macrocode} -\dim_new:N \l_@@_table_fill_mid_dim -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\l_@@_table_pre_box, \l_@@_table_post_box} -% Boxes for the content before and after the numerical part. -% \begin{macrocode} -\box_new:N \l_@@_table_pre_box -\box_new:N \l_@@_table_post_box -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\l_@@_table_mantissa_box} -% When printing with space reserved, the mantissa needs to hang around -% for a while. This is best done by storing the typeset result in a box. -% \begin{macrocode} -\box_new:N \l_@@_table_mantissa_box -% \end{macrocode} -% \end{variable} -% -% \begin{variable}{\l_@@_table_result_box} -% The box which is actually needed for printing. -% \begin{macrocode} -\box_new:N \l_@@_table_result_box -% \end{macrocode} -% \end{variable} -% -% \begin{variable} -% {\l_@@_table_number_align_skip, \l_@@_table_text_align_skip} -% Skips for aligning text and numbers. -% \begin{macrocode} -\skip_new:N \l_@@_table_number_align_skip -\skip_new:N \l_@@_table_text_align_skip -% \end{macrocode} % \end{variable} % -% \begin{macro} -% { -% \@@_table_print_S_direct_main: , -% \@@_table_print_S_parsed: -% } -% \begin{macro}{\@@_table_print_S_reserved_store_fill:n} -% Various functions which are set up by the option system, and so are -% reserved here first for completeness. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_direct_main: { } -\cs_new_protected:Npn \@@_table_print_S_parsed: { } -\cs_new_protected:Npn \@@_table_print_S_reserved_store_fill:n #1 { } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{variable} -% { -% \l_@@_table_align_exponent_bool, -% \l_@@_table_align_text_pre_bool, -% \l_@@_table_align_text_post_bool, -% \l_@@_table_align_uncert_bool, -% \l_@@_table_auto_round_bool, -% \l_@@_table_omit_exponent_bool, -% \l_@@_table_parse_only_bool, -% \l_@@_table_pre_tl, -% \l_@@_table_post_tl -% } +% Activate the document commands here: the unit macros are handled in +% \pkg{siunitx-final}. % \begin{macrocode} -\keys_define:nn { siunitx } +\AtBeginDocument { - table-align-comparator .choice:, - table-align-comparator / - false .code:n = - { - \cs_set_eq:NN \@@_table_print_S_reserved_store_fill:n - \@@_table_print_S_reserved_store_fill_pre:n - }, - table-align-comparator / - true .code:n = - { - \cs_set_eq:NN \@@_table_print_S_reserved_store_fill:n - \@@_table_print_S_reserved_store_fill_mid:n - }, - table-align-comparator .default:n = true, - table-align-exponent .bool_set:N = - \l_@@_table_align_exponent_bool, - table-align-text-pre .bool_set:N = - \l_@@_table_align_text_pre_bool, - table-align-text-post .bool_set:N = - \l_@@_table_align_text_post_bool, - table-align-uncertainty .bool_set:N = \l_@@_table_align_uncert_bool, - table-auto-round .bool_set:N = \l_@@_table_auto_round_bool, - table-number-alignment .choice:, - table-number-alignment / - center .code:n = - { - \skip_set:Nn \l_@@_table_number_align_skip - { 0pt plus 0.5fill } - \cs_set_eq:NN \@@_table_print_S_direct_main: - \@@_table_print_S_direct_reserved: - \cs_set_eq:NN \@@_table_print_S_parsed: - \@@_table_print_S_reserved: - }, - table-number-alignment / - center-decimal-marker .code:n = - { - \skip_set:Nn \l_@@_table_number_align_skip - { 0pt plus 0.5fill } - \cs_set_eq:NN \@@_table_print_S_direct_main: - \@@_table_print_S_direct_centered: - \cs_set_eq:NN \@@_table_print_S_parsed: - \@@_table_print_S_centered: - }, - table-number-alignment / - left .code:n = - { - \skip_zero:N \l_@@_table_number_align_skip - \cs_set_eq:NN \@@_table_print_S_direct_main: - \@@_table_print_S_direct_reserved: - \cs_set_eq:NN \@@_table_print_S_parsed: - \@@_table_print_S_reserved: - }, - table-number-alignment / - right .code:n = - { - \skip_set:Nn \l_@@_table_number_align_skip - { 0pt plus 1fill } - \cs_set_eq:NN \@@_table_print_S_direct_main: - \@@_table_print_S_direct_reserved: - \cs_set_eq:NN \@@_table_print_S_parsed: - \@@_table_print_S_reserved: - }, - table-omit-exponent .bool_set:N = - \l_@@_table_omit_exponent_bool, - table-text-alignment .choice:, - table-text-alignment / - center .code:n = - { - \skip_set:Nn \l_@@_table_text_align_skip - { 0pt plus 0.5fill } - }, - table-text-alignment / - left .code:n = - { \skip_zero:N \l_@@_table_text_align_skip }, - table-text-alignment / - right .code:n = - { - \skip_set:Nn \l_@@_table_text_align_skip - { 0pt plus 1fill } - }, - table-comparator .choice:, - table-comparator / - false .code:n = - { \prop_remove:Nn \l_@@_table_model_prop { comparator } }, - table-comparator / - true .code:n = - { \prop_put:Nnn \l_@@_table_model_prop { comparator } { > } }, - table-comparator .default:n = true, - table-figures-decimal .code:n = + \@ifpackageloaded { hyperref } { - \int_compare:nNnTF {#1} = 0 + \pdfstringdefDisableCommands { - \prop_remove:Nn \l_@@_table_model_prop { mantissa-decimal } - \prop_remove:Nn \l_@@_table_model_prop { mantissa-decimal-raw } - \prop_remove:Nn \l_@@_table_model_prop - { mantissa-decimal-marker } - \prop_if_in:NnTF \l_@@_table_model_prop { mantissa-integer } + \seq_map_inline:Nn \c_@@_bookmark_seq { - \prop_put:Nnn \l_@@_table_model_prop { mantissa } - { true } + \cs_set_eq:Nc #1 + { \cs_to_str:N #1 \c_space_tl ( pdfstring ~ context ) } } - { \prop_remove:Nn \l_@@_table_model_prop { mantissa } } - } - { - \prop_put:Nnx \l_@@_table_model_prop { mantissa-decimal } - { \prg_replicate:nn {#1} { 8 } } - \prop_put:Nnn \l_@@_table_model_prop { mantissa-decimal-raw } - {#1} - \prop_put:Nnn \l_@@_table_model_prop { mantissa } { true } - \prop_put:NnV \l_@@_table_model_prop - { mantissa-decimal-marker } \l_@@_output_decimal_tl - } - }, - table-figures-exponent .code:n = - { - \int_compare:nNnTF {#1} = 0 - { \prop_remove:Nn \l_@@_table_model_prop { exponent-integer } } - { - \prop_put:Nnx \l_@@_table_model_prop { exponent-integer } - { \prg_replicate:nn {#1} { 8 } } - \prop_put:Nnn \l_@@_table_model_prop { exponent } { true } } - }, - table-figures-integer .code:n = - { - \int_compare:nNnTF {#1} = 0 + \pdfstringdefDisableCommands { - \prop_remove:Nn \l_@@_table_model_prop { mantissa-integer } - \prop_if_in:NnTF \l_@@_table_model_prop { mantissa-decimal } + \siunitx_unit_pdfstring_context: + \cs_if_exist:NT \FB@fg { \def \fg { \FB@fg } } + \edef \H { - \prop_put:Nnn \l_@@_table_model_prop { mantissa } - { true } + \exp_not:c { PU-cmd } + \exp_not:N \H + \exp_not:c { PU \token_to_str:N \H } } - { \prop_remove:Nn \l_@@_table_model_prop { mantissa } } - } - { - \prop_put:Nnx \l_@@_table_model_prop { mantissa-integer } - { \prg_replicate:nn {#1} { 8 } } - \prop_put:Nnn \l_@@_table_model_prop { mantissa } { true } - } - }, - table-figures-uncertainty .code:n = - { - \int_compare:nNnTF {#1} = 0 - { \prop_remove:Nn \l_@@_table_model_prop { mantissa-uncertainty } } - { - \prop_put:Nnx \l_@@_table_model_prop { mantissa-uncertainty } - { \prg_replicate:nn {#1} { 8 } } - } - }, - table-parse-only .bool_set:N = \l_@@_table_parse_only_bool, - table-space-text-pre .tl_set:N = \l_@@_table_pre_tl, - table-space-text-post .tl_set:N = \l_@@_table_post_tl, - table-sign-exponent .choice:, - table-sign-exponent / true .code:n = - { \prop_put:Nnn \l_@@_table_model_prop { exponent-sign } { - } }, - table-sign-exponent / false .code:n = - { \prop_remove:Nn \l_@@_table_model_prop { exponent-sign } }, - table-sign-exponent .default:n = true, - table-sign-mantissa .choice:, - table-sign-mantissa / true .code:n = - { \prop_put:Nnn \l_@@_table_model_prop { mantissa-sign } { - } }, - table-sign-mantissa / false .code:n = - { \prop_remove:Nn \l_@@_table_model_prop { mantissa-sign } }, - table-sign-mantissa .default:n = true, - } -% \end{macrocode} -% \end{variable} -% -% A meta-choice for all table alignment is also provided. -% \begin{macrocode} -\keys_define:nn { siunitx } - { - table-alignment .meta:n = - { - table-number-alignment = #1, - table-text-alignment = #1, - table-unit-alignment = #1 - } - } -% \end{macrocode} -% -% Another special option. This converts a number format in compacted -% form into the various internal settings needed. -% \begin{macrocode} -\keys_define:nn { siunitx } - { - table-format .code:n = - { - \bool_set_eq:NN \l_@@_process_plus_saved_bool \l_@@_process_plus_bool - \bool_set_true:N \l_@@_process_plus_bool - \@@_number_in_parse:n {#1} - \prop_set_eq:NN \l_@@_table_model_prop \l_@@_number_in_prop - \tl_clear:N \l_@@_tmpa_tl - \prop_get:NnNT \l_@@_number_in_prop { mantissa-integer } - \l_@@_tmpb_tl - { - \tl_set:Nx \l_@@_tmpa_tl - { table-figures-integer = \l_@@_tmpb_tl } - } - \prop_get:NnNT \l_@@_number_in_prop { mantissa-decimal } - \l_@@_tmpb_tl - { - \clist_put_right:Nx \l_@@_tmpa_tl - { table-figures-decimal = \l_@@_tmpb_tl } - } - \prop_get:NnNT \l_@@_number_in_prop { mantissa-uncertainty } - \l_@@_tmpb_tl - { - \clist_put_right:Nx \l_@@_tmpa_tl - { table-figures-uncertainty = \l_@@_tmpb_tl } - } - \prop_if_in:NnTF \l_@@_number_in_prop { mantissa-sign } - { - \clist_put_right:Nn \l_@@_tmpa_tl - { table-sign-mantissa =true } - } - { - \clist_put_right:Nn \l_@@_tmpa_tl - { table-sign-mantissa =false } - } - \prop_get:NnNT \l_@@_number_in_prop { exponent-integer } - \l_@@_tmpb_tl - { - \clist_put_right:Nx \l_@@_tmpa_tl - { table-figures-exponent = \l_@@_tmpb_tl } - } - \prop_if_in:NnTF \l_@@_number_in_prop { exponent-sign } - { - \clist_put_right:Nn \l_@@_tmpa_tl - { table-sign-exponent =true } - } - { - \clist_put_right:Nn \l_@@_tmpa_tl - { table-sign-exponent =false } - } - \clist_put_right:Nn \l_@@_tmpa_tl - { table-number-alignment = center } - \keys_set:nV { siunitx } \l_@@_tmpa_tl - \bool_set_eq:NN \l_@@_process_plus_bool \l_@@_process_plus_saved_bool - } - } -\bool_new:N \l_@@_process_plus_saved_bool -% \end{macrocode} -% -% \begin{macro}{\@@_table_print_S:} -% The main printing function makes a choice depending on whether there is -% any numerical part to print at all. This affects which set of skips to -% insert. Font detection for the \texttt{S} column is included here as -% this is needed to do this work outside of an \cs{hbox}. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S: - { - \bool_if:NTF \l_@@_table_collect_pre_bool - { - \@@_table_column_begin:n { \l_@@_table_text_align_skip } - \l_@@_table_collect_pre_tl - \@@_table_column_end:n { \l_@@_table_text_align_skip } - } - { - \@@_table_column_begin:n { \l_@@_table_number_align_skip } - \bool_if:NTF \l_@@_table_parse_only_bool - { \@@_table_print_S_no_alignment: } - { \@@_table_print_S_alignment: } - \bool_if:NTF \l_@@_table_align_text_pre_bool - { \@@_table_print_S_pre_aligned: } - { \@@_table_print_S_pre_not_aligned: } - \box_use:N \l_@@_table_result_box - \bool_if:NTF \l_@@_table_align_text_post_bool - { \@@_table_print_S_post_aligned: } - { \@@_table_print_S_post_not_aligned: } - \@@_table_column_end:n { \l_@@_table_number_align_skip } - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_table_print_S_no_alignment:} -% With no alignment to do, the code can be pretty simple. The collected -% number is simply printed between the two non-numerical parts. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_no_alignment: - { - \l_@@_table_collect_pre_tl - \@@_number_output:V \l_@@_table_collect_tl - \l_@@_table_collect_post_tl - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_table_print_S_alignment:} -% This is a pass-through, so that the appropriate alignment mode is -% retained without needing to retest on each use. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_alignment: - { \@@_table_print_S_parsed: } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_table_print_S_parse:} -% A modified version of the number parser for tables. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_parse: - { - \bool_set_false:N \l_@@_error_bool - \@@_number_in_parse:V \l_@@_table_collect_tl - \bool_if:NF \l_@@_error_bool - { - \bool_if:NTF \l_@@_table_omit_exponent_bool - { - \bool_set_true:N \l_@@_process_fixed_bool - \@@_number_process: - \prop_remove:Nn \l_@@_number_in_prop { exponent } - \prop_remove:Nn \l_@@_number_in_prop { exponent-integer } - } - { \@@_number_process: } - \@@_number_format: - \@@_number_output_color: - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_table_print_S_measure:NN} -% A short routine to measure up whatever has been extracted from the -% storage system. Boxing up is avoided for the empty cases, as this saves -% a little time(the print routine is relatively slow). -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_measure:NN #1#2 - { - \tl_if_empty:NTF #1 - { \dim_zero:N #2 } - { - \group_begin: - \hbox_set:Nn \l_@@_tmp_box - { \@@_print:nV { number } #1 } - \exp_args:NNNo \group_end: - \dim_set:Nn #2 { \dim_use:N \box_wd:N \l_@@_tmp_box } - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro} -% { -% \@@_table_print_S_pre_aligned: , -% \@@_table_print_S_pre_not_aligned: , -% \@@_table_print_S_post_aligned: , -% \@@_table_print_S_post_not_aligned: -% } -% The non-numerical material is inserted along with the filler needed -% to maintain alignment. The order in which the two are inserted depends -% on whether those parts are also aligned. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_pre_aligned: - { - \box_use:N \l_@@_table_pre_box - \hbox_to_wd:nn { \l_@@_table_fill_pre_dim } { \tex_hfil:D } - } -\cs_new_protected:Npn \@@_table_print_S_pre_not_aligned: - { - \hbox_to_wd:nn { \l_@@_table_fill_pre_dim } { \tex_hfil:D } - \box_use:N \l_@@_table_pre_box - } -\cs_new_protected:Npn \@@_table_print_S_post_aligned: - { - \hbox_to_wd:nn { \l_@@_table_fill_post_dim } { \tex_hfil:D } - \box_use:N \l_@@_table_post_box - } -\cs_new_protected:Npn \@@_table_print_S_post_not_aligned: - { - \box_use:N \l_@@_table_post_box - \hbox_to_wd:nn { \l_@@_table_fill_post_dim } { \tex_hfil:D } - } -% \end{macrocode} -% \end{macro} -% -% \subsection{Printing the \texttt{S} column with the decimal marker centred} -% -% \begin{macro}{\@@_table_print_S_centered:} -% The main routine for decimal-centred alignment works by boxing up the -% entire output, the integer part and the decimal marker. It then works -% out which part is bigger and calculates the fill correction accordingly. -% Once all of that is done, the various boxes and fill can be inserted. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_centered: - { - \@@_table_print_S_centered_ends: - \bool_if:NT \l_@@_table_math_bool { \c_math_toggle_token } - \@@_table_print_S_parse: - \bool_if:NF \l_@@_error_bool - { - \@@_table_print_S_centered_measure: - \bool_if:NT \l_@@_table_math_bool { \c_math_toggle_token } - \dim_set:Nn \l_@@_table_fill_pre_dim - { - \l_@@_table_result_dim - - \l_@@_table_integer_dim - - \l_@@_table_marker_dim - } - \dim_compare:nNnTF \l_@@_table_integer_dim > - \l_@@_table_fill_pre_dim - { \@@_table_print_S_centered_integer: } - { \@@_table_print_S_centered_decimal: } - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_table_print_S_centered_ends:} -% To deal with the material outside of the number, the first step is to -% box up both parts. If the pre-numeral part has no width, the tokens are -% inserted into the input stream to cover cases where they make a change -% to the colour, font or so forth. After that, the narrower of the two -% boxes is made the same size as the wider: this maintains the alignment. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_centered_ends: - { - \hbox_set:Nn \l_@@_table_pre_box - { - { - \l_@@_table_collect_pre_tl - \bool_if:NT \l_@@_table_math_bool - { - \scan_stop: - \c_math_toggle_token - } - } - } - \dim_compare:nNnT - { \box_wd:N \l_@@_table_pre_box } = \c_zero_dim - { - \box_clear:N \l_@@_table_pre_box - \l_@@_table_collect_pre_tl - \bool_set_false:N \l_@@_font_set_bool - } - \hbox_set:Nn \l_@@_table_post_box - { - \bool_if:NT \l_@@_table_math_bool - { - \c_math_toggle_token - \scan_stop: - } - \l_@@_table_collect_post_tl - } - \dim_compare:nNnTF - { \box_wd:N \l_@@_table_pre_box } > - { \box_wd:N \l_@@_table_post_box } - { - \hbox_set_to_wd:Nnn \l_@@_table_post_box - { \box_wd:N \l_@@_table_pre_box } - { - \hbox_unpack:N \l_@@_table_post_box - \tex_hfil:D - } - } - { - \hbox_set_to_wd:Nnn \l_@@_table_pre_box - { \box_wd:N \l_@@_table_post_box } - { - \tex_hfil:D - \hbox_unpack:N \l_@@_table_pre_box - } - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_table_print_S_centered_measure:} -% \begin{macro} -% { -% \@@_table_print_S_centered_measure_int_part: , -% \@@_table_print_S_centered_measure_marker: , -% \@@_table_print_S_centered_measure_result: -% } -% Here, there are three parts of the number to measure: the integer part, -% the decimal marker and the entire number. Most of the work consists -% of collecting up parts of the number. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_centered_measure: - { - \@@_table_print_S_centered_measure_int_part: - \@@_table_print_S_centered_measure_marker: - \@@_table_print_S_centered_measure_result: - } -\cs_new_protected:Npn \@@_table_print_S_centered_measure_int_part: - { - \prop_get:NnNF \l_@@_number_out_prop { comparator } \l_@@_tmpa_tl - { \tl_clear:N \l_@@_tmpa_tl } - \prop_get:NnNT \l_@@_number_out_prop { mantissa-sign } - \l_@@_tmpb_tl - { \tl_put_right:No \l_@@_tmpa_tl \l_@@_tmpb_tl } - \prop_get:NnNT \l_@@_number_out_prop { mantissa-integer } - \l_@@_tmpb_tl - { \tl_put_right:No \l_@@_tmpa_tl \l_@@_tmpb_tl } - \@@_table_print_S_measure:NN \l_@@_tmpa_tl - \l_@@_table_integer_dim - } -\cs_new_protected:Npn \@@_table_print_S_centered_measure_marker: - { - \@@_table_print_S_measure:NN \l_@@_output_decimal_tl - \l_@@_table_marker_dim - } -% \end{macrocode} -% As the overall result will be needed later, the boxing up here is done -% using a named box that will be retained. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_centered_measure_result: - { - \prop_get:NnN \l_@@_number_out_prop { result } \l_@@_tmpa_tl - \hbox_set:Nn \l_@@_table_result_box - { \@@_print:nV { number } \l_@@_tmpa_tl } - \dim_set:Nn \l_@@_table_result_dim - { \box_wd:N \l_@@_table_result_box } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro} -% { -% \@@_table_print_S_centered_integer: , -% \@@_table_print_S_centered_decimal: -% } -% The appropriate place to insert the fill is determined by whether the -% integer or decimal part of the number is bigger. Two dimensions are -% therefore set, for fill before the number and after it. One of these -% will always be zero. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_centered_integer: - { - \dim_set:Nn \l_@@_table_fill_post_dim - { \l_@@_table_integer_dim - \l_@@_table_fill_pre_dim } - \dim_zero:N \l_@@_table_fill_pre_dim - } -\cs_new_protected:Npn \@@_table_print_S_centered_decimal: - { - \dim_sub:Nn \l_@@_table_fill_pre_dim - { \l_@@_table_integer_dim } - \dim_zero:N \l_@@_table_fill_post_dim - } -% \end{macrocode} -% \end{macro} -% -% \subsection{Printing the \texttt{S} column with space reserved} -% -% \begin{macro}{\@@_table_print_S_reserved:} -% The procedure for inserting a number with space reserved requires a model -% for each part of the number. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_reserved: - { - \@@_table_print_S_reserved_init: - \@@_table_print_S_reserved_ends: - \bool_if:NT \l_@@_table_auto_round_bool - { \@@_table_print_S_reserved_round_auto: } - \@@_table_print_S_parse: - \bool_if:NF \l_@@_error_bool - { - \bool_if:NT \l_@@_table_math_bool { \c_math_toggle_token } - \@@_table_print_S_reserved_comparator: - \@@_table_print_S_reserved_mantissa: - \@@_table_print_S_reserved_exponent: - \bool_if:NT \l_@@_table_math_bool { \c_math_toggle_token } - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_table_print_S_reserved_init:} -% The creation of a model for the cell to follow. Creation of the finalised -% model is done here so that all of the other options will apply without -% needing complex internal tracking. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_reserved_init: - { - \dim_zero:N \l_@@_table_fill_mid_dim - \dim_zero:N \l_@@_table_fill_post_dim - \prop_set_eq:NN \l_@@_number_in_prop \l_@@_table_model_prop - \@@_number_process_sign: - \@@_number_process_zero_fill: - \@@_number_process_mantissa: - \prop_if_in:NnF \l_@@_number_in_prop { symbolic } - { \@@_number_process_uncertainty: } - \@@_number_format: - \prop_get:NnNT \l_@@_table_model_prop { mantissa-decimal-raw } - \l_@@_tmpa_tl - { - \prop_put:NnV \l_@@_number_out_prop { mantissa-decimal-raw } - \l_@@_tmpa_tl - } - \prop_set_eq:NN \l_@@_table_model_prop \l_@@_number_out_prop - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_table_print_S_reserved_ends:} -% The end material here is boxed up into the space already reserved. -% That means doing two boxing ups: one for the model, and one for the -% real thing. As in the centred case, if the pre-numeral part has no -% width then the tokens are inserted \enquote{as is}. To avoid any issues -% with people forgetting to reserve space for the pre-numeral part, it is -% boxed up first at natural width so that the measurement is accurate. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_reserved_ends: - { - \hbox_set:Nn \l_@@_table_pre_box - { - { - \l_@@_table_collect_pre_tl - \bool_if:NT \l_@@_table_math_bool - { - \scan_stop: - \c_math_toggle_token - } - } - } - \dim_compare:nNnT - { \box_wd:N \l_@@_table_pre_box } = \c_zero_dim - { - \box_clear:N \l_@@_table_pre_box - \l_@@_table_collect_pre_tl - \bool_set_false:N \l_@@_font_set_bool - } - \hbox_set:Nn \l_@@_tmp_box { { \l_@@_table_pre_tl } } - \hbox_set_to_wd:Nnn \l_@@_table_pre_box - { \box_wd:N \l_@@_tmp_box } - { - \tex_hfil:D - \hbox_unpack:N \l_@@_table_pre_box - } - \hbox_set:Nn \l_@@_tmp_box { \l_@@_table_post_tl } - \hbox_set_to_wd:Nnn \l_@@_table_post_box - { \box_wd:N \l_@@_tmp_box } - { - { - \bool_if:NT \l_@@_table_math_bool - { - \c_math_toggle_token - \scan_stop: - } - \l_@@_table_collect_post_tl - } - \tex_hfil:D - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_table_print_S_reserved_round_auto:} -% For auto-rounding, the approach is to find how many decimal digits are -% allowed for, and if there are none to simply set the rounding value to -% zero. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_reserved_round_auto: - { - \prop_get:NnNTF \l_@@_table_model_prop { mantissa-decimal-raw } - \l_@@_tmpa_tl - { \int_set:Nn \l_@@_process_precision_int { \l_@@_tmpa_tl } } - { \int_zero:N \l_@@_process_precision_int } - \tl_set:Nn \l_@@_round_tl { places } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\@@_table_print_S_reserved_comparator:} -% The comparator is quite simple to deal with. Assuming that there is a -% comparator in the model, this is measured for the reserved width. The -% real comparator can then simply be typeset in a box of the same size. -% If there is no comparator in the real case, then the space added to -% that for filling: this is needed so that any pre-note can be aligned -% freely. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_reserved_comparator: - { - \prop_get:NnNTF \l_@@_table_model_prop { comparator } - \l_@@_tmpa_tl - { - \hbox_set:Nn \l_@@_tmp_box - { \@@_print:nV { number } \l_@@_tmpa_tl } - \prop_get:NnNTF \l_@@_number_out_prop { comparator } - \l_@@_tmpa_tl - { - \hbox_set_to_wd:Nnn \l_@@_table_result_box - { \box_wd:N \l_@@_tmp_box } - { \@@_print:nV { number } \l_@@_tmpa_tl } - } - { - \dim_add:Nn \l_@@_table_fill_pre_dim - { \box_wd:N \l_@@_tmp_box } - \cs_set_eq:NN \@@_table_print_S_reserved_store_fill:n - \@@_table_print_S_reserved_store_fill_pre:n - } - } - { - \cs_set_eq:NN \@@_table_print_S_reserved_store_fill:n - \@@_table_print_S_reserved_store_fill_pre:n - \prop_if_in:NnT \l_@@_number_out_prop { comparator } - { - \msg_error:nnx { siunitx } { table-partial-number } - { a~comparator } } } + { } } % \end{macrocode} -% \end{macro} -% -% \begin{macro} -% { -% \@@_table_print_S_reserved_store_fill_pre:n , -% \@@_table_print_S_reserved_store_fill_mid:n -% } -% To allow for the various alignment options, fill is stored in a -% flexible way. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_reserved_store_fill_pre:n - { \dim_add:Nn \l_@@_table_fill_pre_dim } -\cs_new_protected:Npn \@@_table_print_S_reserved_store_fill_mid:n - { \dim_add:Nn \l_@@_table_fill_mid_dim } -% \end{macrocode} -% \end{macro} % -% \begin{macro}{\@@_table_print_S_reserved_mantissa:} -% \begin{macro} -% { -% \@@_table_print_S_reserved_mantissa_parts: , -% \@@_table_print_S_reserved_mantissa_integer: -% } -% The mantissa of a number may contain a sign, an integer part, a -% decimal marker, a decimal part and a non-separated uncertainty. That -% means that there are two ways to deal with the alignment. Each part -% could be done separately, or a correction can be made after setting -% the combined mantissa. Here, the later approach is taken. The first -% step is to deal with the mantissa as a whole: work out show much space -% to reserve, and see if there is anything at all to put in it. The -% complexity only starts if there is a mantissa in the current cell. +% \begin{macro}[EXP]{\@@_angle:n} +% \begin{macro}[EXP]{\@@_angle:w} +% Expandable splitting of the angle: simply enough, also outputs the % \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_reserved_mantissa: +\cs_new:Npn \@@_angle:n #1 + { \@@_angle:w #1 ; ; ; \q_stop } +\cs_new:Npn \@@_angle:w #1 ; #2 ; #3 ; #4 \q_stop { - \prop_get:NnNTF \l_@@_table_model_prop { mantissa } - \l_@@_tmpa_tl - { - \hbox_set:Nn \l_@@_tmp_box - { \@@_print:nV { number } \l_@@_tmpa_tl } - \prop_get:NnNTF \l_@@_number_out_prop { mantissa } - \l_@@_tmpa_tl - { - \dim_set:Nn \l_@@_table_mantissa_dim - { \box_wd:N \l_@@_tmp_box } - \hbox_set:Nn \l_@@_table_mantissa_box - { \@@_print:nV { number } \l_@@_tmpa_tl } - \@@_table_print_S_reserved_mantissa_parts: - } - { - \@@_table_print_S_reserved_store_fill:n - { \box_wd:N \l_@@_tmp_box } - } - } - { - \prop_if_in:NnT \l_@@_number_out_prop { mantissa } - { - \msg_error:nnx { siunitx } { table-partial-number } - { a~mantissa } - } - } - } -% \end{macrocode} -% The aim here is to deal with the mantissa with as few measurements as -% possible. The integer part is therefore measured, with the real and model -% versions compared. This allows appropriate fill to be calculated to -% add the mantissa to the result box, after any comparator and with -% the appropriate width. Once that is done, the amount of filler needed -% \emph{after} the integer can be calculated: this is the size of the -% model mantissa, minus the size of the real mantissa and the amount of -% filler needed in the integer part. That is stored in the intermediate -% dimension for the present, although it may get moved. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_reserved_mantissa_parts: - { - \@@_table_print_S_reserved_mantissa_integer: - \hbox_set:Nn \l_@@_table_result_box - { - \hbox_unpack:N \l_@@_table_result_box - \hbox_to_wd:nn { \l_@@_table_fill_mid_dim } { \tex_hfil:D } - \hbox_unpack:N \l_@@_table_mantissa_box - } - \dim_set:Nn \l_@@_table_fill_mid_dim - { - \l_@@_table_mantissa_dim - - \box_wd:N \l_@@_table_mantissa_box - - \l_@@_table_integer_dim - } - \@@_table_print_S_reserved_mantissa_uncert: - } -% \end{macrocode} -% For the integer part, there is a need to measure both the sign and -% the integer itself in the model and in the real number. If there is -% no integer part in the real number, then fill is stored to add either -% before or after any comparator. If there is an integer part, the -% size is measured and the any fill needed is stored for re-insertion. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_reserved_mantissa_integer: - { - \prop_get:NnNF \l_@@_table_model_prop { mantissa-sign } - \l_@@_tmpa_tl - { \tl_clear:N \l_@@_tmpa_tl } - \prop_get:NnNT \l_@@_table_model_prop { mantissa-integer } - \l_@@_tmpb_tl - { \tl_put_right:No \l_@@_tmpa_tl \l_@@_tmpb_tl } - \@@_table_print_S_measure:NN \l_@@_tmpa_tl - \l_@@_table_integer_dim - \prop_get:NnNF \l_@@_number_out_prop { mantissa-sign } - \l_@@_tmpa_tl - { \tl_clear:N \l_@@_tmpa_tl } - \prop_get:NnNT \l_@@_number_out_prop { mantissa-integer } - \l_@@_tmpb_tl - { \tl_put_right:No \l_@@_tmpa_tl \l_@@_tmpb_tl } - \tl_if_empty:NF \l_@@_tmpa_tl - { - \@@_table_print_S_measure:NN \l_@@_tmpa_tl - \l_@@_tmp_dim - \dim_sub:Nn \l_@@_table_integer_dim { \l_@@_tmp_dim } - } - \@@_table_print_S_reserved_store_fill:n - { \l_@@_table_integer_dim } - } -% \end{macrocode} -% Here, a separated uncertainty is handled. If there is one, then there must -% be a \cs{pm} part to add. Once the space calculation is done, a flexible -% auxiliary does the spacing and pasting up. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_reserved_mantissa_uncert: - { - \prop_get:NnNT \l_@@_table_model_prop { mantissa-uncertainty } - \l_@@_tmpa_tl - { - \@@_number_format_join_uncert_pm:N \l_@@_tmpa_tl - \hbox_set:Nn \l_@@_tmp_box - { \@@_print:nV { number } \l_@@_tmpa_tl } - \prop_get:NnNTF \l_@@_number_out_prop { mantissa-uncertainty } - \l_@@_tmpa_tl - { - \dim_set:Nn \l_@@_table_uncert_dim - { \box_wd:N \l_@@_tmp_box } - \@@_number_format_join_uncert_pm:N \l_@@_tmpa_tl - \hbox_set:Nn \l_@@_tmp_box - { \@@_print:nV { number } \l_@@_tmpa_tl } - \bool_if:NTF \l_@@_table_align_uncert_bool - { \@@_table_print_S_reserved_mantissa_uncert_aligned: } - { \@@_table_print_S_reserved_mantissa_uncert_not_aligned: } - } - { - \cs_set_eq:NN \@@_table_print_S_reserved_store_fill:n - \@@_table_print_S_reserved_store_fill_mid:n - \@@_table_print_S_reserved_store_fill:n - { \box_wd:N \l_@@_tmp_box } - } - } - } -% \end{macrocode} -% Two auxiliaries, one to place the uncertainty directly next to the rest -% of the mantissa, one to maintain alignment. In both cases, any fill ends -% up in the middle fill store, but in the alignment case this also removes -% any previous fill. The temporary box here contains the uncertainty part. -% \begin{macrocode} -\cs_new_protected:Npn - \@@_table_print_S_reserved_mantissa_uncert_aligned: - { - \hbox_set:Nn \l_@@_table_result_box - { - \hbox_unpack:N \l_@@_table_result_box - \hbox_to_wd:nn { \l_@@_table_fill_mid_dim } { \tex_hfil:D } - \hbox_unpack:N \l_@@_tmp_box - } - \dim_set:Nn \l_@@_table_fill_mid_dim - { \l_@@_table_uncert_dim - \box_wd:N \l_@@_tmp_box } - } -\cs_new_protected:Npn - \@@_table_print_S_reserved_mantissa_uncert_not_aligned: - { - \hbox_set:Nn \l_@@_table_result_box + \tl_if_blank:nF {#1} + { #1 \degree } + \tl_if_blank:nF {#2} { - \hbox_unpack:N \l_@@_table_result_box - \hbox_unpack:N \l_@@_tmp_box + \tl_if_blank:nF {#1} { \c_space_tl } + #2 \arcminute } - \dim_add:Nn \l_@@_table_fill_mid_dim + \tl_if_blank:nF {#3} { - \l_@@_table_uncert_dim - - \box_wd:N \l_@@_tmp_box + \tl_if_blank:nF {#1#2} { \c_space_tl } + #3 \arcsecond } } % \end{macrocode} % \end{macro} % \end{macro} % -% \begin{macro}{\@@_table_print_S_reserved_exponent:} -% \begin{macro} -% { -% \@@_table_print_S_reserved_exponent_product: , -% \@@_table_print_S_reserved_exponent_product_correction: , -% \@@_table_print_S_reserved_exponent_aligned: , -% \@@_table_print_S_reserved_exponent_not_aligned: -% } -% Printing the exponent needs to deal with the exponent product. This -% is easiest to do by simply re-checking for a mantissa. If there is no -% exponent, then any space which needs to be added must be moved from -% the mid space to the post space at this stage. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_reserved_exponent: - { - \prop_get:NnNTF \l_@@_table_model_prop { exponent-result } - \l_@@_tmpa_tl - { - \prop_if_in:NnT \l_@@_table_model_prop { mantissa } - { \@@_table_print_S_reserved_exponent_product: } - \hbox_set:Nn \l_@@_tmp_box - { \@@_print:nV { number } \l_@@_tmpa_tl } - \prop_get:NnNTF \l_@@_number_out_prop { exponent-result } - \l_@@_tmpa_tl - { - \dim_set:Nn \l_@@_table_exponent_dim - { \box_wd:N \l_@@_tmp_box } - \tl_if_empty:NT \l_@@_output_exponent_tl - { - \prop_if_in:NnTF \l_@@_number_out_prop { mantissa } - { \@@_table_print_S_reserved_exponent_product: } - { \@@_table_print_S_reserved_exponent_product_correction: } - } - \hbox_set:Nn \l_@@_tmp_box - { \@@_print:nV { number } \l_@@_tmpa_tl } - \bool_if:NTF \l_@@_table_align_exponent_bool - { \@@_table_print_S_reserved_exponent_aligned: } - { \@@_table_print_S_reserved_exponent_not_aligned: } - } - { - \dim_set:Nn \l_@@_table_fill_post_dim - { \l_@@_table_fill_mid_dim + \box_wd:N \l_@@_tmp_box } - } - } - { - \prop_if_in:NnT \l_@@_number_out_prop { exponent-result } - { - \msg_error:nnx { siunitx } { table-partial-number } - { an~exponent } - } - \dim_set_eq:NN \l_@@_table_fill_post_dim - \l_@@_table_fill_mid_dim - } - } -% \end{macrocode} -% A short sub-function to deal with the appearance of the exponent product -% for both the real number and the model. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_reserved_exponent_product: - { - \tl_set_eq:NN \l_@@_tmpb_tl \l_@@_exponent_product_tl - \bool_if:NT \l_@@_tight_bool - { - \tl_set:Nx \l_@@_tmpb_tl - { \exp_not:N \mathord \exp_not:o \l_@@_tmpb_tl } - } - \tl_set:Nx \l_@@_tmpa_tl - { - \exp_not:N \ensuremath { { } \exp_not:o \l_@@_tmpb_tl { } } - \exp_not:o \l_@@_tmpa_tl - } - } -% \end{macrocode} -% If there is no mantissa, then some additional space is needed for the -% location where the product symbol would have been. +% \begin{macro}[EXP] +% {\@@_list_use:nnnnn, \@@_list_use:nnVVV, \@@_list_use_aux:nnnnn} +% \begin{macro}[EXP]{\@@_list_use_auxi:w} +% \begin{macro}[EXP]{\@@_list_use_auxii:nnw, \@@_list_use_auxiii:nnw} +% \begin{macro}[EXP]{\@@_list_count:n} +% \begin{macro}[EXP]{\@@_list_count:w} +% Copies of the ideas in the \pkg{l3clist} module but using |;| as a list +% separator. The functions have to be extended to allow for a unit argument. % \begin{macrocode} -\cs_new_protected:Npn - \@@_table_print_S_reserved_exponent_product_correction: +\cs_new:Npn \@@_list_use:nnnnn #1#2#3#4#5 { - \group_begin: - \tl_clear:N \l_@@_tmpa_tl - \@@_table_print_S_reserved_exponent_product: - \tl_set:Nx \l_@@_tmpa_tl - { { } \exp_not:o \l_@@_tmpa_tl { } } - \@@_table_print_S_measure:NN \l_@@_tmpa_tl \l_@@_tmp_dim - \exp_args:NNNo \group_end: - \dim_set:Nn \l_@@_tmp_dim { \dim_use:N \l_@@_tmp_dim } - \@@_table_print_S_reserved_store_fill:n { \l_@@_tmp_dim } - \dim_sub:Nn \l_@@_table_exponent_dim { \l_@@_tmp_dim } + \tl_if_blank:nTF {#2} + { \@@_list_use_aux:nnnnn {#1} { } } + { \@@_list_use_aux:nnnnn {#1} { ~ #2 } } + {#3} {#4} {#5} } -% \end{macrocode} -% There are two cases for adding the exponent to the result box, one -% with additional space to maintain alignment, and one with no space. -% The space needed after the exponent then can be set to either include -% or exclude the mid fill space. Doing that here avoids one extra assignment -% (to clear the mid fill in the aligned case). -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_reserved_exponent_aligned: +\cs_generate_variant:Nn \@@_list_use:nnnnn { nnVVV } +\cs_new:Npn \@@_list_use_aux:nnnnn #1#2#3#4#5 { - \hbox_set:Nn \l_@@_table_result_box + \int_case:nnF { \@@_list_count:n {#1} } { - \hbox_unpack:N \l_@@_table_result_box - \hbox_to_wd:nn { \l_@@_table_fill_mid_dim } { \tex_hfil:D } - \hbox_unpack:N \l_@@_tmp_box + { 0 } { } + { 1 } { \@@_list_use_auxi:nw {#2} #1 ; ; { } } + { 2 } { \@@_list_use_auxi:nw {#2} #1 ; {#3} } } - \dim_set:Nn \l_@@_table_fill_post_dim { - \l_@@_table_exponent_dim - - \box_wd:N \l_@@_tmp_box + \@@_list_use_auxii:nnw {#2} { } #1 ; + \q_mark ; { \@@_list_use_auxii:nnw {#2} {#4} } + \q_mark ; { \@@_list_use_auxiii:nnw {#2} {#5} } + \q_stop { } } } -\cs_new_protected:Npn - \@@_table_print_S_reserved_exponent_not_aligned: +\cs_new:Npn \@@_list_use_auxi:nw #1#2 ; #3 ; #4 + { #2 #1 #4 #3 \tl_if_blank:nF {#3} {#1} } +\cs_new:Npn \@@_list_use_auxii:nnw + #1#2#3 ; #4 ; #5 ; #6 \q_mark ; #7#8 \q_stop #9 + { #7 {#4} ; {#5} ; #6 \q_mark ; {#7} #8 \q_stop { #9 #2 #3 #1 } } +\cs_new:Npn \@@_list_use_auxiii:nnw #1#2#3 ; #4 \q_stop #5 + { #5 #2 #3 #1 } +\cs_new:Npx \@@_list_count:n #1 { - \hbox_set:Nn \l_@@_table_result_box - { - \hbox_unpack:N \l_@@_table_result_box - \hbox_unpack:N \l_@@_tmp_box - } - \dim_set:Nn \l_@@_table_fill_post_dim + \exp_not:N \int_eval:n { - \l_@@_table_fill_mid_dim - + \l_@@_table_exponent_dim - - \box_wd:N \l_@@_tmp_box + 0 + \exp_not:N \@@_list_count:w \c_space_tl + #1 \exp_not:n { ; \q_recursion_tail ; \q_recursion_stop } } } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \subsection{Direct printing in \texttt{S} columns} -% -% When number parsing is turned off the usual approach to printing -% tabular material is not suitable. Instead, the strategy used by -% \pkg{dcolumn} can be applied, which requires the decimal marker to -% be made active in math mode. -% -% \begin{macro}{\@@_table_print_S_direct:} -% \begin{macro}{\@@_table_print_S_direct_text:n} -% Test to see if the very first item -% in the cell is a |{|. If it is, then we use the same approach as for -% parsed columns and set the material as text. Otherwise, switch to math -% mode and hand off to the main routine. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_direct: - { - \peek_catcode_ignore_spaces:NTF \c_group_begin_token - { \@@_table_print_S_direct_text:n } - { \@@_table_print_S_direct_main: } - } -\cs_new_protected:Npn \@@_table_print_S_direct_text:n #1 +\cs_new:Npx \@@_list_count:w #1 ; { - \@@_table_column_begin:n { \l_@@_table_text_align_skip } - #1 - \@@_table_column_end:n { \l_@@_table_text_align_skip } + \exp_not:n { \exp_args:Nf \quark_if_recursion_tail_stop:n } {#1} + \exp_not:N \tl_if_blank:nF {#1} { + 1 } + \exp_not:N \@@_list_count:w \c_space_tl } % \end{macrocode} % \end{macro} % \end{macro} -% -% \begin{macro} -% { -% \@@_table_print_S_direct_centered: , -% @@_table_print_S_direct_centered_begin:, -% \@@_table_print_S_direct_centered_end: -% } -% \begin{macro}{\@@_table_print_S_direct_centered_aux:N} -% When centring the content about a decimal marker, the trick is -% to collect everything into two boxes and then compare the sizes. -% In that sense this is very similar to the normal method, except that -% it will work with non-numerical input. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_direct_centered: - { - \cs_set_eq:NN \@@_table_print: - \@@_table_print_S_direct_centered_end: - \hbox_set:Nn \l_@@_tmp_box - { \ensuremath { \l_@@_output_decimal_tl } } - \hbox_set_to_wd:Nnn \l_@@_table_post_box - { \box_wd:N \l_@@_tmp_box } - { \tex_hfil:D } - \hbox_set:Nw \l_@@_table_pre_box - \c_math_toggle_token - \tl_map_function:NN \l_@@_input_decimal_tl - \@@_table_print_S_direct_centered_aux:N - } -\cs_new_protected:Npn \@@_table_print_S_direct_centered_aux:N #1 - { - \char_set_active_eq:NN #1 \@@_table_print_S_direct_centered_begin: - \char_set_mathcode:nn { `#1 } { "8000 } - } -\cs_new_protected:Npn \@@_table_print_S_direct_centered_begin: - { - \c_math_toggle_token - \hbox_set_end: - \hbox_set:Nw \l_@@_table_post_box - \c_math_toggle_token - \l_@@_output_decimal_tl - } -\cs_new_protected:Npn \@@_table_print_S_direct_centered_end: - { - \c_math_toggle_token - \hbox_set_end: - \dim_compare:nNnTF - { \box_wd:N \l_@@_table_pre_box } > - { \box_wd:N \l_@@_table_post_box } - { - \hbox_set_to_wd:Nnn \l_@@_table_post_box - { \box_wd:N \l_@@_table_pre_box } - { - \hbox_unpack:N \l_@@_table_post_box - \tex_hfil:D - } - } - { - \hbox_set_to_wd:Nnn \l_@@_table_pre_box - { \box_wd:N \l_@@_table_post_box } - { - \tex_hfil:D - \hbox_unpack:N \l_@@_table_pre_box - } - } - \box_use:N \l_@@_table_pre_box - \box_use:N \l_@@_table_post_box - } -% \end{macrocode} % \end{macro} % \end{macro} -% -% \begin{macro} -% { -% \@@_table_print_S_direct_reserved: , -% \@@_table_print_S_direct_reserved_begin:, -% \@@_table_print_S_direct_reserved_end: -% } -% \begin{macro}{\@@_table_print_S_direct_reserved_aux:N} -% The plan here is to box up the entire number using the information -% available about the size of the two parts. Relatively easy, -% but needs a bit of measuring. The first box here does need to use -% \cs{tex_hill:D} as \texttt{fil} glue will not work. -% \begin{macrocode} -\cs_new_protected:Npn \@@_table_print_S_direct_reserved: - { - \cs_set_eq:NN \@@_table_print: - \@@_table_print_S_direct_reserved_end: - \prop_get:NnNF \l_@@_table_model_prop { mantissa-integer } - \l_@@_tmpa_tl - { \tl_clear:N \l_@@_tmpa_tl } - \hbox_set:Nn \l_@@_tmp_box - { - \ensuremath - { - \prop_get:NnNT \l_@@_table_model_prop { mantissa-sign } - \l_@@_tmpb_tl - { \l_@@_tmpb_tl } - \l_@@_tmpa_tl - } - } - \dim_set:Nn \l_@@_table_integer_dim - { \box_wd:N \l_@@_tmp_box } - \prop_get:NnNF \l_@@_table_model_prop { mantissa-decimal } - \l_@@_tmpa_tl - { \tl_clear:N \l_@@_tmpa_tl } - \hbox_set:Nn \l_@@_tmp_box - { - \ensuremath - { - \l_@@_output_decimal_tl - \l_@@_tmpa_tl - } - } - \hbox_set_to_wd:Nnn \l_@@_table_post_box - { \box_wd:N \l_@@_tmp_box } - { \tex_hfil:D } - \tex_setbox:D \l_@@_table_pre_box \tex_hbox:D to \l_@@_table_integer_dim - \c_group_begin_token - \c_math_toggle_token - \tl_map_function:NN \l_@@_input_decimal_tl - \@@_table_print_S_direct_reserved_aux:N - \tex_hfill:D - } -\cs_new_protected:Npn \@@_table_print_S_direct_reserved_aux:N #1 - { - \char_set_active_eq:NN #1 \@@_table_print_S_direct_reserved_begin: - \char_set_mathcode:nn { `#1 } { "8000 } - } -\cs_new_protected:Npn \@@_table_print_S_direct_reserved_begin: - { - \c_math_toggle_token - \c_group_end_token - \tex_setbox:D \l_@@_table_post_box \tex_hbox:D to \box_wd:N \l_@@_tmp_box - \c_group_begin_token - \c_math_toggle_token - \l_@@_output_decimal_tl - } -\cs_new_protected:Npn \@@_table_print_S_direct_reserved_end: - { - \c_math_toggle_token - \tex_hfil:D - \c_group_end_token - \@@_table_align_left:n { \l_@@_table_number_align_skip } - \box_use:N \l_@@_table_pre_box - \box_use:N \l_@@_table_post_box - \@@_table_align_right:n { \l_@@_table_number_align_skip } - } -% \end{macrocode} % \end{macro} -% \end{macro} -% -% \subsection{Table settings} -% -% To allow for the construction above, the table settings are given here. % % \begin{macrocode} -\keys_set:nn { siunitx } - { - table-align-comparator = true, - table-align-exponent = true, - table-align-text-pre = true, - table-align-text-post = true, - table-align-uncertainty = true, - table-omit-exponent = false, - table-parse-only = false, - table-number-alignment = center-decimal-marker, - table-text-alignment = center, - table-figures-decimal = 2, - table-figures-integer = 3 - } -% \end{macrocode} -% -%\subsection{Symbols} -% -% Not all units use letters alone for their symbol. This raises two -% problems. First, the symbols need to work in math and in text mode. -% Second, the user needs to be able to adjust each symbol. -% -%\begin{macro}{\l_@@_redefine_symbols_bool} -% Only one setting applies here! -% \begin{macrocode} -\keys_define:nn { siunitx } - { redefine-symbols .bool_set:N = \l_@@_redefine_symbols_bool } -\keys_set:nn { siunitx } { redefine-symbols = true } -% \end{macrocode} -%\end{macro} -% -% The redefinition of symbols has to do a number of checks to ensure -% that there are no clashes. -% \begin{macrocode} -\AtBeginDocument - { - \bool_if:NT \l_@@_redefine_symbols_bool - { - \@ifpackageloaded { fourier } - { - \@@_option_unchanged:Nnn \l_@@_ohm_text_tl - { \textohm } - { \text { \ensuremath { \l_@@_ohm_math_tl } } } - } - { } - \@ifpackageloaded { mathptmx } - { - \@@_option_unchanged:Nnn \l_@@_ohm_text_tl - { \textohm } - { \text { \ensuremath { \l_@@_ohm_math_tl } } } - } - { } - \str_if_eq:VnT \encodingdefault { OT1 } - { - \@@_option_unchanged:Nnn \l_@@_angstrom_math_tl - { \text { \AA } } - { \text { \capitalring { A } } } - \@@_option_unchanged:Nnn \l_@@_angstrom_text_tl - { \AA } - { \capitalring { A } } - } - \@ifpackageloaded { unicode-math } - { - \exp_args:NNnx - \@@_option_unchanged:Nnn \l_@@_ohm_math_tl - { \text { \ensuremath { \Omega } } } - { \char_generate:nn { "03A9 } { 12 } } - } - { } - \@ifpackageloaded { upgreek } - { - \@@_option_unchanged:Nnn \l_@@_ohm_math_tl - { \text { \ensuremath { \Omega } } } - { \text { \ensuremath { \Upomega } } } - } - { - \cs_if_exist:NT \upOmega - { - \@@_option_unchanged:Nnn \l_@@_ohm_math_tl - { \text { \ensuremath { \Omega } } } - { \text { \ensuremath { \upOmega } } } - } - } - } - } -% \end{macrocode} -% -%\begin{macro}{\l_@@_angstrom_math_tl} -%\begin{macro}{\l_@@_arcminute_math_tl} -%\begin{macro}{\l_@@_arcsecond_math_tl} -%\begin{macro}{\l_@@_celsius_math_tl} -%\begin{macro}{\l_@@_degree_math_tl} -%\begin{macro}{\l_@@_micro_math_tl} -%\begin{macro}{\l_@@_ohm_math_tl} -% The symbol storage macros are created separately for math and text -% mode, although this is all pretty similar. The default definitions use -% what is generally available, except for those for micro, where -% Computer Modern does not have the appropriate symbol at all. For the -% math mode omega option, the "\text{\ensuremath{...}}" construction -% deals with the case where \cs{mathnormal} has the wrong symbol. -% \begin{macrocode} -\keys_define:nn { siunitx } { - math-angstrom .tl_set:N = \l_@@_angstrom_math_tl, - math-arcminute .tl_set:N = \l_@@_arcminute_math_tl, - math-arcsecond .tl_set:N = \l_@@_arcsecond_math_tl, - math-celsius .tl_set:N = \l_@@_celsius_math_tl, - math-degree .tl_set:N = \l_@@_degree_math_tl, - math-micro .tl_set:N = \l_@@_micro_math_tl, - math-ohm .tl_set:N = \l_@@_ohm_math_tl -} -\keys_set:nn { siunitx } { - math-angstrom = \text { \AA }, - math-arcminute = { } ^ { \prime }, - math-arcsecond = { } ^ { \prime \prime }, - math-celsius = \text { \textdegree } \@@_unit_mathrm:n { C } , - math-degree = \text { \textdegree }, - math-micro = \text { \textmu }, - math-ohm = \text { \ensuremath { \Omega } }, -} -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\begin{macro}{\l_@@_angstrom_text_tl} -%\begin{macro}{\l_@@_arcminute_text_tl} -%\begin{macro}{\l_@@_arcsecond_text_tl} -%\begin{macro}{\l_@@_celsius_text_tl} -%\begin{macro}{\l_@@_degree_text_tl} -%\begin{macro}{\l_@@_micro_text_tl} -%\begin{macro}{\l_@@_ohm_text_tl} -% Text versions are similar. -% \begin{macrocode} -\keys_define:nn { siunitx } { - text-angstrom .tl_set:N = \l_@@_angstrom_text_tl, - text-arcminute .tl_set:N = \l_@@_arcminute_text_tl, - text-arcsecond .tl_set:N = \l_@@_arcsecond_text_tl, - text-celsius .tl_set:N = \l_@@_celsius_text_tl, - text-degree .tl_set:N = \l_@@_degree_text_tl, - text-micro .tl_set:N = \l_@@_micro_text_tl, - text-ohm .tl_set:N = \l_@@_ohm_text_tl, -} -\keys_set:nn { siunitx } { - text-angstrom = \AA, - text-arcminute = \ensuremath { { } ^ { \prime } }, - text-arcsecond = \ensuremath { { } ^ { \prime \prime } }, - text-celsius = \text { \textdegree } C, - text-degree = \text { \textdegree }, - text-micro = \textmu , - text-ohm = \textohm -} -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -% -% \begin{macro}{\@@_symbol_new:n} -% For creating the outer symbol macro. -% \begin{macrocode} -\cs_new_protected:Npn \@@_symbol_new:n #1 - { - \cs_set_protected:cpn { SIUnitSymbol #1 } - { - \use:c - { - l__@@_ - \str_foldcase:n {#1} - _ - \mode_if_math:TF { math } { text } - _tl - } - } - } -% \end{macrocode} -% \end{macro} -% -%\begin{macro}{\SIUnitSymbolAngstrom} -%\begin{macro}{\SIUnitSymbolArcminute} -%\begin{macro}{\SIUnitSymbolArcsecond} -%\begin{macro}{\SIUnitSymbolCelsius} -%\begin{macro}{\SIUnitSymbolDegree} -%\begin{macro}{\SIUnitSymbolMicro} -%\begin{macro}{\SIUnitSymbolOhm} -% The wrapper macros are created. -% \begin{macrocode} -\@@_symbol_new:n { Angstrom } -\@@_symbol_new:n { Arcminute } -\@@_symbol_new:n { Arcsecond } -\@@_symbol_new:n { Celsius } -\@@_symbol_new:n { Degree } -\@@_symbol_new:n { Micro } -\@@_symbol_new:n { Ohm } -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -% -%\subsection{Working with other packages} -% -%\begin{macro}{\l_@@_pgf_link_clist} -%\begin{macro}{\@@_pgf_link:} -% Here, the settings used by \pkg{siunitx} are translated into those for -% \pkg{pgf}. Things could be done more efficiently, but the logic would -% be more difficult to follow. -% \begin{macrocode} -\clist_new:N \l_@@_pgf_link_clist -\cs_new_protected:Npn \@@_pgf_link: { - \clist_clear:N \l_@@_pgf_link_clist - \str_if_eq:VnT \l_@@_round_tl { figure } - { - \clist_put_right:Nn \l_@@_pgf_link_clist { fixed } - \clist_put_right:Nn \l_@@_pgf_link_clist - { fixed~zerofill = true } - } - \clist_put_right:Nx \l_@@_pgf_link_clist - { precision = \int_use:N \l_@@_process_precision_int } - \clist_put_right:Nx \l_@@_pgf_link_clist - { - set~decimal~separator = - { { \exp_not:V \l_@@_output_decimal_tl } } - } - \clist_put_right:Nx \l_@@_pgf_link_clist - { set~thousands~separator = { \exp_not:V \l_@@_group_sep_tl } } - \clist_put_right:Nx \l_@@_pgf_link_clist - { - min~exponent~for~1000~sep = \int_eval:n { \l_@@_group_min_int - 1 } - } - \bool_lazy_or:nnF - { \l_@@_group_decimal_bool } { \l_@@_group_integer_bool } - { - \clist_put_right:Nn \l_@@_pgf_link_clist - { min~exponent~for~1000~sep = 999 } - } - \bool_if:NTF \l_@@_process_integer_zero_bool - { - \clist_put_right:Nn \l_@@_pgf_link_clist - { skip~0. = false } - } - { - \clist_put_right:Nn \l_@@_pgf_link_clist - { skip~0. = true } - } - \str_if_eq:VnTF \l_@@_process_sign_tl { + } - { - \clist_put_right:Nn \l_@@_pgf_link_clist - { showpos = true } - } - { - \clist_put_right:Nn \l_@@_pgf_link_clist - { showpos = false } - } - \use:x - { - \exp_not:N \pgfqkeys - { /pgf/number~format } - { \exp_not:V \l_@@_pgf_link_clist } - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\subsection{Messages} -% -% Lots of messages, all of them together in one block to make life -% easier. -% \begin{macrocode} -\msg_new:nnnn { siunitx } { bad-arc-sign } - { Incorrect~use~of~sign~in~degree-minute-second~angle. } - { Only~the~highest~value~part~of~an~angle~can~have~a~sign. } -\msg_new:nnnn { siunitx } { color-not-loaded } - { Package~"color"~not~loaded. } - { The~command~\token_to_str:N \color \ is~not~available. } -\msg_new:nnnn { siunitx } { duplicate-complex-root-token } - { Duplicate~complex~root~token~'#1'~in~input. } - { Only~one~complex~root~token~can~appear~in~a~single~number. } -\msg_new:nnnn { siunitx } { duplicate-decimal-token } - { Duplicate~decimal~marker~token~'#1'~in~input. } - { Only~one~decimal~marker~token~can~appear~in~a~single~number. } -\msg_new:nnnn { siunitx } { duplicate-exponent-token } - { Duplicate~exponent~marker~token~'#1'~in~input. } - { Only~one~exponent~marker~token~can~appear~in~a~single~number. } -\msg_new:nnnn { siunitx } { duplicate-quotient-token } - { Duplicate~quotient~token. } - { Only~one~quotient~token~can~appear~in~a~single~number. } -\msg_new:nnnn { siunitx } { duplicate-sticky-per } - { Duplicate~\token_to_str:N \per. } - { - When~the~'sticky-per'~option~is~active,~only~one - \token_to_str:N \per may~appear~in~a~unit. - } -\msg_new:nnnn { siunitx } { empty-arc } - { Empty~degree-minute-second~angle. } - { The~angle~given~does~not~contain~any~numbers. } -\msg_new:nnnn { siunitx } { empty-uncertainty } - { Empty~uncertainty~given~in~'#1'. } - { The~number~given~contains~an~empty~uncertainty. } -\msg_new:nnnn { siunitx } { ending-product-token } - { Misplaced~product~token. } - { A~number~cannot~end~with~a~product~token. } -\msg_new:nnnn { siunitx } { ending-quotient-token } - { Misplaced~quotient~token. } - { A~number~cannot~end~with~a~quotient~token. } -\msg_new:nnnn { siunitx } { invalid-arc-format } - { Invalid~degree-minute-second angle~'#1'. } - { - Angles~given~in~degree-minute-second~format~should~contain~two~';' - symbols~to~divide~up~the~parts~of~the~input. - } -\msg_new:nnnn { siunitx } { invalid-number } - { Invalid~numerical~input~'#1'. } - { - The~input~given~as~a~number~does~not~make~logical~sense.~ - This~happens,~for~example,~if~a~number~only~contains~a~sign. - } -\msg_new:nnnn { siunitx } { invalid-token-in-exponent } - { Invalid~exponent~in~numerical~input~'#1'. } - { - The~exponent~part~of~a~number~cannot~contain~an~uncertainty~or~ - complex~part: \\ - the~input~given~appears~to~contain~one~of~these~in~the~exponent. - } -\msg_new:nnnn { siunitx } { invalid-token-in-number } - { Invalid~token~'#1'~in~numerical~input. } - { - Numbers~can~only~contain~tokens~defined~using~the~ - 'input-...'~options:\\ - the~token~'#1'~is~not~set~up~as~a~valid~part~of~a~number. - } -\msg_new:nnnn { siunitx } { invalid-token-in-uncertainty } - { Invalid~uncertainty~in~numerical~input~'#1'. } - { - The~uncertainty~part~of~a~number~may~only~contain~digits~or~ - symbols. - } -\msg_new:nnnn { siunitx } { literal-unit } - { Literal~units~disabled. } - { - You~gave~the~literal~input~'#1'~ - but~literal~unit~output~is~disabled. - } -\msg_new:nnnn { siunitx } { misplaced-sign-token } - { Misplaced~sign~token~'#1'. } - { Sign~tokens~can~only~come~at~the~beginning~of~a~number. } -\msg_new:nnnn { siunitx } { misplaced-complex-root-token } - { Misplaced~complex~token~in~numerical~input~'#1'. } - { - The~root~token~must~come~either~before~or~after~the~real~digits~ - of~the~complex~part. - } -\msg_new:nnnn { siunitx } { misplaced-uncertainty-token } - { Misplaced~uncertainty~token~'#1'. } - { - The~uncertainty~in~a~number~must~be~given~between~a~set~of~ - delimiters~as~defined~by~the\\ - \ \ 'input-open-uncertainty'~and~'input-close-uncertainty'~ - options. - } -\msg_new:nnnn { siunitx } { multi-part-range } - { Numerical~range~with~multiple~parts. } - { - The~input~'#1'~is~a~number~which~has~more~than~one~part: \\ - ranges~can~only~contain~one~number~in~each~part. - } -\msg_new:nnn { siunitx } { non-convertible-exponent } - { Exponent~'#1'~cannot~be~converted~into~a~symbolic~prefix. } -\msg_new:nnn { siunitx } { option-not-available } - { Option~'#1'~not~available~in~strict~mode. } -\msg_new:nnn { siunitx } { option-preamble-only } - { Option~'#1'~only~available~in~the~preamble. } -\msg_new:nnnn { siunitx } { prefix-base-mismatch } - { Prefix~bases~do~not~match. } - { - You~have~asked~for~prefixes~to~be~converted~into~a~power,~ - but~the~bases~do~not~match. - } -\msg_new:nnn { siunitx } { prefix-only } - { Prefix~with~no~unit. } -\msg_new:nnnn { siunitx } { qualifier-before-unit } - { Qualifier~before~unit. } - { Unit~qualifiers~have~to~follow~after~units,~not~before~them. } -\msg_new:nnnn { siunitx } { restricted-number } - { Token~'#1'~forbidden~in~restricted~numerical~input. } - { - The~current~input~must~be~a~real~number~and~cannot~contain: \\ - \ -~an~exponent; \\ - \ -~an~uncertainty; \\ - \ -~a~complex~part. - } -\msg_new:nnnn { siunitx } { starting-product-token } - { Misplaced~product~token. } - { A~number~cannot~begin~with~a~product~token. } -\msg_new:nnnn { siunitx } { starting-quotient-token } - { Misplaced~quotient~token. } - { A~number~cannot~begin~with~a~quotient~token. } -\msg_new:nnnn { siunitx } { table-partial-number } - { No~space~reserved~for~#1~\msg_line_context:. } - { - The~number~in~the~current~table~cell~contains~#1~part, - but~you~did~not~reserve~any~space~to~print~it: \\ - it~will~be~missing~in~the~output. - } -\msg_new:nnnn { siunitx } { unknown-option } - { Unknown~option~'#1'. } - { - The~option~file~'#1'~is~not~known~by~siunitx: - perhaps~it~is~spelled~incorrectly. - } -\msg_new:nnnn { siunitx } { version-1-option } - { Version~1~option~'#1'~detected. } - { - Use: \\ - \ \ \token_to_str:N \usepackage [ version-1-compatibility ] - \iow_char:N \{ siunitx \token_to_str:N \iow_char:N \} \\ - in~the~preamble~to~load~the~appropriate~code. - } -% \end{macrocode} -% -%\subsection{Design-level macros} -% -%\begin{macro}{\DeclareBinaryPrefix} -%\begin{macro}{\DeclareSIPostPower} -%\begin{macro}{\DeclareSIPrefix} -%\begin{macro}{\DeclareSIPrePower} -%\begin{macro}{\DeclareSIQualifier} -%\begin{macro}{\DeclareSIUnit} -%\begin{macro}{\DeclareSIUnitWithOptions} -% The macros for creating units and so on are in design name space. -% Basically, a set of shuffles for arguments. -% \begin{macrocode} -\NewDocumentCommand \DeclareBinaryPrefix { m m m } { - \@@_declare_prefix:Nnnn #1 {#2} { 2 } {#3} -} -\NewDocumentCommand \DeclareSIPostPower { m m } { - \@@_declare_power_after:Nn #1 {#2} -} -\NewDocumentCommand \DeclareSIPrefix { m m m } { - \@@_declare_prefix:Nnnn #1 {#2} { 10 } {#3} -} -\NewDocumentCommand \DeclareSIPrePower { m m } { - \@@_declare_power_before:Nn #1 {#2} -} -\NewDocumentCommand \DeclareSIQualifier { m m } { - \@@_declare_qualifier:Nn #1 {#2} -} -\NewDocumentCommand \DeclareSIUnit { O { } m m } { - \@@_declare_unit:Nnn #2 {#3} {#1} -} -\NewDocumentCommand \DeclareSIUnitWithOptions { m m m } { - \@@_declare_unit:Nnn #1 {#2} {#3} -} -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -% -% None of this should be done after the preamble. -% \begin{macrocode} -\@onlypreamble \DeclareBinaryPrefix -\@onlypreamble \DeclareSIPostPower -\@onlypreamble \DeclareSIPrefix -\@onlypreamble \DeclareSIPrePower -\@onlypreamble \DeclareSIQualifier -\@onlypreamble \DeclareSIUnit -\@onlypreamble \DeclareSIUnitWithOptions -% \end{macrocode} -% -%\begin{macro}{\SendSettingsToPgf} -% A settings transfer function. -% \begin{macrocode} -\cs_new_protected:Npn \SendSettingsToPgf { \@@_pgf_link: } -% \end{macrocode} -%\end{macro} -% -%\subsection{Document macros} -% -% The user document macros are all collected together here for ease. -% -%\begin{macro}{\ang} -% The \cs{ang} function does very little beyond setting the local -% keys and passing on the input. -% \begin{macrocode} -\NewDocumentCommand \ang { o > { \SplitArgument { 2 } { ; } } m } { - \group_begin: - \IfNoValueF {#1} - { \keys_set:nn { siunitx } {#1} } - \@@_angle_output:nnn #2 - \group_end: -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\num} -% The \cs{num} macro is quite simple: read the number, check it is -% correct then print it. -% \begin{macrocode} -\NewDocumentCommand \num { o m } { - \leavevmode - \group_begin: - \bool_set_false:N \l_@@_font_set_bool - \IfNoValueF {#1} - { \keys_set:nn { siunitx } {#1} } - \@@_number_output:n {#2} - \group_end: -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\numlist} -% Lists of numbers are trivially easy to work with. -% \begin{macrocode} -\NewDocumentCommand \numlist { o > { \SplitList { ; } } m } { - \leavevmode - \group_begin: - \bool_set_false:N \l_@@_font_set_bool - \IfNoValueF {#1} - { \keys_set:nn { siunitx } {#1} } - \@@_list_numbers:n {#2} - \group_end: -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\numrange} -% A very simple approach is taken here: this is not intended for -% anything complicated. -% \begin{macrocode} -\NewDocumentCommand \numrange { o m m } { - \leavevmode - \group_begin: - \bool_set_false:N \l_@@_font_set_bool - \IfNoValueF {#1} - { \keys_set:nn { siunitx } {#1} } - \@@_range_numbers:nn {#2} {#3} - \group_end: -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \SIlist , -% \SIrange -%} -% Lists and range of values are handled in a very similar way. -% Everything is kept relatively simple, and so there is not too much -% complexity. In theory the two could be combined together, but -% the differences between the two make this less desirable. -% \begin{macrocode} -\NewDocumentCommand \SIlist { o > { \SplitList { ; } } m m } { - \leavevmode - \group_begin: - \bool_set_false:N \l_@@_font_set_bool - \IfNoValueTF {#1} - { \@@_list_units:nnn {#2} {#3} { } } - { - \keys_set:nn { siunitx } {#1} - \@@_list_units:nnn {#2} {#3} {#1} - } - \group_end: -} -\NewDocumentCommand \SIrange { o m m m } { - \leavevmode - \group_begin: - \bool_set_false:N \l_@@_font_set_bool - \IfNoValueTF {#1} - { \@@_range_unit:nnnn {#4} { } {#2} {#3} } - { - \keys_set:nn { siunitx } {#1} - \@@_range_unit:nnnn {#4} {#1} {#2} {#3} - } - \group_end: -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\SI} -% The main \cs{SI} function follows the same pattern as the previous -% ones. -% \begin{macrocode} -\NewDocumentCommand \SI { o m o m } { - \leavevmode - \group_begin: - \bool_set_false:N \l_@@_font_set_bool - \IfNoValueTF {#1} - { \@@_combined:nnnn { } {#2} {#3} {#4} } - { - \keys_set:nn { siunitx } {#1} - \@@_combined:nnnn {#1} {#2} {#3} {#4} - } - \group_end: -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\sisetup} -% The set up macro simply moves to the correct path and executes -% whatever has been passed. -% \begin{macrocode} -\NewDocumentCommand \sisetup { m } { - \keys_set:nn { siunitx } {#1} -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\tablenum} -% A variation on the \cs{num} macro that will retain alignment within -% \cs{multicolumn} and \cs{multirow} situations. The slightly odd code -% for the non-parsed case is needed to reinsert the appropriate tokens -% after \enquote{collection}. -% \begin{macrocode} -\NewDocumentCommand \tablenum { o m } { - \leavevmode - \group_begin: - \bool_set_false:N \l_@@_font_set_bool - \IfNoValueF {#1} - { \keys_set:nn { siunitx } {#1} } - \bool_if:NTF \l_@@_number_parse_bool - { - \tl_set:Nn \l_@@_table_collect_tl {#2} - \bool_set_false:N \l_@@_table_collect_pre_bool - \@@_table_print_S: - } - { \@@_table_print_S_direct: #2 \@@_table_print: } - \group_end: -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\si} -% The \cs{si} macro needs to pass options through to the internal -% function as well as setting them here. This is used so that options -% set for a unit can be overridden on a one-off basis. -% \begin{macrocode} -\NewDocumentCommand \si { o m } { - \leavevmode - \group_begin: - \bool_set_false:N \l_@@_font_set_bool - \IfNoValueTF {#1} - { \@@_unit_output:nn {#2} { } } - { - \keys_set:nn { siunitx } {#1} - \@@_unit_output:nn {#2} {#1} - } - \group_end: -} -% \end{macrocode} -%\end{macro} -% -%\subsection{Precautions for section headings} -% -% There are two issues to be handled for section headings, \emph{etc}. -% First, within the \cs{addcontentline} macro the various unit functions -% need to be \cs{protected}. Secondly, there is a need to worry about -% \pkg{hyperref}, and ensure that everything works cleanly and with -% no unnecessary warnings. -% -% \begin{macro}{\@@_contents_bookmarks:} -% The idea here is two-fold. First, all of the unit macros are set -% up to simply print their literal interpretation: this is hopefully -% good enough for most bookmark situations. Secondly, the document -% commands are made expandable. This allows a bit of re-arrangement -% of the input, removes any set up options (which are being ignored) -% and stops \pkg{hyperref} issuing a warning. -% \begin{macrocode} -\cs_new_protected:Npn \@@_contents_bookmarks: - { - \seq_map_inline:Nn \l_siunitx_unit_symbolic_seq - { \@@_unit_print_literal_aux:N ##1 } - \cs_if_exist:NT \FB@fg - { \cs_set_eq:NN \fg \FB@fg } - \msg_redirect_name:nnn { xparse } { redefine-command } { none } - \cs_set_eq:NN \num \numInBookmark - \cs_set_eq:NN \numrange \numrangeInBookmark - \cs_set_eq:NN \si \siInBookmark - \cs_set_eq:NN \SI \SIInBookmark - \cs_set_eq:NN \SIrange \SIrangeInBookmark - \cs_set_eq:NN \si \siInBookmark - \cs_set_eq:NN \highlight \use_ii:nn - \cs_set_eq:NN \@@_textsuperscript:n \use:n - \cs_set:Npn \SIUnitSymbolAngstrom { \AA } - \cs_set:Npn \SIUnitSymbolArcminute { ' } - \cs_set:Npn \SIUnitSymbolArcsecond { '' } - \cs_set:Npn \SIUnitSymbolCelsius { \textcelsius } - \cs_set:Npn \SIUnitSymbolDegree { \textdegree } - \cs_set:Npn \SIUnitSymbolMicro { \textmu } - \cs_set:Npn \SIUnitSymbolOhm { \textohm } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro} -% { -% \numInBookmark , -% \numrangeInBookmark , -% \SIlistInBookmark , -% \SIrangeInBookmark , -% \SIInBookmark , -% \siInBookmark -% } -% To keep things fast, expandable versions of the document commands -% are created only once. These are then used if necessary to remove -% and re-order arguments in an expandable fashion. -% \begin{macrocode} -\DeclareExpandableDocumentCommand \numInBookmark { o m } {#2} -\DeclareExpandableDocumentCommand \numrangeInBookmark { o m m } - { #2 \l_@@_range_phrase_tl #3 } -\DeclareExpandableDocumentCommand \SIInBookmark { o m o m } - { \IfNoValueF {#3} {#3} #2 ~ #4 } -\DeclareExpandableDocumentCommand \SIlistInBookmark - { o m m } { \@@_bookmark_SIlist_map:nn {#1} {#2} } -\DeclareExpandableDocumentCommand \SIrangeInBookmark - { o m m m } { #2 ~ #4 \l_@@_range_phrase_tl #3 ~ #4 } -\DeclareExpandableDocumentCommand \siInBookmark { o m } {#2} -% \end{macrocode} -% \end{macro} -% -%\begin{macro}{\@@_bookmark_SIlist_map:nn} -%\begin{macro}{\@@_bookmark_SIlist_map_aux:nw} -% An expandable mapping to replace the list separator in the -% input by appropriate output version. -% \begin{macrocode} -\cs_new:Npn \@@_bookmark_SIlist_map:nn #1#2 { - \@@_bookmark_SIlist_map_aux:nw {#2} #1 ; \q_recursion_tail ; - \q_recursion_tail ; \q_recursion_stop -} -\cs_new:Npn \@@_bookmark_SIlist_map_aux:nw #1#2 ; #3 ; #4 { - #2 ~ #1 - \quark_if_recursion_tail_stop:n {#3} - \quark_if_recursion_tail_stop_do:nn {#4} - { - \l_@@_list_separator_final_tl - #3 ~ #1 - } - \l_@@_list_separator_tl - \@@_bookmark_SIlist_map_aux:nw {#1} #3 ; #4 -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -% A short check to get things working. -% \begin{macrocode} -\AtBeginDocument { - \@ifpackageloaded { hyperref } - { \pdfstringdefDisableCommands { \@@_contents_bookmarks: } } - { } -} -% \end{macrocode} -% -%\subsection{Physical units} -% -%\begin{macro}{\kilogram} -%\begin{macro}{\metre} -%\begin{macro}{\meter} -%\begin{macro}{\mole} -%\begin{macro}{\kelvin} -%\begin{macro}{\candela} -%\begin{macro}{\second} -%\begin{macro}{\ampere} -% The basic SI units are always defined, including both variants for -% metre. -% \begin{macrocode} -\DeclareSIUnit \kilogram { \kilo \gram } -\DeclareSIUnit \metre { m } -\DeclareSIUnit \meter { \metre } -\DeclareSIUnit \mole { mol } -\DeclareSIUnit \second { s } -\DeclareSIUnit \ampere { A } -\DeclareSIUnit \kelvin { K } -\DeclareSIUnit \candela { cd } -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\gram} -% The gram is an odd unit as it is needed for the base unit kilogram. -% \begin{macrocode} -\DeclareSIUnit \gram { g } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\yocto} -%\begin{macro}{\zepto} -%\begin{macro}{\atto} -%\begin{macro}{\femto} -%\begin{macro}{\pico} -%\begin{macro}{\nano} -%\begin{macro}{\micro} -%\begin{macro}{\milli} -%\begin{macro}{\centi} -%\begin{macro}{\deci} -% The various SI multiple prefixes are defined here: first the small -% ones. -% \begin{macrocode} -\DeclareSIPrefix \yocto { y } { -24 } -\DeclareSIPrefix \zepto { z } { -21 } -\DeclareSIPrefix \atto { a } { -18 } -\DeclareSIPrefix \femto { f } { -15 } -\DeclareSIPrefix \pico { p } { -12 } -\DeclareSIPrefix \nano { n } { -9 } -\DeclareSIPrefix \micro { \SIUnitSymbolMicro } { -6 } -\DeclareSIPrefix \milli { m } { -3 } -\DeclareSIPrefix \centi { c } { -2 } -\DeclareSIPrefix \deci { d } { -1 } -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\begin{macro}{\deca} -%\begin{macro}{\deka} -%\begin{macro}{\hecto} -%\begin{macro}{\kilo} -%\begin{macro}{\mega} -%\begin{macro}{\giga} -%\begin{macro}{\tera} -%\begin{macro}{\peta} -%\begin{macro}{\exa} -%\begin{macro}{\zetta} -%\begin{macro}{\yotta} -% Now the large ones. -% \begin{macrocode} -\DeclareSIPrefix \deca { da } { 1 } -\DeclareSIPrefix \deka { da } { 1 } -\DeclareSIPrefix \hecto { h } { 2 } -\DeclareSIPrefix \kilo { k } { 3 } -\DeclareSIPrefix \mega { M } { 6 } -\DeclareSIPrefix \giga { G } { 9 } -\DeclareSIPrefix \tera { T } { 12 } -\DeclareSIPrefix \peta { P } { 15 } -\DeclareSIPrefix \exa { E } { 18 } -\DeclareSIPrefix \zetta { Z } { 21 } -\DeclareSIPrefix \yotta { Y } { 24 } -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\becquerel} -%\begin{macro}{\celsius} -%\begin{macro}{\degreeCelsius} -%\begin{macro}{\coulomb} -%\begin{macro}{\farad} -%\begin{macro}{\gray} -%\begin{macro}{\hertz} -%\begin{macro}{\henry} -%\begin{macro}{\joule} -%\begin{macro}{\katal} -%\begin{macro}{\lumen} -%\begin{macro}{\lux} -% A number of derived units with defined names and symbols. -% \begin{macrocode} -\DeclareSIUnit \becquerel { Bq } -\DeclareSIUnit \celsius { \SIUnitSymbolCelsius } -\DeclareSIUnit \degreeCelsius { \SIUnitSymbolCelsius } -\DeclareSIUnit \coulomb { C } -\DeclareSIUnit \farad { F } -\DeclareSIUnit \gray { Gy } -\DeclareSIUnit \hertz { Hz } -\DeclareSIUnit \henry { H } -\DeclareSIUnit \joule { J } -\DeclareSIUnit \katal { kat } -\DeclareSIUnit \lumen { lm } -\DeclareSIUnit \lux { lx } -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\begin{macro}{\newton} -%\begin{macro}{\ohm} -%\begin{macro}{\pascal} -%\begin{macro}{\radian} -%\begin{macro}{\siemens} -%\begin{macro}{\sievert} -%\begin{macro}{\steradian} -%\begin{macro}{\tesla} -%\begin{macro}{\volt} -%\begin{macro}{\watt} -%\begin{macro}{\weber} -% More units. -% \begin{macrocode} -\DeclareSIUnit \newton { N } -\DeclareSIUnit \ohm { \SIUnitSymbolOhm } -\DeclareSIUnit \pascal { Pa } -\DeclareSIUnit \radian { rad } -\DeclareSIUnit \siemens { S } -\DeclareSIUnit \sievert { Sv } -\DeclareSIUnit \steradian { sr } -\DeclareSIUnit \tesla { T } -\DeclareSIUnit \volt { V } -\DeclareSIUnit \watt { W } -\DeclareSIUnit \weber { Wb } -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\arcminute} -%\begin{macro}{\arcsecond} -%\begin{macro}{\day} -%\begin{macro}{\degree} -%\begin{macro}{\hectare} -%\begin{macro}{\hour} -%\begin{macro}{\litre} -%\begin{macro}{\liter} -%\begin{macro}{\minute} -%\begin{macro}{\percent} -%\begin{macro}{\tonne} -% Non-SI, but accepted for general use. -% \begin{macrocode} -\DeclareSIUnit [ number-unit-product = ] \arcmin { \arcminute } -\DeclareSIUnit [ number-unit-product = ] - \arcminute { \SIUnitSymbolArcminute } -\DeclareSIUnit [ number-unit-product = ] - \arcsecond { \SIUnitSymbolArcsecond } -\DeclareSIUnit \day { d } -\DeclareSIUnit[ number-unit-product = ] \degree { \SIUnitSymbolDegree } -\DeclareSIUnit \hectare { ha } -\DeclareSIUnit \hour { h } -\DeclareSIUnit \litre { l } -\DeclareSIUnit \liter { L } -\DeclareSIUnit \minute { min } -\DeclareSIUnit \percent { \char 37 } -\DeclareSIUnit \tonne { t } -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\astronomicalunit} -%\begin{macro}{\atomicmassunit} -%\begin{macro}{\electronvolt} -%\begin{macro}{\dalton} -% A few units based on physical measurements exist. -% \begin{macrocode} -\DeclareSIUnit \astronomicalunit { au } -\DeclareSIUnit \atomicmassunit { u } -\DeclareSIUnit \electronvolt { eV } -\DeclareSIUnit \dalton { Da } -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\begin{macro}{\clight} -%\begin{macro}{\electronmass} -%\begin{macro}{\planckbar} -% A set of \enquote{natural units}. -% \begin{macrocode} -\group_begin: -\cs_set_eq:NN \endgroup \group_end: -\char_set_catcode_math_subscript:N \_ -\use:n - { - \endgroup - \DeclareSIUnit \clight { \text { \ensuremath { c _ { 0 } } } } - \DeclareSIUnit \electronmass - { \text { \ensuremath { m _ { \textup { e } } } } } - } -\DeclareSIUnit \planckbar { \text { \ensuremath { \hbar } } } -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -%\begin{macro}{\elementarycharge} -%\begin{macro}{\bohr} -%\begin{macro}{\hartree} -% A set of \enquote{atomic units}. -% \begin{macrocode} -\DeclareSIUnit \elementarycharge { \text { \ensuremath { e } } } -\group_begin: -\cs_set_eq:NN \endgroup \group_end: -\char_set_catcode_math_subscript:N \_ -\use:n - { - \endgroup - \DeclareSIUnit \bohr { \text { \ensuremath { a _ { 0 } } } } - \DeclareSIUnit \hartree - { \text { \ensuremath { E _ { \textup { h } } } } } - } -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\angstrom} -%\begin{macro}{\bar} -%\begin{macro}{\barn} -%\begin{macro}{\bel} -%\begin{macro}{\decibel} -%\begin{macro}{\knot} -%\begin{macro}{\mmHg} -%\begin{macro}{\nauticalmile} -%\begin{macro}{\neper} -% There are then some day-to-day units which are accepted for use -% with SI, but are not part of the official specification. -% \begin{macrocode} -\DeclareSIUnit \angstrom { \SIUnitSymbolAngstrom } -\DeclareSIUnit \bar { bar } -\DeclareSIUnit \barn { b } -\DeclareSIUnit \bel { B } -\DeclareSIUnit \decibel { \deci \bel } -\DeclareSIUnit \knot { kn } -\DeclareSIUnit \mmHg { mmHg } -\DeclareSIUnit \nauticalmile { M } -\DeclareSIUnit \neper { Np } -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -% -%\begin{macro}{\square} -%\begin{macro}{\squared} -%\begin{macro}{\cubic} -%\begin{macro}{\cubed} -% The basic powers are also defined. -% \begin{macrocode} -\DeclareSIPrePower \square { 2 } -\DeclareSIPostPower \squared { 2 } -\DeclareSIPrePower \cubic { 3 } -\DeclareSIPostPower \cubed { 3 } -% \end{macrocode} -%\end{macro} -%\end{macro} -%\end{macro} -%\end{macro} -% -%\subsection{Strict application of the rules} -% -%\begin{macro}{\@@_strict_option:n} -%\begin{macro}{\@@_strict_option_aux:n} -% When sticking to the rules closely, a few options are not available. -% \begin{macrocode} -\keys_define:nn { siunitx } { - strict .code:n = - { - \keys_set:nn { siunitx } - { - bracket-numbers = true, - detect-family = false, - detect-mode = false, - detect-shape = false, - detect-weight = false, - multi-part-units = brackets, - parse-numbers = true, - parse-units = true, - product-units = repeat - } - \@@_strict_option:n - { - bracket-numbers , - detect-family , - detect-italic , - detect-mode , - detect-shape , - detect-weight , - multi-part-units , - parse-numbers , - parse-units , - product-units - } - \keys_define:nn { siunitx } - { - per-mode / repeated-symbol .code:n = - { - \msg_warning:nnx { siunitx } { option-not-available } - { per-mode~=~repeated-symbol } - } - } - } -} -\@@_option_deactivate:n { strict } -\cs_new_protected:Npn \@@_strict_option:n #1 { - \clist_map_function:nN {#1} \@@_strict_option_aux:n -} -\cs_new_protected:Npn \@@_strict_option_aux:n #1 { - \keys_define:nn { siunitx } - { #1 .code:n = - { \msg_warning:nnx { siunitx } { option-not-available } {#1} } - } -} -% \end{macrocode} -%\end{macro} -%\end{macro} -% -%\subsection{Locales} -% -% The basics for defining locales are easy: these are just meta keys. -% The US locale is simply an alias for the UK one, which is the default. -% \begin{macrocode} -\keys_define:nn { siunitx } { - locale .choice:, - locale / - DE .meta:n = - { - exponent-product = \ensuremath { \cdot } , - inter-unit-product = \, , - output-decimal-marker = { , } - }, - locale / - FR .meta:n = - { - exponent-product = \ensuremath { \times } , - inter-unit-product = \, , - output-decimal-marker = { , } - }, - locale / - UK .meta:n = - { - exponent-product = \ensuremath { \times } , - inter-unit-product = \, , - output-decimal-marker = . - }, - locale / - US .meta:n = { locale = UK }, - locale / - USA .meta:n = { locale = UK }, - locale / - ZA .meta:n = - { - exponent-product = \ensuremath { \times } , - inter-unit-product = \ensuremath { \cdot } , - output-decimal-marker = { , } - }, -} -% \end{macrocode} -% -%\subsection{Localisation} -% -% Localisation makes use of the \pkg{translator} package. This only -% happens if it is available, and is transparent to the user. -% \begin{macrocode} -\file_if_exist:nT { translator.sty } - { - \RequirePackage { translator } - \usedictionary { translator-basic-dictionary } - \providetranslation [ to = English ] - { to~(numerical~range) } { to } - \providetranslation [ to = French ] - { to~(numerical~range) } { \`a } - \providetranslation [ to = German ] - { to~(numerical~range) } { bis } - \providetranslation [ to = Spanish ] - { to~(numerical~range) } { a } - \sisetup - { - list-final-separator = { ~ \translate { and } ~ }, - list-pair-separator = { ~ \translate { and } ~ }, - range-phrase = { ~ \translate { to~(numerical~range) } ~ } - } - } -% \end{macrocode} -% -% \subsection{Loading additional configurations} -% -% \begin{variable}{\c_@@_configuration_ext_tl} -% Logical mark-up for the file extension. -% \begin{macrocode} -\tl_const:Nn \c_@@_configuration_ext_tl { cfg } -% \end{macrocode} -% \end{variable} -% -% \begin{macro}{\@@_load_abbreviations:} -% \begin{macro}{\@@_load_binary:} -% Loading abbreviations is on by default, which therefore requires a bit -% of juggling. The idea here is that the abbreviations will be loaded unless -% specifically turned off. This can occur anywhere in the preamble. -% \begin{macrocode} -\keys_define:nn { siunitx } - { - abbreviations .choice:, - abbreviations / - true .code:n = { \@@_load_abbreviations: }, - abbreviations / - false .code:n = - { \cs_set_eq:NN \@@_load_abbreviations: \prg_do_nothing: } , - abbreviations .default:n = true , - binary-units .choice:, - binary-units / - true .code:n = { \AtBeginDocument { \@@_load_binary: } }, - binary-units / - false .code:n = - { \cs_set_eq:NN \@@_load_binary: \prg_do_nothing: } , - binary-units .default:n = true - } -\cs_new_protected:Npn \@@_load_abbreviations: - { - \@onefilewithoptions { siunitx-abbreviations } [ ] [ ] - \c_@@_configuration_ext_tl - } -\cs_new_protected:Npn \@@_load_binary: - { - \@onefilewithoptions { siunitx-binary } [ ] [ ] - \c_@@_configuration_ext_tl - } -\AtBeginDocument { \@@_load_abbreviations: } -\@@_option_deactivate:n { abbreviations , binary } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% The version 1 options are not loaded as standard. -% \begin{macrocode} -\keys_define:nn { siunitx } - { - version-1-compatibility .choice: , - version-1-compatibility / - true .code:n = - { - \@onefilewithoptions { siunitx-version-1 } [ ] [ ] - \c_@@_configuration_ext_tl - }, - version-1-compatibility / - false .code:n = { } , - version-1-compatibility .default:n = true - } -\@@_option_deactivate:n { version-1-compatibility } -% \end{macrocode} -% -% Dealing with the old \opt{load-configurations} option is pretty easy, as -% only one choice is important. -% \begin{macrocode} -\keys_define:nn { siunitx } { - load-configurations .code:n = - { - \clist_if_in:nnT {#1} { version-1 } - { - \@onefilewithoptions { siunitx-version-1 } [ ] [ ] - \c_@@_configuration_ext_tl - } - } -} -\@@_option_deactivate:n { load-configurations } -% \end{macrocode} -% -% Load any local configuration file. -% \begin{macrocode} -\file_if_exist:nT { siunitx . \c_@@_configuration_ext_tl } - { - \@onefilewithoptions { siunitx } [ ] [ ] - \c_@@_configuration_ext_tl - } -% \end{macrocode} -% -% Finally apply the settings given at load time. -% \begin{macrocode} -\ProcessKeysOptions { siunitx } -% \end{macrocode} -% -% Creating document commands has to happen here so it is after any load-time -% changes to the units available. -% \begin{macrocode} -\AtBeginDocument { - \bool_if:NTF \l_@@_create_free_bool - { \@@_unit_create_functions: } - { \@@_unit_create_empty_functions: } -} +%</interfaces> % \end{macrocode} % % \begin{macrocode} %</package> % \end{macrocode} % -%\subsection{Support for version one} -% -% \begin{macrocode} -%<*version-1> -% \end{macrocode} -% -% \begin{macrocode} -\ProvidesExplFile {siunitx-version-1.cfg} {2021-04-17} {2.8e} - {siunitx: Version 1 settings} -% \end{macrocode} -% -% The re-arrangements made to the code in version two, and in particular -% the new option names, mean that support for version one needs to be -% included explicitly. -% -% \begin{macrocode} -\keys_define:nn { siunitx } { - addsign .choice: , - addsign / - all .meta:n = { explicit-sign = + }, - addsign / - exp .meta:n = { explicit-sign = + }, - addsign / - false .meta:n = { explicit-sign = }, - addsign / - mant .meta:n = { explicit-sign = + }, - addsign / - none .meta:n = { explicit-sign = }, - addsign / - true .meta:n = { explicit-sign = + }, - addsign .default:n = { true }, - allowlitunits .meta:n = { free-standing-units = #1 }, - allowlitunits .default:n = { true }, - allowoptarg .meta:n = { unit-optional-argument = #1 }, - allowoptargs .default:n = { true }, - allowzeroexp .meta:n = { retain-zero-exponent = #1 }, - allowzeroexp .default:n = { true }, - alsoload .code:n = , - angformat .code:n = , - anglesep .choice: , - anglesep / - cdot .meta:n = - { arc-separator = \ensuremath { { } \cdot { } } }, - anglesep / - comma .meta:n = { arc-separator = \ensuremath { { {,} } } }, - anglesep / - fullstop .meta:n = { arc-separator = \ensuremath { { { . } } } }, - anglesep / - med .meta:n = { arc-separator = \ensuremath { \: } }, - anglesep / - medium .meta:n = { arc-separator = \ensuremath { \: } }, - anglesep / - none .meta:n = { arc-separator = }, - anglesep / - period .meta:n = { arc-separator = \ensuremath { { { . } } } }, - anglesep / - space .meta:n = { arc-separator = \text { ~ } }, - anglesep / - stop .meta:n = { arc-separator = \ensuremath { { { . } } } }, - anglesep / - thick .meta:n = { arc-separator = \ensuremath { \; } }, - anglesep / - thin .meta:n = { arc-separator = \ensuremath { \, } }, - anglesep / - tightcdot .meta:n = - { arc-separator = \ensuremath { \bgroup \cdot \egroup } }, - anglesep / - tighttimes .meta:n = - { arc-separator = \ensuremath { \bgroup \times \egroup } }, - anglesep / - times .meta:n = { arc-separator = \ensuremath { \times } }, - anglesep / - unknown .meta:n = { arc-separator = \ensuremath {#1} }, - astroang .meta:n = - { angle-symbol-over-decimal = #1 }, - astroang .default:n = { true }, - closeerr .meta:n = { close-bracket = \ensuremath {#1} }, - closefrac .meta:n = { close-bracket = \ensuremath {#1} }, - closerange .meta:n = { close-bracket = \ensuremath {#1} }, - colour .code:n = { color = #1 }, - colorall .code:n = , - colourall .code:n = , - colorneg .code:n = , - colourneg .code:n = , - colorunits .meta:n = , - colourunits .meta:n = , - colorvalues .meta:n = , - colourvalues .meta:n = , - decimalsymbol .choice: , - decimalsymbol / - cdot .meta:n = - { output-decimal-marker = \ensuremath { { } \cdot { } } }, - decimalsymbol / - comma .meta:n = { output-decimal-marker = { \ensuremath { { , } } } }, - decimalsymbol / - fullstop .meta:n = { output-decimal-marker = { \ensuremath { { . } } } }, - decimalsymbol / - period .meta:n = { output-decimal-marker = { \ensuremath { { . } } } }, - decimalsymbol / - stop .meta:n = { output-decimal-marker = { \ensuremath { { . } } } }, - decimalsymbol / - tightcdot .code:n = - { output-decimal-marker = \ensuremath { \bgroup \cdot \egroup } }, - decimalsymbol / - unknown .meta:n = { output-decimal-marker = \ensuremath {#1} }, - debug .code:n = , - detectdisplay .meta:n = { detect-display-math = #1 }, - detectdisplay .default:n = { true }, - digitsep .choice: , - digitsep / - cdot .meta:n = - { group-separator = \ensuremath { { } \cdot { } } }, - digitsep / - comma .meta:n = { group-separator = \ensuremath { { , } } }, - digitsep / - fullstop .meta:n = { group-separator = \ensuremath { . } }, - digitsep / - med .meta:n = { group-separator = \ensuremath { \: } }, - digitsep / - medium .meta:n = { group-separator = \ensuremath { \: } }, - digitsep / - none .meta:n = { group-separator = }, - digitsep / - period .meta:n = { group-separator = \ensuremath { . } }, - digitsep / - space .meta:n = { group-separator = \text { ~ } }, - digitsep / - stop .meta:n = { group-separator = \ensuremath { . } }, - digitsep / - thick .meta:n = { group-separator = \ensuremath { \; } }, - digitsep / - thin .meta:n = { group-separator = \ensuremath { \, } }, - digitsep / - tightcdot .meta:n = - { group-separator = \ensuremath { \bgroup \cdot \egroup } }, - digitsep / - tighttimes .meta:n = - { group-separator = \ensuremath { \bgroup \times \egroup } }, - digitsep / - times .meta:n = { group-separator = \ensuremath { \times } }, - digitsep / - unknown .meta:n = { group-separator = \ensuremath {#1} }, - dp .meta:n = - { - round-mode = places, - round-precision = #1, - }, - emulate .code:n = , - errspace .choice: , - errspace / - med .meta:n = { uncertainty-separator = \ensuremath { \: } }, - errspace / - medium .meta:n = { uncertainty-separator = \ensuremath { \: } }, - errspace / - none .meta:n = { uncertainty-separator = }, - errspace / - space .meta:n = { uncertainty-separator = \text { ~ } }, - errspace / - thick .meta:n = { uncertainty-separator = \ensuremath { \; } }, - errspace / - thin .meta:n = { uncertainty-separator = \ensuremath { \, } }, - errspace / - unknown .meta:n = { uncertainty-separator = \ensuremath {#1} }, - eVcorra .code:n = , - eVcorrb .code:n = , - expbase .choice: , - expbase / - ten .meta:n = { exponent-base = 10 }, - expbase / - two .meta:n = { exponent-base = 2 }, - expbase / - unknown .meta:n = { exponent-base = #1 }, - expproduct .choice: , - expproduct / - cdot .meta:n = - { exponent-product = \ensuremath { { } \cdot { } } }, - expproduct / - tightcdot .meta:n = - { exponent-product = \ensuremath { \bgroup \cdot \egroup } }, - expproduct / - tighttimes .meta:n = - { exponent-product = \ensuremath { \bgroup \times \egroup } }, - expproduct / - times .meta:n = { exponent-product = \ensuremath { \times } }, - expproduct / - unknown .meta:n = { exponent-product = \ensuremath {#1} }, - fixdp .choice:, - fixdp / - false .meta:n = { round-mode = none }, - fixdp / - true .meta:n = { round-mode = places }, - fixdp .default:n = { true }, - fixsf .choice: , - fixsf / - false .meta:n = { round-mode = none }, - fixsf / - true .meta:n = { round-mode = figures }, - fixsf .default:n = { true }, - fraction .choice: , - fraction / - frac .meta:n = { fraction-function = \frac }, - fraction / - nice .meta:n = { fraction-function = \frac }, - fraction / - sfrac .meta:n = { fraction-function = \sfrac }, - fraction / - ugly .meta:n = - { - fraction-function = \frac , - per-mode = symbol-or-fraction - }, - inlinebold .meta:n = { detect-inline-weight = #1 }, - log .code:n = , - load .code:n = , - loctolang .code:n = , - mathOmega .meta:n = { math-ohm = #1 }, - mathcelsius .meta:n = { math-celsius = #1 }, - mathdegree .meta:n = { math-degree = #1 }, - mathminute .meta:n = { math-arcminute = #1 }, - mathmu .meta:n = { math-micro = #1 }, - mathringA .meta:n = { math-angstrom = #1 }, - mathrm .code:n = - { \use:x { \keys_set:nn { siunitx } { math-rm = \exp_not:c {#1} } } }, - mathsOmega .meta:n = { math-ohm = #1 }, - mathscelsius .meta:n = { math-celsius = #1 }, - mathsdegree .meta:n = { math-degree = #1 }, - mathsecond .meta:n = { math-arcsecond = #1 }, - mathsf .code:n = - { \use:x { \keys_set:nn { siunitx } { math-sf = \exp_not:c {#1} } } }, - mathsminute .meta:n = { math-arcminute = #1 }, - mathsmu .meta:n = { math-micro = #1 }, - mathsringA .meta:n = { math-angstrom = #1 }, - mathsrm .code:n = - { \use:x { \keys_set:nn { siunitx } { math-rm= \exp_not:c {#1} } } }, - mathssecond .meta:n = { math-arcsecond = #1 }, - mathssf .code:n = - { \use:x { \keys_set:nn { siunitx } { math-sf = \exp_not:c {#1} } } }, - mathstt .code:n = - { \use:x { \keys_set:nn { siunitx } { math-tt = \exp_not:c {#1} } } }, - mathtt .code:n = - { \use:x { \keys_set:nn { siunitx } { math-tt = \exp_not:c {#1} } } }, - negcolor .meta:n = { negative-color = #1 }, - negcolour .meta:n = { negative-color = #1 }, - noload .code:n = , - numaddn .meta:n = { input-symbols = #1 }, - numcloseerr .meta:n = { input-close-uncertainty = #1 }, - numdecimal .meta:n = { input-decimal-markers = #1 }, - numdigits .meta:n = { input-digits = #1 }, - numdiv .meta:n = { input-quotient = #1 }, - numexp .meta:n = { input-exponent-markers = #1 }, - numgobble .meta:n = { input-ignore = #1 }, - numopenerr .meta:n = { input-open-uncertainty = #1 }, - numprod .meta:n = { input-product = #1 }, - numsign .meta:n = { input-signs = #1 }, - obeyall .meta:n = { detect-all = #1 }, - obeyall .default:n = { true }, - obeybold .meta:n = { detect-weight = #1 }, - obeybold .default:n = { true }, - obeyfamily .meta:n = { detect-family = #1 }, - obeyfamily .default:n = { true }, - obeyitalic .meta:n = { detect-shape = #1 }, - obeyitalic .default:n = { true }, - obeymode .meta:n = { detect-mode = #1 }, - obeymode .default:n = { true }, - openerr .meta:n = { open-bracket = \ensuremath {#1} }, - openfrac .meta:n = { open-bracket = \ensuremath {#1} }, - openrange .meta:n = { open-bracket = \ensuremath {#1} }, - padangle .choice: , - padangle / - all .meta:n = - { - add-arc-degree-zero = true, - add-arc-minute-zero = true, - add-arc-second-zero = true - }, - padangle / - both .meta:n = - { - add-arc-degree-zero = true, - add-arc-minute-zero = true, - add-arc-second-zero = true - }, - padangle / - false .meta:n = - { - add-arc-degree-zero = false, - add-arc-minute-zero = false, - add-arc-second-zero = false - }, - padangle / - large .meta:n = - { - add-arc-degree-zero = true, - add-arc-minute-zero = true, - add-arc-second-zero = false - }, - padangle / - none .meta:n = - { - add-arc-degree-zero = false, - add-arc-minute-zero = false, - add-arc-second-zero = false - }, - padangle / - small .meta:n = - { - add-arc-degree-zero = false, - add-arc-minute-zero = true, - add-arc-second-zero = true - }, - true .meta:n = - { - add-arc-degree-zero = true, - add-arc-minute-zero = true, - add-arc-second-zero = true - }, - padnumber .choice: , - padnumber / - all .meta:n = - { - add-decimal-zero = true, - add-integer-zero = true - }, - padnumber / - both .meta:n = - { - add-decimal-zero = true, - add-integer-zero = true - }, - padnumber / - false .meta:n = - { - add-decimal-zero = false, - add-integer-zero = false - }, - padnumber / - leading .meta:n = - { - add-decimal-zero = true, - add-integer-zero = false - }, - padnumber / - none .meta:n = - { - add-decimal-zero = false, - add-integer-zero = false - }, - padnumber / - trailing .meta:n = - { - add-decimal-zero = false, - add-integer-zero = true - }, - padnumber / - true .meta:n = - { - add-decimal-zero = true, - add-integer-zero = true - }, - per .choice: , - per / - frac .meta:n = { per-mode = fraction }, - per / - fraction .meta:n = { per-mode = fraction }, - per / - reciprocal .meta:n = { per-mode = reciprocal }, - per / - slash .meta:n = { per-mode = symbol }, - prefixbase .code:n = , - prefixproduct .code:n = , - prefixsymbolic .meta:n = { prefixes-as-symbols = #1 }, - prefixsymbolic .default:n = { true }, - prespace .meta:n = { space-before-unit = #1 }, - prespace .default:n = { true }, - redefsymbols .meta:n = { redefine-symbols = #1 }, - redefsymbols .default:n = { true }, - repeatunits .choice: , - repeatunits / - false .meta:n = - { - multi-part-units = single, - product-units = single, - range-units = single - }, - repeatunits / - power .meta:n = - { - multi-part-units = repeat, - product-units = power, - range-units = repeat - }, - repeatunits / - true .meta:n = - { - multi-part-units = repeat, - product-units = repeat, - range-units = repeat - }, - repeatunits .default:n = { true }, - retainplus .meta:n = { retain-explicit-plus = #1 }, - retainplus .default:n = { true }, - seperr .meta:n = { separate-uncertainty = #1 }, - seperr .default:n = { true }, - sepfour .meta:n = { group-four-digits = true }, - sepfour .default:n = { true }, - sf .meta:n = - { - round-mode = figures, - round-precision = #1, - }, - sign .meta:n = { explicit-sign = #1 }, - slash .choice: , - slash / - slash .meta:n = { per-symbol = \ensuremath { / } }, - slash / - unknown .meta:n = { per-symbol = \ensuremath {#1} }, - stickyper .meta:n = { sticky-per = #1 }, - stickyper .default:n = { true }, - strictarc .code:n = , - tabalign .code:n = - { - \str_if_eq:nnTF {#1} { centre } - { \keys_set:nn { siunitx } { table-alignment = center } } - { \keys_set:nn { siunitx } { table-alignment = #1 } } - }, - tabalignexp .code:n = { table-align-exponent = #1 }, - tabautofit .meta:n = { table-auto-round = #1 }, - tabautofit .default:n = { true }, - tabexpalign .code:n = { table-align-exponent = #1 }, - tabformat .meta:n = { table-format = #1 }, - tabnumalign .code:n = - { - \str_if_eq:nnTF {#1} { centre } - { \keys_set:nn { siunitx } { table-number-alignment = center } } - { - \str_if_eq:nnTF {#1} { centredecimal } - { - \keys_set:nn { siunitx } - { table-number-alignment = center-decimal-marker } - } - { - \str_if_eq:nnTF {#1} { centerdecimal } - { - \keys_set:nn { siunitx } - { table-number-alignment = center-decimal-marker } - } - { - \keys_set:nn { siunitx } - { table-number-alignment = #1 } - } - } - } - }, - tabparseonly .meta:n = { table-parse-only = #1 }, - tabparseonly .default:n = { true }, - tabtextalign .code:n = - { - \str_if_eq:nnTF {#1} { centre } - { \keys_set:nn { siunitx } { table-text-alignment = center } } - { \keys_set:nn { siunitx } { table-text-alignment = #1 } } - }, - tabunitalign .code:n = - { - \str_if_eq:nnTF {#1} { centre } - { \keys_set:nn { siunitx } { table-unit-alignment = center } } - { \keys_set:nn { siunitx } { table-unit-alignment = #1 } } - }, - textOmega .meta:n = { text-ohm = #1 }, - textcelsius .meta:n = { text-celsius = #1 }, - textdegree .meta:n = { text-degree = #1 }, - textminute .meta:n = { text-arcminute = #1 }, - textmode .choice: , - textmode / - true .meta:n = { mode = text }, - textmode / - false .meta:n = { mode = math }, - textmode .default:n = { true }, - textmu .meta:n = { text-micro = #1 }, - textringA .meta:n = { text-angstrom = #1 }, - textrm .code:n = - { \use:x { \keys_set:nn { siunitx } { text-rm = \exp_not:c {#1} } } }, - textsecond .meta:n = { text-arcsecond = #1 }, - textsf .code:n = - { \use:x { \keys_set:nn { siunitx } { text-sf = \exp_not:c {#1} } } }, - texttt .code:n = - { \use:x { \keys_set:nn { siunitx } { text-tt = \exp_not:c {#1} } } }, - tightpm .meta:n = { tight-spacing = #1 }, - tightpm .default:n = { true }, - tophrase .meta:n = { range-phrase = #1 }, - trapambigerr .choice: , - trapambigerr - / false .meta:n = { multi-part-units = single }, - trapambigerr - / true .meta:n = { multi-part-units = brackets }, - trapambigerr .default:n = { true }, - trapambigfrac .meta:n = { bracket-numbers = #1 }, - trapambigfrac .default:n = { true }, - trapambigrange .choice: , - trapambigrange - / false .meta:n = { range-units = single }, - trapambigrange - / true .meta:n = { range-units = brackets }, - trapambigrange .default:n = { true }, - unitcolor .meta:n = { unit-color = #1 }, - unitcolour .meta:n = { unit-color = #1 }, - unitmathrm .code:n = - { \use:x { \keys_set:nn { siunitx } { unit-math-rm = \exp_not:c {#1} } } }, - unitmathsf .code:n = - { \use:x { \keys_set:nn { siunitx } { unit-math-sf = \exp_not:c {#1} } } }, - unitmathsrm .code:n = - { \use:x { \keys_set:nn { siunitx } { unit-math-rm = \exp_not:c {#1} } } }, - unitmathssf .code:n = - { \use:x { \keys_set:nn { siunitx } { unit-math-sf = \exp_not:c {#1} } } }, - unitmathstt .code:n = - { \use:x { \keys_set:nn { siunitx } { unit-math-tt = \exp_not:c {#1} } } }, - unitmathtt .code:n = - { \use:x { \keys_set:nn { siunitx } { unit-math-tt = \exp_not:c {#1} } } }, - unitmode .meta:n = { unit-mode = #1 }, - unitsep .choice: , - unitsep / - cdot .meta:n = - { inter-unit-product = \ensuremath { { } \cdot { } } }, - unitsep / - comma .meta:n = { inter-unit-product = { {,} } }, - unitsep / - fullstop .meta:n = { inter-unit-product = { { . } } }, - unitsep / - med .meta:n = { inter-unit-product = \ensuremath { \: } }, - unitsep / - medium .meta:n = { inter-unit-product = \ensuremath { \: } }, - unitsep / - none .meta:n = { inter-unit-product = }, - unitsep / - period .meta:n = { inter-unit-product = { { . } } }, - unitsep / - space .meta:n = { inter-unit-product = \text { ~ } }, - unitsep / - stop .meta:n = { inter-unit-product = { { . } } }, - unitsep / - thick .meta:n = { inter-unit-product = \ensuremath { \; } }, - unitsep / - thin .meta:n = { inter-unit-product = \, }, - unitsep / - tightcdot .meta:n = - { inter-unit-product = \ensuremath { \bgroup \cdot \egroup } }, - unitsep / - tighttimes .meta:n = - { inter-unit-product = \ensuremath { \bgroup \times \egroup } }, - unitsep / - times .meta:n = { inter-unit-product = \ensuremath { \times } }, - unitsep / - unknown .meta:n = { inter-unit-product = \ensuremath {#1} }, - unitspace .choice: , - unitspace / - med .meta:n = { inter-unit-product = \ensuremath { \: } }, - unitspace / - medium .meta:n = { inter-unit-product = \ensuremath { \: } }, - unitspace / - none .meta:n = { inter-unit-product = }, - unitspace / - space .meta:n = { inter-unit-product = \text { ~ } }, - unitspace / - thick .meta:n = { inter-unit-product = \ensuremath { \; } }, - unitspace / - thin .meta:n = { inter-unit-product = \, }, - unitspace / - unknown .meta:n = { inter-unit-product = \ensuremath {#1} }, - valuecolor .meta:n = { number-color = #1 }, - valuecolour .meta:n = { number-color = #1 }, - valuemathrm .code:n = - { \use:x { \keys_set:nn { siunitx } { number-math-rm = \exp_not:c {#1} } } }, - valuemathsf .code:n = - { \use:x { \keys_set:nn { siunitx } { number-math-sf = \exp_not:c {#1} } } }, - valuemathsrm .code:n = - { \use:x { \keys_set:nn { siunitx } { number-math-rm = \exp_not:c {#1} } } }, - valuemathssf .code:n = - { \use:x { \keys_set:nn { siunitx } { number-math-sf = \exp_not:c {#1} } } }, - valuemathstt .code:n = - { \use:x { \keys_set:nn { siunitx } { number-math-tt = \exp_not:c {#1} } } }, - valuemathtt .code:n = - { \use:x { \keys_set:nn { siunitx } { number-math-tt = \exp_not:c {#1} } } }, - valuemode .meta:n = { number-mode = #1 }, - valuesep .choice: , - valuesep / - cdot .meta:n = - { number-unit-product = \ensuremath { { } \cdot { } } }, - valuesep / - comma .meta:n = { number-unit-product = { {,} } }, - valuesep / - fullstop .meta:n = { number-unit-product = { { . } } }, - valuesep / - med .meta:n = { number-unit-product = \ensuremath { \: } }, - valuesep / - medium .meta:n = { number-unit-product = \ensuremath { \: } }, - valuesep / - none .meta:n = { number-unit-product = }, - valuesep / - period .meta:n = { number-unit-product = { { . } } }, - valuesep / - space .meta:n = { number-unit-product = \text { ~ } }, - valuesep / - stop .meta:n = { number-unit-product = { { . } } }, - valuesep / - thick .meta:n = { number-unit-product = \ensuremath { \; } }, - valuesep / - thin .meta:n = { number-unit-product = \, }, - valuesep / - tightcdot .meta:n = - { number-unit-product = \ensuremath { \bgroup \cdot \egroup } }, - valuesep / - tighttimes .meta:n = - { number-unit-product = \ensuremath { \bgroup \times \egroup } }, - valuesep / - times .meta:n = { number-unit-product = \ensuremath { \times } }, - valuesep / - unknown .meta:n = { number-unit-product = \ensuremath {#1} }, - xspace .meta:n = { use-xspace = #1 }, - xspace .default:n = { true }, -} -% \end{macrocode} -% -% The error can be simplified here: if the option is not known, then -% it really is an error. -% \begin{macrocode} -\keys_define:nn { siunitx } { - unknown .code:n = - { - \msg_error:nnx { siunitx } { unknown-option } - { \exp_not:V \l_keys_key_tl } - } -} -% \end{macrocode} -% -% A couple of settings which are slightly different by default in -% version 1. -% \begin{macrocode} -\keys_set:nn { siunitx } {free-standing-units = true} -% \end{macrocode} -% -%\begin{macro}{ -% \newunit , -% \renewunit , -% \provideunit -%} -% The functions for creating units from version one are easy to create. -% \begin{macrocode} -\cs_new_eq:NN \newunit \DeclareSIUnit -\cs_new_eq:NN \renewunit \DeclareSIUnit -\cs_new_eq:NN \provideunit \DeclareSIUnit -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \newpower , -% \renewpower , -% \providepower -%} -% Slightly more complex: an optional argument to check. A simple -% assumption is made that it will be \texttt{post}: anything else -% would not make sense anyway. -% \begin{macrocode} -\NewDocumentCommand \newpower { o m m } { - \IfNoValueTF {#1} - { \DeclareSIPrePower #2 {#3} } - { \DeclareSIPostPower #2 {#3} } -} -\NewDocumentCommand \renewpower { o m m } { - \IfNoValueTF {#1} - { \DeclareSIPrePower #2 {#3} } - { \DeclareSIPostPower #2 {#3} } -} -\NewDocumentCommand \providepower { o m m } { - \IfNoValueTF {#1} - { \DeclareSIPrePower #2 {#3} } - { \DeclareSIPostPower #2 {#3} } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \newprefix , -% \renewprefix , -% \provideprefix -%} -% Slightly more complex: an optional argument to check. A simple -% assumption is made that it will be \texttt{post}: anything else -% would not make sense anyway. -% \begin{macrocode} -\NewDocumentCommand \newprefix { o m m m } { - \IfNoValueTF {#1} - { \DeclareSIPrefix #2 {#3} {#4} } - { \DeclareBinaryPrefix #2 {#3} {#4} } -} -\NewDocumentCommand \renewprefix { o m m m } { - \IfNoValueTF {#1} - { \DeclareSIPrefix #2 {#3} {#4} } - { \DeclareBinaryPrefix #2 {#3} {#4} } -} -\NewDocumentCommand \provideprefix { o m m m } { - \IfNoValueTF {#1} - { \DeclareSIPrefix #2 {#3} {#4} } - { \DeclareBinaryPrefix #2 {#3} {#4} } -} -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \newqualifier , -% \renewqualifier , -% \providequalifier -%} -% The functions for creating qualifiers are easy to create again. -% \begin{macrocode} -\NewDocumentCommand \newqualifier { m m } { - \@@_declare_qualifier:Nn #1 {#2} -} -\cs_new_eq:NN \renewqualifier \newqualifier -\cs_new_eq:NN \providequalifier \newqualifier -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \Square , -% \ssquare -%} -% In version 1, \cs{square} is not used with these two alternatives -% preferred. -% \begin{macrocode} -\DeclareSIPrePower \Square { 2 } -\DeclareSIPrePower \ssquare { 2 } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \BAR , -% \bbar , -% \Day , -% \dday , -% \Gray , -% \ggray -%} -% Units which are given awkward names in version one. -% \begin{macrocode} -\DeclareSIUnit \BAR { \bar } -\DeclareSIUnit \bbar { \bar } -\DeclareSIUnit \Day { \day } -\DeclareSIUnit \dday { \day } -\DeclareSIUnit \Gray { \gray } -\DeclareSIUnit \ggray { \gray } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \atomicmass , -% \arcmin , -% \arcsec -%} -% Slightly different: given more complete names in version two. -% \begin{macrocode} -\DeclareSIUnit \atomicmass { \atomicmassunit } -\DeclareSIUnit \arcmin { \arcminute } -\DeclareSIUnit \arcsec { \arcsecond } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \are , -% \curie , -% \gal , -% \millibar , -% \rad , -% \rem , -% \roentgen -%} -% Units which were defined in version one but are no longer listed -% by the \textsc{bipm} as acceptable. -% \begin{macrocode} -\DeclareSIUnit \are { a } -\DeclareSIUnit \curie { Ci } -\DeclareSIUnit \gal { Gal } -\DeclareSIUnit \millibar { \milli \bar } -\DeclareSIUnit \rad { rad } -\DeclareSIUnit \rem { rem } -\DeclareSIUnit \roentgen { R } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \micA , -% \micmol , -% \micl , -% \micL , -% \nanog , -% \micg , -% \picm , -% \micm , -% \Sec , -% \mics , -% \cmc , -% \dmc , -% \cms -%} -% A few abbreviations which have been renamed. -% \begin{macrocode} -\DeclareSIUnit \micA { \micro \ampere } -\DeclareSIUnit \micmol { \micro \mole } -\DeclareSIUnit \micl { \micro \litre } -\DeclareSIUnit \micL { \micro \liter } -\DeclareSIUnit \nanog { \nano \gram } -\DeclareSIUnit \micg { \micro \gram } -\DeclareSIUnit \picm { \pico \metre } -\DeclareSIUnit \micm { \micro \metre } -\DeclareSIUnit \Sec { \second } -\DeclareSIUnit \mics { \micro \second } -\DeclareSIUnit \cmc { \centi \metre \cubed } -\DeclareSIUnit \dmc { \deci \metre \cubed } -\DeclareSIUnit \cms { \centi \metre \squared } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \centimetrecubed , -% \centimetresquared , -% \cubiccentimetre , -% \cubicdecimetre , -% \squarecentimetre , -% \squaremetre , -% \squarekilometre -%} -% Units from version one that did not seem like a good idea to retain. -% \begin{macrocode} -\DeclareSIUnit \centimetrecubed { \centi \metre \cubed } -\DeclareSIUnit \centimetresquared { \centi \metre \squared } -\DeclareSIUnit \cubiccentimetre { \centi \metre \cubed } -\DeclareSIUnit \cubicdecimetre { \deci \metre \cubed } -\DeclareSIUnit \squarecentimetre { \centi \metre \squared } -\DeclareSIUnit \squaremetre { \metre \squared } -\DeclareSIUnit \squarekilometre { \kilo \metre \squared } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \parsec , -% \lightyear -%} -% A few units for astronomy that version 1 provided. -% \begin{macrocode} -\DeclareSIUnit \parsec { pc } -\DeclareSIUnit \lightyear { ly } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \gmol , -% \kgmol , -% \lbmol -%} -% Slightly odd chemical engineering units, again provided in version 1. -% \begin{macrocode} -\DeclareSIUnit \gmol { g \text { - } mol } -\DeclareSIUnit \kgmol { kg \text { - } mol } -\DeclareSIUnit \lbmol { lb \text { - } mol } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \molar , -% \Molar , -% \torr -%} -% A few common units for chemistry from version 1. \cs{molar} is -% simply a handy abbreviation: \cs{Molar} is common but rather -% questionable. -% \begin{macrocode} -\DeclareSIUnit \molar { \mole \per \cubic \deci \metre } -\DeclareSIUnit \Molar { \textsc { m } } -\DeclareSIUnit \torr { Torr } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\gon} -% A single unit for geophysics that version 1 included. -% \begin{macrocode} -\DeclareSIUnit \gon { gon } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{\clight} -% Version one had a different definition for \cs{clight}. -% \begin{macrocode} -\DeclareSIUnit \clight { \text { \ensuremath { c } } } -% \end{macrocode} -%\end{macro} -% -%\begin{macro}{ -% \micron , -% \mrad , -% \gauss , -% \eVperc , -% \nanobarn , -% \picobarn , -% \femptobarn , -% \attobarn , -% \zeptobarn , -% \yoctobarn , -% \nb , -% \pb , -% \fb , -% \ab , -% \zb -%} -% High-energy physics units from version one. -% \begin{macrocode} -\DeclareSIUnit \micron { \micro \metre } -\DeclareSIUnit \mrad { \milli \rad } -\DeclareSIUnit \gauss { G } -\DeclareSIUnit \eVperc { \eV \per \clight } -\DeclareSIUnit \nanobarn { \nano \barn } -\DeclareSIUnit \picobarn { \pico \barn } -\DeclareSIUnit \femtobarn { \femto \barn } -\DeclareSIUnit \attobarn { \atto \barn } -\DeclareSIUnit \zeptobarn { \zepto \barn } -\DeclareSIUnit \yoctobarn { \yocto \barn } -\DeclareSIUnit \nb { \nano \barn } -\DeclareSIUnit \pb { \pico \barn } -\DeclareSIUnit \fb { \femto \barn } -\DeclareSIUnit \ab { \atto \barn } -\DeclareSIUnit \zb { \zepto \barn } -\DeclareSIUnit \yb { \yocto \barn } -% \end{macrocode} -%\end{macro} -% -% \begin{macro}{\requiresiconfigs} -% Version one provides this, and it might pop up so should not -% cause errors. -% \begin{macrocode} -\NewDocumentCommand \requiresiconfigs { m } - { \keys_set:nn { siunitx } { version-1-compatibility } } -% \end{macrocode} -% \end{macro} -% -% \begin{macrocode} -%</version-1> -% \end{macrocode} -% -% \subsection{Abbreviated units} -% -% \begin{macrocode} -%<*abbreviations> -% \end{macrocode} -% -% \begin{macrocode} -\ProvidesExplFile {siunitx-abbreviations.cfg} {2021-04-17} {2.8e} - {siunitx: Abbreviated units} -% \end{macrocode} -% -% The abbreviation file contains a number of short (mainly two or -% three letter) versions of the usual long names. They are divided up -% into related groups, mainly to avoid an overly long list in one -% place. -% -% \begin{macro}{\A, \pA, \nA, \uA, \mA, \kA} -% Currents. -% \begin{macrocode} -\DeclareSIUnit \A { \ampere } -\DeclareSIUnit \pA { \pico \ampere } -\DeclareSIUnit \nA { \nano \ampere } -\DeclareSIUnit \uA { \micro \ampere } -\DeclareSIUnit \mA { \milli \ampere } -\DeclareSIUnit \kA { \kilo \ampere } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\Hz, \mHz, \kHz, \MHz, \GHz, \THz} -% Then frequencies. -% \begin{macrocode} -\DeclareSIUnit \Hz { \hertz } -\DeclareSIUnit \mHz { \milli \hertz } -\DeclareSIUnit \kHz { \kilo \hertz } -\DeclareSIUnit \MHz { \mega \hertz } -\DeclareSIUnit \GHz { \giga \hertz } -\DeclareSIUnit \THz { \tera \hertz } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\mol, \fmol, \pmol, \nmol, \umol, \mmol, \kmol} -% Amounts of substance (moles). -% \begin{macrocode} -\DeclareSIUnit \mol { \mole } -\DeclareSIUnit \fmol { \femto \mole } -\DeclareSIUnit \pmol { \pico \mole } -\DeclareSIUnit \nmol { \nano \mole } -\DeclareSIUnit \umol { \micro \mole } -\DeclareSIUnit \mmol { \milli \mole } -\DeclareSIUnit \kmol { \kilo \mole } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\V, \pV, \nV, \uV, \mV, \kV} -% Potentials. -% \begin{macrocode} -\DeclareSIUnit \V { \volt } -\DeclareSIUnit \pV { \pico \volt } -\DeclareSIUnit \nV { \nano \volt } -\DeclareSIUnit \uV { \micro \volt } -\DeclareSIUnit \mV { \milli \volt } -\DeclareSIUnit \kV { \kilo \volt } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\hl, \l, \ml, \ul, \hL, \L, \mL, \uL} -% Volumes. -% \begin{macrocode} -\DeclareSIUnit \hl { \hecto \litre } -\DeclareSIUnit \l { \litre } -\DeclareSIUnit \ml { \milli \litre } -\DeclareSIUnit \ul { \micro \litre } -\DeclareSIUnit \hL { \hecto \liter } -\DeclareSIUnit \L { \liter } -\DeclareSIUnit \mL { \milli \liter } -\DeclareSIUnit \uL { \micro \liter } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\fg, \pg, \ng, \ug, \mg, \g, \kg, \amu} -% Masses. -% \begin{macrocode} -\DeclareSIUnit \fg { \femto \gram } -\DeclareSIUnit \pg { \pico \gram } -\DeclareSIUnit \ng { \nano \gram } -\DeclareSIUnit \ug { \micro \gram } -\DeclareSIUnit \mg { \milli \gram } -\DeclareSIUnit \g { \gram } -\DeclareSIUnit \kg { \kilo \gram } -\DeclareSIUnit \amu { \atomicmassunit } -% \end{macrocode} -% \end{macro} -% \begin{macro} -% {\W, \uW, \mW, \kW, \MW, \GW, \kJ, \J, \mJ, \uJ, \eV, \meV, \keV, \MeV, \GeV, \TeV, \kWh} -% Energies. -% \begin{macrocode} -\DeclareSIUnit \W { \watt } -\DeclareSIUnit \uW { \micro \watt } -\DeclareSIUnit \mW { \milli \watt } -\DeclareSIUnit \kW { \kilo \watt } -\DeclareSIUnit \MW { \mega \watt } -\DeclareSIUnit \GW { \giga \watt } -\DeclareSIUnit \J { \joule } -\DeclareSIUnit \uJ { \micro \joule } -\DeclareSIUnit \mJ { \milli \joule } -\DeclareSIUnit \kJ { \kilo \joule } -\DeclareSIUnit \eV { \electronvolt } -\DeclareSIUnit \meV { \milli \electronvolt } -\DeclareSIUnit \keV { \kilo \electronvolt } -\DeclareSIUnit \MeV { \mega \electronvolt } -\DeclareSIUnit \GeV { \giga \electronvolt } -\DeclareSIUnit \TeV { \tera \electronvolt } -\DeclareSIUnit [ inter-unit-product = ] \kWh { \kilo \watt \hour } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\m, \pm, \nm, \um, \mm, \cm, \dm, \km} -% Lengths. -% \begin{macrocode} -\DeclareSIUnit \m { \metre } -\DeclareSIUnit \pm { \pico \metre } -\DeclareSIUnit \nm { \nano \metre } -\DeclareSIUnit \um { \micro \metre } -\DeclareSIUnit \mm { \milli \metre } -\DeclareSIUnit \cm { \centi \metre } -\DeclareSIUnit \dm { \deci \metre } -\DeclareSIUnit \km { \kilo \metre } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\K} -% Temperatures. -% \begin{macrocode} -\DeclareSIUnit \K { \kelvin } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\dB} -% \begin{macrocode} -\DeclareSIUnit \dB { \deci \bel } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\F, \fF, \pF} -% \begin{macrocode} -\DeclareSIUnit \F { \farad } -\DeclareSIUnit \fF { \femto \farad } -\DeclareSIUnit \pF { \pico \farad } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\N, \mN, \kN, \MN} -% Forces. -% \begin{macrocode} -\DeclareSIUnit \N { \newton } -\DeclareSIUnit \mN { \milli \newton } -\DeclareSIUnit \kN { \kilo \newton } -\DeclareSIUnit \MN { \mega \newton } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\Pa, \kPa, \MPa, \GPa} -% Pressures. -% \begin{macrocode} -\DeclareSIUnit \Pa { \pascal } -\DeclareSIUnit \kPa { \kilo \pascal } -\DeclareSIUnit \MPa { \mega \pascal } -\DeclareSIUnit \GPa { \giga \pascal } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\mohm, \kohm, \Mohm} -% Resistances. -% \begin{macrocode} -\DeclareSIUnit \mohm { \milli \ohm } -\DeclareSIUnit \kohm { \kilo \ohm } -\DeclareSIUnit \Mohm { \mega \ohm } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\s, \as, \fs, \ps, \ns, \us, \ms} -% Finally, times. -% \begin{macrocode} -\DeclareSIUnit \s { \second } -\DeclareSIUnit \as { \atto \second } -\DeclareSIUnit \fs { \femto \second } -\DeclareSIUnit \ps { \pico \second } -\DeclareSIUnit \ns { \nano \second } -\DeclareSIUnit \us { \micro \second } -\DeclareSIUnit \ms { \milli \second } -% \end{macrocode} -% \end{macro} -% -% \begin{macrocode} -%</abbreviations> -% \end{macrocode} -% -% \subsection{Binary units} -% -% \begin{macrocode} -%<*binary> -% \end{macrocode} -% -% \begin{macrocode} -\ProvidesExplFile {siunitx-binary.cfg} {2021-04-17} {2.8e} - {siunitx: Binary units} -% \end{macrocode} -% -% \begin{macro}{\kibi, \mebi, \gibi, \tebi, \pebi, \exbi, \zebi, \yobi} -% The binary units as specified by the IEC. -% \begin{macrocode} -\DeclareBinaryPrefix \kibi { Ki } { 10 } -\DeclareBinaryPrefix \mebi { Mi } { 20 } -\DeclareBinaryPrefix \gibi { Gi } { 30 } -\DeclareBinaryPrefix \tebi { Ti } { 40 } -\DeclareBinaryPrefix \pebi { Pi } { 50 } -\DeclareBinaryPrefix \exbi { Ei } { 60 } -\DeclareBinaryPrefix \zebi { Zi } { 70 } -\DeclareBinaryPrefix \yobi { Yi } { 80 } -% \end{macrocode} -% \end{macro} -% \begin{macro}{\bit, \byte} -% Now the units. -% \begin{macrocode} -\DeclareSIUnit \bit { bit } -\DeclareSIUnit \byte { B } -% \end{macrocode} -% \end{macro} -% -% \begin{macrocode} -%</binary> -% \end{macrocode} -% % \end{implementation} % -% \begin{thebibliography}{1} -% -% \bibitem{BIPM} -% \emph{The International System of Units (SI)}, -% \url{http://www.bipm.org/en/measurement-units/}. -% -% \bibitem{NIST} -% \emph{International System of Units from NIST}, -% \url{http://physics.nist.gov/cuu/Units/index.html}. -% -% \bibitem{SI:2.1} -% \emph{SI base units}, -% \url{http://www.bipm.org/en/publications/si-brochure/section2-1.html}. -% -% \bibitem{SI:2.2.2} -% \emph{Units with special names and symbols; units that -% incorporate special names and symbols}, -% \url{http://www.bipm.org/en/publications/si-brochure/section2-2-2.html}. -% -% \bibitem{SI:3.1} -% \emph{SI Prefixes}, -% \url{http://www.bipm.org/en/publications/si-brochure/chapter3.html}. -% -% \bibitem{SI:4.1.T6} -% \emph{Non-SI units accepted for use with the International -% System of Units}, -% \url{http://www.bipm.org/en/publications/si-brochure/table6.html}. -% -% \bibitem{SI:4.1.T7} -% \emph{Non-SI units whose values in SI units must be obtained -% experimentally}, -% \url{http://www.bipm.org/en/publications/si-brochure/table7.html}. -% -% \bibitem{SI:4.1.T8} -% \emph{Other non-SI units}, -% \url{http://www.bipm.org/en/publications/si-brochure/table8.html}. -% -% \bibitem{SI:5.3.3} -% \emph{Formatting the value of a quantity}, -% \url{http://www.bipm.org/en/publications/si-brochure/section5-3-3.html}. -% -% \end{thebibliography} -% -% \PrintChanges -% -% \newpage -% % \PrintIndex diff --git a/macros/latex/contrib/siunitx/siunitx.ins b/macros/latex/contrib/siunitx/siunitx.ins new file mode 100644 index 0000000000..18e3a12736 --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx.ins @@ -0,0 +1,104 @@ +\iffalse meta-comment + +File: siunitx.ins Copyright (C) 2014-2021 Joseph Wright + +It may be distributed and/or modified under the conditions of the +LaTeX Project Public License (LPPL), either version 1.3c of this +license or (at your option) any later version. The latest version +of this license is in the file + + https://www.latex-project.org/lppl.txt + +This file is part of the "siunitx bundle" (The Work in LPPL) +and all files in that bundle must be distributed together. + +The released version of this bundle is available from CTAN. + +----------------------------------------------------------------------- + +The development version of the bundle can be found at + + https://github.com/josephwright/siunitx + +for those people who are interested. + +----------------------------------------------------------------------- + +\fi + +\input l3docstrip.tex +\askforoverwritefalse + +% stop DocStrip adding rather wordy text +\preamble +\endpreamble +\postamble +Copyright (C) 2008-2021 by + Joseph Wright <joseph.wright@morningstar2.co.uk> + +It may be distributed and/or modified under the conditions of +the LaTeX Project Public License (LPPL), either version 1.3c of +this license or (at your option) any later version. The latest +version of this license is in the file: + + https://www.latex-project.org/lppl.txt + +This work is "maintained" (as per LPPL maintenance status) by + Joseph Wright. + +This work consists of the files siunitx.dtx, + siunitx.ins, + siunitx.tex, + siunitx-abbreviation.cfg, + siunitx-abbreviation.dtx, + siunitx-angle.dtx, + siunitx-binary.cfg, + siunitx-binary.dtx, + siunitx-code.tex, + siunitx-command.dtx, + siunix-complex.dtx, + siunitx-compound.dtx, + siunitx-emulation.dtx, + siunitx-locale.dtx, + siunitx-number.dtx, + siunitx-print.dtx, + siunitx-quantity.dtx, + siunitx-symbol.dtx, + siunitx-table.dtx, + siunitx-unit.dtx, + siunitx-v2.sty and + siunitx-version-1.cfg, + and the derived files siunitx.pdf, + siunitx.sty and + siunitx-code.pdf. + +\endpostamble + +\keepsilent + +\generate + {% + \file{siunitx.sty} + {% + \from{siunitx.dtx} {package,init} + \from{siunitx-angle.dtx} {package} + \from{siunitx-complex.dtx} {package} + \from{siunitx-compound.dtx} {package} + \from{siunitx-locale.dtx} {package} + \from{siunitx-number.dtx} {package} + \from{siunitx-print.dtx} {package} + \from{siunitx-table.dtx} {package} + \from{siunitx-unit.dtx} {package} + \from{siunitx-quantity.dtx} {package} + \from{siunitx-symbol.dtx} {package} + \from{siunitx-abbreviation.dtx}{package} + \from{siunitx-binary.dtx} {package} + \from{siunitx-command.dtx} {package} + \from{siunitx-emulation.dtx} {package,options} + \from{siunitx.dtx} {package,options} + \from{siunitx-emulation.dtx} {package,interfaces} + \from{siunitx.dtx} {package,interfaces} + }% + } + +\endbatchfile diff --git a/macros/latex/contrib/siunitx/siunitx.pdf b/macros/latex/contrib/siunitx/siunitx.pdf Binary files differindex 84e23eb006..23c1e8fea4 100644 --- a/macros/latex/contrib/siunitx/siunitx.pdf +++ b/macros/latex/contrib/siunitx/siunitx.pdf diff --git a/macros/latex/contrib/siunitx/siunitx.tex b/macros/latex/contrib/siunitx/siunitx.tex new file mode 100644 index 0000000000..2637236df4 --- /dev/null +++ b/macros/latex/contrib/siunitx/siunitx.tex @@ -0,0 +1,3621 @@ +\iffalse meta-comment + +File: siunitx.tex Copyright (C) 2014-2021 Joseph Wright + +It may be distributed and/or modified under the conditions of the +LaTeX Project Public License (LPPL), either version 1.3c of this +license or (at your option) any later version. The latest version +of this license is in the file + + https://www.latex-project.org/lppl.txt + +This file is part of the "siunitx bundle" (The Work in LPPL) +and all files in that bundle must be distributed together. + +The released version of this bundle is available from CTAN. + +----------------------------------------------------------------------- + +The development version of the bundle can be found at + + https://github.com/josephwright/siunitx + +for those people who are interested. + +----------------------------------------------------------------------- + +\fi + +\documentclass{l3doc} + +% The next line is needed so that \GetFileInfo will be able to pick up +% version data (quite apart from making the demos work). +\usepackage{siunitx} +\DeclareSIUnit\noop{\relax} % For printing prefixes +\DeclareSIPower\quartic\tothefourth{4} % For demos +\DeclareSIUnit\KWH{kWh} +\DeclareSIQualifier\polymer{pol} +\DeclareSIQualifier\catalyst{cat} +\DeclareSIUnit\millimetremercury{mmHg} + +% Commands for this document +\ExplSyntaxOn +\makeatletter +\NewDocumentCommand \acro { m } + { + \textsc + { + \exp_args:NV \tl_if_head_eq_charcode:nNTF \f@series { m } + { \tl_lower_case:n } + { \use:n } + {#1} + } + } +\makeatother +\ExplSyntaxOff +\NewDocumentCommand\email{m}{\href{mailto:#1}{\nolinkurl{#1}}} +\NewDocumentCommand\ext{m}{\texttt{.#1}} +\NewDocumentCommand\foreign{m}{\textit{#1}} +\NewDocumentCommand\opt{m}{\texttt{#1}} +% Tidy up the above in bookmarks +\makeatletter +\pdfstringdefDisableCommands{% + \let\acro\@firstofone + \let\ext\@firstofone + \let\foreign\@firstofone + \let\opt\@firstofone +} +\makeatother + +\NewDocumentCommand\DescribePrefix{m}{% + #1 & + \cs{#1} & + \unit{\csname #1\endcsname\noop} +} +\NewDocumentCommand\DescribeUnit{O{#2}m}{% + #1 & + \cs{#2} & + \unit{\csname #2\endcsname} +} + +% For demos +\usepackage[french,german,spanish,UKenglish]{babel} +\AtBeginDocument{\shorthandoff{:<>}} +\usepackage{translations} +\usepackage{cancel} +\usepackage{collcell} +\usepackage{sansmath} +\newlength{\mylength} + +% For creating code demonstrations +% This needs access to some code-level interfaces in listings +\usepackage{listings} +\makeatletter +\lst@RequireAspects{writefile} +\newsavebox\LaTeXdemo@box +\lstnewenvironment{LaTeXdemo}[1][code and example] + {% + \global\let\lst@intname\@empty + \edef\LaTeXdemo@end{% + \expandafter\noexpand\csname LaTeXdemo@@#1@end\endcsname + }% + \@nameuse{LaTeXdemo@@#1}% + } + {\LaTeXdemo@end} +\newcommand\LaTeXdemo@new[3]{% + \@namedef{LaTeXdemo@@#1}{#2}% + \@namedef{LaTeXdemo@@#1@end}{#3}% +} +\newcommand*\LaTeXdemo@common{% + \setkeys{lst} + {% + basicstyle = \small\ttfamily, + basewidth = 0.51em, + gobble = 2, + language = [LaTeX]{TeX}, + }% +} +\newcount\LaTeXdemo@count +\newcommand*\LaTeXdemo@input{% + \catcode`\^^M = 10\relax + \input{\jobname-\number\LaTeXdemo@count.tmp}% +} +\LaTeXdemo@new{code and example}{% + \setbox\LaTeXdemo@box=\hbox\bgroup + \global\advance\LaTeXdemo@count by 1 % + \lst@BeginAlsoWriteFile{\jobname-\number\LaTeXdemo@count.tmp}% + \LaTeXdemo@common +}{% + \lst@EndWriteFile + \egroup + \begin{center} + \ifdim\wd\LaTeXdemo@box > 0.48\linewidth + \begin{minipage}{\linewidth} + \usebox\LaTeXdemo@box + \end{minipage}% + \par + \begin{minipage}{\linewidth} + \LaTeXdemo@input + \end{minipage} + \else + \begin{minipage}{0.48\linewidth} + \LaTeXdemo@input + \end{minipage}% + \hfil + \begin{minipage}{0.48\linewidth} + \usebox\LaTeXdemo@box + \end{minipage}% + \fi + \end{center} +} +\LaTeXdemo@new{code and float}{% + \global\advance\LaTeXdemo@count by 1 % + \lst@BeginAlsoWriteFile{\jobname-\number\LaTeXdemo@count.tmp}% + \LaTeXdemo@common +}{% + \lst@EndWriteFile + \LaTeXdemo@input +} +\LaTeXdemo@new{code only}{\LaTeXdemo@common}{} +\makeatother + +% For table demos +\usepackage{datatool} +\usepackage{multirow} +\usepackage[table]{xcolor} +% Has to come after xcolor +\usepackage{pgfplots} +\pgfplotsset{compat = 1.16, compat/show suggested version = false} +\usepackage{xfp} + +% For the extra-long tables +\usepackage{xtab} + +% For the table notes +\usepackage{threeparttable} + +% Design changes +\usepackage{caption} +\makeatletter +\edef\@floatboxreset{% + \unexpanded\expandafter{\@floatboxreset}% + \noexpand\centering +} +\makeatother +\usepackage[osf]{mathpazo} + +\hypersetup{hidelinks} + +\begin{document} + +\GetFileInfo{siunitx.sty} + +\title{% + \pkg{siunitx} -- A comprehensive (\acro{SI}) units package% + \thanks{This file describes \fileversion, + last revised \filedate.}% +} + +\author{% + Joseph Wright% + \thanks{% + E-mail: + \href{mailto:joseph.wright@morningstar2.co.uk} + {joseph.wright@morningstar2.co.uk}% + }% +} + +\date{Released \filedate} + +\maketitle + +\tableofcontents + +\begin{abstract} + Physical quantities have both numbers and units, and each physical quantity + should be expressed as the product of a number and a unit. Typesetting + physical quantities requires care to ensure that the combined mathematical + meaning of the number--unit combination is clear. In particular, the + \acro{SI} units system lays down a consistent set of units with rules on how + these are to be used. However, different countries and publishers have + differing conventions on the exact appearance of numbers (and units). The + \pkg{siunitx} package provides a set of tools for authors to typeset + quantities in a consistent way. The package has an extended set of + configuration options which make it possible to follow varying typographic + conventions with the same input syntax. The package includes automated + processing of numbers and units, and the ability to control tabular alignment + of numbers. +\end{abstract} + +\begin{documentation} + +\section{Introduction} + +The correct application of units of measurement is very important in technical +applications. For this reason, carefully-crafted definitions of a coherent +units system have been laid down by the \foreign{Conférence Génrale des Poids +et Mesures} (\acro{CGPM}): this has resulted in the \foreign{Système +International d'Unités}~(\acro{SI}). At the same time, typographic conventions +for correctly displaying both numbers and units exist to ensure that no loss of +meaning occurs in printed matter. + +The \pkg{siunitx} package aims to provide a unified method for \LaTeX{} users +to typeset numbers and units correctly and easily. The design philosophy of +\pkg{siunitx} is to follow the agreed rules by default, but to allow variation +through option settings. In this way, users can use \pkg{siunitx} to follow the +requirements of publishers, co-authors, universities, \foreign{etc}.\ without +needing to alter the input at all. + +\section{\pkg{siunitx} for the impatient} + +The package provides the user macros: +\begin{itemize} + \item \cs{ang}\oarg{options}\marg{angle} + \item \cs{num}\oarg{options}\marg{number} + \item \cs{unit}\oarg{options}\marg{unit} + \item \cs{qty}\oarg{options}\marg{number}\marg{unit} + \item \cs{numlist}\oarg{options}\marg{numbers} + \item \cs{numproduct}\oarg{options}\marg{numbers} + \item \cs{numrange}\oarg{options}\marg{numbers}\marg{number2} + \item \cs{qtylist}\oarg{options}\marg{numbers}\marg{unit} + \item \cs{qtyproduct}\oarg{options}\marg{numbers}\marg{unit} + \item \cs{qtyrange}\oarg{options}\marg{number1}\marg{number2}\marg{unit} + \item \cs{complexnum}\oarg{options}\marg{number} + \item \cs{complexqty}\oarg{options}\marg{number}\marg{unit} + \item \cs{sisetup}\marg{options} + \item \cs{tablenum}\oarg{options}\marg{number} +\end{itemize} +plus the \texttt{S} column type for decimal alignments and units in tabular +environments. These user macros and column types are designed for typesetting +numbers and units with control of appearance and with intelligent processing. + +Numbers are processed with understanding of exponents, or using additional +commands for products and complex numbers. +\begin{LaTeXdemo} + \num{12345,67890} \\ + \num{.3e45} \\ + \complexnum{1+-2i} \\ + \numproduct{1.654 x 2.34 x 3.430} +\end{LaTeXdemo} + +The unit system can interpret units given as text to be used directly or as +macro-based units. In the latter case, different formatting is possible. +\begin{LaTeXdemo} + \unit{kg.m.s^{-1}} \\ + \unit{\kilogram\metre\per\second} \\ + \unit[per-mode = symbol] + {\kilogram\metre\per\second} \\ + \unit[per-mode = symbol] + {\kilogram\metre\per\ampere\per\second} +\end{LaTeXdemo} + +Simple lists and ranges of numbers can be handled. +\begin{LaTeXdemo} + \numlist{10;20;30} \\ + \qtylist{0.13;0.67;0.80}{\milli\metre} \\ + \numrange{10}{20} \\ + \qtyrange{0.13}{0.67}{\milli\metre} +\end{LaTeXdemo} + +By default, all text is typeset in the current upright math font. This can be +changed by setting the appropriate options. + +\section{Using the \pkg{siunitx} package} + +\subsection{Numbers} + +\begin{function}{\num} + \begin{syntax} + \cs{num}\oarg{options}\marg{number} + \end{syntax} +\end{function} +Numbers are automatically formatted by the \cs{num} macro. This takes one +optional argument, \meta{options}, and one mandatory one, \meta{number}. The +contents of \meta{number} are automatically formatted. The formatter removes +both \enquote{soft} (\verb*| |) and \enquote{hard} spaces (|\,| and |~|), +automatically identifies exponents (as standard marked using |e|, |E|, |d| or +|D|) and adds the appropriate spacing of large numbers. With the standard +settings a leading zero is added before a decimal marker, if needed: both |.| +and "," are recognised as decimal markers. +\begin{LaTeXdemo} + \num{123} \\ + \num{1234} \\ + \num{12345} \\ + \num{0.123} \\ + \num{0,1234} \\ + \num{.12345} \\ + \num{3.45d-4} \\ + \num{-e10} +\end{LaTeXdemo} + +Note that numbers are parsed before typesetting, which does have a performance +overhead (only obvious with very large amounts of numerical input). The parser +understands a range of input syntaxes, as demonstrated above. + +\begin{function}{\numlist} + \begin{syntax} + \cs{numlist}\oarg{options}\marg{numbers} + \end{syntax} +\end{function} +Lists of numbers may be processed using the \cs{numlist} function. Each +\meta{number} is given within the list of \meta{numbers} within a brace pair, +as the list can have a flexible length. +\begin{LaTeXdemo} + \numlist{10;30;50;70} +\end{LaTeXdemo} + +\begin{function}{\numproduct} + \begin{syntax} + \cs{numproduct}\oarg{options}\marg{numbers} + \end{syntax} +\end{function} +Runs of products of numbers may be inserted using the \cs{numproduct} function. +This acts in the same way as \cs{num}, but inserts either a symbol or phrase +between the entries. The latter should be separated by |x| tokens. +\begin{LaTeXdemo} + \numproduct{10 x 30} +\end{LaTeXdemo} + +\begin{function}{\numrange} + \begin{syntax} + \cs{numrange}\oarg{options}\marg{number1}\marg{number2} + \end{syntax} +\end{function} +Simple ranges of numbers can be handled using the \cs{numrange} function. This +acts in the same way as \cs{num}, but inserts a phrase or other text between +the two entries. +\begin{LaTeXdemo} + \numrange{10}{30} +\end{LaTeXdemo} + +\subsection{Angles} + +\begin{function}{\ang} + \begin{syntax} + \cs{ang}\oarg{options}\marg{angle} + \end{syntax} +\end{function} +Angles can be typeset using the \cs{ang} command. The \meta{angle} can be given +either as a decimal number or as a semi-colon separated list of degrees, +minutes and seconds, which is called \enquote{arc format} in this document. The +numbers which make up an angle are processed using the same system as other +numbers. +\begin{LaTeXdemo} + \ang{10} \\ + \ang{12.3} \\ + \ang{4,5} \\ + \ang{1;2;3} \\ + \ang{;;1} \\ + \ang{+10;;} \\ + \ang{-0;1;} +\end{LaTeXdemo} + +\subsection{Units} + +\begin{function}{\unit} + \begin{syntax} + \cs{unit}\oarg{options}\marg{unit} + \end{syntax} +\end{function} +The symbol for a unit can be typeset using the \cs{unit} macro: this provides +full control over output format for the unit. Like the \cs{num} macro, +\cs{unit} takes one optional and one mandatory argument. The unit formatting +system can accept two types of input. When the \meta{unit} contains literal +items (for example letters or numbers) then \pkg{siunitx} converts |.| and |~| +into inter-unit product and correctly positions sub- and superscripts specified +using |_| and |^|. The formatting methods will work with both math and text +mode. +\begin{LaTeXdemo} + \unit{kg.m/s^2} \\ + \unit{g_{polymer}~mol_{cat}.s^{-1}} +\end{LaTeXdemo} + +The second operation mode for the \cs{unit} macro is an \enquote{interpreted} +system, Here, each unit, \acro{SI} multiple prefix and power is given a macro +name. These are entered in a method very similar to the reading of the unit +name in English. +\begin{LaTeXdemo} + \unit{\kilo\gram\metre\per\square\second} \\ + \unit{\gram\per\cubic\centi\metre} \\ + \unit{\square\volt\cubic\lumen\per\farad} \\ + \unit{\metre\squared\per\gray\cubic\lux} \\ + \unit{\henry\second} +\end{LaTeXdemo} + +On its own, this is less convenient than the direct method, although it does +use meaning rather than appearance for input. However, the package allows you +to define new unit macros; a large number of pre-defined abbreviations are also +supplied. More importantly, by defining macros for units, instead of literal +input, new functionality is made available. By altering the settings used by +the package, the same input can yield a variety of different output formats. +For example, the \cs{per} macro can give reciprocal powers, slashes or be used +to construct units as fractions. + +\begin{function}{\qty} + \begin{syntax} + \cs{qty}\oarg{options}\marg{number}\marg{unit} + \end{syntax} +\end{function} +Very often, numbers and units are given together. Formally, the value of a +quantity is the product of the number and the unit, the space being regarded as +a multiplication sign. The \cs{qty} macro combines the +functionality of \cs{num} and \cs{unit}, and makes this both possible and easy. +The \meta{number} and \meta{unit} arguments work exactly like those for the +\cs{num} and \cs{unit} macros, respectively. +\begin{LaTeXdemo} + \qty[mode = text]{1.23}{J.mol^{-1}.K^{-1}} \\ + \qty{.23e7}{\candela} \\ + \qty[per-mode = symbol]{1.99}{\per\kilogram} \\ + \qty[per-mode = fraction]{1,345}{\coulomb\per\mole} +\end{LaTeXdemo} + +It is possible to set up the unit macros to be available outside of the +\cs{qty} and \cs{unit} functions. This is not the standard behaviour as there +is the risk of name clashes (for example, \cs{bar} is used by other packages, +and several packages define \cs{degree}). Full details of using \enquote{stand +alone} units are found in \ref{sec:units:creating}. + +\begin{function}{\qtylist} + \begin{syntax} + \cs{qtylist}\oarg{options}\marg{numbers}\marg{unit} + \end{syntax} +\end{function} +Lists of numbers with units can be handled using the \cs{qtylist} function. The +behaviour of this function is similar to \cs{numlist}, but with the addition of +the unit to each number. +\begin{LaTeXdemo} + \qtylist{10;30;45}{\metre} +\end{LaTeXdemo} + +\begin{function}{\qtyproduct} + \begin{syntax} + \cs{qtyproduct}\oarg{options}\marg{numbers}\marg{unit} + \end{syntax} +\end{function} +Runs of products of of numbers with units can be handled using the +\cs{qtyproduct} function. The behaviour of this function is similar to +\cs{numproduct}, but with the addition of a unit to each number. +\begin{LaTeXdemo} + \qtyproduct{10 x 30 x 45}{\metre} +\end{LaTeXdemo} + +\begin{function}{\qtyrange} + \begin{syntax} + \cs{qtyrange}\oarg{options}\marg{number1}\meta{number2}\marg{unit} + \end{syntax} +\end{function} +Products of numbers with units can be handled using the \cs{qtyrange} +function. The behaviour of this function is similar to \cs{numrange}, but +with the addition of a unit to each number. +\begin{LaTeXdemo} + \qtyrange{10}{30}{\metre} +\end{LaTeXdemo} + +The input of lists, products and ranges of quantities using a single command +allows them to be adjusted together. These commands are intended to allow +consistent formatting of related values: as such, they apply a a single +unit to all of the values. This is particularly notable when using +adjustment of the numerical values. + +\subsection{Complex numbers and quantities} + +\begin{function}{\complexnum} + \begin{syntax} + \cs{complexnum}\oarg{options}\marg{number} + \end{syntax} +\end{function} +Typesets the complex number, which must be given in the form $a + b\mathrm{i}$ +or $a + \mathrm{i}b$. Processing of the numerical parts is otherwise identical +to the standard \cs{num} command. + +\begin{function}{\complexqty} + \begin{syntax} + \cs{complexqty}\oarg{options}\marg{number}\marg{unit} + \end{syntax} +\end{function} +Typesets the complex quantity, which must be given in the form $a + b\mathrm{i}$ +or $a + \mathrm{i}b$. Processing of the numerical parts is otherwise identical +to the standard \cs{qty} command. + +\subsection{The unit macros} + +The package always defines the basic set of \acro{SI} units with macro names. +This includes the base \acro{SI} units, the derived units with special names +and the prefixes. A small number of powers are also given pre-defined names. +Full details of units in the \acro{SI} are available on-line~\cite{BIPM}. + +The seven base \acro{SI} units are always defined (Table~\ref{tab:unit:base}). +In addition, the macro \cs{meter} is available as an alias for \cs{metre}, for +users of US spellings. The full details of the base units are given in the +\acro{SI} Brochure. +\begin{table} + \caption{\acro{SI} base units.% + \label{tab:unit:base}} + \begin{tabular}{@{}lll@{}} + \toprule + Unit & Command & Symbol \\ + \midrule + \DescribeUnit{ampere} \\ + \DescribeUnit{candela} \\ + \DescribeUnit{kelvin} \\ + \DescribeUnit{kilogram} \\ + \DescribeUnit{metre} \\ + \DescribeUnit{mole} \\ + \DescribeUnit{second} \\ + \bottomrule + \end{tabular} +\end{table} + +The \acro{SI} also lists a number of units which have special names and +symbols: these are listed in Table~\ref{tab:unit:derived}. +\begin{table} + \caption{Coherent derived units in the \acro{SI} with special names and + symbols.% + \label{tab:unit:derived}} + \begin{tabular}{@{}lll>{\qquad}lll@{}} + \toprule + Unit & Command & Symbol & Unit & Command & Symbol \\ + \midrule + \DescribeUnit{becquerel} & + \DescribeUnit{newton} \\ + \DescribeUnit[degree Celsius]{degreeCelsius} & + \DescribeUnit{ohm} \\ + \DescribeUnit{coulomb} & + \DescribeUnit{pascal} \\ + \DescribeUnit{farad} & + \DescribeUnit{radian} \\ + \DescribeUnit{gray} & + \DescribeUnit{siemens} \\ + \DescribeUnit{hertz} & + \DescribeUnit{sievert} \\ + \DescribeUnit{henry} & + \DescribeUnit{steradian} \\ + \DescribeUnit{joule} & + \DescribeUnit{tesla} \\ + \DescribeUnit{lumen} & + \DescribeUnit{volt} \\ + \DescribeUnit{katal} & + \DescribeUnit{watt} \\ + \DescribeUnit{lux} & + \DescribeUnit{weber} \\ + \bottomrule + \end{tabular} +\end{table} + +In addition to the official \acro{SI} units, \pkg{siunitx} also provides macros +for a number of units which are accepted for use in the \acro{SI} although they +are not \acro{SI} units. Table~\ref{tab:unit:accepted} lists the +\enquote{accepted} units. The command \cs{percent} is also provided for use in +units: this is accepted with the \acro{SI} as detailed in Section~5.3.7 of the +Brochure. +\begin{table} + \caption{Non-\acro{SI} units accepted for use with the International System of + Units.% + \label{tab:unit:accepted}} + \begin{tabular}{@{}lll@{}} + \toprule + Unit & Command & Symbol \\ + \midrule + \DescribeUnit{astronomicalunit} \\ + \DescribeUnit{bel} \\ + \DescribeUnit{dalton} \\ + \DescribeUnit{day} \\ + \DescribeUnit{decibel} \\ + \DescribeUnit{degree} \\ + \DescribeUnit{electronvolt} \\ + \DescribeUnit{hectare} \\ + \DescribeUnit{hour} \\ + \DescribeUnit{litre} \\ + & \cs{liter} & \unit{\liter} \\ + \DescribeUnit[minute (plane angle)]{arcminute} \\ + \DescribeUnit[minute (time)]{minute} \\ + \DescribeUnit[second (plane angle)]{arcsecond} \\ + \DescribeUnit{neper} \\ + \DescribeUnit{tonne} \\ + \bottomrule + \end{tabular} +\end{table} + +In addition to the units themselves, \pkg{siunitx} provides pre-defined macros +for all of the \acro{SI} prefixes (Table~\ref{tab:unit:prefix}). +The spelling \enquote{\cs{deka}} is provided for US users as an alternative to +\cs{deca}. +\begin{table} + \caption{SI prefixes.% + \label{tab:unit:prefix}} + \sisetup{table-number-alignment = right, table-format = 2} + \begin{tabular}{@{}llcS[table-format = -2]>{\qquad}llcS@{}} + \toprule + Prefix & Command & Symbol & \multicolumn{1}{l}{Power} & + Prefix & Command & Symbol & \multicolumn{1}{l@{}}{Power} \\ + \midrule + \DescribePrefix{yocto} & -24 & + \DescribePrefix{deca} & 1 \\ + \DescribePrefix{zepto} & -21 & + \DescribePrefix{hecto} & 2 \\ + \DescribePrefix{atto} & -18 & + \DescribePrefix{kilo} & 3 \\ + \DescribePrefix{femto} & -15 & + \DescribePrefix{mega} & 6 \\ + \DescribePrefix{pico} & -12 & + \DescribePrefix{giga} & 9 \\ + \DescribePrefix{nano} & -9 & + \DescribePrefix{tera} & 12 \\ + \DescribePrefix{micro} & -6 & + \DescribePrefix{peta} & 15 \\ + \DescribePrefix{milli} & -3 & + \DescribePrefix{exa} & 18 \\ + \DescribePrefix{centi} & -2 & + \DescribePrefix{zetta} & 21 \\ + \DescribePrefix{deci} & -1 & + \DescribePrefix{yotta} & 24 \\ + \bottomrule + \end{tabular} +\end{table} + +A small number of pre-defined powers are provided as macros. \cs{square} and +\cs{cubic} are intended for use before units, with \cs{squared} and \cs{cubed} +going after the unit. +\begin{LaTeXdemo} + \unit{\square\becquerel} \\ + \unit{\joule\squared\per\lumen} \\ + \unit{\cubic\lux\volt\tesla\cubed} +\end{LaTeXdemo} +Generic powers can be inserted on a one-off basis using the \cs{tothe} and +\cs{raiseto} macros. These are the only macros for units which take an +argument: +\begin{LaTeXdemo} + \unit{\henry\tothe{5}} \\ + \unit{\raiseto{4.5}\radian} +\end{LaTeXdemo} +Reciprocal powers are indicated using the \cs{per} macro. This applies to the +next unit only, unless the \opt{sticky-per} option is turned on. +\begin{LaTeXdemo} + \unit{\joule\per\mole\per\kelvin} \\ + \unit{\joule\per\mole\kelvin} \\ + \unit{\per\henry\tothe{5}} \\ + \unit{\per\square\becquerel} +\end{LaTeXdemo} +As for generic powers, generic qualifiers are also available using the \cs{of} +function: +\begin{LaTeXdemo} + \unit{\kilogram\of{metal}} \\ + \qty[qualifier-mode = bracket] + {0.1}{\milli\mole\of{cat}\per\kilogram\of{prod}} +\end{LaTeXdemo} + +When the \pkg{cancel} package is loaded, it is possible to \enquote{cancel out} +units using the \cs{cancel} macro. This applies to the next unit, in a similar +manner to a prefix. The \cs{highlight} macro is also available to selectively +color units. Both \cs{cancel} and \cs{highlight} are outside of the normal +semantic meaning of units, but are provided as they may be useful in some +cases. +\begin{LaTeXdemo} + \unit[per-mode = fraction] + {\cancel\kilogram\metre\per\cancel\kilogram\per\second} \\ + \unit{\highlight{red}\kilogram\metre\per\second} \\ + \unit[unit-color = purple] + {\highlight{blue}\kilogram\metre\per\second} +\end{LaTeXdemo} + +\subsection{Unit abbreviations} + +In addition to the \enquote{full} names, \pkg{siunitx} loads a set of +abbreviated versions of the \acro{SI} units (Table~\ref{tab:unit:abbr}). The +standard \pkg{siunitx} settings only create these abbreviations within the +scope of the \cs{unit} and \cs{qty} functions, meaning that no clashes should +occur (for example with the standard \cs{pm} symbol). +\begin{center} + \label{tab:unit:abbr} + \tablefirsthead{% + \toprule + \multicolumn{1}{@{}l}{Unit} & + \multicolumn{1}{l}{Abbreviation} & + \multicolumn{1}{l@{}}{Symbol} \\ + \midrule + } + \tablehead{% + \multicolumn{3}{@{}l@{}}{\emph{Continued from previous page}} \\ + \toprule + \multicolumn{1}{@{}l}{Unit} & + \multicolumn{1}{l}{Abbreviation} & + \multicolumn{1}{l@{}}{Symbol} \\ + \midrule + } + \tabletail{% + \bottomrule + \multicolumn{3}{@{}r@{}}{\emph{Continued on next page}} \\ + } + \tablelasttail{\bottomrule} + \begin{xtabular}{@{}lcc@{}} + \DescribeUnit[femtogram]{fg} \\ + \DescribeUnit[picogram]{pg} \\ + \DescribeUnit[nanogram]{ng} \\ + \DescribeUnit[microgram]{ug} \\ + \DescribeUnit[milligram]{mg} \\ + \DescribeUnit[gram]{g} \\ + \DescribeUnit[kilogram]{kg} \\ + + \midrule + + \DescribeUnit[picometre]{pm} \\ + \DescribeUnit[nanometre]{nm} \\ + \DescribeUnit[micrometre]{um} \\ + \DescribeUnit[millimetre]{mm} \\ + \DescribeUnit[centimetre]{cm} \\ + \DescribeUnit[decimetre]{dm} \\ + \DescribeUnit[metre]{m} \\ + \DescribeUnit[kilometre]{km} \\ + + \midrule + + \DescribeUnit[attosecond]{as} \\ + \DescribeUnit[femtosecond]{fs} \\ + \DescribeUnit[picosecond]{ps} \\ + \DescribeUnit[nanosecond]{ns} \\ + \DescribeUnit[microsecond]{us} \\ + \DescribeUnit[millisecond]{ms} \\ + \DescribeUnit[second]{s} \\ + + \midrule + + \DescribeUnit[femtomole]{fmol} \\ + \DescribeUnit[picomole]{pmol} \\ + \DescribeUnit[nanomole]{nmol} \\ + \DescribeUnit[micromole]{umol} \\ + \DescribeUnit[millimole]{mmol} \\ + \DescribeUnit[mole]{mol} \\ + \DescribeUnit[kilomole]{kmol} \\ + + \midrule + + \DescribeUnit[picoampere]{pA} \\ + \DescribeUnit[nanoampere]{nA} \\ + \DescribeUnit[microampere]{uA} \\ + \DescribeUnit[milliampere]{mA} \\ + \DescribeUnit[ampere]{A} \\ + \DescribeUnit[kiloampere]{kA} \\ + + \midrule + + \DescribeUnit[microlitre]{ul} \\ + \DescribeUnit[millilitre]{ml} \\ + \DescribeUnit[litre]{l} \\ + \DescribeUnit[hectolitre]{hl} \\ + \DescribeUnit[microliter]{uL} \\ + \DescribeUnit[milliliter]{mL} \\ + \DescribeUnit[liter]{L} \\ + \DescribeUnit[hectoliter]{hL} \\ + + \midrule + + \DescribeUnit[millihertz]{mHz} \\ + \DescribeUnit[hertz]{Hz} \\ + \DescribeUnit[kilohertz]{kHz} \\ + \DescribeUnit[megahertz]{MHz} \\ + \DescribeUnit[gigahertz]{GHz} \\ + \DescribeUnit[terahertz]{THz} \\ + + \midrule + + \DescribeUnit[millinewton]{mN} \\ + \DescribeUnit[newton]{N} \\ + \DescribeUnit[kilonewton]{kN} \\ + \DescribeUnit[meganewton]{MN} \\ + + \midrule + + \DescribeUnit[pascal]{Pa} \\ + \DescribeUnit[kilopascal]{kPa} \\ + \DescribeUnit[megapacal]{MPa} \\ + \DescribeUnit[gigapascal]{GPa} \\ + + \midrule + + \DescribeUnit[milliohm]{mohm} \\ + \DescribeUnit[kilohm]{kohm} \\ + \DescribeUnit[megohm]{Mohm} \\ + + \midrule + + \DescribeUnit[picovolt]{pV} \\ + \DescribeUnit[nanovolt]{nV} \\ + \DescribeUnit[microvolt]{uV} \\ + \DescribeUnit[millivolt]{mV} \\ + \DescribeUnit[volt]{V} \\ + \DescribeUnit[kilovolt]{kV} \\ + + \midrule + + \DescribeUnit[watt]{W} \\ + \DescribeUnit[microwatt]{uW} \\ + \DescribeUnit[milliwatt]{mW} \\ + \DescribeUnit[kilowatt]{kW} \\ + \DescribeUnit[megawatt]{MW} \\ + \DescribeUnit[gigawatt]{GW} \\ + \DescribeUnit[joule]{J} \\ + \DescribeUnit[microjoule]{uJ} \\ + \DescribeUnit[millijoule]{mJ} \\ + \DescribeUnit[kilojoule]{kJ} \\ + \DescribeUnit[electronvolt]{eV} \\ + \DescribeUnit[millielectronvolt]{meV} \\ + \DescribeUnit[kiloelectronvolt]{keV} \\ + \DescribeUnit[megaelectronvolt]{MeV} \\ + \DescribeUnit[gigaelectronvolt]{GeV} \\ + \DescribeUnit[teraelectronvolt]{TeV} \\ + \DescribeUnit[kilowatt hour]{kWh} \\ + + \midrule + + \DescribeUnit[farad]{F} \\ + \DescribeUnit[femtofarad]{fF} \\ + \DescribeUnit[picofarad]{pF} \\ + \DescribeUnit[nanofarad]{nF} \\ + \DescribeUnit[microfarad]{uF} \\ + + \midrule + + \DescribeUnit[henry]{H} \\ + \DescribeUnit[millihenry]{mH} \\ + \DescribeUnit[microhenry]{uH} \\ + + \midrule + + \DescribeUnit[kelvin]{K} \\ + + \midrule + + \DescribeUnit[decibel]{dB} \\ + + \end{xtabular} +\end{center} + +\DescribeMacro{bit} +\DescribeMacro{byte} +Binary data is expressed in units of bits and bytes. These are normally given +prefixes which use powers of two, rather than the powers of ten used by the +\acro{SI} prefixes. As these binary prefixes are closely related to the +\acro{SI} prefixes, they are defined by \pkg{siunitx}. +\begin{table} + \caption{Binary prefixes.% + \label{tab:unit:binary}} + \sisetup{table-number-alignment = right, table-format = 2} + \begin{tabular}{@{}llcS@{}} + \toprule + Prefix & Command & Symbol & \multicolumn{1}{l@{}}{Power} \\ \\ + \midrule + \DescribePrefix{kibi} & 10 \\ + \DescribePrefix{mebi} & 20 \\ + \DescribePrefix{gibi} & 30 \\ + \DescribePrefix{tebi} & 40 \\ + \DescribePrefix{pebi} & 50 \\ + \DescribePrefix{exbi} & 60 \\ + \DescribePrefix{zebi} & 70 \\ + \DescribePrefix{yobi} & 80 \\ + \bottomrule + \end{tabular} +\end{table} + +\subsection{Creating new macros} + +The various macro components of a unit have to be defined before they can be +used. The package supplies a number of common definitions, but new definitions +are also possible. As the definition of a logical unit should remain the same +in a single document, these creation functions are all preamble-only. + +\begin{function}{\DeclareSIUnit} + \begin{syntax} + \cs{DeclareSIUnit}\oarg{options}\marg{unit}\marg{symbol} + \end{syntax} +\end{function} +New units are produced using the \cs{DeclareSIUnit} macro. The \meta{symbol} +can contain literal input, other units, multiple prefixes, powers and \cs{per}, +although literal text should not be intermixed with unit macros. Units can be +created with \meta{options} from the usual list understood by \pkg{siunitx}, +and apply the specific unit macro only. The (first) optional argument to +\cs{qty} and \cs{unit} can be used to override the settings for the unit: an +example is the \cs{degree} unit. +\begin{LaTeXdemo} + \qty{3.1415}{\degree} +\end{LaTeXdemo} + This is declared in the package (effectively) as +\begin{LaTeXdemo}[code only] + \DeclareSIUnit[quantity-product = {}] + \degree{\text{\textdegree}} +\end{LaTeXdemo} + The spacing can still be altered at point of use: +\begin{LaTeXdemo} + \qty{67890}{\degree} \\ + \qty[quantity-product = \,]{67890}{\degree} +\end{LaTeXdemo} +The meaning of a pre-defined unit can be altered by using \cs{DeclareSIUnit} +after loading \pkg{siunitx}. This will overwrite the original definition with +the newer version. + +\begin{function}{\DeclareSIPrefix} + \begin{syntax} + \cs{DeclareSIPrefix}\marg{prefix}\marg{symbol}\marg{powers-ten} + \end{syntax} +\end{function} +The standard \acro{SI} powers of ten are defined by the package, and are +described above. However, the user can define new prefixes with +\cs{DeclareSIPrefix}. For example, \cs{kilo} is defined +\begin{LaTeXdemo}[code only] + \DeclareSIPrefix\kilo{k}{3} +\end{LaTeXdemo} + +\begin{function}{\DeclareSIPower} + \begin{syntax} + \cs{DeclareSIPower}\marg{symbol-before}\marg{symbol-after}\marg{power} + \end{syntax} +\end{function} +This function creates two symbols, one for use before a unit, the second +for use after a unit, both of which are equivalent to the \meta{power}. +For example, one might use +\begin{LaTeXdemo}[code only] + \DeclareSIPower\quartic\tothefourth{4} +\end{LaTeXdemo} + with the functions then used in the document as +\begin{LaTeXdemo} + \unit{\kilogram\tothefourth}\\ + \unit{\quartic\metre} +\end{LaTeXdemo} + +\begin{function}{\DeclareSIQualifier} + \begin{syntax} + \cs{DeclareSIQualifier}\marg{qualifier}\marg{symbol} + \end{syntax} +\end{function} +Following the syntax of the other macros, qualifiers may be created using the +\cs{DeclareSIQualifier} command. In contrast to the other parts of a unit, +there are no pre-defined qualifiers. It is therefore entirely up to the user to +create these. For example, to identify the mass of a product created when using +a particular catalyst, the preamble could contain: +\begin{LaTeXdemo}[code only] + \DeclareSIQualifier\polymer{pol} + \DeclareSIQualifier\catalyst{cat} +\end{LaTeXdemo} + and then in the body the document could read +\begin{LaTeXdemo} + \qty{1.234}{\gram\polymer\per\mole\catalyst\per\hour} +\end{LaTeXdemo} + +\subsection{Tabular material} + +Aligning numbers in tabular content is handled by a new column type, the +\texttt{S} column. This new column type can align material using a number of +different strategies, with the aim of flexibility of output without needing to +alter the input. The method used as standard is to place the decimal marker in +the number at the centre of the cell and to align the material appropriately +(Table~\ref{tab:S:standard}). +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Standard behaviour of the \texttt{S} column type.% + \label{tab:S:standard}} + \begin{tabular}{@{}S@{}} + \toprule + {Some Values} \\ + \midrule + 2.3456 \\ + 34.2345 \\ + -6.7835 \\ + 90.473 \\ + 5642.5 \\ + 1.2e3 \\ + e4 \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +The \texttt{S} column will attempt to automatically detect material which +should be placed before or after a number, and will maintain the alignment of +the numerical data (Table~\ref{tab:S:extras}). If the material could be +mistaken for part of a number, it should be protected by braces. The use of +\cs{color} in a table cell will also be detected and will override any general +color applied by \pkg{siunitx}. +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Detection of surrounding material in an \texttt{S} column.% + \label{tab:S:extras}} + \begin{tabular}{@{}S[color = orange]@{}} + \toprule + {Some Values} \\ + \midrule + 12.34 \\ + \color{purple} 975,31 \\ + 44.268 \textsuperscript{\emph{a}} \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +\begin{function}{\tablenum} + \begin{syntax} + \cs{tablenum}\oarg{options}\marg{number} + \end{syntax} +\end{function} +Within more complex tables, aligned numbers may be desirable within the +argument of \cs{multicolumn} or \cs{multirow}.\footnote{Provided by the +\pkg{multirow} package} The \cs{tablenum} function is available to achieve +alignment in these situations: this is, in effect, a macro version of the +\texttt{S} column (Table~\ref{tab:tablenum}). +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Controlling complex alignment with the \cs{tablenum} macro.% + \label{tab:tablenum}} + \begin{tabular}{@{}lr@{}} + \toprule + Heading & Heading \\ + \midrule + Info & More info \\ + Info & More info \\ + \multicolumn{2}{c}{\tablenum[table-format = 4.4]{12,34}} \\ + \multicolumn{2}{c}{\tablenum[table-format = 4.4]{333.5567}} \\ + \multicolumn{2}{c}{\tablenum[table-format = 4.4]{4563.21}} \\ + \bottomrule + \end{tabular} + \hfil + \begin{tabular}{@{}lr@{}} + \toprule + Heading & Heading \\ + \midrule + \multirow{2}*{\tablenum{88,999}} & aaa \\ + & bbb \\ + \multirow{2}*{\tablenum{33,435}} & ccc \\ + & ddd \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +\section{Package control options} + +\subsection{The key--value control system} + + The package uses a range of different key types: +\begin{description} + \item[\texttt{Choice}] Takes a limited number of choices, which are described + separately for each key. + \item[\texttt{Integer}] Requires a number as the argument. + \item[\texttt{Length}] Requires a length, either as a literal + value such as \texttt{2.0cm}, or stored as a \LaTeX{} length. + \item[\texttt{Literal}] A key which uses the value(s) given directly, + either to check input or in output. + \item[\texttt{Macro}] Requires a macro, which may need a single argument. + \item[\texttt{Math}] Similar to a \texttt{literal} option, but the input is + always used in math mode, irrespective of other \pkg{siunitx} settings. + Thus to text-mode only input must be placed inside the argument of a + \cs{text} macro. + \item[\texttt{Meta}] These are options which actually apply a number of + other options. + \item[\texttt{Switch}] These are on--off switches, and recognise \opt{true} + and \opt{false}. Giving just the key name also turns the key on. +\end{description} +The tables of option names use these descriptions to indicate how the keys +should be used. + +\subsection{Printing% + \label{sec:print}} + +The \pkg{siunitx} package can control the font used to print output +independently of the surrounding material. Which aspects of the font follow +those of the surroundings is influenced by a range of setting as detailed in +Table~\ref{tab:opt:print}. +\begin{table} + \caption{Print options.% + \label{tab:opt:print}} + \begin{tabular}{@{}>{\ttfamily}ll>{\ttfamily}l@{}} + \toprule + \multicolumn{1}{@{}l}{Option name} & + Type & + \multicolumn{1}{l@{}}{Default} \\ + \midrule + color & Literal & \meta{none} \\ + mode & Choice & math \\ + number-color & Literal & \meta{none} \\ + number-mode & Choice & math \\ + propagate-math-font & Switch & false \\ + reset-math-version & Switch & true \\ + reset-text-family & Switch & true \\ + reset-text-series & Switch & true \\ + reset-text-shape & Switch & true \\ + text-family-to-math & Switch & false \\ + text-font-command & Literal & \meta{none} \\ + text-series-to-math & Switch & false \\ + unit-color & Literal & \meta{none} \\ + unit-mode & Choice & math \\ + \bottomrule + \end{tabular} +\end{table} + +\DescribeOption{mode} +\DescribeOption{number-mode} +\DescribeOption{unit-mode} +The \opt{mode} option determines whether \pkg{siunitx} uses math or text mode +when printing output. The choices are \opt{match}, \opt{math}, \opt{text}. The +\opt{match} setting means that printing uses the prevailing mode unchanged +whereas \opt{math} and \opt{text} select the appropriate \TeX{} mode. It is +possible to have different fonts in math and text modes, which will highlight +the difference. The font settings which apply are also different depending on +the mode. As well as the overall setting, it is possible to apply mode +to numbers and units separately using the \opt{number-mode} and \opt{unit-mode} +options. + +\DescribeOption{reset-text-family} +\DescribeOption{reset-text-series} +\DescribeOption{reset-text-shape} +When printing in text mode, the options \opt{reset-text-family}, +\opt{reset-text-series} and \opt{reset-text-shape} apply. When these are +active, \pkg{siunitx} resets the relevant font selection axis property +when printing: the standard font setting is upright mid-weight roman +(|\upshape| |\mdseries| |\rmfamily|). +\begin{LaTeXdemo} + \sisetup{mode = text} + {\itshape \num{1234}}\\ + {\bfseries \num{1234}}\\ + {\sffamily \num{1234}}\\ + \sisetup{ + reset-text-family = false , + reset-text-series = false , + reset-text-shape = false + } + {\itshape \num{1234}}\\ + {\bfseries \num{1234}}\\ + {\sffamily \num{1234}}\\ +\end{LaTeXdemo} + +\DescribeOption{propagate-math-font} +\DescribeOption{reset-math-version} +In math mode, the font used by \LaTeX{} is \enquote{invariant}, and this is +reflected in the options available. With the standard settings, in math mode +printing uses the standard math font and version (weight). The option +\opt{propagate-math-font} may be used to apply the a prevailing math font +to the printed material. The setting \opt{reset-math-version} controls +whether the math version is reset or not. Note that math version is typically +used to set \enquote{bold math} but may also be used for other effects, for +example all sanserif math. +\begin{LaTeXdemo} + {\boldmath \unit{\kilogram}}\\ + {\sansmath $\unit{\kilogram}$}\\ + {$\mathsf{\unit{\kilogram}}$}\\ + \sisetup{ + propagate-math-font = true , + reset-math-version = false + } + {\boldmath \unit{\kilogram}}\\ + {\sansmath $\unit{\kilogram}$}\\ + {$\mathsf{\unit{\kilogram}}$} +\end{LaTeXdemo} + +\DescribeOption{text-family-to-math} +\DescribeOption{text-series-to-math} +The options \opt{text-family-to-math} and \opt{text-family-to-math} can be +used to match (as far as possible) math mode output to the surrounding text. +These options work by detecting the current text settings and making the +appropriate choice in math mode. +\begin{LaTeXdemo} + {\sffamily \unit{\kilogram}}\\ + {\bfseries $\unit{\kilogram}$}\\ + \sisetup{ + text-family-to-math = true , + text-series-to-math = true + } + {\sffamily \unit{\kilogram}}\\ + {\bfseries $\unit{\kilogram}$} +\end{LaTeXdemo} + +\DescribeOption{text-font-command} +In some circumstances, it may be desirable to use a non-standard font command +when printing in text mode. This might be used for example to switch from +old-style to lining numbers whilst still using text mode. This may be achieved +by setting \opt{text-font-command}. For example, this document uses old-style +numbers in text mode as-standard, which can be over-ridden by selecting the +font variant which does not feature them. +\begin{LaTeXdemo} + \sisetup{number-mode = text} + \qty{123456789}{\kilo\volt\per\centi\metre} \\ + \sisetup{text-font-command = \fontfamily{pplx}\selectfont} + \qty{123456789}{\kilo\volt\per\centi\metre} +\end{LaTeXdemo} + +\DescribeOption{color} +\DescribeOption{number-color} +\DescribeOption{unit-color} +The color of printed output can be set using the \opt{color} option. When no +color is given, printing follows the surrounding text. In contrast, when a +specific color is given, it is used irrespective of the surroundings. As with +\opt{mode}, the \opt{color} setting may also be applied to numbers and units +independently. +\begin{LaTeXdemo} + \color{red}% + Some text \\ + \qty{4}{\kilogram} \\ + More text \\ + \qty[color = blue]{4}{\kilogram} \\ + Still red here! +\end{LaTeXdemo} + +\subsection{Parsing numbers} + +The package uses a sophisticated parsing system to understand numbers. This +allows \pkg{siunitx} to carry out a range of formatting, as described later. +All of the input options take lists of literal tokens, and are summarised in +Table~\ref{tab:opt:num:in}. +\begin{table} + \caption{Options for number parsing.% + \label{tab:opt:num:in}} + \begin{tabular}{@{}>{\ttfamily}ll>{\ttfamily}l@{}} + \toprule + \multicolumn{1}{@{}l}{Option name} & + Type & + \multicolumn{1}{l@{}}{Default} \\ + \midrule + evaluate-expression & Switch & false \\ + expression & Literal & |#1| \\^^A ( + input-close-uncertainty & Literal & ) \\ + input-comparators & Literal & + <=>\cs{approx}\cs{ge}\cs{geq} \\ + & & \cs{gg}\cs{le}\cs{leq}\cs{ll} \cs{sim} \\ + input-decimal-markers & Literal & ., \\ + input-digits & Literal & 0123456789 \\ + input-exponent-markers & Literal & dDeE \\ + input-ignore & Literal & \meta{none} \\ + input-open-uncertainty & Literal & ( \\ ^^A ) + input-signs & Literal & +-\cs{pm}\cs{mp} \\ + input-uncertainty-signs & Literal & \cs{pm} \\ + parse-numbers & Switch & true \\ + retain-explicit-plus & Switch & false \\ + retain-zero-uncertainty & Switch & false \\ + \bottomrule + \end{tabular} +\end{table} + +\DescribeOption{input-digits} +\DescribeOption{input-decimal-markers} +\DescribeOption{input-signs} +\DescribeOption{input-exponent-markers} +The basic parts of a number are the digits, any sign and a separator between +the integer and decimal parts. These are stored in the input options +\opt{input-digits}, \opt{input-decimal-markers} and \opt{input-signs}, +respectively. More than one input decimal marker can be used: it will be +converted by the package to the appropriate output marker. Numbers which +include an exponent part also require a marker for the exponent: this again is +taken from the range of tokens in the \opt{input-exponent-markers} option. + +\DescribeOption{input-ignore} +Tokens given in the \opt{input-ignore} list are totally passed over by +\pkg{siunitx}: they will be removed from the input with no further processing. + +\DescribeOption{input-comparators} +In addition to signs, \pkg{siunitx} can recognise comparators, such as |<|. The +package will automatically carry out conversions for |<<|, |>>|, |<=| and |>=| +to |\ll|, |\gg|, |\le| and |\ge|, respectively. +\begin{LaTeXdemo} + \num{< 10} \\ + \qty{>> 5}{\metre} \\ + \num{\le 0.12} +\end{LaTeXdemo} + +\DescribeOption{input-open-uncertainty} +\DescribeOption{input-close-uncertainty} +\DescribeOption{input-uncertainty-signs} +In some fields, it is common to give the uncertainty in a number in brackets +after the main part of the number, for example \enquote{\num{1.234(5)}}. The +opening and closing symbols used for this type of input are set as +\opt{input-open-uncertainty} and \opt{input-close-uncertainty}. Alternatively, +the uncertainty may be given as a separate part following a sign. Which signs +are valid for this operation is determined by the \opt{input-uncertainty-signs} +option. As with other signs, the combination |+-| will automatically be +converted to |\pm| internally. +\begin{LaTeXdemo} + \num{9.99(9)} \\ + \num{9.99 +- 0.09} \\ + \num{9.99 \pm 0.09} \\ + \num{123 +- 4.5} \\ + \num{12.3 +- 6} +\end{LaTeXdemo} + +Uncertainties which cross the decimal marker may be given with or without a +decimal marker in \enquote{compact} form. These are treated as equivalent by +the code.\footnote{The package author favors the form without a decimal marker, +and formal guidance is ambiguous on which is correct. The form with a decimal +marker is seen in for example some \acro{NIST} publications.} +\begin{LaTeXdemo} + \num{123.4(12)} \\ + \num{123.4(1.2)} +\end{LaTeXdemo} + +\DescribeOption{parse-numbers} +The \opt{parse-numbers} option turns the entire parsing system on and off. The +option is made available for two reasons. First, if all of the numbers in a +document are to be reproduced \enquote{as given}, turning off the parser will +represent a significant saving in processing required. Second, it allows the +use of arbitrary \TeX{} code in numbers. If the parser is turned off, the input +will be printed in math mode (requiring |\text| to protect any text in the +number). +\begin{LaTeXdemo} + \num[parse-numbers = false]{\sqrt{2}} \\ + \qty[parse-numbers = false]{\sqrt{3}}{\metre} +\end{LaTeXdemo} + +\DescribeOption{evaluate-expression} +\DescribeOption{expression} +With the standard settings, numerical input is parsed \enquote{as is} with no +attempt to interpret it mathematically. By enabling the +\opt{evaluate-expression} option, the input can be processed by the standard +\LaTeX3 \acro{FPU} (see package \pkg{xfp} for more). The nature of the +expression itself can be adjusted using the \opt{expression} setting: as +standard, the entire input is simply parsed with no change, but this setting +may be used to add additional steps. The \emph{input} in such an expression is +represented by |#1|. Note that the \acro{FPU} uses its own syntax for numbers, +most notably in that a decimal marker must be |.|. +\begin{LaTeXdemo} + \sisetup{evaluate-expression}% + \qty{2 + 4 * 3}{\joule} \\ + \qty[expression = 10 * (#1)]{2 + 4 * 3}{\joule} +\end{LaTeXdemo} + +\DescribeOption{retain-explicit-plus} +\DescribeOption{retain-zero-uncertainty} +The inclusion of a leading plus sign is usually unnecessary for positive +numbers, and so they are not retained as-standard when parsing. The +\opt{retain-explicit-plus} option is available to control this behaviour. +Similarly, an uncertainty of zero is normally not meaningful, and so is +ignored by the parser. This can be controlled using the +\opt{retain-zero-uncertainty} option. +\begin{LaTeXdemo} + \num{+345} \\ + \num[retain-explicit-plus]{+345} \\ + \num{12.3(0)} \\ + \num[retain-zero-uncertainty]{12.3(0)} +\end{LaTeXdemo} + +\subsection{Post-processing numbers} + +Before typesetting numbers, various post-processing steps can be carried out. +These involve adding or removing information from the number in a systematic +way; the options are summarised in Table~\ref{tab:opt:num:post}. +\begin{table} + \caption{Number post-processing options.% + \label{tab:opt:num:post}} + \begin{tabular}{@{}>{\ttfamily}ll>{\ttfamily}l@{}} + \toprule + \multicolumn{1}{@{}l}{Option name} & + Type & + \multicolumn{1}{l@{}}{Default} \\ + \midrule + drop-exponent & Switch & false \\ + drop-uncertainty & Switch & false \\ + drop-zero-decimal & Switch & false \\ + exponent-mode & Switch & input \\ + fixed-exponent & Integer & 0 \\ + minimum-integer-digits & Integer & 0 \\ + minimum-decimal-digits & Integer & 0 \\ + round-half & Choice & up \\ + round-minimum & Literal & 0 \\ + round-mode & Choice & none \\ + round-pad & Switch & true \\ + round-precision & Integer & 2 \\ + \bottomrule + \end{tabular} +\end{table} + +\DescribeOption{exponent-mode} +\DescribeOption{fixed-exponent} +Numbers can be converted to scientific notation by the package. This is +controlled by the \opt{exponent-mode} option, which takes choices \opt{input}, +\opt{fixed}, \opt{engineering} and \opt{scientific}. The \opt{fixed} setting +will use the exponent value by the \opt{fixed-exponent} option. When +\opt{engineering} is set, the exponent is always a power of three. +\begin{LaTeXdemo} + \num{0.001} \\ + \num{0.0100} \\ + \num{1200} \\ + \sisetup{exponent-mode = scientific}% + \num{0.001} \\ + \num{0.0100} \\ + \num{1200} \\ + \sisetup{exponent-mode = engineering}% + \num{0.001} \\ + \num{0.0100} \\ + \num{1200} \\ + \sisetup{ + exponent-mode = fixed, + fixed-exponent = 2, + }% + \num{0.001} \\ + \num{0.0100} \\ + \num{1200} +\end{LaTeXdemo} +When used with a \opt{fixed-exponent} of zero, this may be used to remove +scientific notation from the input +\begin{LaTeXdemo} + \num{1.23e4} \\ + \num[exponent-mode = fixed, fixed-exponent = 0]{1.23e4} +\end{LaTeXdemo} +Exponent mode applies \emph{after} rounding, such that the number of decimal +places for rounding is those which appear in the output. + +\DescribeOption{drop-exponent} +\DescribeOption{drop-uncertainty} +The use of an uncertainty can be suppressed entirely using the +\opt{drop-uncertainty} option: this applies \emph{before} rounding is +attempted. Similarly, exponents can be dropped using \opt{drop-exponent} can be +used to suppress the exponent part (\emph{after} conversion to a fixed +exponent). +\begin{LaTeXdemo} + \num{0.01(2)} \\ + \num[drop-uncertainty]{0.01(2)} \\ + \num{0.01e3} \\ + \num[drop-exponent]{0.01e3} +\end{LaTeXdemo} + +\DescribeOption{round-mode} +\DescribeOption{round-precision} +\DescribeOption{round-pad} +The package can round numerical input to a fixed number of significant figures +or decimal places. This is controlled by the \opt{round-mode} option, which +takes the choices \opt{none}, \opt{figures}, \opt{places} and +\opt{uncertainty}. When rounding is turned on, the number of digits used +(either decimal places or significant figures in the mantissa) is set using the +\opt{round-precision} option. Rounding numbers with uncertainties may be +carried out using the \opt{uncertainty} setting to \opt{round-mode}. In this +case the precision is used first to round the uncertainty itself (to a number +of figures), before rounding the main value to follow. +\begin{LaTeXdemo} + \num{1.23456} \\ + \num{14.23} \\ + \num{0.12345(9)} \\ + \sisetup{ + round-mode = places, + round-precision = 3 + }% + \num{1.23456} \\ + \num{14.23} \\ + \num{0.12345(9)} \\ + \sisetup{ + round-mode = figures, + round-precision = 3 + }% + \num{1.23456} \\ + \num{14.23} \\ + \num{0.12345(9)} \\ + \sisetup{ + round-mode = uncertainty, + round-precision = 1 + }% + \num{0.12345(9)} \\ + \num{0.12345(23)} \\ + \num{0.12345(234)} +\end{LaTeXdemo} +Rounding my \enquote{extend} a short number to more digits (or figures): this +is controlled by the switch \opt{round-pad}, which is \opt{true} as standard. +\begin{LaTeXdemo} + \sisetup{round-mode = figures, round-precision = 4}% + \num{12.3} \\ + \num[round-pad = false]{12.3} +\end{LaTeXdemo} + +\DescribeOption{round-half} +In cases where the rounded part of a number is exactly half, there are two +common methods for \enquote{breaking the tie}. The choice of method is +determined by the option \opt{round-half}, which recognises the choices +\opt{up} and \opt{even}. +\begin{LaTeXdemo} + \sisetup{ + round-mode = figures, + round-precision = 1, + round-half = up + }% + \num{0.055} \\ + \num{0.045} \\ + \sisetup{round-half = even}% + \num{0.055} \\ + \num{0.045} +\end{LaTeXdemo} + +\DescribeOption{round-minimum} +There are cases in which rounding will result in the number reaching zero. It +may be desirable to show such results as below a threshold value. This can be +achieved by setting \opt{round-minimum} to the threshold value. There will be +no effect when rounding to a number of significant figures as it is not +possible to obtain the value zero in these cases. +\begin{LaTeXdemo} + \sisetup{round-mode = places}% + \num{0.0055} \\ + \num{0.0045} \\ + \sisetup{round-minimum = 0.01}% + \num{0.0055} \\ + \num{0.0045} +\end{LaTeXdemo} + +\DescribeOption{drop-zero-decimal} +It may be desirable to convert decimals to integers when the decimal part is +zero. This is set up using the \opt{drop-zero-decimal} option, which applies +after rounding but before setting minimum numbers of digits. +\begin{LaTeXdemo} + \num{2.0} \\ + \num{2.1} \\ + \sisetup{drop-zero-decimal}% + \num{2.0} \\ + \num{2.1} +\end{LaTeXdemo} + +\DescribeOption{minimum-decimal-digits} +\DescribeOption{minimum-integer-digits} +The \opt{minimum-decimal-digits} and \opt{minimum-integer-digits} option may be +used to pad numbers to a given size. This applies independent of any rounding. +\begin{LaTeXdemo} + \num{123} \\ + \num[minimum-integer-digits = 2]{123} \\ + \num[minimum-integer-digits = 4]{123} \\ + \num{0.123} \\ + \num[minimum-decimal-digits = 2]{0.123} \\ + \num[minimum-decimal-digits = 4]{0.123} \\ +\end{LaTeXdemo} + +\subsection{Printing numbers} + +Actually printing numbers is controlled by a number of settings, which apply +ideas such as differing decimal markers, digit grouping and so on. All of these +options are concerned with the appearance of output, rather than the data it +conveys. The options are summarised in Table~\ref{tab:opt:num:out}. +\begin{table} + \caption{Output options for numbers.% + \label{tab:opt:num:out}} + \begin{tabular}{@{}>{\ttfamily}ll>{\ttfamily}l@{}} + \toprule + \multicolumn{1}{l}{Option name} & + Type & + \multicolumn{1}{l}{Default} \\ + \midrule + bracket-negative-numbers & Switch & false \\ + exponent-base & Literal & 10 \\ + exponent-product & Math & \verb=\times= \\ + group-digits & Choice & all \\ + group-minimum-digits & integer & 5 \\ + group-separator & Literal & \cs{,} \\ + negative-color & Literal & \meta{none} \\ ^^A ( + output-close-uncertainty & Literal & ) \\ + output-decimal-marker & Literal & . \\ + output-open-uncertainty & Literal & ( \\ ^^A ) + print-implicit-plus & Switch & false \\ + print-unity-mantissa & Switch & true \\ + print-zero-exponent & Switch & false \\ + tight-spacing & Switch & false \\ + uncertainty-mode & Choice & compact \\ + uncertainty-separator & Literal & \meta{none} \\ + \bottomrule + \end{tabular} +\end{table} + +\DescribeOption{group-digits} +\DescribeOption{group-four-digits} +\DescribeOption{group-separator} +Grouping digits into blocks of three is a common method to increase the ease of +reading of numbers. The \opt{group-digits} choice controls whether this +behaviour applies, and takes the values \opt{all}, \opt{none}, \opt{decimal} +and \opt{integer}. Grouping can be activated separately for the integer and +decimal parts of a number using the appropriately-named values. +\begin{LaTeXdemo} + \num{12345.67890} \\ + \num[group-digits = none]{12345.67890} \\ + \num[group-digits = decimal]{12345.67890} \\ + \num[group-digits = integer]{12345.67890} +\end{LaTeXdemo} +The separator used between groups of digits is stored by the +\opt{group-separator} option. This takes literal input and may be used in math +mode: for a text-mode full space use \verb*|\ |. +\begin{LaTeXdemo} + \num{12345} \\ + \num[group-separator = {,}]{12345} \\ + \num[group-separator = \ ]{12345} +\end{LaTeXdemo} + +\DescribeOption{group-minimum-digits} +Grouping is not always applied to smaller numbers; this can be controlled using +the option \opt{group-minimum-digits}, which specifies how many digits must be +present before grouping is applied. The number of digits is considered +separately for the integer and decimal parts of the number: grouping does not +\enquote{cross the boundary}. +\begin{LaTeXdemo} + \num{1234} \\ + \num{12345} \\ + \num[group-minimum-digits = 5]{1234} \\ + \num[group-minimum-digits = 5]{12345} \\ + \num{1234.5678} \\ + \num{12345.67890} \\ + \num[group-minimum-digits = 5]{1234.5678} \\ + \num[group-minimum-digits = 5]{12345.67890} +\end{LaTeXdemo} + +\DescribeOption{output-decimal-marker} +The decimal marker used in output is set using the \opt{output-decimal-marker} +option; this can differ from the input marker. +\begin{LaTeXdemo} + \num{1.23} \\ + \num[output-decimal-marker = {,}]{1.23} \\ +\end{LaTeXdemo} + +\DescribeOption{exponent-base} +\DescribeOption{exponent-product} +When exponents are present in the input, the \opt{exponent-base} and +\opt{exponent-product} options set the obvious parts of the output. +\begin{LaTeXdemo} + \num[exponent-product = \times]{1e2} \\ + \num[exponent-product = \cdot]{1e2} \\ + \num[exponent-base = 2]{1e2} +\end{LaTeXdemo} + +\DescribeOption{uncertainty-separator} +\DescribeOption{output-open-uncertainty} +\DescribeOption{output-close-uncertainty} +\DescribeOption{uncertainty-separator} +When input is given including an uncertainty in a number, it can be printed +either with the uncertainty in brackets or as a separate number. This behaviour +is controlled by the \opt{uncertainty-mode} choice.When this is set to +\opt{separate}, the uncertainty is printed as an entirely separate number +preceded by \cs{pm}. Other settings all place the uncertainty in brackets +directly attached to the main value. The standard setting of \opt{compact} +prints digits of uncertainty in the least-significant digits. It does +\emph{not} print a decimal marker if the uncertainty crosses the decimal. The +setting \opt{full} prints the full value of the uncertainty. Finally, +\opt{compact-marker} is available to print in the \opt{compact} style except +where the uncertainty crosses the decimal, in which case the \opt{full} style +is used. When the uncertainty is given in brackets, a space may be added +between the main number and the uncertainty: this is stored using the +\opt{uncertainty-separator} option. The opening and closing brackets used are +stored in \opt{output-open-uncertainty} and \opt{output-close-uncertainty}, +respectively. Tokens may be inserted before the opening bracket using +\opt{uncertainty-separator}. +\begin{LaTeXdemo} + \num{123.45(120)} \\ + \num{0.035(14)} \\ + \sisetup{uncertainty-mode = full} + \num{123.45(120)} \\ + \num{0.035(14)} \\ + \sisetup{uncertainty-mode = compact-marker} + \num{123.45(120)} \\ + \num{0.035(14)} \\ + \sisetup{uncertainty-mode = separate} + \sisetup{ + output-open-uncertainty = [, + output-close-uncertainty = ], + uncertainty-separator = \, + }% + \num{1.234(5)} +\end{LaTeXdemo} + +\DescribeOption{bracket-ambiguous-numbers} +There are certain combinations of numerical input which can be ambiguous. This +can be corrected by adding brackets in the appropriate place, and is controlled +by the \opt{bracket-ambiguous-numbers} switch. This option only applies to pure +numbers: when formatting quantities, the need for brackets also depends on the +placement of units, so is controlled by \opt{seperate-uncertainty-units}. +\begin{LaTeXdemo} + \sisetup{separate-uncertainty} + \num{1.2(3)e4} \\ + \num[bracket-ambiguous-numbers = false]{1.2(3)e4} +\end{LaTeXdemo} + +\DescribeOption{negative-color} +The package can detect negative mantissa values and alter print color +accordingly. This is disabled by setting the option to an empty value. +\begin{LaTeXdemo} + \num{-15673} \\ + \num[negative-color = red]{-15673} +\end{LaTeXdemo} + +\DescribeOption{bracket-negative-numbers} +A common means to display negative numbers in financial situations is to place +them in brackets. This can be carried out automatically using the +\opt{bracket-negative-numbers} option. +\begin{LaTeXdemo} + \num{-15673} \\ + \num[bracket-negative-numbers]{-15673} \\ + \qty{-10}{\metre} \\ + \qty[bracket-negative-numbers]{-10}{\metre} +\end{LaTeXdemo} + +\DescribeOption{tight-spacing} +Under some circumstances is may be desirable to \enquote{squeeze} the output +spacing. This is turned on using the \opt{tight-spacing} switch, which +compresses spacing where possible. +\begin{LaTeXdemo} + \num{2e3} \\ + \num[tight-spacing = true]{2e3} +\end{LaTeXdemo} + +\DescribeOption{print-implicit-plus} +It may be useful to force all numbers to have a sign. This behaviour is +controlled by the \opt{print-implicit-plus} option: this is used if given and +if no sign was present in the input. +\begin{LaTeXdemo} + \num{345} \\ + \num[print-implicit-plus]{345} +\end{LaTeXdemo} + +\DescribeOption{print-unity-mantissa} +\DescribeOption{print-zero-exponent} +Printing of a mantissa of $1$ and an exponent of $0$ is controllable by the +options \opt{print-unity-mantissa} and \opt{print-zero-exponent}. The standard +settings print a mantissa of $1$ but omit an exponent of $0$. +\begin{LaTeXdemo} + \num{1e4} \\ + \num[print-unity-mantissa = false]{1e4} \\ + \num{444e0} \\ + \num[print-zero-exponent = true]{444e0} +\end{LaTeXdemo} + +\subsection{Lists, products and ranges} + +Lists, products and ranges of numbers and quantities have a small number of +specialised options, which apply to these more unusual input forms +(Table~\ref{tab:opt:num:list}). +\begin{table} + \begin{threeparttable} + \caption{Output options for lists, products and ranges of numbers and + quantities.% + \label{tab:opt:num:list}} + \begin{tabular}{@{}>{\ttfamily}ll>{\ttfamily}l@{}} + \toprule + \multicolumn{1}{l}{Option name} & + Type & + \multicolumn{1}{l}{Default\tnote{*}} \\ + \midrule + list-exponents & Choice & individual \\ + list-final-separator & Literal & \verb*= \text{and} = \\ + list-pair-separator & Literal & \verb*= \text{and} = \\ + list-separator & Literal & \verb*=\text{,} = \\ + list-units & Choice & repeat \\ + product-exponents & Choice & individual \\ + product-mode & Choice & symbol \\ + product-phrase & Literal & \verb*= \text{by} = \\ + product-symbol & Literal & \cs{times} \\ + product-units & Choice & repeat \\ + range-exponents & Choice & individual \\ + range-phrase & Literal & \verb*= \text{to} = \\ + range-units & Choice & repeat \\ + \bottomrule + \end{tabular} + \footnotesize + \begin{tablenotes} + \item[*] The default values are actually more complex for two + reasons: allowing spaces to work in both math and text modes, + and localization of strings. + \end{tablenotes} + \end{threeparttable} +\end{table} + +\DescribeOption{list-final-separator} +\DescribeOption{list-pair-separator} +\DescribeOption{list-separator} +Lists of numbers are printed with a separator between each item, which is +stored using the \opt{list-separator} option. The separator before the last +item of a list may be different, and is therefore set using the +\opt{list-final-separator} option. The separator used for exactly two items is +set using the \opt{list-pair-separator} option. Any spaces needed should be +included in the option settings: none are added within the code. The separators +are always printed in text mode. +\begin{LaTeXdemo} + \numlist{0.1;0.2;0.3} \\ + \numlist[list-separator = {; }]{0.1;0.2;0.3} \\ + \numlist[list-final-separator = {, }]{0.1;0.2;0.3} \\ + \numlist[ + list-separator = { and }, + list-final-separator = { and finally } + ]{0.1;0.2;0.3} \\ + \numlist{0.1;0.2} \\ + \numlist[list-pair-separator = {, and }]{0.1;0.2} +\end{LaTeXdemo} + +\DescribeOption{product-mode} +\DescribeOption{product-phrase} +\DescribeOption{product-symbol} +Products of numbers can be output using either a product symbol or phrase: +this is controlled by the \opt{product-mode} setting. When \opt{symbol} is +set, the appropriate symbol is stored in \opt{product-symbol}. When using +\opt{phrase-mode}, the information is stored in \opt{product-phrase}. Phrases +are always printed in text mode; symbols are printed using the same routine +as for numbers. +\begin{LaTeXdemo} + \numproduct{5 x 100 x 2} \\ + \numproduct[product-symbol = \ensuremath{\cdot}]{5 x 100 x 2} \\ + \sisetup{product-mode = phrase}% + \numproduct{5 x 100 x 2}\\ + \numproduct[product-phrase = { BY }]{5 x 100 x 2} \\ +\end{LaTeXdemo} + +\DescribeOption{range-phrase} +Ranges of numbers can be given as input. These will have an appropriate word or +symbol inserted between the two entries: this is stored using the +\opt{range-phrase} option. The phrase should include any necessary spaces: no +extra space is added. The phrase is always printed in text mode. +\begin{LaTeXdemo} + \numrange{5}{100} \\ + \numrange[range-phrase = --]{5}{100} +\end{LaTeXdemo} + +\DescribeOption{list-exponents} +\DescribeOption{product-exponents} +\DescribeOption{range-exponents} +Lists, products and ranges can be \enquote{compressed} by combining the +exponent parts. This is controlled by the options \opt{list-exponents}, +\opt{product-exponents} and \opt{range-exponents}, all of which take the +choices \opt{individual}, \opt{combine-bracket} and \opt{combine}. The standard +setting, \opt{individual}, leaves the exponent with the matching value. Both +\opt{combine} and \opt{combine-bracket} take the exponent of the first entry +and apply to to all other entries, with the exponent itself places at the end. +\begin{LaTeXdemo} + \numlist{5e3;7e3;9e3;1e4} \\ + \numproduct{5e3 x 7e3 x 9e3 x 1e4} \\ + \numrange{5e3}{7e3} \\ + \sisetup + { + list-exponents = combine-bracket , + product-exponents = combine-bracket , + range-exponents = combine-bracket + } + \numlist{5e3;7e3;9e3;1e4} \\ + \numproduct{5e3 x 7e3 x 9e3 x 1e4} \\ + \numrange{5e3}{7e3} \\ + \sisetup + { + list-exponents = combine , + product-exponents = combine , + range-exponents = combine + } + \numlist{5e3;7e3;9e3;1e4} \\ + \numproduct{5e3 x 7e3 x 9e3 x 1e4} \\ + \numrange{5e3}{7e3} +\end{LaTeXdemo} + +\DescribeOption{list-units} +\DescribeOption{product-units} +\DescribeOption{range-units} +The \opt{list-units}, \opt{product-units} and \opt{range-units} options +determine how \cs{qtylist}, \cs{qtyproduct} and \cs{qtyrange} command print +units, respectively. The standard setting for these is \opt{repeat}, where each +number will be printed with a unit. Alternatives are \opt{bracket} and +\opt{single}. If set to \opt{single}, this will override collection of +exponents. +\begin{LaTeXdemo} + \qtylist{2;4;6;8}{\tesla} \\ + \qtylist[list-units = bracket]{2;4;6;8}{\tesla} \\ + \qtylist[list-units = repeat]{2;4;6;8}{\tesla} \\ + \qtylist[list-units = single]{2;4;6;8}{\tesla} \\ + \qtyrange{2}{4}{\degreeCelsius} \\ + \qtyrange[range-units = bracket]{2}{4}{\degreeCelsius} \\ + \qtyrange[range-units = repeat]{2}{4}{\degreeCelsius} \\ + \qtyrange[range-units = single]{2}{4}{\degreeCelsius} +\end{LaTeXdemo} + +\subsection{Complex numbers} + +A small number of options apply specifically to the handling of complex +numbers; these are summarised in Table~\ref{tab:opt:num:complex}. +\begin{table} + \caption{Options for complex numbers.% + \label{tab:opt:num:complex}} + \begin{tabular}{@{}>{\ttfamily}ll>{\ttfamily}l@{}} + \toprule + \multicolumn{1}{@{}l}{Option name} & + Type & + \multicolumn{1}{l@{}}{Default} \\ + \midrule + complex-root-position & Choice & after-number \\ + input-complex-root & Literal & ij \\ + output-complex-root & Literal & \verb=\mathrm{i}= \\ + \bottomrule + \end{tabular} +\end{table} + +\DescribeOption{input-complex-root} +When using complex numbers in input, the complex root $(\mathrm{i} = +\sqrt{-1}\,)$ is indicated by one of the tokens stored in +\opt{input-complex-roots}. The parser understands complex root symbols given +either before or after the associated number (but will detect any invalid +arrangement): +\begin{LaTeXdemo} + \complexnum{9.99 + 88.8i} \\ + \complexnum{9.99 + i88.8} +\end{LaTeXdemo} + +\DescribeOption{output-complex-root} +The output complex root symbol is independent of the input and can be changed +using the \opt{output-complex-root} setting. +\begin{LaTeXdemo} + \complexnum[output-complex-root = i]{1+2i} \\ + \complexnum[output-complex-root = j]{1+2i} +\end{LaTeXdemo} + +\DescribeOption{complex-root-position} + The position of the complex root can be adjusted to place it + either before or after the associated numeral in a complex number + using the \opt{complex-root-position} option. +\begin{LaTeXdemo} + \complexnum{67-0.9i} \\ + \complexnum[complex-root-position = before-number]{67-0.9i} \\ + \complexnum[complex-root-position = after-number]{67-0.9i} +\end{LaTeXdemo} + +\subsection{Angles} + +Angle processing provided by the \cs{ang} function has a set of options which +apply in addition to the general ones set up for number processing. +\begin{table} + \caption{Angle options.% + \label{tab:opt:ang}} + \begin{tabular}{@{}>{\ttfamily}ll>{\ttfamily}l@{}} + \toprule + \multicolumn{1}{@{}l}{Option name} & + Type & + \multicolumn{1}{l@{}}{Default} \\ + \midrule + angle-mode & Choice & input \\ + angle-symbol-degree & Literal & \cs{degree} \\ + angle-symbol-minute & Literal & \cs{arcminute} \\ + angle-symbol-over-decimal & Switch & false \\ + angle-symbol-second & Literal & \cs{arcsecond} \\ + angle-separator & Literal & \meta{empty} \\ + fill-angle-degrees & Switch & false \\ + fill-angle-minutes & Switch & false \\ + fill-angle-seconds & Switch & false \\ + number-angle-product & Literal & \meta{empty} \\ + \bottomrule + \end{tabular} +\end{table} + +\DescribeOption{angle-mode} +The format in which angles are printed can be set using the \opt{angle-mode} +option. With the standard setting (\opt{input}), the angle is printed as-given. +By setting the option to \opt{arc} or \opt{decimal}, the output format can +be set to an arc (degrees/minutes/seconds) or decimal value. Conversion uses +the \LaTeX3 floating-point unit, so is limited to $16$ decimal places. +\begin{LaTeXdemo} + \ang{2.67} \\ + \ang{2;3;4} \\ + \ang[angle-mode = arc]{2.67} \\ + \ang[angle-mode = arc]{2;3;4} \\ + \ang[angle-mode = decimal]{2.67} \\ + \ang[angle-mode = decimal]{2;3;4} \\ +\end{LaTeXdemo} + +\DescribeOption{number-angle-product} +The separator between the number and angle symbol (degrees, minutes or seconds) +can be set using the \opt{number-angle-product} option, independent of the +related \opt{number-unit-product} option used by the \cs{qty} command. +\begin{LaTeXdemo} + \ang{2.67} \\ + \ang[number-angle-product = \,]{2.67} +\end{LaTeXdemo} + +\DescribeOption{angle-separator} +When angles are printed in arc format, the separation of the different parts is +set up using the \opt{arc-separator} option. +\begin{LaTeXdemo} + \ang{6;7;6.5} \\ + \ang[angle-separator = \,]{6;7;6.5} +\end{LaTeXdemo} + +\DescribeOption{fill-angle-degrees} +\DescribeOption{fill-angle-minutes} +\DescribeOption{fill-angle-seconds} +Zero-filling for the degree, minute or second parts of an arc is controlled +using the \opt{fill-angle-degrees}, \opt{fill-angle-minutes} and +\opt{fill-angle-seconds} options. All are off as standard. +\begin{LaTeXdemo} + \ang{-1;;} \\ + \ang{;-2;} \\ + \ang{;;-3} \\ + { + \sisetup{fill-angle-degrees} + \ang{-1;;} \\ + \ang{;-2;} \\ + \ang{;;-3} \\ + } + { + \sisetup{fill-angle-minutes} + \ang{-1;;} \\ + \ang{;-2;} \\ + \ang{;;-3} \\ + } + { + \sisetup{fill-angle-seconds} + \ang{-1;;} \\ + \ang{;-2;} \\ + \ang{;;-3} + } +\end{LaTeXdemo} + +\DescribeOption{angle-symbol-degree} +\DescribeOption{angle-symbol-minute} +\DescribeOption{angle-symbol-second} +With the standard settings, the symbols used for arc angles are the unit +commands \cs{degree}, \cs{arcminute} and \cs{arcsecond}. These can be altered +using \opt{angle-symbol-degree}, \opt{angle-symbol-minute} and +\opt{angle-symbol-second}. This is most likely to be used when the definition +of the unit macros is altered, for example to set \cs{arcsecond} as +\texttt{as}. +\begin{LaTeXdemo} + \ang{6;7;6.5} \\ + \sisetup{ + angle-symbol-degree = d , + angle-symbol-minute = m , + angle-symbol-second = s + } + \ang{6;7;6.5} +\end{LaTeXdemo} + +\DescribeOption{angle-symbol-over-decimal} +In some subject areas, most notably astronomy, the angle symbols are given over +the decimal marker, rather than at the end of the number. This behaviour is +available using the \opt{angle-symbol-over-decimal} option. +\begin{LaTeXdemo} + \ang{45.697} \\ + \ang{6;7;6.5} \\ + \ang[angle-symbol-over-decimal]{45.697} \\ + \ang[angle-symbol-over-decimal]{6;7;6.5} +\end{LaTeXdemo} + +\subsection{Creating units% + \label{sec:units:creating}} + +The various macro units are created at the start of the document. \pkg{siunitx} +can define these such that they are only available for use within the \cs{unit} +and \cs{qty} functions, or can make the unit macros available throughout the +document body. There are a number of settings which control this creation +process (Table~\ref{tab:opt:units:def}). As a result, these options all apply +in the preamble only. +\begin{table} + \caption{Unit creation options.% + \label{tab:opt:units:def}} + \begin{tabular}{@{}>{\ttfamily}ll>{\ttfamily}l@{}} + \toprule + \multicolumn{1}{@{}l}{Option name} & + Type & + \multicolumn{1}{l@{}}{Default} \\ + \midrule + free-standing-units & Switch & false \\ + overwrite-command & Switch & false \\ + space-before-unit & Switch & false \\ + unit-optional-argument & Switch & false \\ + use-xspace & Switch & false \\ + \bottomrule + \end{tabular} +\end{table} + +\DescribeOption{free-standing-units} +\DescribeOption{overwrite-functions} +The \opt{free-standing-units} option controls whether the unit macros exist +outside of the \cs{unit} and \cs{qty} arguments. When this option is +\opt{true}, \pkg{siunitx} creates the macros for general use. The standard +method to achieve this does not overwrite any existing macros: this behaviour +can be altered using the \opt{overwrite-commands} switch. + +\DescribeOption{space-before-unit} +\DescribeOption{unit-optional-argument} +\DescribeOption{use-xspace} +When \enquote{free standing} unit macros are created, their behaviour can be +adjusted by a number of options. These are mainly intended for emulating the +input syntax of older packages. The option \opt{unit-optional-argument} gives +the same behaviour for the inputs +\begin{LaTeXdemo}[code only] + \qty{10}{\metre} +\end{LaTeXdemo} +and +\begin{LaTeXdemo}[code only] + \metre[10]. +\end{LaTeXdemo} +The \opt{space-before-unit} and \opt{use-xspace} options control the behaviour +at the \enquote{ends} of the unit macros. Activating \opt{space-before-unit} +inserts the number--unit space before the unit is printed. This is suitable for +the input syntax +\begin{LaTeXdemo}[code only] + 30\metre +\end{LaTeXdemo} +but does mean that the unit macros are incorrectly spaced in running text. On +the other hand, the \opt{use-xspace} option attempts to correctly space input +such as +\begin{LaTeXdemo}[code only] + \metre is the symbol for metres. +\end{LaTeXdemo} + +\subsection{Using units} + +Part of the power of \pkg{siunitx} is the ability to alter the output format +for units without changing the input. The behaviour of units is therefore +controlled by a number of options which alter either the processing of units or +the output directly (Table~\ref{tab:opt:units:out}). +\begin{table} + \centering + \caption{Unit output options.% + \label{tab:opt:units:out}} + \begin{tabular}{@{}>{\ttfamily}ll>{\ttfamily}l@{}} + \toprule + \multicolumn{1}{@{}l}{Option name} & + Type & + \multicolumn{1}{l@{}}{Default} \\ + \midrule + bracket-unit-denominator & Switch & true \\ + forbid-literal-units & Switch & false \\ + inter-unit-product & Literal & \cs{,} \\ + parse-units & Switch & true \\ + per-mode & Choice & power \\ + per-symbol & Literal & / \\ + qualifier-mode & Choice & subscript \\ + qualifier-phrase & Literal & \meta{empty} \\ + sticky-per & Switch & false \\ + unit-font-command & Literal & \cs{mathrm} \\ + \bottomrule + \end{tabular} +\end{table} + +\DescribeOption{inter-unit-product} +The separator between each unit is stored using the \opt{inter-unit-product} +option. The standard setting is a thin space: another common choice is a +centred dot. To get the correct spacing it is necessary to use +|\ensuremath{{}\cdot{}}| in the latter case. +\begin{LaTeXdemo} + \unit{\farad\squared\lumen\candela} \\ + \unit[inter-unit-product = \ensuremath{{}\cdot{}}] + {\farad\squared\lumen\candela} +\end{LaTeXdemo} + +\DescribeOption{per-mode} +\DescribeOption{per-symbol} +\DescribeOption{bracket-unit-denominator} +The handling of \cs{per} is altered using the \opt{per-mode} choice option. The +standard setting is \opt{power}, meaning that \cs{per} generates reciprocal +powers for units. Setting the option to \opt{fraction} uses the |\frac| +function to typeset the positive and negative powers of a unit separately. +\begin{LaTeXdemo} + \unit{\joule\per\mole\per\kelvin} \\ + \unit{\metre\per\second\squared} \\ + \unit[per-mode = fraction]{\joule\per\mole\per\kelvin} \\ + \unit[per-mode = fraction]{\metre\per\second\squared} +\end{LaTeXdemo} +The closely-related \opt{power-positive-first} setting acts in the same way but +places all of the positive powers before any negative ones. +\begin{LaTeXdemo} + \unit{\ampere\per\mole\second} \\ + \unit[per-mode = power-positive-first] + {\ampere\per\mole\second} +\end{LaTeXdemo} +It is possible to use a symbol (usually |/|) to separate the two parts of a +unit by setting \opt{per-mode} to \opt{symbol}; the symbol used is stored using +the setting \opt{per-symbol}. This method for displaying units can be +ambiguous, and so brackets are added unless \opt{bracket-unit-denominator} is +set to \opt{false}. Notice that \opt{bracket-unit-denominator} only applies +when \opt{per-mode} is set to \opt{symbol} or \opt{symbol-or-fraction}. +\begin{LaTeXdemo} + \sisetup{per-mode = symbol}% + \unit{\joule\per\mole\per\kelvin} \\ + \unit{\metre\per\second\squared} \\ + \unit[per-symbol = \ \text{div}\ ]{\joule\per\mole\per\kelvin} \\ + \unit[bracket-unit-denominator = false]{\joule\per\mole\per\kelvin} +\end{LaTeXdemo} +The often-requested (but mathematically invalid) \opt{repeated-symbol} option +is also available to repeat the symbol for each \cs{per}. +\begin{LaTeXdemo} + \unit[per-mode = repeated-symbol]{\joule\per\mole\per\kelvin} +\end{LaTeXdemo} +Finally, it is possible for the behaviour of the \cs{per} function to depend on +the prevailing math style. Setting \opt{per-mode} to \opt{symbol-or-fraction} +will use the \opt{symbol} setting for in line math, and the \opt{fraction} +setting when used in display math. +\begin{LaTeXdemo} + \sisetup{per-mode = symbol-or-fraction}% + $ \unit{\joule\per\mole\per\kelvin} $ + \[ \unit{\joule\per\mole\per\kelvin} \] + \unit{\joule\per\mole\per\kelvin} \\ + $ + \displaystyle + \unit{\joule\per\mole\per\kelvin} + $ + \[ + \textstyle + \unit{\joule\per\mole\per\kelvin} + \] +\end{LaTeXdemo} + +\DescribeOption{sticky-per} +By default, \cs{per} applies only to the next unit given.\footnote{This is the +standard method of reading units in English: for example, +\unit{\joule\per\mole\per\kelvin} is pronounced \enquote{joules per mole per +kelvin}.} By setting the \opt{sticky-per} flag, this behaviour is changed so +that \cs{per} applies to all subsequent units. +\begin{LaTeXdemo} + \unit{\pascal\per\gray\henry} \\ + \unit[sticky-per]{\pascal\per\gray\henry} +\end{LaTeXdemo} + +\DescribeOption{qualifier-mode} +\DescribeOption{qualifier-phrase} +Unit qualifiers can be printed in three different formats, set by the +\opt{qualifier-mode} option. The standard setting is \opt{subscript}, while the +options \opt{bracket}, \opt{combine} and \opt{phrase} are also possible. With +the last settings, powers can lead to ambiguity and are automatically detected +and brackets added as appropriate. +\begin{LaTeXdemo} + \unit{\kilogram\of{pol}\squared\per\mole\of{cat}\per\hour} \\ + \unit[qualifier-mode = bracket] + {\kilogram\of{pol}\squared\per\mole\of{cat}\per\hour} \\ + \unit[qualifier-mode = combine] + {\deci\bel\of{i}} +\end{LaTeXdemo} +The \opt{phrase} option is used with \opt{qualifier-phrase}, which allows for +example a space or other linking text to be inserted. +\begin{LaTeXdemo} + \sisetup{qualifier-mode = phrase, qualifier-phrase = \ }% + \unit{\kilogram\of{pol}\squared\per\mole\of{cat}\per\hour} \\ + \sisetup{qualifier-phrase = \ \mbox{of}\ }% + \unit{\kilogram\of{pol}\squared\per\mole\of{cat}\per\hour} +\end{LaTeXdemo} + +\DescribeOption{parse-units} +Normally, \pkg{siunitx} is used with the unit parse enabled, and only prints +units directly if there is literal input. However, if the input is known to be +essentially consistent and high performance is desired, then the parser can be +turned off using the \opt{parse-units} switch. +\begin{LaTeXdemo} + \qty{300}{\MHz} \\ + \qty[parse-units = false]{300}{\MHz} +\end{LaTeXdemo} + +\DescribeOption{forbid-literal-units} +Some users may prefer to completely disable the use of literal input in units, +for example to enforce consistency. This can be accomplished by setting the +\opt{forbid-literal-units} switch. With this option enabled, only macro-based +units can be used in a document. This only applies when \opt{parse-units} is +\opt{true}. + +\DescribeOption{unit-font-command} +The command used to set unit themselves may be adjusted using the +\opt{unit-font-command} option. This is typically set to |\mathrm|. +\begin{LaTeXdemo} + \unit{\lumen} \\ + \unit[unit-font-command = \mathit]{\lumen} +\end{LaTeXdemo} + +\subsection{Quantities} + +Some options apply to quantities (the combination of a number and a unit), +rather than to the numbers or units alone (Table~\ref{tab:opt:quantities}). +\begin{table} + \centering + \caption{Options for quantities.% + \label{tab:opt:quantities}} + \begin{tabular}{@{}>{\ttfamily}ll>{\ttfamily}l@{}} + \toprule + \multicolumn{1}{@{}l}{Option name} & + Type & + \multicolumn{1}{@{}l}{Default} \\ + \midrule + allow-quantity-breaks & Switch & false \\ + extract-mass-in-kilograms & Switch & true \\ + prefix-mode & Choice & input \\ + quantity-product & Literal & \cs{,} \\ + separate-uncertainty-units & Choice & bracket \\ + \bottomrule + \end{tabular} +\end{table} + +\DescribeOption{allow-quantity-breaks} +Usually, the combination of a number and unit is regarded as a single +mathematical entity which should not be split across lines. However, there are +cases (very long units, narrow columns, \foreign{etc}.) where breaks may be +needed. This can be turned on using the \opt{allow-quantity-breaks} option. +\begin{LaTeXdemo} + \begin{minipage}{2.55cm} + % Gives an underfull hbox + Some filler text \qty{10}{\metre} \\ + \sisetup{allow-quantity-breaks} + Some filler text \qty{10}{\metre} + \end{minipage} +\end{LaTeXdemo} + +\DescribeOption{number-unit-product} +The product symbol between the number and unit is set using the +\opt{quantity-product} option. +\begin{LaTeXdemo} + \qty{2.67}{\farad} \\ + \qty[quantity-product = \ ]{2.67}{\farad} \\ + \qty[quantity-product = ]{2.67}{\farad} +\end{LaTeXdemo} + +\DescribeOption{prefix-mode} +\DescribeOption{extract-mass-in-kilograms} +The unit prefixes (\cs{kilo}, \foreign{etc}.) are normally given as letters. +However, the package can convert these into numerical powers. This is +controlled by the \opt{prefix-mode} option, which takes the values \opt{input}, +\opt{combine-exponent} and \opt{extract-exponent}. The \opt{input} setting +leaves the prefixes unchanged. Using \opt{combine-exponent} will add any +exponent amount from the number to the first unit: this will modify any +existing prefix. Finally, using \opt{extract-exponent} will remove all prefixes +and express them as an exponent. The treatment of kilograms in this case can be +set using \opt{extract-mass-in-kilograms}: when \opt{true}, the \emph{kilo} +prefix is retained as part of the unit. This will mean that all grams are +converted to kilograms. +\begin{LaTeXdemo} + \qty{1e3}{\metre\second} \\ + \qty[prefix-mode = combine-exponent]{1e3}{\metre\second} \\ + \qty{10}{\kilo\gram\squared\deci\second} \\ + \qty[prefix-mode = extract-exponent]{10}{\kilo\gram\squared\deci\second}\\ + \qty[prefix-mode = extract-exponent]{7.5}{\gram} \\ + \sisetup{extract-mass-in-kilograms = false} + \qty{10}{\kilo\gram\squared\deci\second} \\ + \qty[prefix-mode = extract-exponent]{10}{\kilo\gram\squared\deci\second} \\ + \qty[prefix-mode = extract-exponent]{7.5}{\gram} \\ +\end{LaTeXdemo} + +\DescribeOption{separate-uncertainty-units} +When a number has multiple parts (such as a separate uncertainty) then the unit +must apply to all parts of the number. How this is shown is controlled using +the \opt{separate-uncertainty-units} options. The standard setting is +\opt{brackets}, which will place the entire numerical part in brackets and use +a single unit symbol. Alternative options are \opt{repeat} (print the unit for +each part of the number) and \opt{single} (print only one unit symbol: +mathematically incorrect). +\begin{LaTeXdemo} + \sisetup{separate-uncertainty} + \qty{12.3(4)}{\kilo\gram} \\ + \qty[separate-uncertainty-units = bracket]{12.3(4)}{\kilo\gram} \\ + \qty[separate-uncertainty-units = repeat]{12.3(4)}{\kilo\gram} \\ + \qty[separate-uncertainty-units = single]{12.3(4)}{\kilo\gram} +\end{LaTeXdemo} + +\subsection{Tabular material} + +Processing of material in tables obeys the same settings as described for the +functions already described. However, there are some settings which apply only +to the layout of tabular material (Table~\ref{tab:opt:tables}). +\begin{table} + \caption{Options for tabular material.% + \label{tab:opt:tables}} + \begin{tabular}{@{}>{\ttfamily}ll>{\ttfamily}l@{}} + \toprule + \multicolumn{1}{@{}l}{Option name} & + Type & + \multicolumn{1}{l@{}}{Default} \\ + \midrule + table-align-comparator & Switch & true \\ + table-align-exponent & Switch & true \\ + table-align-text-after & Switch & true \\ + table-align-text-before & Switch & true \\ + table-align-uncertainty & Switch & true \\ + table-alignment & Meta & center \\ + table-alignment-mode & Choice & marker \\ + table-auto-round & Switch & false \\ + table-column-width & Length & 0pt \\ + table-fixed-width & Switch & false \\ + table-format & Special & 2.2 \\ + table-number-alignment & Choice & center \\ + table-text-alignment & Choice & center \\ + \bottomrule + \end{tabular} +\end{table} + +\DescribeOption{table-mode} +The method used by \pkg{siunitx} to align numbers is selected using the +\opt{table-mode} option, which may be one of \opt{marker}, \opt{format} or +\meta{none}. With the standard setting, \meta{marker}, the package centers the +decimal marker in a tabular column, potentially leaving white space at the +shorter end of a number. The \meta{format} mode uses information from the +\meta{table-format} key to construct a model: this is then used to define the +space available to a number. For asymmetrical numbers, this method is strongly +preferable. Finally, \opt{none} disables alignment entirely: numbers are simply +parsed. + +\DescribeOption{table-number-alignment} +When \opt{table-mode} is set to \meta{format} or \meta{none}, the placement of +the number \enquote{block} within the cell as a whole is set by the +\meta{table-number-alignment} option, which may be one of \meta{left}, +\meta{center} or \meta{right}. (When \opt{table-mode} is set to \meta{marker}, +the decimal marker is always centered in the cell.) The different alignment +choices are illustrated in Table~\ref{tab:S:align}, which uses somewhat +exaggerated column headings to show the relative position of the cell contents. +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Aligning the \texttt{S} column.% + \label{tab:S:align}} + \centering + \sisetup{table-format = 2.4, table-alignment-mode = format} + \begin{tabular}{@{} + S[table-alignment-mode = marker] + S[table-number-alignment = center] + S[table-number-alignment = left] + S[table-number-alignment = right] + @{}} + \toprule + {Some Values} & {Some Values} & {Some Values} & {Some Values} \\ + \midrule + 2.3456 & 2.3456 & 2.3456 & 2.3456 \\ + 34.2345 & 34.2345 & 34.2345 & 34.2345 \\ + 56.7835 & 56.7835 & 56.7835 & 56.7835 \\ + 90.473 & 90.473 & 90.473 & 90.473 \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} +When the alignment mode is set to \opt{none}, number are simply collected and +parsed without any further processing, as illustrated in +Table~\ref{tab:S:parse}. +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Parsing without aligning in an \texttt{S} column.% + \label{tab:S:parse}} + \begin{tabular} + {@{} + S + S[table-alignment-mode = none] + @{}} + \toprule + {Decimal-centred} & + {Simple centring} \\ + \midrule + 12.345 & 12.345 \\ + 6,78 & 6,78 \\ + -88.8(9) & -88.8(9) \\ + 4.5e3 & 4.5e3 \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +\DescribeOption{table-format} +When the \opt{table-alignment-mode} is set to \opt{format}, \pkg{siunitx} uses +the information set in \meta{table-format} to construct a \enquote{model} which +defines the space to reserve for a number. The \opt{table-format} key is +interpreted in much the same way as a table cell. The numerical part should +consist of a number showing how many figures to reserve in each part of the +input, plus any comparators, signs, \foreign{etc.} A variety of examples are +given in Table~\ref{tab:S:format}. +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Reserving space in \texttt{S} columns.% + \label{tab:S:format}} + \sisetup{ + table-alignment-mode = format, + table-number-alignment = center, + } + \begin{tabular}{@{} + S[table-format = 2.2] + S[table-format = 2.2, table-number-alignment = right] + S[table-format = 2.2(1)] + S[table-format = 2.2(1), separate-uncertainty] + S[table-format = +2.2] + S[table-format = 2.2e1] + @{}} + \toprule + {Values} + & {Values} + & {Values} + & {Values} + & {Values} + & {Values} \\ + \midrule + 2.3 & 2.3 & 2.3(5) & 2.3(5) & 2.3 & 2.3e8 \\ + 34.23 & 34.23 & 34.23(4) & 34.23(4) & 34.23 & 34.23 \\ + 56.78 & 56.78 & 56.78(3) & 56.78(3) & -56.78 & 56.78e3 \\ + 3,76 & 3,76 & 3,76(2) & 3.76(2) & +-3.76 & e6 \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} +It is important to note that any parts of a number \emph{not} specified in the +table format argument are set to be absent (the number of figures is set to +zero). Setting the \opt{table-format} option also resets +\opt{table-alignment-mode} to \opt{format}. + +Space for material before and after the \texttt{S} column can be reserved by +giving model text as part of the \opt{table-format} key. This is then used to +provide the necessary gap while maintaining alignment (Table~\ref{tab:S:ends}). +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Text before and after numbers.% + \label{tab:S:ends}} + \sisetup{table-format = {now }2.4{\textsuperscript{\emph{a}}}} + \begin{tabular}{@{}S@{}} + \toprule + {Values} \\ + \midrule + 2.3456 \\ + 34.2345 \textsuperscript{\emph{a}}\\ + 56.7835 \\ + now~ 90.473 \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +\DescribeOption{table-align-exponent} +\DescribeOption{table-align-uncertainty} +When printing exponents in tables, there is a choice of aligning the exponent +parts or having these close up to the mantissa. This is controlled by the +\opt{table-align-exponent} option (Table~\ref{tab:align:exp}). Similarly, +uncertainty parts which are printed separately from the mantissa can be aligned +or closed up. This is set by the \opt{table-align-uncertainty} option +(Table~\ref{tab:align:uncert}). Finally, the same approach is available for the +comparator with the \opt{table-align-comparator} option +(Table~\ref{tab:align:comp}). +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{The \opt{table-align-exponent} option.% + \label{tab:align:exp}} + \sisetup{table-format = 1.3e2} + \begin{tabular}{@{}SS[table-align-exponent = false]@{}} + \toprule + {Header} & {Header} \\ + \midrule + 1.2e3 & 1.2e3 \\ + 1.234e56 & 1.234e56 \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{The \opt{table-align-uncertainty} option.% + \label{tab:align:uncert}} + \sisetup{ + separate-uncertainty, + table-format = 1.3(1), + } + \begin{tabular}{@{}SS[table-align-uncertainty = false]@{}} + \toprule + {Header} & {Header} \\ + \midrule + 1.2(1) & 1.2(3) \\ + 1.234(5) & 1.234(5) \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{The \opt{table-align-comparator} option.% + \label{tab:align:comp}} + \sisetup{table-format = >2.2} + \begin{tabular}{@{}SS[table-align-comparator = false]@{}} + \toprule + {Header} & {Header} \\ + \midrule + > 1.2 & > 1.2 \\ + < 12.34 & < 12.34 \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +\DescribeOption{table-align-text-before} +\DescribeOption{table-align-text-after} +Note markers are often given in tables after the numerical content. It may be +desirable for these to close up to the numbers. Whether this takes place is +controlled by the \opt{table-align-text-before} and \opt{\ldots-after} + option (Table~\ref{tab:S:notes}). +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Closing notes up to text.% + \label{tab:S:notes}} + \newrobustcmd\NoteMark[1]{% + \textsuperscript{\emph{#1}}% + } + \sisetup{table-format = {\NoteMark{a}}2.4} + \begin{tabular}{@{} + S + S[table-align-text-before = false] + @{}} + \toprule + {Values} & {Values} \\ + \midrule + 2.3456 & 2.3456 \\ + \NoteMark{a} 4.234 & \NoteMark{a} 4.234 \\ + \NoteMark{b} .78 & \NoteMark{b} .78 \\ + \NoteMark{d} 88 & \NoteMark{d} 88 \\ + \bottomrule + \end{tabular} + \hfil + \sisetup{table-format = 2.4\NoteMark{a}} + \begin{tabular}{@{} + S + S[table-align-text-after = false] + @{}} + \toprule + {Values} & {Values} \\ + \midrule + 2.3456 & 2.3456 \\ + 34.234 \NoteMark{a} & 34.234 \NoteMark{a} \\ + 56.78 \NoteMark{b} & 56.78 \NoteMark{b} \\ + 90.4 \NoteMark{c} & 90.4 \NoteMark{c} \\ + 88 \NoteMark{d} & 88 \NoteMark{d} \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +\DescribeOption{table-auto-round} +The contents of table cells can automatically be rounded or zero-filled to the +number of decimal digits given for the decimal part of the \opt{table-format} +option. This mode is activated using the \opt{table-auto-round} switch, as +illustrated in Table~\ref{tab:S:auto}. +\begin{LaTeXdemo}[code and float] + \begin{table} + \centering + \caption{The \opt{table-auto-round} option.% + \label{tab:S:auto}} + \sisetup{table-format = 1.3} + \begin{tabular}{@{}SS[table-auto-round]@{}} + \toprule + {Header} & {Header} \\ + \midrule + 1.2 & 1.2 \\ + 1.2345 & 1.2345 \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +\DescribeOption{parse-numbers} +When the \opt{parse-numbers} option is set to \opt{false}, then the alignment +code for tables takes a different approach. The output is always set in math +mode, and alignment takes place at the first decimal marker. This is achieved +by making it active in math mode. When reserving space for content only the +integer and decimal values for the mantissa are considered +(Table~\ref{tab:S:nonparsed}). +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Aligning without parsing.% + \label{tab:S:nonparsed}} + \sisetup{ + parse-numbers = false, + table-format = 3.3 + } + \centering + \begin{tabular}{@{} + S + S[table-number-alignment = center] + S[table-number-alignment = right] + S[table-number-alignment = left] + @{}} + \toprule + {Some values} + & {Some values} + & {Some values} + & {Some values} \\ + \midrule + 2.35 & 2.35 & 2.35 & 2.35 \\ + 34.234 & 34.234 & 34.234 & 34.234 \\ + 56.783 & 56.783 & 56.783 & 56.783 \\ + 3,762 & 3,762 & 3,762 & 3.762 \\ + \sqrt{2} & \sqrt{2} & \sqrt{2} & \sqrt{2} \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +\DescribeOption{drop-exponent} +In cases where data cover a range of values, printing using a fixed exponent in +a table may make presentation clearer. In these cases, dropping the exponent +value from the table is useful. The general numerical options \opt{drop-exponent} +combined with \opt{exponent-mode = fixed} can be used to achieve this +(Table~\ref{tab:exp:omit}). +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{The \opt{table-omit-exponent} option.% + \label{tab:exp:omit}} + \begin{tabular}{@{} + S[table-format = 1.1e1] + S[ + drop-exponent = true, + exponent-mode = fixed, + fixed-exponent = 3, + table-format = 2.1, + ] + @{}} + \toprule + {Header} & + \multicolumn{1}{c@{}}{Header / \num[print-unity-mantissa = false]{e3}} \\ + \midrule + 1.2e3 & 1.2e3 \\ + 3e2 & 3e2 \\ + 1.0e4 & 1.0e4 \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +\DescribeOption{table-column-width} +\DescribeOption{table-fixed-width} +Usually, the width of the numerical column is allowed to vary depending on the +content. However, there are cases where a strictly fixed width is desirable. +For these cases, the \opt{table-fixed-width} and \opt{table-column-width} +options are available. The \opt{table-fixed-width} option activates fixed-width +columns, whilst \opt{table-column-width} defines the target width +(Table~\ref{tab:width:fixed}). +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Fixed-width columns.% + \label{tab:width:fixed}} + \begin{tabular} + {@{} + S + S[table-column-width = 2cm] + @{}} + \toprule + {Flexible} & + {Fixed} \\ + \midrule + 1.23 & 1.23 \\ + 45.6 & 45.6 \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +The \opt{table-column-width} option can also be used to achieve special +effects. One example is centring a column of numbers under a wide heading, with +the numbers themselves right-aligned (Table~\ref{tab:width:special}). +\begin{LaTeXdemo}[code and float] + \begin{table} + \centering + \caption{Right-aligning under a heading.% + \label{tab:width:special}} + \settowidth{\mylength}{Long header} + \sisetup{ + table-alignment-mode = none , + table-column-width = \mylength , + table-number-alignment = right + } + \begin{tabular}{@{}S@{}} + \toprule + {Long header} \\ + \midrule + 12.33 \\ + 2 \\ + 1234 \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +\DescribeOption{table-text-alignment} +\DescribeOption{table-alignment} +Cell contents which are not part of a number can be protected using braces, as +illustrated. Cells which contain no numerical data at all are aligned using the +setting specified by the \opt{table-text-alignment} option, which recognises +the values \opt{center}, \opt{left} and \opt{right} (Table~\ref{tab:S:text}). +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Aligning text in \texttt{S} columns.% + \label{tab:S:text}} + \sisetup{table-format = 4.4} + \centering + \begin{tabular}{@{} + S + S[table-text-alignment = left] + S[table-text-alignment = right] + @{}} + \toprule + {Values} + & {Values} + & {Values} \\ + \midrule + 992.435 & 992.435 & 992.435 \\ + 7734.2344 & 7734.2344 & 7734.2344 \\ + 56.7834 & 56.7834 & 56.7834 \\ + 3,7462 & 3,7462 & 3,7462 \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +\DescribeOption{table-alignment} +The table alignment options \opt{table-number-alignment} and +\opt{table-text-alignment} can be set to the same value using the +\opt{table-alignment} option. This will set all three alignment options to the +same value (one of \opt{center}, \opt{right} or \opt{left}). + +\subsection{Locale options} + +\DescribeOption{locale} +\pkg{siunitx} allows the user to switch between the typographic conventions of +different (geographical) areas by using locales. Currently, the package is +supplied with configurations for locales \opt{UK}, \opt{US}, \opt{DE} +(Germany), \opt{FR} (French) and \opt{ZA} (South Africa). The \opt{locale} +option is used to switch to a particular locale. +\begin{LaTeXdemo} + \qty{1.234}{\metre}\\ + \qty[locale = DE]{6.789}{\metre} +\end{LaTeXdemo} + +\subsection{Preamble-only options} + +\DescribeOption{table-column-type} +The letter(s) used to create table columns can be adjusted using the +\opt{table-column-type} option. The standard setting is |S|, but one or more +letters may be used: these must be single tokens. For example, provided the +\pkg{numprint} package has not been loaded, the letter |n| could be used as +this would suggest a numerical column. + +\section{Upgrading from version~\texorpdfstring{$2$}{2}} + +The package has been largely re-written internally between versions $2$ and +$3$. A significant number of key--value settings have new, more descriptive, +names. Where possible, older names are mapped to newer ones internally: you +will be warned in the log if this is the case. + +It is possible to use the \LaTeXe{} kernel mechanism to load the last +version~$2$ release for documents that cannot be successfully processed using +version~$3$. This can be achieved using +\begin{LaTeXdemo}[code only] + \usepackage{siunitx}[=2021-04-09] +\end{LaTeXdemo} +or +\begin{LaTeXdemo}[code only] + \usepackage{siunitx}[=v2] +\end{LaTeXdemo} + +\begin{function}{\SI, \SIlist, \SIrange, \si} + In version~$3$, the document commands have been revised to be more + descriptive. As such, the commands \cs{SI}, \cs{SIlist}, \cs{SIrange} + and \cs{si} remain available but are not recommended for use in new + documents. +\end{function} + +Some changes have been made to the semantics of commands or options. Most +notably +\begin{itemize} + \item prefixes cannot now be given without units; + \item prefixes can only be interconverted with numbers as part + of a quantity, not as stand-alone units. +\end{itemize} + +The font control system has been completely re-written for version~$3$. The +method used in entirely different from version~$2$. Emulation is therefore not +provided for all outcomes: if you need non-standard font settings, you will +need to adjust your source. See Section~\ref{sec:print} for more details on the +options available in this area. + +The input approach for version~$3$ is slightly more structured and restricted +than for version~$2$. As well as the updated names for document commands, +this means that +\begin{itemize} + \item Products of numbers must now be given using the dedicated + \cs{numproduct} and \cs{qtyproduct} commands; + \item Quotients of numbers are only supported as literals; + \item Complex values need to be given using the dedicated command + \cs{complexnum}. +\end{itemize} + +A new approach has been taken to providing non-Latin symbols for use in +units: these are now handled directly where needed, for example in the +definition of the \cs{micro} prefix. + +The letter used for a numerical tabular column can now be selected by the +user: the letter |S| has been retained as the standard interface. The unit +column (|s|) has been removed from this release. It can be emulated using +the \pkg{collcell} package, for example +\begin{LaTeXdemo}[code only] + \usepackage{collcell} + \newcolumntype{s}{>{\collectcell\unit}c<{\endcollectcell}} +\end{LaTeXdemo} +or +\begin{LaTeXdemo}[code only] + \usepackage{collcell} + \newcolumntype{s}{>{\collectcell\si}c<{\endcollectcell}} +\end{LaTeXdemo} + +If you are using \opt{table-column-width} to have fixed-width columns, you +also now need \opt{table-fixed-width} to set this option active. + +\section{Localisation} + +The \pkg{translations} package provides a structured framework for localisation +of words and phrases, and is part of the larger \pkg{beamer} bundle. The +\pkg{translations} package provides the \cs{translate} macro, which will provide +appropriate translations based on the current \pkg{babel} or \pkg{polyglossia} +language setting. + +If \pkg{translations} is available, \pkg{siunitx} will load it and alter the +standard settings for the \opt{list-final-separator} and \opt{range-phrase} +options to read: +\begin{LaTeXdemo}[code only] + \sisetup{ + list-final-separator = { \GetTranslation{and} }, + list-pair-separator = { \GetTranslation{and} }, + range-phrase = { \GetTranslation{to (numerical range)} }, + } +\end{LaTeXdemo} +If the current language is known to the \pkg{translator} package then the +result will be localised text. The preamble for this manual loads English, +French, German and Spanish as options, and also loads the \pkg{babel} package: +\begin{LaTeXdemo} + % In English by default + \numlist{1;2;3} \\ + \numrange{1}{10} \\ + \selectlanguage{french}% + \numlist{1;2;3} \\ + \numrange{1}{10} \\ + \selectlanguage{german}% + \numlist{1;2;3} \\ + \numrange{1}{10} \\ + \selectlanguage{spanish}% + \numlist{1;2;3} \\ + \numrange{1}{10} +\end{LaTeXdemo} + +\section{Compatibility with other packages} + +In general, \pkg{siunitx} should be usable with other packages without +interference. + +When the \pkg{physics} package is loaded before \pkg{siunitx}, the command +\cs{qty} is not defined: users will need to use the version~$2$ command +\cs{SI}. + +\section{Hints for using \pkg{siunitx}} + +\subsection{Ensuring text or math output% + \label{sec:hint:text-math}} + +The macros \cs{ensuremath} and \cs{text} should be used to ensure that a +particular item is always printed in the desired mode. Some mathematical output +does not work well in \cs{mathrm} (the font setting used by \pkg{siunitx} for +printing units). The easiest way to solve this is to use the construction +"\text{\ensuremath{...}}", which will print the material in the standard +mathematics font without affecting the rest of the output. In some cases, +simply forcing \cs{mathnormal} will suffice, but this is less reliable with +non-Latin characters. + +\subsection{Expanding content in tables% + \label{sec:hint:expanding}} + +When processing tables, \pkg{siunitx} will expand anything stored inside a +macro, unless it is long or protected. \LaTeXe{} robust commands are also +detected and are not expanded (Table~\ref{tab:xmpl:macro}). Values which would +otherwise be expanded can be protected by wrapping them in a set of braces. As +\TeX{} itself will expand the first token in a table cell before \pkg{siunitx} +can act on it, using the \eTeX{} protected mechanism is the recommended course +of action to prevent expansion of macros in table cells. (As is shown in the +table, \TeX's expansion of \LaTeXe{} robust commands can lead to unexpected +results.) +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Values as macros in \texttt{S} columns.% + \label{tab:xmpl:macro}} + \newcommand*\myvaluea{1234} + \newcommand\myvalueb{1234} + \DeclareRobustCommand*\myvaluec{1234} + \protected\def\myvalued{1234} + \begin{tabular}{@{}S@{}} + \toprule + {Some Values} \\ + \midrule + \myvaluea 8.8 \myvaluea \\ % Both expanded + \myvalueb 8.8 \myvalueb \\ % First expanded by TeX + % to numbers + \myvaluec 8.8 \myvaluec \\ % First expanded by TeX + % but not to numbers! + \myvalued 8.8 \myvalued \\ % Neither expanded + {\myvaluea\ 8.8 \myvaluea} \\ % Neither expanded + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +It is possible to use calculated values in tables. For this to work, the +calculation must take place before attempting to parse the number (the parser +cannot \enquote{know} all of the possible values inside an expression). This is +most conveniently handled using the \pkg{xfp} package, which is distributed as +part of the required support for \pkg{siunitx}. The general approach is +illustrated in Table~\ref{tab:xmpl:calc} +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Calculated values.% + \label{tab:xmpl:calc}} + \newcommand{\valuea}{66.7012} + \newcommand{\valueb}{66.0212} + \newcommand{\valuec}{64.9026} + \begin{tabular}{ + @{} + S[table-format = 2.4] + S[table-format = 3.4] + @{} + } + \toprule + {Value} & {Doubled} \\ + \midrule + \valuea & \fpeval{\valuea * 2} \\ + \valueb & \fpeval{\valueb * 2} \\ + \valuec & \fpeval{\valuec * 2} \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +A more sophisticated approach is to generate the rows themselves from a +database: this is illustrated in Section~\ref{sec:hint:datatool}. + +\subsection{Using \pkg{siunitx} with \pkg{datatool}% + \label{sec:hint:datatool}} + +As illustrated in Table~\ref{tab:xmpl:calc}, \pkg{siunitx} can be used to +typeset data stored using \pkg{datatool}. For quickly displaying the contents +of tables, \pkg{datatool} offers the \cs{DTLshowtable} macro. This will only +work with \texttt{S} columns if number parsing is turned off +(Table~\ref{tab:xmpl:datatool}). +\begin{LaTeXdemo}[code and float] + \DTLnewdb{moredata} + \DTLnewrow{moredata}\DTLnewdbentry{moredata}{value}{ 6.7012} + \DTLnewrow{moredata}\DTLnewdbentry{moredata}{value}{66.0212} + \DTLnewrow{moredata}\DTLnewdbentry{moredata}{value}{64.902 } + \begin{table} + \caption{Displaying a \textsf{datatool} table.% + \label{tab:xmpl:datatool}} + \sisetup{parse-numbers= false, table-format = 2.4} + \renewcommand*\dtlrealalign{S} + \DTLdisplaydb{moredata} + \end{table} +\end{LaTeXdemo} + +The \pkg{datatool} package may also be used to create on-the-fly tables using +calculations. For example, the demonstration in Table~\ref{tab:xmpl:calc} may +be achieved without needing to write out each row, as shown in +Table~\ref{tab:xmpl:datatool-calc}. An extra column is used to contain the +calculations in this case. +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Calculated values using \pkg{datatool}.% + \label{tab:xmpl:datatool-calc}} + \DTLnewdb{data} + \DTLnewrow{data}\DTLnewdbentry{data}{value}{66.7012} + \DTLnewrow{data}\DTLnewdbentry{data}{value}{66.0212} + \DTLnewrow{data}\DTLnewdbentry{data}{value}{64.9026} + \begin{tabular}{ + @{} + S[table-format = 2.4] + S[table-format = 3.4] + @{}l + @{} + } + \toprule + {Value} & {Doubled} & + \DTLforeach{data}{\myvalue=value}{% + \DTLiffirstrow {\\ \midrule}{\\}% + \myvalue & % First column + \fpeval{\myvalue * 2} % second column + & }\\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +\subsection{Using units in section headings and bookmarks% + \label{sec:hint:bookmarks}} + +The \pkg{siunitx} code is designed to work correctly with functions in +headings. They will print correctly in headings and in the table of contents. +As illustrated here, the standard behaviour is to ignore font changes. When the +\pkg{hyperref} package is loaded, the functions automatically \enquote{degrade +gracefully} to produce useful information in \acro{pdf} bookmarks. If you want +more control over the bookmark text, use the \cs{texorpdfstring} function from +\pkg{hyperref}, for example: +\begin{LaTeXdemo}[code only] + \section{Some text + \texorpdfstring + {\unit{\joule\per\mole\per\kelvin}} + {J mol-1 K-1}% + } +\end{LaTeXdemo} + +You may find it useful to load \pkg{hyperref} with the \opt{unicode} option, +as this will allow \unit{\ohm} to appear in bookmarks. Without the option, +the encoding used by \pkg{hyperref} does not support this symbol. + +\subsection{A left-aligned column visually centred under a heading% + \label{sec:hint:left-column}} + +When you have a column of non-related numbers, the usual advice is to make +these left-aligned and then centre the resulting column under the heading. With +the \pkg{dcolumn} package, that would be done with something like +|D{x}{}{5.0}|. This is something of an abuse of the nature of a number, but can +also be done using \pkg{siunitx} (Table~\ref{tbl:xmpl:unrel}). +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Formatting unrelated numbers.% + \label{tbl:xmpl:unrel}} + \centering + \begin{tabular} + { + @{} + S[ + table-format = 5.0, + parse-numbers = false, + input-digits = .0123456789, + input-decimal-markers = x + ] + @{} + } + \toprule + \multicolumn{1}{@{}c@{}}{Header} \\ + \midrule + 120 \\ + 12.3 \\ + 12340 \\ + 12.02 \\ + 123 \\ + 1 \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +\subsection{Maximising performance% + \label{sec:hint:performance}} + +Both the number and unit parsers require significant effort in terms of \TeX{} +programming. For input that does not require such processing, the maximum +performance for \pkg{siunitx} can therefore be obtained by turning off both +systems: +\begin{LaTeXdemo} + \qty{7.3}{\Hz} \\ + \qty[parse-units = false]{7.3}{\Hz} \\ + \qty[ + parse-numbers = false, + parse-units = false + ]{7.3}{\Hz} +\end{LaTeXdemo} + +\subsection{Special considerations for the \cs{kWh} unit% + \label{sec:hint:kWh}} + +The standard settings provide the \cs{kWh} unit set up with no spacing between +the \enquote{\unit{\kilo\watt}} and the \enquote{\unit{\hour}} unit to give +\enquote{\unit{\kWh}}. However, this only applies when the unit is given on its +own: combinations will follow the normal rules +\begin{LaTeXdemo} + \unit{\kWh} \\ + \unit{\kWh\per\metre} +\end{LaTeXdemo} +This is because the unit \cs{kWh} is defined so that it can still be varied by +altering \cs{kilo}, \cs{watt} and \cs{hour}, and so that the prefix can still +be turned into a number. However, some users may prefer to have a non-flexible +macro which never adds a space. This can be achieved by redefining \cs{kWh} +with \cs{DeclareSIUnit}, by added an alternative definition +\begin{LaTeXdemo}[code only] + \DeclareSIUnit\kWh{kWh} + \DeclareSIUnit\KWH{kWh} +\end{LaTeXdemo} + or of course by using literal unit input. +\begin{LaTeXdemo} + \unit{\KWH\per\metre}\\ + \unit{kWh.m^{-1}} +\end{LaTeXdemo} + +Another point to notice is that the \cs{per} macro applies to the next unit, +and not an entire unit combination. Thus in +\begin{LaTeXdemo} + \unit{\candela\per\kWh} +\end{LaTeXdemo} +\cs{per} applies to the watts but not to the hours. In this case, the units +need to be written out in full or the \opt{sticky-per} option should be used. +\begin{LaTeXdemo} + \unit{\candela\per\kilo\watt\per\hour} \\ + \unit[sticky-per]{\candela\per\kWh} +\end{LaTeXdemo} + +\subsection{Creating a column with numbers and units% + \label{sec:hint:mixed}} + +Usually, numbers in a table should be given with the units in the column +heading. However, there are cases where a series of data are best presented in +a table but have different units. There are two ways to do this +(Table~\ref{tab:xmpl:mixed}). The first is to place the units in the first +column of the table, which makes sense if there are several related items in +the table. The second method is to generate two columns, one for numbers and a +second for units, and then to format these to give the visual effect of a +single column. The later effect is most appropriate when only one set of +numbers are presented in a table. This method requires cell content is +collected, easiest to do using the \pkg{collcell} package. +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Tables where numbers have different units.% + \label{tab:xmpl:mixed}} + \hfil + \begin{tabular} + { + @{} + >{$}l<{$} + S[table-format = 3.3(1)] + S[table-format = 3.3(1)] + @{} + } + \toprule + & {One} & {Two} \\ + \midrule + a / \unit{\pm} & 123.4(2) & 567.8(4) \\ + \beta / \unit{\degree} & 90.34(4) & 104.45(5) \\ + \mu / \unit{\per\mm} & 0.532 & 0.894 \\ + \bottomrule + \end{tabular} + \hfil + \begin{tabular} + { + @{} + S[table-format=1.3]@{\,} + >{\collectcell\unit}l<{\endcollectcell} + @{} + } + \toprule + \multicolumn{2}{@{}c}{Heading} \\ + \midrule + 1.234 & \metre \\ + 0.835 & \candela \\ + 4.23 & \joule\per\mole \\ + \bottomrule + \end{tabular} + \hfil + \end{table} +\end{LaTeXdemo} + +\subsection{Tables with heading rows% + \label{sec:hint:heading}} + +A common format for tables is to make the heading row visually distinct using a +background color and bold text. If numbers appear in such a heading row within +an \texttt{S} column then getting the appearance right can be challenging. The +best approach is to make the \cs{bfseries} macro \enquote{robust} (as +demonstrated in Section~\ref{sec:hint:expanding}), then to use this macro to +make the heading cells bold. This approach is illustrated in +Table~\ref{tab:xmpl:headers}, along with the use of \cs{rowcolor} to provide a +background color. +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Header row in a table.% + \label{tab:xmpl:headers}} + \robustify\bfseries + \centering + \begin{tabular} + {@{}S[text-series-to-math, table-format = 3.3]@{}} + \rowcolor[gray]{0.9} + \bfseries 123.456 \\ + 23.45 \\ + 123.4 \\ + 3.456 \\ + \end{tabular} + \end{table} +\end{LaTeXdemo} + +\subsection{Associating a locale with a \pkg{babel} language% + \label{sec:hint:babel}} + +It is possible to instruct the \pkg{babel} package to switch to a particular +\pkg{siunitx} locale when changing language. This can be done using the +\pkg{babel} \cs{extras\meta{language}} system. For example, to associate the +\texttt{DE} locale with the \texttt{german} \pkg{babel} language, the +appropriate code would be +\begin{LaTeXdemo}[code only] + \addto\extrasgerman{\sisetup{locale = DE}} +\end{LaTeXdemo} + +\section{Using (\acro{SI}) units} + +Consistent and logical units are a necessity for scientific work, and have +applicability everywhere. Historically, a number of systems have been used for +physical units. \acro{SI} units were introduced by the \foreign{Conférence +Générale des Poids et Mesures} (\acro{CGPM}) in 1960. \acro{SI} units are a +coherent system based on seven base units, from which all other units may be +derived. + +At the same time, physical quantities with units are mathematical entities, and +as such way that they are typeset is important. In mathematics, changes of type +(such as using bold, italic, sans serif typeface and so on) convey information. +This means that rules exist not only for the type of units to be used under the +\acro{SI} system, but also the way they should appear in print. Advice on best +practice has been made available by the \emph{National Institute of Standards +and Technology} (\acro{NIST})~\cite{NIST}. + +As befits an agreed international standard, the full rules are detailed. It is +not appropriate to reproduce these in totality here; instead, a useful summary +of the key points is provided. The full details are available from the +\foreign{Bureau International des Poids et Mesures}~\cite{BIPM}. + +The \pkg{siunitx} package takes account of the information given here, so far +as is possible. Thus the package defaults follow the recommendations made for +typesetting numbers and units. Spacing and so forth is handled in such a way as +to make implementing the rules (relatively) easy. + +\subsection{Units} + +There are seven base \acro{SI} units, listed in Table~\ref{tab:unit:base}.% +\footnote{Some base units need others defined first; there is therefore a +required order of definition.} The base units have been chosen such that all +physical quantities can be expressed using an appropriative combination of +these units, needing no others and with no redundancy. + +All other units within the \acro{SI} system are regarded as \enquote{derived} +from the seven base units. At the most basic, all other \acro{SI} units can be +expressed as combinations of the base units. However, many units (listed in +Tables~\ref{tab:unit:derived} and~\ref{tab:unit:accepted}) have a special name +and symbol. Most of these units are simple combinations of one or more base +units (raised to powers as appropriate). + +A series of \acro{SI} prefixes for decimal multiples and sub-multiples are +provided, and can be used as modifiers for any \acro{SI} unit (either base or +derived units) with the exception of the kilogram. The prefixes are listed in +Table~\ref{tab:unit:prefix}. No space should be used between a prefix and the +unit, and only a single prefix should be used. Even the degree Celsius can be +given a prefix, for example \qty{1}{\milli\degreeCelsius}. + +It is important to note that the kilogram is the only \acro{SI} unit with a +prefix as part of its name and symbol. Only single prefix may be used, and so +in the case of the kilogram prefix names are used with the unit name +\enquote{gram} and the prefix symbols are used with the unit symbol +\unit{\gram}. For example $\qty{1e-6}{\kilo\gram} = \qty{1e-3}{\gram} = +\qty{1}{\milli\gram}$. + +The application of \acro{SI} units is meant to provide a single set of units +which ensure consistency and clarity across all areas. However, other units are +common is many areas, and are not without merit. The units provided by +\pkg{siunitx} by default do not include any of these; only units which are part +of the \acro{SI} set or are accepted for use with \acro{SI} units are defined. +However, several other sets of units can be loaded as optional modules. The +binary prefixes and units (Table~\ref{tab:unit:binary}) are the most obvious +example. These are \emph{not} part of the \acro{SI} specifications, but the +prefix names are derived from those in Table~\ref{tab:unit:prefix}. + +Other units are normally to be avoided where possible. \acro{SI} units should, +in the main, be preferred due to the advantages of clear definition and +self-consistency this brings. However, there will probably always be a place +for specialist or non-standard units. This is particularly true of units +derived from basic physical constants. + +There are also many areas where non-standard units are used so commonly that to +do otherwise is difficult or impossible. For example, most synthetic chemists +measure the pressure inside vacuum apparatus in \unit{\millimetremercury}, +partly because the most common gauge for the task still uses a column of +mercury metal. For these reasons, \pkg{siunitx} allows definition of such +units. + +\subsection{Mathematical meaning} + +As explained earlier, a quantity combination is a single mathematical entity. +This has implications for how both the number and the unit should be printed. +Firstly, the two parts should not be separated: a quantity is a product of the +number and the unit. With the exception of the symbols for plane angles +(\unit{\degree}, \unit{\arcminute} and \unit{\arcsecond}), the \acro{BIPM} +specifies either a space or half-height (centred) dot should be +used~\cite{BIPM}. +\begin{LaTeXdemo} + A space for \qty{10}{\percent}\\ + and also for \qty{100}{\degreeCelsius}\\ + but not for \ang{1.23}. +\end{LaTeXdemo} + +The mathematical meaning of units also means that the shape, weight and family +are important. Units are supposed to be typeset in an upright, medium weight +font. Italic, bold and sans serif are all used mathematically to convey other +meanings. (In an all sanserif document, using sans serif for units is +reasonable.) The \pkg{siunitx} package defaults again follow this convention: +any local settings are ignored, and uses the current upright math font. +However, there are occasions where this may not be the most desirable +behaviour. A classic example would be in an all-bold section heading. As the +surrounding text is bold, some people feel that any units should follow this. +\begin{LaTeXdemo} + Units should \textbf{not be bold: \qty{54}{\farad}}\\ + \textbf{But perhaps in a running block,\\ + it might look better: + \qty[text-series-to-math]{54}{\farad}} +\end{LaTeXdemo} + +Symbols for units formed from other units by multiplication are indicated by +means of either a half-height (that is, centred) dot or a (thin) space. +\begin{LaTeXdemo} + $\unit{\metre\second} = \text{metre second}$ \\ + $\unit{\milli\second} = \text{millisecond}$ \\ + \sisetup{inter-unit-product = \ensuremath { { } \cdot { } } } + $\unit{\metre\second} = \text{metre second}$ \\ + $\unit{\milli\second} = \text{millisecond}$ +\end{LaTeXdemo} +There are some circumstances under which it is common practice to omit any +spaces. The classic example is \unit{\kWh}, where +\enquote{\unit[inter-unit-product = \,]{\kWh}} does not add any useful +information. If using such a unit repeatedly, users of \pkg{siunitx} are +advised to create a custom unit to ensure consistency. It is important to note +that while this is common practice, it is \emph{not} allowed by the +\acro{BIPM}~\cite{BIPM}. + +Symbols for units formed from other units by division are indicated by means of +a virgule (oblique stroke, slash, "/"), a horizontal line, or negative +exponents.\footnote{Notice that a virgule and a solidus are not the same +symbol.} However, to avoid ambiguity, the virgule must not be repeated on the +same line unless parentheses are used. This is ensured when using named unit +macros in \pkg{siunitx}, which will \enquote{trap} repeated division and format +it correctly. In complicated cases, negative exponents are to be preferred over +other formats. +\begin{LaTeXdemo} + \unit{\joule\per\mole\per\kelvin} \\ + \unit[per-mode = fraction]{\joule\per\mole\per\kelvin} \\ + \unit[per-mode = symbol]{\joule\per\mole\per\kelvin} +\end{LaTeXdemo} + +Products and errors should show what unit applies to each number given. Thus +\qtyproduct[product-units = bracket]{2x3}{\metre} is an ordered set of lengths +of a geometric area, whereas \qtyproduct[product-units = single]{2x3}{\metre} +is a length (and equal to \qty{6}{\metre}). Thus, $\times$ is not a product but +is a mathematical operator; in the same way, a $2 \times 3$ matrix is not a $6$ +matrix! In some areas, areas and volumes are given with separated units but a +unit raised to the appropriate power: \qtyproduct[product-units = power]{2 x +3}{\metre}. Although this does display the correct overall units, it is +potentially-confusing and is not encouraged. + +Care must be taken when writing ranges of numbers. For purely numerical values, +it is common to use a en-dash to show a range, for example \enquote{see pages +1--5}. On the other hand, physical quantities could be misinterpret as negative +values if written in this way. As the quantity is a single mathematical entity, +writing the values with an en-dash followed by a single unit is also incorrect. +As a result, using the word \enquote{to} is strongly recommended. +\begin{LaTeXdemo} + \qtyrange{1}{5}{\metre} long. +\end{LaTeXdemo} + +\subsection{Graphs and tables} + +In graphs and tables, repetition of the units following each entry or axis mark +is confusing and repetitive. It is therefore best to place the unit in the +label part of the information. Placing the unit in square brackets is common +but mathematically poor.\footnote{For example, for an acceleration \(a\), the +expression $[a]$ is the dimensions of $a$, \foreign{i.e.}~length per time +squared in this case.} Much better is to show division of all quantities by the +unit, which leaves the entries as unitless ratios. This is illustrated in +Tables~\ref{tab:xmpl:unitless} and~\ref{fig:xmpl:unitless}. +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{An example of table labelling.% + \label{tab:xmpl:unitless}} + \sisetup{ + table-number-alignment = center, + table-format = 1.4 + } + \begin{tabular}{@{}cS@{}} + \toprule + Entry & {Length/\unit{\metre}} \\ + \midrule + 1 & 1.1234 \\ + 2 & 1.1425 \\ + 3 & 1.7578 \\ + 4 & 1.9560 \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} +\begin{LaTeXdemo}[code and float] + \begin{figure} + \begin{tikzpicture} + \begin{axis}[ + xlabel = $t/\unit{\second}$, + xmax = 6, + xmin = 0, + ylabel = $d/\unit{\metre}$, + ymin = 0 + ] + \addplot[smooth,mark=*] + plot coordinates { + (0,0) + (1,5) + (2,8) + (3,9) + (4,8) + (5,5) + (6,0) + }; + \end{axis} + \end{tikzpicture} + \caption{An example of graph labelling.% + \label{fig:xmpl:unitless}} + \end{figure} +\end{LaTeXdemo} + + In most cases, adding exponent values in the body of a table is + less desirable than adding a fixed exponent to column headers. An + example is shown in Table~\ref{tab:good}. The use of \cs{multicolumn} is + needed here due to the \enquote{\texttt{<}}; without \cs{multicolumn}, + the titles are followed by \enquote{\unit{\kilo\gram}}! +\begin{LaTeXdemo}[code and float] + \begin{table} + \caption{Good and bad columns.% + \label{tab:good}} + \sisetup{table-number-alignment = center} + \begin{tabular}{ + @{} + c + S[table-format = 1.3e1] + @{\,\unit{\kilogram}} + S[table-format = 2.2] + @{} + } + \toprule + Entry & \multicolumn{1}{c}{Mass} & + {Mass/\qty[print-unity-mantissa = false]{e3}{\kilogram}} \\ + \midrule + 1 & 4.56e3 & 4.56 \\ + 2 & 2.40e3 & 2.40 \\ + 3 & 1.345e4 & 13.45 \\ + 4 & 4.5e2 & 0.45 \\ + \bottomrule + \end{tabular} + \end{table} +\end{LaTeXdemo} + +\section{Installation} + +For most users, there will be no need to explicitly install \pkg{siunitx}: +it is available from the package management system in current \TeX{} Live +and MiK\TeX{} systems. + +For manual installation, the package is available from +\href{http://ctan.org/pkg/siunitx}{\acro{CTAN}}. As well as the raw source +files, \acro{CTAN} hold the package as a pre-extracted zip file, +\file{siunitx.tds.zip}. The later is most convenient for most users: simply +unzip this in your local \path{texmf} directory. + +The package requires \LaTeX3 support as provided in the \pkg{l3kernel} and +\pkg{l3packages} bundles. Both of these are included in \TeX{} Live and +MiK\TeX{}, or are again available in ready-to-install form from \acro{CTAN}. + +\section{Thanks} + +Many users have provided feedback, bug reports and ideas for new features for +\pkg{siunitx}: thanks to all of them. Particular thanks to Stefan Pinnow, who +has taken the lead role as beta tester for \pkg{siunitx}, finding incorrect +output, bad documentation and the odd spelling mistake in the documentation. +Thanks also to Enrico Gregorio for encouraging me to complete a fully +\pkg{expl3}-compliant version of the package. Thanks also to Danie Els and +Marcel Heldoorn for the \pkg{SIstyle} and \pkg{SIunits} packages, respectively, +which provided the starting point for the development of \pkg{siunitx}. + +\section{Making suggestions and reporting bugs} + +Feedback on \pkg{siunitx} is always welcome, either to make suggestions or to +report problems. When sending feedback, it is always useful if a small example +file is included, showing the bug being reported or illustrating the desired +output. It is helpful if a \enquote{reference rendering} is included, showing +what the output should look like. A typical example file might read +\begin{verbatim} + \listfiles + % Use the article class unless the problem is class-dependent + \documentclass{article} + \usepackage{siunitx} + % Other packages loaded as required + \begin{document} + Reference output: $1.23\,\mathrm{m}$ + + \textsf{siunitx} output: \qty{1.23}{\metre} + \end{document} +\end{verbatim} +As illustrated, it is usually best to use the \cls{article} class and to only +load packages which are needed to show the issue. It is also useful to include +a copy of the log file generate by \LaTeX{} when reporting a bug (as the +versions of packages can be important to solving the issue). + +Feedback can be sent in a range of ways. The development code and issue tracker +are hosted on \href{https://github.com/josephwright/siunitx/}{GitHub}. Issues +opened there are visible to other users and makes sure that they cannot be +forgotten. + +\end{documentation} + +\begin{thebibliography}{10} + \bibitem{BIPM} + \emph{The International System of Units (\acro{SI})}, + \url{https://www.bipm.org/en/measurement-units/}. + \bibitem{NIST} + \emph{International System of Units from \acro{NIST}}, + \url{http://physics.nist.gov/cuu/Units/index.html}. +\end{thebibliography} + +\PrintIndex + +\end{document} diff --git a/macros/latex/contrib/tiscreen/README b/macros/latex/contrib/tiscreen/README new file mode 100644 index 0000000000..23693c804f --- /dev/null +++ b/macros/latex/contrib/tiscreen/README @@ -0,0 +1,15 @@ +tiscreen (TI calculator screen) +v1.0 + +This package mimics the screen of older Texas instruments dot matrix display +calculators, specifically the TI-82 STATS. + +Changes: +- 2021/05/17 Initial version + +For more information, please see the documentation. + +Copyright 2021 +This work may be distributed and/or modified under the conditions of the LaTeX +Project Public License, either version 1.3c or higher. The latest version the +license is at: http://www.latex-project.org/lppl.txt diff --git a/macros/latex/contrib/tiscreen/doc/tiscreen-doc.pdf b/macros/latex/contrib/tiscreen/doc/tiscreen-doc.pdf Binary files differnew file mode 100644 index 0000000000..4c0f4f9f05 --- /dev/null +++ b/macros/latex/contrib/tiscreen/doc/tiscreen-doc.pdf diff --git a/macros/latex/contrib/tiscreen/doc/tiscreen-doc.tex b/macros/latex/contrib/tiscreen/doc/tiscreen-doc.tex new file mode 100644 index 0000000000..f959f56640 --- /dev/null +++ b/macros/latex/contrib/tiscreen/doc/tiscreen-doc.tex @@ -0,0 +1,127 @@ +\documentclass[a4paper,12pt]{article} +\usepackage[margin=1in]{geometry} +\usepackage[english]{babel} +\usepackage{parskip} +\usepackage[color]{tiscreen} +\usepackage{multicol} + +\usepackage{listings} +\lstset{ + numbers=left, numberstyle=\tiny, + frame=single, + basicstyle=\footnotesize\ttfamily, + language=Tex, +} + +\newcommand{\LCDsymb}[1]{\large \textLCD{1}|{#1}~|} +\newcommand{\LCDcode}[1]{\texttt{\{#1\}}} + +\title{TI calculator display\\{\small(TI-82 STATS)}} +\author{Mustafa Ibrahim} +\date{2021/05/17} + +\begin{document} + +\maketitle +\begin{center} +\tiscreen +|10^6*(4^7+1){rarrow}X | +| 1.6385E10| +|{sqrt}(X)*X/10! | +| 577971782.1| +|cos{ar}(cos(Ans)) | +| 62.11246| +|{fcur} | +| | +\end{center} +\tableofcontents +\newpage + +\section{Quickstart} +\tiscreen +|4+1 | +| 5| +|Ans{sq} | +| 25| +| | +| | +| | +| | + +\begin{lstlisting} +\documentclass{article} +\usepackage[color]{tiscreen} +% Remove 'color' to display in back and white + +\begin{document} + +\tiscreen +|4+1 | +| 5| +|Ans{sq} | +| 25| +| | +| | +| | +| | + +\end{document} +\end{lstlisting} + +\section{Package option(s)} +\subsection{Color} +Using the \texttt{color} option will change the colors used by the +\texttt{\textbackslash LCD} command. The colors are defined as +\texttt{tiscreenfg} (foreground. i.e. font color) and \texttt{tiscreenbg} +(background). These colors can be redefined like this: + +\begin{lstlisting} +% Add this to your preamble +\definecolor{tiscreenbg}{HTML}{5d9345} +\definecolor{tiscreenfg}{HTML}{FFFFFF} +\end{lstlisting} + +\section{LCD size} +The default LCD size is $8\times 16$ (the size of the TI-82 STATS). It can be +changed by redefining the variables used to determine the size of the display +or by using the original {\textbackslash LCD} command. + +\begin{lstlisting} +% First method: +\def\tiscreenX{16} +\def\tiscreenY{8} + +% Second method: +\LCD{5}{11} +|ANOTHER | +|EXAMPLE | +|WITH A | +|DIFFERENT| +|SIZE | +\end{lstlisting} + +\section{Additional defined characters} \LCDcolors{black}{white} +\begin{tabular}{l|l|l} + Name & Symbol & Code \\ + \hline + E (scientific notation) & \LCDsymb{sciE} & \LCDcode{sciE} \\ + Sigma (lowercase) & \LCDsymb{sigma} & \LCDcode{sigma} \\ + $\bar x$ & \LCDsymb{barx} & \LCDcode{barx} \\ + $\bar y$ & \LCDsymb{bary} & \LCDcode{bary} \\ + $^\wedge 2$ (square root) & \LCDsymb{sq} & \LCDcode{sq} \\ + $^\wedge (-1)$ & \LCDsymb{ar} & \LCDcode{ar} \\ +\end{tabular} + +\subsection{Redefined characters} +Predefined characters that where redefined to match the TI-82 STATS. + +\begin{tabular}{l|l|l} + Name & Symbol & Code \\ + \hline + e & \LCDsymb{e} & \texttt{e} \\ + i & \LCDsymb{i} & \texttt{i} \\ + Square root & \LCDsymb{sqrt} & \LCDcode{sqrt} \\ + ! & \LCDsymb{!} & \LCDcode{!} \\ +\end{tabular} + +\end{document} diff --git a/macros/latex/contrib/tiscreen/tex/tiscreen.sty b/macros/latex/contrib/tiscreen/tex/tiscreen.sty new file mode 100644 index 0000000000..2d911d6b2e --- /dev/null +++ b/macros/latex/contrib/tiscreen/tex/tiscreen.sty @@ -0,0 +1,32 @@ +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{tiscreen}[2021/05/17 Ti calculator screen] + +% TODO +% Scaling option + +\def\tiscreenX{16} +\def\tiscreenY{8} + +\RequirePackage{lcd} +% Undefine +\DefineLCDchar{barx}{11111000001000101010001000101010001} +\DefineLCDchar{bary}{11111000001000110001011110000101110} +\DefineLCDchar{ar}{00011000011100100001000010000000000} +\DefineLCDchar{sciE}{00000000000111101000011100100001111} +\DefineLCDchar{sigma}{00000000000111110010100101001001100} +\DefineLCDchar{sq}{01100000100010001000011100000000000} +% Redefine +\DefineLCDchar{sqrt}{00111001000010000100101000110000100} +\DefineLCDchar{!}{00100001000010000100000000010000100} +\DefineLCDchar{e}{00000000000111010001111101000001100} +\DefineLCDchar{i}{01000000001100001000010000101000100} + +\RequirePackage{xcolor} +\definecolor{tiscreenfg}{HTML}{000000} +\definecolor{tiscreenbg}{HTML}{5d9345} + +\DeclareOption{color}{\LCDcolors{tiscreenfg}{tiscreenbg}} +\DeclareOption*{\PackageWarning{tiscreen}{Unknown ‘\CurrentOption’}} +\ProcessOptions\relax + +\newcommand{\tiscreen}{\LCD{\tiscreenY}{\tiscreenX}} diff --git a/macros/luatex/generic/luatexja/README b/macros/luatex/generic/luatexja/README index c8513509e7..e0f26c370c 100644 --- a/macros/luatex/generic/luatexja/README +++ b/macros/luatex/generic/luatexja/README @@ -1,4 +1,4 @@ -The LuaTeX-ja Package 20210319.0 +The LuaTeX-ja Package 20210517.0 -------------------------------- Copyright (c) 2011--2021 The LuaTeX-ja project License: modified BSD (see COPYING) @@ -42,9 +42,9 @@ Installation 2. If you must/want to install manually: a. Download the source archive from CTAN, - or tagged as 20210319.0 in the Git repository by + or tagged as 20210517.0 in the Git repository by <http://git.osdn.jp/view?p=luatex-ja/luatexja.git - ;a=snapshot;h=refs/tags/20210319.0;sf=tgz> + ;a=snapshot;h=refs/tags/20210517.0;sf=tgz> b. Extract the archive and process following three files by LuaLaTeX to generate classes for Japanese typesetting: @@ -93,4 +93,4 @@ Notes This file and ltj-kinsoku.lua are not used anymore. (Do not remove ltj-kinsoku.tex.) -Last commit date: Fri Mar 19 19:52:23 2021 +0900 +Last commit date: Mon May 17 11:57:27 2021 +0900 diff --git a/macros/luatex/generic/luatexja/doc/luatexja-en.pdf b/macros/luatex/generic/luatexja/doc/luatexja-en.pdf Binary files differindex e0bc2215ff..12aada4965 100644 --- a/macros/luatex/generic/luatexja/doc/luatexja-en.pdf +++ b/macros/luatex/generic/luatexja/doc/luatexja-en.pdf diff --git a/macros/luatex/generic/luatexja/doc/luatexja-ja.pdf b/macros/luatex/generic/luatexja/doc/luatexja-ja.pdf Binary files differindex 41f5012b67..8799ab20c8 100644 --- a/macros/luatex/generic/luatexja/doc/luatexja-ja.pdf +++ b/macros/luatex/generic/luatexja/doc/luatexja-ja.pdf diff --git a/macros/luatex/generic/luatexja/doc/luatexja-ruby.pdf b/macros/luatex/generic/luatexja/doc/luatexja-ruby.pdf Binary files differindex 31dc6d4270..2ca312ab06 100644 --- a/macros/luatex/generic/luatexja/doc/luatexja-ruby.pdf +++ b/macros/luatex/generic/luatexja/doc/luatexja-ruby.pdf diff --git a/macros/luatex/generic/luatexja/doc/luatexja-ruby.tex b/macros/luatex/generic/luatexja/doc/luatexja-ruby.tex index 08bb579204..a01994faa7 100644 --- a/macros/luatex/generic/luatexja/doc/luatexja-ruby.tex +++ b/macros/luatex/generic/luatexja/doc/luatexja-ruby.tex @@ -853,6 +853,8 @@ $r_2$,~$g_2$を行Bから除去・メモリ解放し,代わりに$n_3$を行B ◆\ruby{A}{◆◆◆◆◆}◆\\◆\ruby{A}{◆◆◆◆◆◆}◆\\◆A◆ \makebox[10\zw][s]{値とは\ruby{\texttt{;}}{セミコロン}で区切}% + + \ltjruby{痛}{いたみ}(\ltjruby{病}{びやう}あ } \fbox{\box0} diff --git a/macros/luatex/generic/luatexja/doc/luatexja.dtx b/macros/luatex/generic/luatexja/doc/luatexja.dtx index 7e6ccb9f42..4b1dd88c84 100644 --- a/macros/luatex/generic/luatexja/doc/luatexja.dtx +++ b/macros/luatex/generic/luatexja/doc/luatexja.dtx @@ -238,9 +238,6 @@ grammatical (and contextual) errors.} Also, several parts are written in Japanese only. %</en> -%<*ja> -\emph{\large 本ドキュメントはまだまだ未完成です.} -%</ja> \clearpage %<en>\part{User's manual} @@ -3371,28 +3368,36 @@ Returned value&\texttt{4}&\texttt{3}&\texttt{1}&\texttt{11}&\texttt{0}\\ %</ja> %<*en> -\subsection{Overridden box primitives} -To cope with multiple directions, the following primitives are -overridden by \LuaTeX-ja, using~\verb+\protected\def+. +\section{Redefined primitives by \LuaTeX-ja} +The following primitives are redefined by \LuaTeX-ja (using~\verb+\protected\def+), +for supporting Japanese typesetting and multiple directions: \begin{cslist}[style=standard] + \item[\cs{/}] \item[\cs{unhbox}<num>\textrm{, }\cs{unvbox}<num>\textrm{, }\cs{unhcopy}<num>\textrm{, }\cs{unvcopy}<num>] \item[\cs{vadjust}\{<material>\}] \item[\cs{insert}<number>\{<material>\}] \item[\cs{lastbox}] - \item[\cs{raise}<dimen><box>\textrm{, }\cs{lower}<dimen><box>\textrm{\ etc., }\cs{vcenter}] - \item[\cs{vcenter}] + \item[\cs{raise}<dimen><box>\textrm{, }\cs{lower}<dimen><box>\textrm{, } + \cs{moveleft}<dimen><box>\textrm{, }\cs{moveright}<dimen><box>\textrm{, }] + \item[\cs{split}<number>to<dimen>\textrm{, }\cs{vcenter}\{<material>\}] \end{cslist} + +On each primitive \cs{<primitive>} in the list above, +its meaning just before loading \LuaTeX-ja is backed up into \cs{ltj@@orig@<primitive>}, +and the meaning after redefinition by \LuaTeX-ja is stored in \cs{ltj@@<primitive>}. +For example, \autoref{fig:primitive_meaning} shows the situation of \cs{vadjust} primitive. %</en> %<*ja> -\subsection{プリミティブの再定義} -異なる組方向に対応するために,以下に挙げるプリミティブは -\LuaTeX-jaによる前処理もしくは後処理が行われるように -\ \verb+\protected\def+ により再定義してある. +\section{プリミティブの再定義} +\LuaTeX-jaでは和文組版や異なる組方向に対応するために,以下に挙げるプリミティブは +\ \verb+\protected\def+ により再定義を行っている. \begin{cslist} - \item[\cs{unhbox}<num>\textrm{, }\cs{unvbox}<num>\textrm{, }\cs{unhcopy}<num>\textrm{, }\cs{unvcopy}<num>] + \item[\cs{/}] + 和文フォントに対するイタリック補正のサポートが追加されている. + \item[\cs{unhbox}<number>\textrm{, }\cs{unvbox}<number>\textrm{, }\cs{unhcopy}<number>\textrm{, }\cs{unvcopy}<number>] ボックスの組方向が現在のリストと異なる場合は事前にエラーメッセージを出力する. - \pTeX と異なり,エラーを無視して無理矢理 \cs{unhbox}, \cs{unvbox} を + \pTeX と異なり,エラーを無視して無理矢理 \cs{unhbox}, \cs{unvbox} 等を 続行させることもできるが,その場合の組版結果は保証しない. \item[\cs{vadjust}\{<material>\}] 一旦プリミティブ本来の挙動を行う.その後,<material>の組方向が 周囲の垂直リストの組方向と一致しない場合にエラーを出力し, @@ -3403,10 +3408,81 @@ overridden by \LuaTeX-ja, using~\verb+\protected\def+. \item[\cs{lastbox}] ボックスの「中身」を現在の組方向に合わせるためのノード (\textit{dir\_box}という)を必要ならば除去し, 正しく「中身」のボックスが返されるように前処理をする. - \item[\cs{raise}<dimen><box>\textrm{, }\cs{lower}<dimen><box>\textrm{\ etc., }\cs{vcenter}] - 一方,こちらでは必要に応じて\textit{dir\_box}を作成する前処理を追加している. + \item[\cs{raise}<dimen><box>\textrm{, }\cs{lower}<dimen><box>\textrm{, } + \cs{moveleft}<dimen><box>\textrm{, }\cs{moveright}<dimen><box>\textrm{, }] + \leavevmode\vspace{-\baselineskip} + \item[\cs{split}<number>to<dimen>\textrm{, }\cs{vcenter}\{<material>\}] + これらのプリミティブについては必要に応じて\textit{dir\_box}を作成する前処理を追加している. \end{cslist} + +上記の一覧中にあるプリミティブ\cs{<primitive>}については, +\LuaTeX-ja読み込み前の意味が\cs{ltj@@orig@<primitive>}に, +そして\LuaTeX-jaによる再定義後の意味が\cs{ltj@@<primitive>}に保存される. +例えば,\cs{vadjust}については\autoref{fig:primitive_meaning}のようになっている. +%</ja> +\begin{figure} +\begin{LTXexample}[width=.55\textwidth] +\makeatletter\scriptsize\ttfamily +\meaning\vadjust \\ % current +\meaning\ltj@@vadjust \\ % LuaTeX-ja +\meaning\ltj@@orig@vadjust % original +\end{LTXexample} +\caption{Redefining \cs{vadjust} primitive by \LuaTeX-ja} +\label{fig:primitive_meaning} +\end{figure} + +%<*en> +\subsection{Suppressing redefinitions} +Sometimes redefining primitives by \LuaTeX-ja causes a problem. +For example, the \Pkg{breqn} package~(v0.98k) assumes that \cs{vadjust}~and~\cs{insert} have +their primitive meanings. +So, this package cannot by loaded after \LuaTeX-ja by default. + +\LuaTeX-ja version~20210517.0 has features for that problem. Namely: +\begin{itemize} + \item Primitives which is listed in \cs{ltj@stop@overwrite@primitive} are + retain their meanings at just before loading \LuaTeX-ja. + \item After loading \LuaTeX-ja, + one can specify primitives to \cs{ltj@overwrite@primitive}, to redefine them by \LuaTeX-ja. +\end{itemize} +See \autoref{fig:primitive_overwrite} for an example. +%</en> +%<*ja> +\subsection{再定義の抑制} +場合によっては\LuaTeX-jaによるプリミティブの再定義が不都合を起こすこともある. +たとえば,\Pkg{breqn}パッケージ(少なくともv0.98k, 2020\nobreakdash-09\nobreakdash-24))は +読み込み時に\cs{vadjust}, \cs{insert}がプリミティブのままであることを要請するので, +このままでは\LuaTeX-jaの後で読み込むことはできない. + +この状況に対応するため,バージョン20210517.0以降では +\begin{itemize} + \item 制御綴\cs{ltj@stop@overwrite@primitive}内に並べられたプリミティブは, + \LuaTeX-ja読み込み直前時の意味のままとなる. + \item \LuaTeX-ja読み込み後に + \cs{ltj@overwrite@primitive}に引数として与えたプリミティブを与えることで, + それらを「\LuaTeX-jaによって再定義する」際の意味に再定義する +\end{itemize} +機能を導入した.使用例については\autoref{fig:primitive_overwrite}を参照. %</ja> +\begin{figure} +\begin{lstlisting} +\makeatletter +\def\ltj@stop@overwrite@primitive{\insert\vadjust\/\unhbox\vcenter\fontseries} +\makeatother + %% Keep the meaning of \insert, \vadjust, \/, \unhbox and \vcenter. + %% \fontseries will still be redefined by \LuaTeX-ja, because it is not primitive. +\usepackage{luatexja} +... +\usepackage{breqn} +... +\makeatletter +\ltj@overwrite@primitive\expandafter{\insert\vadjust\/\unhbox\vcenter} +\makeatother + %% Redefine \insert, \vadjust, \/, \unhbox and \vcenter. +\end{lstlisting} +\caption{\cs{ltj@stop@overwrite@primitive} and \cs{ltj@overwrite@primitive}} +\label{fig:primitive_overwrite} +\end{figure} %<en>\section{Font Metric and Japanese Font} %<ja>\section{フォントメトリックと和文フォント} diff --git a/macros/luatex/generic/luatexja/src/addons/luatexja-ruby.sty b/macros/luatex/generic/luatexja/src/addons/luatexja-ruby.sty index 0dacf32bf8..c8f933ec92 100644 --- a/macros/luatex/generic/luatexja/src/addons/luatexja-ruby.sty +++ b/macros/luatex/generic/luatexja/src/addons/luatexja-ruby.sty @@ -4,7 +4,7 @@ % LaTeX only! \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{luatexja-ruby}[2020-12-25 v0.51] +\ProvidesPackage{luatexja-ruby}[2021-05-04 v0.52] \RequirePackage{luatexja} %%------------------ diff --git a/macros/luatex/generic/luatexja/src/lltjext.sty b/macros/luatex/generic/luatexja/src/lltjext.sty index 9fe18f4f01..532e7a2934 100644 --- a/macros/luatex/generic/luatexja/src/lltjext.sty +++ b/macros/luatex/generic/luatexja/src/lltjext.sty @@ -3,7 +3,7 @@ % \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{lltjext}[2020-09-30 v1.2k-ltj-12 Macros for vertical writing] +\ProvidesPackage{lltjext}[2021-04-20 v1.2k-ltj-13 Macros for vertical writing] \RequirePackage{luatexja} \newcount\ltj@ext@dir \let\ltj@lltjext@orig@tabular=\tabular @@ -28,7 +28,7 @@ \setlength\dimen@{#2}% \edef\@halignto{to\the\dimen@}\p@tabular<#1>} \def\p@tabular<#1>{\leavevmode \hbox \bgroup - \ltj@ext@dir=\ltjgetparameter{direction} + \ltj@ext@dir=\ltjgetparameter{direction}\relax $\let\@acol\@tabacol \let\@classz\@tabclassz \let\@classiv\@tabclassiv \let\\\@tabularcr\p@tabarray<#1>} @@ -36,6 +36,7 @@ {\p@array<#1>}{\p@array<#1>[c]}} \def\p@array<#1>[#2]#3{% + \ifnum\ltj@ext@dir=0 \ltj@ext@dir=\ltjgetparameter{direction}\relax\fi \let\box@dir\relax \if #1z\relax \ifnum\ltj@ext@dir=3\relax @@ -674,7 +675,7 @@ \def\ltj@lltjext@patch@array{% \patchcmd{\@tabular}{\hbox\bgroup}{% - \hbox\bgroup\ltj@ext@dir=\ltjgetparameter{direction}}{}{} + \hbox\bgroup\ltj@ext@dir=\ltjgetparameter{direction}\relax}{}{} \pretocmd{\array}% {\ltj@ext@dir=\ltjgetparameter{direction}\relax}{}{} \expandafter\let\csname tabular*\endcsname=\ltj@lltjext@orig@tabularS @@ -702,6 +703,7 @@ }% \def\@tabarray{\@ifnextchar<\p@tabarray{\p@tabarray<Z>}} \def\p@array<##1>[##2]##3{% + \ifnum\ltj@ext@dir=0 \ltj@ext@dir=\ltjgetparameter{direction}\relax\fi \let\box@dir\relax \if ##1z\relax \ifnum\ltj@ext@dir=3\relax @@ -734,7 +736,7 @@ \fork@array@option<##1>[##2]% \begingroup \@mkpream{##3}% - \xdef\@preamble{\ialign \noexpand \@halignto + \xdef\@preamble{\noexpand\ialign \noexpand \@halignto \bgroup \tabskip \z@skip \@arstrut \@preamble \tabskip \z@ \cr}% \endgroup diff --git a/macros/luatex/generic/luatexja/src/ltj-latex.sty b/macros/luatex/generic/luatexja/src/ltj-latex.sty index 6517262f56..7e4ec507c6 100644 --- a/macros/luatex/generic/luatexja/src/ltj-latex.sty +++ b/macros/luatex/generic/luatexja/src/ltj-latex.sty @@ -12,7 +12,7 @@ \def\luatexjalatexLoaded{\endinput} \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{ltj-latex}[2021-03-18 LaTeX support of LuaTeX-ja] +\ProvidesPackage{ltj-latex}[2021-05-17 LaTeX support of LuaTeX-ja] \endlinechar=13 @@ -46,7 +46,6 @@ \ifcsname tex_shipout:D\endcsname \expandafter\let\csname tex_shipout:D\endcsname\ltj@shipout \fi - \directlua{luatexja.direction.shipout_lthook = nil} \else \directlua{% luatexbase.add_to_callback('pre_shipout_filter',luatexja.direction.shipout_lthook, 'ltj.direction', 1) @@ -122,6 +121,50 @@ \RequirePackage{lltjp-geometry} +\def\ltj@@q@stop{\ltj@@q@stop} +\ifdefined\ltj@stop@overwrite@primitive + \begingroup + \def\ltj@loop#1{% + \unless\ifx#1\ltj@@q@stop + \escapechar-1 + \ifcsname ltj@@orig@\string#1\endcsname + \ifcsname ltj@@\string#1\endcsname + \edef\ltj@@next{\unexpanded{\global\let#1}\csname ltj@@orig@\string#1\endcsname}% + \edef\ltj@@temp{ltj@@orig@\string#1}% + \escapechar92 + \PackageInfo{luatexja}{% + Restoring \string#1\space into its orignal meaning\MessageBreak + (\expandafter\meaning\csname\ltj@@temp\endcsname)}% + \ltj@@next% + \fi + \fi + \let\ltj@@next\ltj@loop + \else\let\ltj@@next\relax\fi\ltj@@next + }% + \expandafter\ltj@loop\ltj@stop@overwrite@primitive\ltj@@q@stop + \endgroup +\fi +\def\ltj@overwrite@primitive#1{% + \begingroup + \def\ltj@loop##1{% + \unless\ifx##1\ltj@@q@stop + \escapechar-1 + \edef\ltj@@next{\unexpanded{\let\ltj@@temp}\csname ltj@@\string##1\endcsname}\ltj@@next + \ifx\ltj@@temp\relax + \else\ifx\ltj@@temp##1 + \escapechar92 + \PackageInfo{luatexja}{No need to redefine \string##1}% + \else + \edef\ltj@@next{\unexpanded{\global\let##1}\csname ltj@@\string##1\endcsname}% + \escapechar92\PackageInfo{luatexja}{Redefining \string##1}\ltj@@next% + \fi\fi + \let\ltj@@next\ltj@loop + \else\let\ltj@@next\relax\fi\ltj@@next + }% + \ltj@loop#1\ltj@@q@stop + \endgroup +} + %%------------------ all done \ltj@latex@AtEnd \endinput diff --git a/macros/luatex/generic/luatexja/src/ltj-ruby.lua b/macros/luatex/generic/luatexja/src/ltj-ruby.lua index cd8b98aa27..d5bc393963 100644 --- a/macros/luatex/generic/luatexja/src/ltj-ruby.lua +++ b/macros/luatex/generic/luatexja/src/ltj-ruby.lua @@ -3,7 +3,7 @@ -- luatexbase.provides_module({ name = 'luatexja.ruby', - date = '2020-10-30', + date = '2021-05-04', description = 'Ruby annotation', }) luatexja.ruby = {} @@ -544,12 +544,13 @@ local function pre_high(ahead) local op = (atr>0) and (old_break_info[atr] or post_intrusion_backup) or 0 max_allow_pre = max(0, -max_allow_pre - op) end - if rst.exclude_pre_from_prev_ruby and ((atr>0) and (old_break_info[-atr]>0) or post_jfmgk_backup) then + if rst.exclude_pre_from_prev_ruby and atr>0 and old_break_info[-atr] + and (old_break_info[-atr]>0 or post_jfmgk_backup) then -- 「直前のルビが JFM グルーに進入→現在のルビの前文字進入はなし」という状況 max_allow_pre = 0; rst.exclude_pre_from_prev_ruby=false end if rst.exclude_pre_jfmgk_from_prev_ruby - and (atr>0) and ((old_break_info[atr] or post_intrusion_backup) > 0) then + and atr>0 and ((old_break_info[atr] or post_intrusion_backup) > 0) then -- 「直前のルビが文字に進入→現在のルビの和文処理グルーへの進入はなし」という状況 rst.before_jfmgk = 0 end diff --git a/macros/luatex/generic/luatexja/src/luatexja-core.sty b/macros/luatex/generic/luatexja/src/luatexja-core.sty index 3f3f102191..5f596574e2 100644 --- a/macros/luatex/generic/luatexja/src/luatexja-core.sty +++ b/macros/luatex/generic/luatexja/src/luatexja-core.sty @@ -65,7 +65,7 @@ \expandafter\let\csname ifltj@in@latex\expandafter\endcsname \csname iftrue\endcsname \NeedsTeXFormat{LaTeX2e} - \ProvidesPackage{luatexja-core}[2021-03-16 Core of LuaTeX-ja] + \ProvidesPackage{luatexja-core}[2021-05-11 Core of LuaTeX-ja] \fi %</LaTeX> %% Load prerequisite packages. @@ -215,7 +215,11 @@ stop_time_measure(scan_arg()) end } -\protected\def\/{\relax\luafunction\ltj@@italic@inner} +\begingroup\catcode`\/=11 +\global\let\ltj@@orig@/=\/ +\protected\gdef\ltj@@/{\relax\luafunction\ltj@@italic@inner} +\global\let\/\ltj@@/ %% PRIMITIVE +\endgroup \luadef\ltj@@start@time@measure\ltj@@start@time@measure@inner \luadef\ltj@@stop@time@measure\ltj@@stop@time@measure@inner @@ -603,7 +607,7 @@ \yoko %%%% insert -\let\orig@insert=\insert +\let\ltj@@orig@insert\insert \newluafunction\ltj@@lua@populate@insertwhatsit@inner \directlua{ local t = lua.get_functions_table() @@ -611,20 +615,29 @@ = luatexja.direction.populate_insertion_dir_whatsit } \luadef\ltj@@lua@populate@insertwhatsit\ltj@@lua@populate@insertwhatsit@inner -\protected\def\insert{\begingroup\afterassignment\ltj@@insert@A\ltj@tempcnta} -\protected\def\ltj@@insert@A{\orig@insert\ltj@tempcnta\bgroup +\protected\def\ltj@@insert{\begingroup\afterassignment\ltj@@insert@A\ltj@tempcnta} +\let\insert\ltj@@insert %% PRIMITIVE +\protected\def\ltj@@insert@A{\ltj@@orig@insert\ltj@tempcnta\bgroup \aftergroup\ltj@@insert@B\let\ltj@@next} \protected\def\ltj@@insert@B{\ltj@@lua@populate@insertwhatsit\endgroup} %%%% vadjust -\let\ltj@@orig@vadjust=\vadjust -\protected\def\vadjust{% - \ltj@@orig@vadjust\bgroup - \directlua{luatexja.direction.set_list_direction_hook('adj')}% - \aftergroup\ltj@@vadjust@check@dir\let\ltj@@next} -\protected\def\ltj@@vadjust@check@dir{% - \directlua{luatexja.direction.check_adjust_direction()}% +\let\ltj@@orig@vadjust\vadjust +\newluafunction\ltj@@vadjust@dirhook@inner +\newluafunction\ltj@@vadjust@check@dir@inner +\directlua{ + local t = lua.get_functions_table() + t[\the\ltj@@vadjust@dirhook@inner] + = function () luatexja.direction.set_list_direction_hook('adj') end + t[\the\ltj@@vadjust@check@dir@inner] + = luatexja.direction.check_adjust_direction() } +\luadef\ltj@@vadjust@dirhook\ltj@@vadjust@dirhook@inner +\protected\luadef\ltj@@vadjust@check@dir\ltj@@vadjust@check@dir@inner +\protected\def\ltj@@vadjust{% + \ltj@@orig@vadjust\bgroup\ltj@@vadjust@dirhook + \aftergroup\ltj@@vadjust@check@dir\let\ltj@@next} +\let\vadjust\ltj@@vadjust %% PRIMITIVE %%%% \hbox, \vbox, \vtop \setbox\z@\hbox{% @@ -653,9 +666,9 @@ \PushPreHook{hbox}{\ltj@@box@dirhook\aftergroup\ltj@@reset@badness} \PushPreHook{vbox}{\ltj@@box@dirhook\aftergroup\ltj@@reset@badness} \else - \let\ltj@@everyhbox=\everyhbox\let\ltj@@everyvbox=\everyvbox + \let\ltj@@everyhbox\everyhbox\let\ltj@@everyvbox\everyvbox \newtoks\ltj@@i@everyhbox\newtoks\ltj@@i@everyvbox - \let\everyhbox=\ltj@@i@everyhbox\let\everyvbox=\ltj@@i@everyvbox + \let\everyhbox\ltj@@i@everyhbox\let\everyvbox\ltj@@i@everyvbox \ltj@@everyhbox{\ltj@@box@dirhook \aftergroup\ltj@@reset@badness\the\ltj@@i@everyhbox} \ltj@@everyvbox{\ltj@@box@dirhook @@ -671,35 +684,41 @@ t[\the\ltj@@lua@raisebox@inner]=luatexja.direction.raise_box } \protected\luadef\ltj@@lua@raisebox\ltj@@lua@raisebox@inner -\let\ltj@@orig@raise=\raise -\let\ltj@@orig@lower=\lower -\protected\def\raise{\ltj@reset@globaldefs\afterassignment\ltj@@raise\ltj@tempdima} -\protected\def\lower{\ltj@reset@globaldefs\afterassignment\ltj@@raise\ltj@tempdima-} -\protected\def\ltj@@raise{% +\let\ltj@@orig@raise\raise +\let\ltj@@orig@lower\lower +\protected\def\ltj@@raise{\ltj@reset@globaldefs\afterassignment\ltj@@raise@\ltj@tempdima} +\protected\def\ltj@@lower{\ltj@reset@globaldefs\afterassignment\ltj@@raise@\ltj@tempdima-} +\protected\def\ltj@@raise@{% \ltj@restore@globaldefs \edef\ltj@@raise@a{% \ltj@@lua@raisebox\ltj@@orig@raise\the\ltj@tempdima\noexpand\box\ltj@afbox }\ltj@afterbox\ltj@@raise@a} -\let\ltj@@orig@moveleft=\moveleft -\let\ltj@@orig@moveright=\moveright -\protected\def\moveleft{\ltj@reset@globaldefs\afterassignment\ltj@@moveleft\ltj@tempdima} -\protected\def\moveright{\ltj@reset@globaldefs\afterassignment\ltj@@moveleft\ltj@tempdima-} -\protected\def\ltj@@moveleft{% +\let\ltj@@orig@moveleft\moveleft +\let\ltj@@orig@moveright\moveright +\protected\def\ltj@@moveleft{\ltj@reset@globaldefs\afterassignment\ltj@@moveleft@\ltj@tempdima} +\protected\def\ltj@@moveright{\ltj@reset@globaldefs\afterassignment\ltj@@moveleft@\ltj@tempdima-} +\protected\def\ltj@@moveleft@{% \ltj@restore@globaldefs \edef\ltj@@moveleft@a{% \ltj@@lua@raisebox\ltj@@orig@moveleft\the\ltj@tempdima\noexpand\box\ltj@afbox }\ltj@afterbox\ltj@@moveleft@a} +\let\raise\ltj@@raise %% PRIMITIVE +\let\lower\ltj@@lower %% PRIMITIVE +\let\moveleft\ltj@@moveleft %% PRIMITIVE +\let\moveright\ltj@@moveright %% PRIMITIVE %%%%\vsplit -\let\ltj@@orig@vsplit=\vsplit -\protected\def\vsplit{\directlua{luatexja.direction.vsplit()}} +\let\ltj@@orig@vsplit\vsplit +\protected\def\ltj@@vsplit{\directlua{luatexja.direction.vsplit()}} +\let\vsplit\ltj@@vsplit %% PRIMITIVE %%%% \vcenter -\let\ltj@@orig@vcenter=\vcenter -\protected\def\vcenter{\ltj@afterbox\ltj@@vcenter\vbox} -\protected\def\ltj@@vcenter{% +\let\ltj@@orig@vcenter\vcenter +\protected\def\ltj@@vcenter{\ltj@afterbox\ltj@@vcenter@\vbox} +\protected\def\ltj@@vcenter@{% \ltj@@lua@raisebox\ltj@@orig@vcenter{\box\ltj@afbox}% } +\let\vcenter\ltj@@vcenter %% PRIMITIVE %%%% \unhbox and \unvbox \newluafunction\ltj@@lua@unboxcheckdir@inner @@ -709,40 +728,38 @@ } \luadef\ltj@@lua@unboxcheckdir\ltj@@lua@unboxcheckdir@inner \long\def \@gobbletwo #1#2{} -\let\ltj@@orig@unhbox=\unhbox -\let\ltj@@orig@unvbox=\unvbox -\protected\def\unhbox{\ltj@reset@globaldefs\afterassignment\ltj@@unhbox\ltj@tempcnta} -\protected\def\unvbox{\ltj@reset@globaldefs\afterassignment\ltj@@unvbox\ltj@tempcnta} -\protected\def\ltj@@unhbox{% - \ltj@@lua@unboxcheckdir\ltj@@orig@unhbox\ltj@tempcnta} -\protected\def\ltj@@unvbox{% - \ltj@@lua@unboxcheckdir\ltj@@orig@unvbox\ltj@tempcnta} -\let\ltj@@orig@unhcopy=\unhcopy -\let\ltj@@orig@unvcopy=\unvcopy -\protected\def\unhcopy{\ltj@reset@globaldefs\afterassignment\ltj@@unhcopy\ltj@tempcnta} -\protected\def\unvcopy{\ltj@reset@globaldefs\afterassignment\ltj@@unvcopy\ltj@tempcnta} -\protected\def\ltj@@unhcopy{% +\let\ltj@@orig@unhbox\unhbox +\let\ltj@@orig@unvbox\unvbox +\protected\def\ltj@@unhbox{\ltj@reset@globaldefs\afterassignment\ltj@@unhbox@\ltj@tempcnta} +\protected\def\ltj@@unvbox{\ltj@reset@globaldefs\afterassignment\ltj@@unvbox@\ltj@tempcnta} +\protected\def\ltj@@unhbox@{\ltj@@lua@unboxcheckdir\ltj@@orig@unhbox\ltj@tempcnta} +\protected\def\ltj@@unvbox@{\ltj@@lua@unboxcheckdir\ltj@@orig@unvbox\ltj@tempcnta} +\let\ltj@@orig@unhcopy\unhcopy +\let\ltj@@orig@unvcopy\unvcopy +\protected\def\ltj@@unhcopy{\ltj@reset@globaldefs\afterassignment\ltj@@unhcopy@\ltj@tempcnta} +\protected\def\ltj@@unvcopy{\ltj@reset@globaldefs\afterassignment\ltj@@unvcopy@\ltj@tempcnta} +\protected\def\ltj@@unhcopy@{% \directlua{luatexja.direction.unbox_check_dir(true)}% \ltj@@orig@unhcopy\ltj@tempcnta \directlua{luatexja.direction.uncopy_restore_whatsit()}} -\protected\def\ltj@@unvcopy{% +\protected\def\ltj@@unvcopy@{% \directlua{luatexja.direction.unbox_check_dir(true)}% \ltj@@orig@unvcopy\ltj@tempcnta \directlua{luatexja.direction.uncopy_restore_whatsit()}} +\let\unhbox\ltj@@unhbox %% PRIMITIVE +\let\unvbox\ltj@@unvbox %% PRIMITIVE +\let\unhcopy\ltj@@unhcopy %% PRIMITIVE +\let\unvcopy\ltj@@unvcopy %% PRIMITIVE %%%% lastbox \let\ltj@@orig@lastbox=\lastbox -\protected\def\lastbox{% - \directlua{luatexja.direction.lastbox_hook()}\ltj@@orig@lastbox -} +\protected\def\ltj@@lastbox{\directlua{luatexja.direction.lastbox_hook()}\ltj@@orig@lastbox} +\let\lastbox\ltj@@lastbox %% PRIMITIVE %%%%%%%% \ltjgetwd<box_num> etc. -\def\ltj@@getwd{% - \directlua{luatexja.direction.get_box_dim('width', token.scan_int())}} -\def\ltj@@getht{% - \directlua{luatexja.direction.get_box_dim('height', token.scan_int())}} -\def\ltj@@getdp{% - \directlua{luatexja.direction.get_box_dim('depth', token.scan_int())}} +\def\ltj@@getwd{\directlua{luatexja.direction.get_box_dim('width', token.scan_int())}} +\def\ltj@@getht{\directlua{luatexja.direction.get_box_dim('height', token.scan_int())}} +\def\ltj@@getdp{\directlua{luatexja.direction.get_box_dim('depth', token.scan_int())}} \let\ltjgetwd=\ltj@@getwd\let\ltjgetht=\ltj@@getht\let\ltjgetdp=\ltj@@getdp %%%%%%%% \ltjsetwd<box_num>=<dimen> etc. diff --git a/macros/luatex/generic/luatexja/src/luatexja.lua b/macros/luatex/generic/luatexja/src/luatexja.lua index 8c01db173b..878f791181 100644 --- a/macros/luatex/generic/luatexja/src/luatexja.lua +++ b/macros/luatex/generic/luatexja/src/luatexja.lua @@ -521,7 +521,7 @@ local function debug_show_node_X(p,print_fn, limit, inner_depth) s = s .. ' stream=' .. p.stream print_fn(s) for i=1,#p.data do - print_fn(s .. ' [' .. i .. '] = ' .. tostring(p.data[i].csname)) + print_fn(s .. ' [' .. i .. '] = ' .. tostring(p.data[i] and p.date[i].csname)) end elseif p.subtype==16 then s = s .. ' mode=' .. p.mode .. ', literal="' .. p.data .. '"' diff --git a/macros/luatex/generic/luatexja/src/luatexja.sty b/macros/luatex/generic/luatexja/src/luatexja.sty index 13e67dc392..28b139d95e 100644 --- a/macros/luatex/generic/luatexja/src/luatexja.sty +++ b/macros/luatex/generic/luatexja/src/luatexja.sty @@ -35,13 +35,13 @@ \expandafter\let\csname ifltj@in@latex\expandafter\endcsname \csname iftrue\endcsname \NeedsTeXFormat{LaTeX2e} - \ProvidesPackage{luatexja}[2021-03-19 Japanese Typesetting with Lua(La)TeX] + \ProvidesPackage{luatexja}[2021-05-17 Japanese Typesetting with Lua(La)TeX] \DeclareOption{disablejfam}{\ltj@disablejfamtrue} \DeclareOption*{} \ProcessOptions\relax \fi %</LaTeX> %%%% VERSION -\def\LuaTeXjaversion{20210319.0} +\def\LuaTeXjaversion{20210517.0} \directlua{require('ltj-unicode-ccfix.lua')}% catcode of ideographs diff --git a/macros/luatex/generic/luatexja/src/patches/lltjcore.sty b/macros/luatex/generic/luatexja/src/patches/lltjcore.sty index 19fe320fad..19b365ad48 100644 --- a/macros/luatex/generic/luatexja/src/patches/lltjcore.sty +++ b/macros/luatex/generic/luatexja/src/patches/lltjcore.sty @@ -3,7 +3,7 @@ % \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{lltjcore}[2021-03-19 Patch to LaTeX2e Kernel for LuaTeX-ja] +\ProvidesPackage{lltjcore}[2021-03-25 Patch to LaTeX2e Kernel for LuaTeX-ja] \RequirePackage{etoolbox} %%% expl3 @@ -266,44 +266,17 @@ \newif\iffnfixbottom \newif\ifltj@ftn@unvboxed %%% @makecol -\gdef \@makecol {% - \ifvoid\footins - \ltj@ftn@unvboxedfalse - \setbox\@outputbox \box\@cclv - \else - \ltj@ftn@unvboxedtrue - \setbox\@outputbox \vbox {% - \boxmaxdepth \@maxdepth - \unvbox \@cclv - \iffnfixbottom\vskip\z@ \@plus.0001fil\fi - \vskip \skip\footins - \color@begingroup - \normalcolor - \footnoterule - \unvbox \footins - \color@endgroup - }% - \fi - \let\@elt\relax - \xdef\@freelist{\@freelist\@midlist}% - \global \let \@midlist \@empty - \@combinefloats - \ifvbox\@kludgeins - \@makespecialcolbox - \else - \setbox\@outputbox \vbox to\@colht {% - \@texttop - \dimen@ \dp\@outputbox - \unvbox \@outputbox - \unless\ifnum\ltjgetparameter{direction}=4 - \vbox{\primitive\everypar{}\hskip\z@}% - \fi %%% LuaTeX-ja - \vskip -\dimen@ - \ifltj@ftn@unvboxed\iffnfixbottom\else\@textbottom\fi\else\@textbottom\fi - }% - \fi - \global \maxdepth \@maxdepth -} +\def\pltx@adjust@wd@outputbox{% + \unless\ifnum\ltjgetparameter{direction}=4 + \vbox{\primitive\everypar{}\hskip\z@}% + \fi} +\patchcmd\@makecol{\vskip -\dimen@\@textbottom}% + {\pltx@adjust@wd@outputbox + \vskip -\dimen@ + \ifltj@ftn@unvboxed\iffnfixbottom\else\@textbottom\fi\else\@textbottom\fi}{}{} +\patchcmd\@makecol{\vskip\skip\footins}{\iffnfixbottom\vskip\z@\@plus.0001fil\fi\vskip\skip\footins}{}{} +\patchcmd\@makecol{\ifvoid\footins}{\ifvoid\footins\ltj@ftn@unvboxedfalse}{}{} +\patchcmd\@makecol{\setbox\@outputbox \vbox}{\ltj@ftn@unvboxedtrue\setbox\@outputbox \vbox}{}{} \let\ltj@orig@makecol=\@makecol \patchcmd\@makespecialcolbox{\@textbottom}{\ifltj@ftn@unvboxed\iffnfixbottom\else\@textbottom\fi\else\@textbottom\fi}{}{} diff --git a/macros/luatex/generic/luatexja/src/patches/lltjdefs.sty b/macros/luatex/generic/luatexja/src/patches/lltjdefs.sty index 07b2c0d58b..8bf6bac9f3 100644 --- a/macros/luatex/generic/luatexja/src/patches/lltjdefs.sty +++ b/macros/luatex/generic/luatexja/src/patches/lltjdefs.sty @@ -21,7 +21,7 @@ \ifnum\ltj@@latex@plv<1500 % <=2020-10-01 \kanjiseries{m} \kanjishape{n} -\else % >=2021-05-01 +\else % >=2021-06-01 \def\k@series{m} \def\k@shape{n} \fi diff --git a/macros/luatex/generic/luatexja/src/patches/lltjfont.sty b/macros/luatex/generic/luatexja/src/patches/lltjfont.sty index 4932e07480..31f0f645d8 100644 --- a/macros/luatex/generic/luatexja/src/patches/lltjfont.sty +++ b/macros/luatex/generic/luatexja/src/patches/lltjfont.sty @@ -3,13 +3,13 @@ % \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{lltjfont}[2021-02-14 Patch to NFSS2 for LuaTeX-ja] +\ProvidesPackage{lltjfont}[2021-04-29 Patch to NFSS2 for LuaTeX-ja] %%%%%%%% LaTeX2e version detection \newcount\ltj@@latex@plv \ltj@@latex@plv=-1 \ifltj@ltfilehook@avail \IfHookExistsTF{selectfont}% - {\ltj@@latex@plv=1500}% 2021-05-01 + {\ltj@@latex@plv=1500}% 2021-06-01 {\ifnum\patch@level>2 \ltj@@latex@plv=1300\else \ltj@@latex@plv=1000\fi}% 2020-10-01 \else\ifdefined\@rmfamilyhook % 2020-02-02 \ifx\@forced@seriestrue\@undefined % 2020-02-02 pl0--2 @@ -451,7 +451,7 @@ \ltj@@EverySelectfont@Init } \EverySelectfont{\ltj@selectfont@patch} -\else % LaTeX2e >=2021-05-01 +\else % LaTeX2e >=2021-06-01 \AddToHook{selectfont}[luatexja]{% \ltj@@start@time@measure{selectfont}% \ifx\delayed@k@adjustment\@empty @@ -473,6 +473,7 @@ \fi \let\delayed@k@adjustment\@empty \fi + \@forced@series@kanjifalse \let\tmp@error@fontshape\error@fontshape \let\error@fontshape\error@kfontshape \ltj@@is@kyenc{\k@encoding}\ifin@% @@ -806,7 +807,7 @@ \fi \fi } -\else % >=2021-05-01 +\else % >=2021-06-01 \def\merge@kanji@series@#1#2#3\@nil{% \def\reserved@a{#3}% \ifx\reserved@a\@empty @@ -891,6 +892,7 @@ \let\delayed@merge@kanji@shape\merge@kanji@shape@without@substitution \fi +\newif\if@forced@series@kanji \ifnum\ltj@@latex@plv=300 % 2020-02-02 pl3, 4 \DeclareRobustCommand\romanseries[1]{\merge@font@series{#1}} \DeclareRobustCommand\kanjiseries[1]{\merge@kanji@series{#1}} @@ -898,20 +900,20 @@ \DeclareRobustCommand\kanjiseriesforce[1]{\edef\k@series{#1}} \else\ifnum\ltj@@latex@plv<1500% >=2020-02-02 pl5 and <=2020-10-01 \DeclareRobustCommand\romanseries[1]{\@forced@seriesfalse\merge@font@series{#1}} - \DeclareRobustCommand\kanjiseries[1]{\@forced@seriesfalse\merge@kanji@series{#1}} + \DeclareRobustCommand\kanjiseries[1]{\@forced@series@kanjifalse\merge@kanji@series{#1}} \DeclareRobustCommand\romanseriesforce[1]{\@forced@seriestrue\edef\f@series{#1}} - \DeclareRobustCommand\kanjiseriesforce[1]{\@forced@seriestrue\edef\k@series{#1}} -\else% >=2021-05-01 + \DeclareRobustCommand\kanjiseriesforce[1]{\@forced@series@kanjitrue\edef\k@series{#1}} +\else% >=2021-06-01 \DeclareRobustCommand\romanseries[1]{\@forced@seriesfalse \expandafter\def\expandafter\delayed@f@adjustment\expandafter {\delayed@f@adjustment\delayed@merge@font@series{#1}}} - \DeclareRobustCommand\kanjiseries[1]{\@forced@seriesfalse + \DeclareRobustCommand\kanjiseries[1]{\@forced@series@kanjifalse \expandafter\def\expandafter\delayed@k@adjustment\expandafter {\delayed@k@adjustment\delayed@merge@kanji@series{#1}}} \DeclareRobustCommand\romanseriesforce[1]{\@forced@seriestrue \expandafter\def\expandafter\delayed@f@adjustment\expandafter {\delayed@f@adjustment\edef\f@series{#1}}} - \DeclareRobustCommand\kanjiseriesforce[1]{\@forced@seriestrue + \DeclareRobustCommand\kanjiseriesforce[1]{\@forced@series@kanjitrue \expandafter\def\expandafter\delayed@k@adjustment\expandafter {\delayed@k@adjustment\edef\k@series{#1}}} \let\delayed@k@adjustment\@empty @@ -930,7 +932,7 @@ \DeclareRobustCommand\romanshapeforce[1]{\edef\f@shape{#1}} \DeclareRobustCommand\kanjishapeforce[1]{\edef\k@shape{#1}} \DeclareRobustCommand\fontshapeforce[1]{\set@safe@kanji@shape{#1}{}\romanshapeforce{#1}} -\else% >=2021-05-01 +\else% >=2021-06-01 \DeclareRobustCommand\romanshape[1]{% \expandafter\def\expandafter\delayed@f@adjustment\expandafter {\delayed@f@adjustment\delayed@merge@font@shape{#1}}} @@ -953,8 +955,20 @@ \expandafter\def\expandafter\delayed@k@adjustment\expandafter {\delayed@k@adjustment\set@safe@kanji@shape{#1}{}}} \fi -\ifnum\ltj@@latex@plv>1000 -%%%% LaTeX >= 2020-10-01 PL3 +\ifnum\ltj@@latex@plv>1499 +%%%% LaTeX >= 2021-06-01 +\DeclareRobustCommand\usekanji[4]{% + \kanjiencoding{#1}\edef\k@family{#2}% + \set@target@series@kanji{#3}\edef\k@shape{#4}% + \let\delayed@k@adjustment\@empty + \selectfont\ignorespaces} +\DeclareRobustCommand\useroman[4]{% + \romanencoding{#1}\edef\f@family{#2}% + \set@target@series{#3}\edef\f@shape{#4}% + \let\delayed@f@adjustment\@empty + \selectfont\ignorespaces} +\else\ifnum\ltj@@latex@plv>1000 +%%%% 2021-10-01 PL3 <= LaTeX < 2021-06-01 \DeclareRobustCommand\usekanji[4]{% \kanjiencoding{#1}\edef\k@family{#2}% \set@target@series@kanji{#3}\edef\k@shape{#4}% @@ -971,7 +985,7 @@ \DeclareRobustCommand\useroman[4]{% \romanencoding{#1}\edef\f@family{#2}\edef\f@series{#3}\edef\f@shape{#4}% \selectfont\ignorespaces} -\fi +\fi\fi %%%% LaTeX >= 2020-02-02 END \else %%%% LaTeX 2019-10-01 @@ -1014,6 +1028,7 @@ %%%% LaTeX >= 2020-02-02 \let\prepare@family@series@update@kanji=\prepare@family@series@update \patchcmd\prepare@family@series@update{\fontfamily}{\romanfamily}{}{} +\patchcmd\prepare@family@series@update@kanji{\if@forced@series}{\if@forced@series@kanji}{}{} \patchcmd\prepare@family@series@update@kanji{\fontfamily}{\kanjifamily}{}{} \patchcmd\prepare@family@series@update@kanji{\update@series@target@value}{\update@series@target@value@kanji}{}{} \patchcmd\prepare@family@series@update@kanji{\f@family}{\k@family}{}{} @@ -1153,12 +1168,23 @@ \let\reset@font\normalfont \fi\fi } + +\ifnum\ltj@@latex@plv>1499 +\@ltj@hook@dfh{% + \kanjiencoding{\kanjiencodingdefault}% + \edef\k@family{\kanjifamilydefault}% + \edef\k@series{\kanjiseriesdefault}% + \edef\k@shape{\kanjishapedefault}% + \let\delayed@k@adjustment\empty +} +\else \@ltj@hook@dfh{% \kanjiencoding{\kanjiencodingdefault}% \edef\k@family{\kanjifamilydefault}% \edef\k@series{\kanjiseriesdefault}% \edef\k@shape{\kanjishapedefault}% } +\fi \let\@ltj@hook@dfh\@undefined %%%% LaTeX >= 2020-02-02 END \else diff --git a/macros/luatex/generic/luatexja/src/patches/lltjp-atbegshi.sty b/macros/luatex/generic/luatexja/src/patches/lltjp-atbegshi.sty index d1a21a0e5c..27680205f6 100644 --- a/macros/luatex/generic/luatexja/src/patches/lltjp-atbegshi.sty +++ b/macros/luatex/generic/luatexja/src/patches/lltjp-atbegshi.sty @@ -13,7 +13,7 @@ \RequirePackage{expl3} \ExplSyntaxOn\makeatletter \box_new:N \l__platex_shipout_dummy_box -\if_cs_exist:N \__shipout_execute_main_cont:Nnnn %% 2021-05-01 +\if_cs_exist:N \__shipout_execute_main_cont:Nnnn %% 2021-06-01 \cs_new_eq:NN \__platex_original_shipout_execute_main_cont:Nnnn \__shipout_execute_main_cont:Nnnn \cs_set:Npn \__shipout_execute_main_cont:Nnnn #1#2#3#4 { diff --git a/macros/luatex/generic/luatexja/src/patches/lltjp-footmisc.sty b/macros/luatex/generic/luatexja/src/patches/lltjp-footmisc.sty index 99ed190631..b838fd92fe 100644 --- a/macros/luatex/generic/luatexja/src/patches/lltjp-footmisc.sty +++ b/macros/luatex/generic/luatexja/src/patches/lltjp-footmisc.sty @@ -3,7 +3,7 @@ % \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{lltjp-footmisc}[2021-03-17 Patch to footmisc for LuaTeX-ja] +\ProvidesPackage{lltjp-footmisc}[2021-03-25 Patch to footmisc for LuaTeX-ja] \RequirePackage{footmisc} \let \if@tempswa \ifFN@bottom @@ -47,9 +47,7 @@ \setbox\@outputbox \vbox to\@colht{% \@texttop \dimen@\dp\@outputbox \unvbox\@outputbox - \unless\ifnum\ltjgetparameter{direction}=4 - \vbox{\primitive\everypar{}\hskip\z@}% - \fi %%% LuaTeX-ja + \pltx@adjust@wd@outputbox \vskip -\dimen@\@textbottom }% \fi diff --git a/macros/luatex/generic/luatexja/src/patches/lltjp-siunitx.sty b/macros/luatex/generic/luatexja/src/patches/lltjp-siunitx.sty index c6bebc36cd..db444aecb7 100644 --- a/macros/luatex/generic/luatexja/src/patches/lltjp-siunitx.sty +++ b/macros/luatex/generic/luatexja/src/patches/lltjp-siunitx.sty @@ -1,5 +1,5 @@ % -% lltjp-siunitx.sty 2019-06-06 +% lltjp-siunitx.sty 2021-04-19 % \NeedsTeXFormat{LaTeX2e} @@ -7,6 +7,32 @@ \RequirePackage{siunitx} \makeatletter \ExplSyntaxOn +\cs_if_exist:NTF \siunitx_print_text:n {% siunitx v3.00 +\cs_set_protected:Npn \siunitx_print_text:n #1 + { + \text + { + \ltj@allalchar % <--- LuaTeX-ja + \bool_if:NT \l__siunitx_print_text_family_bool + { + \fontfamily { \familydefault } + \selectfont + } + \bool_if:NT \l__siunitx_print_text_series_bool + { + \fontseries { \seriesdefault } + \selectfont + } + \bool_if:NT \l__siunitx_print_text_shape_bool + { + \fontshape { \shapedefault } + \selectfont + } + \__siunitx_print_text_replace:n {#1} + } + } +}% siunitx v3.00 end +{% siunitx v2.xx \cs_generate_variant:Nn \tl_if_in:NnT { coT } \cs_new:Nn \__ltj_siunix_patch_inner:n { \cs_if_exist:cT { #1_tl } { @@ -91,6 +117,6 @@ } { } } - +} \ExplSyntaxOff \endinput diff --git a/macros/luatex/generic/luatexja/src/patches/lltjp-stfloats.sty b/macros/luatex/generic/luatexja/src/patches/lltjp-stfloats.sty index 6ce9528d72..c4cd3ca53e 100644 --- a/macros/luatex/generic/luatexja/src/patches/lltjp-stfloats.sty +++ b/macros/luatex/generic/luatexja/src/patches/lltjp-stfloats.sty @@ -1,5 +1,5 @@ % -% lltjp-stfloats.sty 2021-03-17 +% lltjp-stfloats.sty 2021-03-25 % \NeedsTeXFormat{LaTeX2e} @@ -14,9 +14,7 @@ \global\let\org@makecol\ltj@orig@makecol \patchcmd\fn@makecol{\vskip -\dimen@\@textbottom}% - {\unless\ifnum\ltjgetparameter{direction}=4 - \vbox{\primitive\everypar{}\hskip\z@}% - \fi %%% LuaTeX-ja + {\pltx@adjust@wd@outputbox \vskip -\dimen@ \ifltj@ftn@unvboxed\iffnfixbottom\else\@textbottom\fi\else\@textbottom\fi}{}{} \patchcmd\fn@makecol{\vskip\skip\footins}{\iffnfixbottom\vskip\z@\@plus.0001fil\fi\vskip\skip\footins}{}{} diff --git a/macros/musixtex/README b/macros/musixtex/README index 257051bce4..da1567d60d 100644 --- a/macros/musixtex/README +++ b/macros/musixtex/README @@ -1,4 +1,4 @@ -This is MusiXTeX, version 1.32 (2021-05-13). +This is MusiXTeX, version 1.32a (2021-05-16). MusiXTeX is a TeX-based system for typesetting music. The main author was Daniel Taupin, who died in a climbing diff --git a/macros/musixtex/doc/musixdoc.pdf b/macros/musixtex/doc/musixdoc.pdf Binary files differindex 8503c82411..ec5eac0642 100644 --- a/macros/musixtex/doc/musixdoc.pdf +++ b/macros/musixtex/doc/musixdoc.pdf diff --git a/macros/musixtex/doc/musixdoc/beams.tex b/macros/musixtex/doc/musixdoc/beams.tex index 6cf562a9c3..dbf57e2eb4 100644 --- a/macros/musixtex/doc/musixdoc/beams.tex +++ b/macros/musixtex/doc/musixdoc/beams.tex @@ -622,6 +622,6 @@ In this example we see not only multiple uses of \keyindex{nextstaff} and \section{Discontinuities in Long Beams} -Beams are normally produced by \texttt{musixtex} using special fonts. Unfortunately, very long beams may have +By default, \texttt{musixtex} produces beams using special fonts. Unfortunately, long beams may have unsightly discontinuities (gaps or bumps). See Section~\ref{musixvbm} -for an experimental solution to this problem. +for a solution to this problem. diff --git a/macros/musixtex/doc/musixdoc/extensions.tex b/macros/musixtex/doc/musixdoc/extensions.tex index 5bf8dd667d..c31772897e 100644 --- a/macros/musixtex/doc/musixdoc/extensions.tex +++ b/macros/musixtex/doc/musixdoc/extensions.tex @@ -2178,38 +2178,52 @@ Available are: \section{musixvbm}\ixtt{musixvbm.tex} \label{musixvbm} -Beams are normally produced by \texttt{musixtex} using special fonts. Unfortunately, very long beams may have -unsightly discontinuities (gaps or bumps). This experimental add-on -(by Hiroaki \textsc{Morimoto}) produces vectorized beams without these -discontinuities. Compare -\begin{description} -\item{} +By default, \texttt{musixtex} produces beams using special fonts. Unfortunately, long beams may have +unsightly discontinuities (gaps or bumps). The \texttt{musixvbm} add-on +by Hiroaki \textsc{Morimoto} produces smooth vectorized beams. +Compare + +\medskip \begin{music} +\let\extractline\hbox +\vectorizedbeamfalse \nostartrule \setclef1{\bass} +\hbox to \hsize{% +\hss \startextract \nnotes\ibbl0G1\qb0{GJKLMLMLMLMLMLMK}\tqb0L\en -\endextract -\end{music} -\end{description} -and -\begin{description} -\item{} -\begin{music} -\input musixvbm -\nostartrule -\setclef1{\bass} +\zendextract +\hss +\raise20pt\hbox{ and } +\hss +\vectorizedbeamtrue \startextract \nnotes\ibbl0G1\qb0{GJKLMLMLMLMLMLMK}\tqb0L\en -\endextract +\zendextract +\hss} \end{music} -\end{description} -especially when magnified. - -The only known disadvantage is that some \texttt{dvi} viewers -including \texttt{xdvi} and \texttt{yap} do not support the \texttt{tpic} specials -that implement the vectorized beams so that no beams are shown; however, Postscript and PDF -output generated using \texttt{dvips} and \texttt{ps2pdf} (or \texttt{dvipdfm}) should be satisfactory. +\medskip +\noindent +with various magnifications. The output on the left shows a font-based beam; the one +on the right (like all the other beams in this report) shows the same beam with +\texttt{musixvbm} activated. + + +The only known disadvantage with use of \texttt{musixvbm} is that many \texttt{dvi} viewers +(including \texttt{xdvi} and \texttt{yap}) do not support the ``\texttt{tpic} specials'' +that implement vectorized beams in \texttt{dvi} output, so that no beams are shown\footnote{% +The \texttt{dviout} program for Windows supports \texttt{tpic} specials; +it is available from CTAN and in the Win32 distribution of TeXLive.}; +however, Postscript and PDF +output generated using \texttt{dvips} and \texttt{ps2pdf} (or using +\texttt{dvipdfm}, +or by processing the score using \texttt{pdfetex}) should be satisfactory. + +If Postscript hairpins +as described in Section~\ref{PostscriptSlurs} are not being used, +the \texttt{musixvbm} add-on also vectorizes crescendos and +decrescendos. \section{tuplet} @@ -2218,9 +2232,7 @@ This file does nothing; it is provided for compatibility with Since version 1.21, \verb|musixtex.tex| itself contains all the functions of the older \texttt{tuplet.tex}, namely definitions of -\begin{itemize} -\item \keyindex{tuplettxt} -\item \keyindex{uptuplet} -\item \keyindex{downtuplet} -\end{itemize} +\keyindex{tuplettxt}, +\keyindex{uptuplet} and +\keyindex{downtuplet}. See Section~\ref{tuplet}. diff --git a/macros/musixtex/doc/musixdoc/frontmatter.tex b/macros/musixtex/doc/musixdoc/frontmatter.tex index e0d9515830..3eedf3665c 100644 --- a/macros/musixtex/doc/musixdoc/frontmatter.tex +++ b/macros/musixtex/doc/musixdoc/frontmatter.tex @@ -1,6 +1,6 @@ \title{\Huge\bfseries\musixtex\\[\bigskipamount] \LARGE\bfseries Using \TeX{} to write polyphonic\\or -instrumental music\\\Large\itshape Version 1.32} +instrumental music\\\Large\itshape Version 1.32a} \author{} diff --git a/macros/musixtex/doc/musixdoc/musixdoc.sty b/macros/musixtex/doc/musixdoc/musixdoc.sty index 95b9c5a291..d06328eb8e 100644 --- a/macros/musixtex/doc/musixdoc/musixdoc.sty +++ b/macros/musixtex/doc/musixdoc/musixdoc.sty @@ -47,7 +47,7 @@ \usepackage{textcomp} \input musixtex -%\input musixvbm % experimental vectorized beams +\input musixvbm % experimental vectorized beams \input musixbm \input musixcho \input musixdat diff --git a/macros/musixtex/windows/musixflx.bat b/macros/musixtex/scripts/musixflx.bat index 684441ebb3..684441ebb3 100644 --- a/macros/musixtex/windows/musixflx.bat +++ b/macros/musixtex/scripts/musixflx.bat diff --git a/macros/musixtex/windows/musixtex.bat b/macros/musixtex/scripts/musixtex.bat index 249ae595c4..249ae595c4 100644 --- a/macros/musixtex/windows/musixtex.bat +++ b/macros/musixtex/scripts/musixtex.bat diff --git a/macros/musixtex/tex/musixvbm.tex b/macros/musixtex/tex/musixvbm.tex index 09fa03da42..a22a60e4c9 100644 --- a/macros/musixtex/tex/musixvbm.tex +++ b/macros/musixtex/tex/musixvbm.tex @@ -1,5 +1,5 @@ %% -%% musixvbm.tex - MusiXTeX Extention, Vectorized Beams (& crescendos) +%% musixvbm.tex - MusiXTeX Extension, Vectorized Beams (& crescendos) %% by tpic specials / pdfTeX raw literal %% %% Copyright (C) 2000-2007 Hiroaki MORIMOTO (Kuuku) @@ -31,7 +31,7 @@ %% This is a successor of `musixtpb.tex' ver.1.10. %% \ifx\ifvectorizedbeam\undefined\else\endinput\fi -\immediate\write16{MusiXTeX Extention, Vectorized Beams and crescendos v1.20-beta6 <2007/01/01>}% +\immediate\write16{MusiXTeX Extension, Vectorized Beams and crescendos v1.20-beta6 <2007/01/01>}% % \edef\catcodeat{\the\catcode`\@}\catcode`\@=11 % @@ -87,13 +87,13 @@ \advance\y@iv \tw@\b@amthick \@dimentomil{-\y@iv}{\@Yend@u}% % \special{pn 1}% - \special{sh 1}% - \@addbeampath{0}{\@Ystart@l}% + \special{sh 1}% set beam shading to black + \@addbeampath{0}{\@Ystart@l}% add points to define the beam perimeter \@addbeampath{\@Xend}{\@Yend@l}% \@addbeampath{\@Xend}{\@Yend@u}% \@addbeampath{0}{\@Ystart@u}% - \@addbeampath{0}{\@Ystart@l}% - \special{ip}% + \@addbeampath{0}{\@Ystart@l}% close the perimeter + \special{ip}% draw the beam (without the outline) \kern\y@ii }% % |