% \iffalse meta-comment % !TEX program = pdflatex % !TEX encoding = ISO-8859-1 %<*internal> \iffalse % %<*readme> ---------------------------------------------------------------- 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 ---------------------------------------------------------------- Typesetting values with units requires care to ensure that the combined mathematical meaning of the value plus 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 numbers and units 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. A number of LaTeX packages have been developed in the past for formatting units: SIunits, sistyle, unitsdef, units, fancyunits and fancynum. Support for users of all of these packages is available as emulation modules in siunitx. In addition, siunitx can carry out many of the functions of the dcolumn, rccol and numprint packages % %<*internal> \fi \begingroup % %<*install> \input docstrip.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-2009 by 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: 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}} } % %\endbatchfile %<*internal> \usedir{source/latex/siunitx} \generate{ \file{\jobname.ins}{\from{\jobname.dtx}{install}} } \nopreamble\nopostamble \usedir{doc/latex/siunitx} \generate{ \file{README.txt}{\from{\jobname.dtx}{readme}} } \endgroup \immediate \write18{makeindex -s gind.ist -o \jobname.ind \jobname.idx} \immediate \write18{makeindex -s gglo.ist -o \jobname.gls \jobname.glo} % %<*package> \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{siunitx} [2009/02/07 v2.0alpha A comprehensive (SI) units package] % %<*driver> \documentclass[full]{l3doc} \usepackage[osf]{mathpazo} \usepackage[scaled=0.95]{helvet} \usepackage[final]{listings,microtype} \usepackage{booktabs,caption} \renewcommand*{\MakePrivateLetters}{% \makeatletter } \EnableCrossrefs \CodelineIndex \RecordChanges \usepackage{\jobname} \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % %\CheckSum{0} % %\GetFileInfo{\jobname.sty} % %\makeatletter %^^A To index options %\newcommand*{\DescribeOption}{^^A % \leavevmode % \@bsphack % \begingroup % \MakePrivateLetters % \Describe@Option %} %\newcommand*{\Describe@Option}[1]{^^A % \endgroup % \marginpar{^^A % \raggedleft % \PrintDescribeEnv{#1}^^A % }^^A % \SpecialOptionIndex{#1}^^A % \@esphack % \ignorespaces %} %\newcommand*{\SpecialOptionIndex}[1]{^^A % \@bsphack % \begingroup % \HD@target % \let\HDorg@encapchar\encapchar % \edef\encapchar usage{^^A % \HDorg@encapchar hdclindex{\the\c@HD@hypercount}{usage}^^A % }^^A % \index{^^A % #1\actualchar{\protect\ttfamily#1} (option)^^A % \encapchar usage^^A % }^^A % \index{^^A % options:\levelchar#1\actualchar{\protect\ttfamily#1}^^A % \encapchar usage^^A % }^^A % \endgroup % \@esphack %} % %^^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 %}{^^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 = { % num, % SI, % sisetup, % } % }^^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 only}{^^A % \LaTeXdemo@common %}{^^A %} %\makeatother % %^^A Commands for this document %\providecommand*{\module}{\textsf} %\providecommand*{\option}{\texttt} % %\title{% % \textsf{siunitx} --- A comprehensive (SI) units package\thanks{% % This file describes version \fileversion, last revised \filedate.% % }% %} %\author{% % Joseph Wright\thanks{E-mail: joseph.wright@morningstar2.co.uk}% %} %\date{Released \filedate} % %\maketitle % %\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{v2.0}{2008/02/07}{Complete re-write of package to add many new % features} % %\begin{abstract} % Typesetting values with units requires care to ensure that the % combined mathematical meaning of the value plus 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 \module{siunitx} package provides a set of tools for authors % to typeset numbers and units 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. % % A number of \LaTeX\ packages have been developed in the past for % formatting units: \module{SIunits}, \module{SIstyle}, % \module{unitsdef}, \module{units}, \module{fancyunits} and % \module{fancynum}. Support for users of all of these packages is % available as emulation modules in \module{siunitx}. In addition, % \module{siunitx} can carry out many of the functions of the % \module{dcolumn}, \module{rccol} and \module{numprint} packages. %\end{abstract} % %\begin{multicols}{2} % \tableofcontents %\end{multicols} % %\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}\footnote{General Conference on Weights and Measures.} % (CGPM): this has resulted in the \emph{Syst\`eme International % d'Unit\'es}\footnote{International System of Units.} (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. % % \module{siunitx} aims to provide a unified method for \LaTeX\ users to % typeset units and values correctly and easily. The design % philosophy of \module{siunitx} is to follow the agreed rules by % default, but to allow variation through option settings. In this way, % users can use \module{siunitx} to follow the requirements of % publishers, co-authors, universities, \emph{etc}.~without needing to % alter the input at all. % % \module{siunitx} is intended as a complete replacement for % \module{SIunits}, \module{SIstyle}, \module{unitsdef}, \module{units}, % \module{fancyunits} and \module{fancynum}. As such, emulation modes % are provided for all of these packages. Where possible, conventions % from the existing solutions have been used here. For example, the % macros \cs{num}, \cs{ang} and \cs{SI} act in a very similar fashion % to those in existing packages. % %\section{Installation} % % The entire bundle is supplied with the TDS-ready \texttt{zip} file, % \texttt{siunitx.tds.zip}. Simply unzip this into your local texmf % tree and run your hash program (\texttt{texhash} for \TeX{}Live or % \texttt{initextmf -u} for MiK\TeX). % % To extract the package \texttt{siunitx.sty} and the % configuration files from \texttt{siunitx.dtx}, two methods are % available. To extract the files using the \texttt{ins} file, % simply run (pdf)\TeX\ on \texttt{siunitx.ins}. This will produce all % of the package files, and also \texttt{README.txt}. To extract the % files and build the documentation, run (pdf)\LaTeX\ on % \texttt{siunitx.dtx}. Three (pdf)\LaTeX\ runs with \cs{write18} % enabled will also build the index and table of contents in the PDF. % % Compilation of the package documentation requires the \module{l3doc} % class, from the \module{expl3} bundle produced by the \LaTeX3 team. % To compile the package documentation, you will need to get a recent % version of \module{expl3} from the % \href{http://www.latex-project.org/code.html}{\LaTeX\ project % website}. % %\section{\module{siunitx} for the impatient} % % The package provides the user macros: %\begin{itemize} % \item \cs{SI}\oarg{options}\marg{value}\oarg{pre-unit}\marg{unit} % \item \cs{si}\oarg{options}\marg{unit} % \item \cs{num}\oarg{options}\marg{number} % \item \cs{ang}\oarg{options}\marg{angle} % \item \cs{sisetup}\marg{options} %\end{itemize} % plus the \texttt{S} and \texttt{s} column types for decimal % alignments and units in tables. These macros are designed for % typesetting units and values with control of appearance and with % intelligent processing. %\begin{LaTeXdemo} % \num{12345,67890} \\ % \num{1+-2i} \\ % \num{.3e45} %\end{LaTeXdemo} % % By default, all text is typeset in the current upright, serif maths % font. This can be changed by setting the appropriate options: % |\sisetup{font/detect/all}| will use the current font for typesetting. % %\section{Using the \module{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 package does not use load-time options, although it does % support those from version 1 of the package and predecessor packages. % %\subsection{Numbers} % %\DescribeMacro{\num} % Numbers are automatically formatted by the \cs{num} macro. This % takes one optional and one mandatory argument: % \cs{num}\oarg{options}\marg{number}. The contents of \meta{number} % are automatically formatted. The formatter removes ``hard'' spaces % (\cs{,} and |~|), automatically identifies exponents (by default % marked using \texttt{e} or \texttt{d}) and adds the appropriate % spacing of large numbers. A leading zero is added before a decimal % marker, if needed: both ``\texttt{.}'' and ``\texttt{,}'' are % recognised as decimal marker. %\begin{LaTeXdemo} % \num{123} \num{1234} \num{12345} \\ % \num{0.123} \num{0,1234} \num{.12345} \\ % \num{3.45d-4} \num{-e10} %\end{LaTeXdemo} % %\section{The key--value control system} % %\DescribeMacro{\sisetup} % The behaviour of the \module{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. % % All of the keys are controlled using the \module{pgfkeys} approach to % organisation. This means that the keys are split into ``paths'' of % related keys. A single key is set by giving the path plus key name; if % you need to set several keys on the same path, you can ``change'' to % the appropriate path and give the key name alone. For example, valid % numerical input is controlled by keys in the \texttt{numbers/input/} % path: %\begin{LaTeXdemo}[code only] % \sisetup{ % numbers/input/signs = +-\pm\mp, % numbers/input/exponent markers = dDeE % } %\end{LaTeXdemo} % or %\begin{LaTeXdemo}[code only] % \sisetup{ % numbers/input/.cd, % signs = +-\pm\mp, % exponent markers = dDeE % } %\end{LaTeXdemo} % are both valid. % % 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{Literal}] A key which uses the value(s) given directly, % either to check input (for example the \option{numbers/input} keys) % or in output. % \item[\texttt{Maths}] Similar to a \texttt{literal} option, but the % input is always used in maths mode, irrespective of other % \module{siunitx} settings. Thus to text-mode only input must be % placed inside the argument of a \cs{text} macro. % \item[\texttt{Macro}] Requires a macro, which may need a single % argument. % \item[\texttt{Style}] A key which contains a number of other keys to % set. Only the key name should be given: no value is required. This % type of key is user-definable, as described in % Section~\ref{sec:styles}. % \item[\texttt{Switch}] These are on--off switches, and recognise % \texttt{true}, \texttt{on} and \texttt{yes} to turn on, and % \texttt{false}, \texttt{off} and \texttt{no} to turn off. 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. % % In all cases, UK and US English spellings are available for both % option names and for settings. Thus \option{centre} and % \option{center} can be used for alignment options, and \option{maths} % or \option{math} is valid in the names of font options. In the rest of % this document, UK English spelling is used. % %\subsection{Detecting fonts} % % The \module{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 upright maths % font for all printing.\footnote{This will typically use \cs{mathrm}.} % However, the package can detect and follow surrounding bold, italic % and font family changes. The font detection options are available in % path \texttt{font/detect/} and are summarised in % Table~\ref{tab:opt:font:det}. %\begin{table} % \centering % \caption{\texttt{font/detect/} options} % \label{tab:opt:font:det} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % Type & % \multicolumn{1}{c}{Default} \\ % \midrule % all & Style & \m{none} \\ % bold & Switch & false \\ % display maths & Switch & false \\ % family & Switch & false \\ % inline bold & Choice & text \\ % italic & Switch & false \\ % mode & Switch & false \\ % none & Style & \m{none} \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{font/detect/bold} %\DescribeOption{font/detect/family} %\DescribeOption{font/detect/italic} %\DescribeOption{font/detect/mode} % The four basic options \option{bold} and \option{italic} set detection % of the prevailing bold and italic states, respectively. The italic % state is only checked if the surrounding material is not in maths mode % (as maths text is always italic). Detecting the current family (roman, % sans serif or monospaced) is controlled by the \option{family} % setting, while the current mode (text or maths) is detected using the % \option{mode} switch. % %\DescribeOption{font/detect/all} %\DescribeOption{font/detect/none} % The two style options \option{all} and \option{none} can be used to % turn on or off all of the detection functions in one go. These are % style options, and so need no value. %\begin{LaTeXdemo} % \sisetup{font/detect/none}% % $\num{1234}$ \\ % \num{1234} \\ % \emph{\num{1234}} \\ % \textbf{\num{1234}} \\ % \textbf{$\num{1234}$} \\ % \sisetup{font/detect/all}% % $\num{1234}$ \\ % \num{1234} \\ % \emph{\num{1234}} \\ % \textbf{\num{1234}} \\ % \textbf{$\num{1234}$} \\\ %\end{LaTeXdemo} % %\DescribeOption{font/detect/inline bold} % Bold detection is influenced by the value of \option{inline bold}, % which takes values \option{text} and \option{maths}. The package % can detect the local value of bold for either the surrounding text, % or the surrounding inline (|$|\ldots|$|) maths. %\begin{LaTeXdemo} % \sisetup{ % font/detect/bold = on, % font/detect/inline bold = maths % }% % $\num{1234}$ \\ % { \boldmath $\num{1234}$ } \\ % { \bfseries $\num{1234}$ } \\ % \sisetup{ % font/detect/inline bold = text % } % { \boldmath $\num{1234}$ } \\ % { \bfseries $\num{1234}$ } %\end{LaTeXdemo} % %\DescribeOption{font/detect/display maths} % The font detection system can treat displayed mathematical content % in two ways. This is controlled by the \option{display} option. % When set \option{on}, display mathematics is treated independently % from the body of the document. Thus the local \emph{maths} font is % checked for matching. In contrast, when set \option{off}, display % material is treated with the current running text font. %\begin{LaTeXdemo} % \sffamily % Some text % \sisetup{ % font/detect/all, % font/detect/display maths = true % } % \[ x = \SI{1.2e3}{\kg\kelvin\candela} \] % More text % \sisetup{font/detect/display maths = false} % \[ y = \SI{3}{\metre\second\mole} \] %\end{LaTeXdemo} % %\subsection{Output font families} % % 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. % This is controlled by the \option{font/output} options. % %\begin{table} % \centering % \caption{^^A % \texttt{font/} options (all also apply in % \texttt{font/units/} and \texttt{font/numbers})^^A % } % \label{tab:opt:font:set} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % Type & % \multicolumn{1}{c}{Default} \\ % \midrule % maths rm & Macro & \cs{mathrm} \\ % maths sf & Macro & \cs{mathsf} \\ % maths tt & Macro & \cs{mathtt} \\ % mode & Choice & maths \\ % text rm & Macro & \cs{rmfamily} \\ % text sf & Macro & \cs{sffamily} \\ % text tt & Macro & \cs{ttfamily} \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{font/mode} % The \option{mode} option determines whether \module{siunitx} uses % maths or text mode when printing output. The choices are % \option{maths}, \option{math} and \option{text}. When using maths % mode, text is printed using a maths 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 \option{font/detect/mode} switch is % \option{on}. % %\DescribeOption{font/maths rm} %\DescribeOption{font/text rm} % If font family detection is inactive, \module{siunitx} uses the font % family stored in either \option{maths rm} or \option{text rm} for % output. The choice of \option{maths} or \option{text} depends on the % \option{mode} setting. %\DescribeOption{font/maths sf} %\DescribeOption{font/maths tt} %\DescribeOption{font/text sf} %\DescribeOption{font/text tt} % If font family detection is active, \module{siunitx} may be using a % sans serif or monospaced font for output. In maths mode, these are % stored in \option{maths sf} and \option{maths tt}, and for text mode % in \option{text sf} and \option{text tt}. Notice that the detected % and output font families can differ. %\begin{LaTeXdemo} % \sisetup{font/detect/family = yes}% % \num{1234} \\ % { \sffamily \num{1234} } \\ % \SI{99}{\metre} \\ % \sisetup{font/maths rm = \mathtt}% % \SI{99}{\metre} %\end{LaTeXdemo} % This can be used to good effect to change all output from % \module{siunitx} without needing to detect the font. For example, % when creating \module{beamer} presentations the settings %\begin{LaTeXdemo}[code only] % \sisetup{ % font/maths rm = \mathsf, % font/text rm = \sffamily %} %\end{LaTeXdemo} % given all output in sans serif font without font detection. % % Every one of the font options can be given independently for units % and number, with the option paths \option{font/units/} and % \option{font/numbers/}, respectively. This allows fine control of % output. % %\subsection{Parsing numbers} % % The package uses a sophisticated parsing system to understand % numbers. This allows \module{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} % \centering % \caption{\texttt{numbers/input/} options} % \label{tab:opt:num:in} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % Type & % \multicolumn{1}{c}{Default} \\ % \midrule % complex roots & Literal & ij \\ ^^A ( % close uncertainty & Literal & ) \\ % decimal markers & Literal & ., \\ % digits & Literal & 0123456789 \\ % exponent markers & Literal & dDeE \\ % ignore & Literal & \m{none} \\ % open uncertainty & Literal & ( \\ ^^A ) % signs & Literal & +-\cs{pm}\cs{mp} \\ % symbols & Literal & \cs{pi} \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{numbers/input/digits} %\DescribeOption{numbers/input/decimal markers} %\DescribeOption{numbers/input/signs} %\DescribeOption{numbers/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 \option{digits}, \option{decimal markers} and \option{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 \option{exponent % markers} option. % %\DescribeOption{numbers/input/ignore} %\DescribeOption{numbers/input/symbols} % As well as ``normal'' digits, the package will interpret symbolic % ``numbers'' (such as \cs{pi}) correctly if they are included in the % \option{symbols} list. Tokens given in the \option{ignore} list are % totally passed over by \module{siunitx}: they will be removed from the % input with no further processing. % %\DescribeOption{numbers/input/open uncertainty} %\DescribeOption{numbers/input/close uncertainty} % In some fields, it is common to give the uncertainty in a value % in brackets after the main part of the number, for example % ``\num{1.234(5)}''. The opening and closing symbols used for this type % of input are set as \option{open uncertainty} and \option{close % uncertainty}. % %\DescribeOption{numbers/input/complex roots} % When using complex numbers in input, the complex root ($\sqrt{-1}$) is % indicated by one of the tokens stored in \option{complex roots}. % %\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} % \centering % \caption{\texttt{numbers/process/} options} % \label{tab:opt:num:post} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % Type & % \multicolumn{1}{c}{Default} \\ % \midrule % add zero decimal & Switch & false \\ % add zero integer & Switch & false \\ % explicit sign & Literal & + \\ % include explicit sign & Switch & false \\ % retain explicit plus & Switch & false \\ % retain zero exponent & Switch & false \\ % round mode & Choice & off \\ % round figures & Number & 2 \\ % round places & Number & 2 \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{numbers/process/round mode} %\DescribeOption{numbers/process/round figures} %\DescribeOption{numbers/process/round places} % The \module{siunitx} package can round numerical input to a fixed % number of significant figures or decimal places. This is controlled by % the \option{round mode} option, which takes the choices \option{off}, % \option{figures} and \option{places}. When rounding is turned on, the % number of figures to use is determined by the \option{round figures} % and \option{round places} option: both of these options require a % number. % %\DescribeOption{numbers/process/add zero decimal} %\DescribeOption{numbers/process/add zero integer} % 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 \option{add zero decimal} and \option{add % zero integer} allow the package to ``fill in'' the missing zero. % %\DescribeOption{numbers/process/explicit sign} %\DescribeOption{numbers/process/include explicit sign} %\DescribeOption{numbers/process/retain explicit plus} % The inclusion of a leading plus sign is usually unnecessary for % positive numbers, and so the \option{retain explicit plus} option is % available to control whether these are printed. As the same time, it % may be useful to force all numbers to have a sign. This behaviour % is controlled by the \option{include explicit sign} option, with the % sign to use stored by the \option{explicit sign} option. % %\subsection{Printing numbers} % % Actually prinitng 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} % \centering % \caption{\texttt{numbers/output/} options} % \label{tab:opt:num:out} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % Type & % \multicolumn{1}{c}{Default} \\ % \midrule ^^A ( % close bracket & Literal & ) \\ ^^A ( % close uncertainty & Literal & ) \\ % complex root & Maths & i \\ % decimal marker & Maths & . \\ % exponent base & Literal & 10 \\ % exponent product & Maths & \cs{times} \\ % group digits & Switch & true \\ % group four digits & Switch & false \\ % group separator & Maths & \cs{,} \\ % open bracket & Literal & ( \\ ^^A ) % open uncertainty & Literal & ( \\ ^^A ) % separate uncertainty & Switch & false \\ % tight spacing & Switch & false \\ % use brackets & Switch & true \\ % uncertainty space & Maths & \m{none} \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{numbers/output/group digits} %\DescribeOption{numbers/output/group four digits} %\DescribeOption{numbers/output/group separator} % Grouping digits into blocks of three is a common method to increase % the ease of reading of numbers. The \option{group digits} choice % turns this behaviour on and off, with grouping for numbers of exactly % four digits controlled by the \option{group four digits} choice. Note % that the later only applies if \option{group digits} is turned on. % The separator used between groups of digits is stored by the % \option{group separator} option. This takes literal input and is % used in maths mode: for a text-mode full space use |\text{~}|. %\begin{LaTeXdemo} % \num{12345} \\ % \num[numbers/output/group digits = off]{12345} \\ % \num{1234} \\ % \num[numbers/output/group four digits = on]{1234} \\ % \num{12345} \\ % \num[numbers/output/group separator = {,}]{12345} \\ % \num[numbers/output/group separator = \text{~}]{12345} %\end{LaTeXdemo} % %\DescribeOption{numbers/output/complex root} %\DescribeOption{numbers/output/decimal marker} % The decimal marker used in output is set using the \option{decimal % marker} option. This can differ from the input marker, as can the root % of $\sqrt{-1}$, which is stored in the \option{complex root} option. % The later is always in maths mode, but notice that \module{siunitx} % uses \cs{mathrm} by default. Thus an italic $i$ is obtained by % forcing \cs{mathnormal}. %\begin{LaTeXdemo} % \num{1.23} \\ % \num[numbers/output/decimal marker = {,}]{1.23} \\ % \num{1+2i} \\ % \num[numbers/output/complex root = \mathnormal{i}]{1+2i} %\end{LaTeXdemo} % %\DescribeOption{numbers/output/exponent base} %\DescribeOption{numbers/output/exponent product} % When exponents are present in the input, the options \option{exponent % base} and \option{exponent product} set the obvious parts of the % output. Notice that the base is in the current mode, but the product % sign is always in maths mode. %\begin{LaTeXdemo} % \num[numbers/output/exponent product = \times]{1e2} \\ % \num[numbers/output/exponent product = \cdot]{1e2} \\ % \num[numbers/output/exponent base = 2]{1e2} %\end{LaTeXdemo} % %\DescribeOption{numbers/output/separate uncertainty} %\DescribeOption{numbers/output/uncertainty space} %\DescribeOption{numbers/output/open uncertainty} %\DescribeOption{numbers/output/close uncertainty} % When input is given including an uncertatinty in a value, it can be % printed either with the uncertainty in brackets or as a separate % number. This behaviour is controlled by the \option{separate % uncertainty} choice. If the uncertainty is given in brackets, a space % may be added between the main value and the uncertainty: this is % stored using the \option{uncertainty space} option. The opening and % closing brackets used are stored \option{open uncertainty} and % \option{close uncertainty}, respectively. %\begin{LaTeXdemo} % \num{1.234(5)} \\ % \num[numbers/output/separate uncertainty = on]{1.234(5)} \\ % \sisetup{ % numbers/output, % open uncertainty = [, % close uncertainty = ], % uncertainty space = {\,} % } % \num{1.234(5)} %\end{LaTeXdemo} % %\DescribeOption{numbers/output/use brackets} %\DescribeOption{numbers/output/open bracket} %\DescribeOption{numbers/output/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 \option{use brackets} switch. The % opening and closing brackets used are stored \option{open bracket} and % \option{close bracket}, respectively. %\begin{LaTeXdemo} % \num{1+2i e10} \\ % \num[numbers/output/use brackets = false]{1+2i e10} \\ % \sisetup{ % numbers/output, % open bracket = \{, % close bracket = \}, % } % \num{1+2i e10} %\end{LaTeXdemo} % %\DescribeOption{numbers/output/tight spacing} % Under some circumstances is may be desirable to ``squeeze'' the output % spacing. This is turned on using the \option{tight spacing} switch, % which compresses spacing where possible. %\begin{LaTeXdemo} % \num{1\pm2i e3} \\ % \num[numbers/output/tight spacing = true]{1\pm2i e3} \\ %\end{LaTeXdemo} % % %\StopEventually{^^A % \PrintChanges % \PrintIndex %} % %\section{Implementation} % %\subsection{Preliminaries} % % The package requires \eTeX, so this is the first check made. % \begin{macrocode} %<*package> \begingroup \@ifundefined{eTeXversion}{% \PackageError{siunitx}{Not running under e-TeX}{% This package requires e-TeX. Try compiling the document with \MessageBreak `elatex' instead of `latex'. When using pdfTeX, try `pdfelatex' \MessageBreak instead of `pdflatex' }% \endgroup\endinput }{% \endgroup } % \end{macrocode} % There are also a number of packages that are incompatible with % \textsf{siunitx}. These are all checked for next. % \begin{macrocode} \begingroup \@for\@tempa:=SIunits,sistyle,siunits,SIstyle,unitsdef,fancyunits\do{% \@ifpackageloaded{\@tempa}{% \PackageError{siunitx}{Package `\@tempa' incompatible}{% The \@tempa\space package and siunitx are incompatible. \MessageBreak Use the `emulate=\@tempa' package option when loading siunitx }% }{}% } \endgroup % \end{macrocode} % %\begin{macro}{\si@catcode@restore} %\begin{macro}{\si@catcode@set} %\begin{macro}{\si@catcode@store} %\begin{macro}{\si@catcode@symbols} % The internals of the package are now protected from any strange % category codes in force. Some of these are used in a few places % and always take the same values: this set is made available as % the \cs{si@catcode@symbols} macro. % \begin{macrocode} \newcommand*{\si@catcode@restore}{} \newcommand*{\si@catcode@set}{} \newcommand*{\si@catcode@store}[2]{% \edef\si@catcode@restore{% \si@catcode@restore \catcode#1 \the\catcode#1\relax }% \catcode#1 #2\relax } \newcommand*{\si@catcode@symbols}{% \si@catcode@set{42}{12}% * \si@catcode@set{43}{12}% + \si@catcode@set{44}{12}% , \si@catcode@set{46}{12}% . \si@catcode@set{47}{12}% / \si@catcode@set{58}{12}% : \si@catcode@set{59}{12}% ; \si@catcode@set{60}{12}% < \si@catcode@set{61}{12}% = \si@catcode@set{62}{12}% > } \let\si@catcode@set\si@catcode@store \si@catcode@symbols \si@catcode@set{45}{12}% - \si@catcode@set{94}{7}% ^ \si@catcode@set{95}{8}% _ \si@catcode@set{126}{13}% ~ \renewcommand*{\si@catcode@set}[2]{\catcode#1 #2\relax} % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % % Supporting packages. % \begin{macrocode} \RequirePackage{amstext,array,pgfkeys} % \end{macrocode} % %\begin{macro}{\si@encoding@ts@one} % Some of the \texttt{TS1} encoding is needed to provide symbols in % text mode. If the user has not loaded the encoding themselves, it is % done here. % \begin{macrocode} \newcommand*{\si@encoding@ts@one}{% \@ifundefined{T@TS1}{% \DeclareFontEncoding{TS1}{}{}% \DeclareFontSubstitution{TS1}{cmr}{m}{n}% }{}% } \AtBeginDocument{% \si@encoding@ts@one } % \end{macrocode} %\end{macro} % %\subsection{Key--value basics} % % \module{pgfkeys} is set up with the basic settings for managing all of % the key--value options. % %\begin{macro}{\si@key@path} % A storage area. % \begin{macrocode} \newcommand*{\si@key@path}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\si@key@error} %\begin{macro}{\si@key@error@aux} % The basic structure for keys is created, and standardised errors % are defined. % \begin{macrocode} \newcommand*{\si@key@error}{% \expandafter\si@key@error@aux\pgfkeyscurrentkey\si@stop } \newcommand*{\si@key@error@aux}{} \def\si@key@error@aux/siunitx/#1\si@stop{% \si@log@error{Unknown option `#1'}{% The option `#1' is not known to siunitx. }% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@keys@family} % To create a new family; the base family is done by hand. % \begin{macrocode} \newcommand*{\si@keys@family}[1]{% \pgfkeys{ /siunitx/#1/.is family, /siunitx/#1/.unknown/.code = \si@key@error }% } \pgfkeys{ /siunitx/.is family, /siunitx/.unknown/.code = \si@key@error } % \end{macrocode} %\end{macro} % % A short-cut is provided for switches which take true/false and % related values. % \begin{macrocode} \pgfkeys{ /handlers/.is siunitx switch/.code = {% \edef\si@key@path{\pgfkeyscurrentpath}% \pgfkeys{ \si@key@path/.is choice, \si@key@path/.default = true, \si@key@path/true/.code = {\si@bool@cs@true{si@#1@bool}}, \si@key@path/false/.code = {\si@bool@cs@false{si@#1@bool}}, \si@key@path/yes/.code = {\si@bool@cs@true{si@#1@bool}}, \si@key@path/no/.code = {\si@bool@cs@false{si@#1@bool}}, \si@key@path/on/.code = {\si@bool@cs@true{si@#1@bool}}, \si@key@path/off/.code = {\si@bool@cs@false{si@#1@bool}}, \si@key@path/true/.default }% } } % \end{macrocode} % %\subsection{Variables and constants} % % The scratch registers used internally are defined here. % %\begin{macro}{\si@false} %\begin{macro}{\si@true} % Two values inspired by \LaTeX3, to provide switches in place of % \cs{iftrue} and \cs{iffalse}. This makes life a lot easier in the % nested expansions. % \begin{macrocode} \newcommand*{\si@false}{01} \newcommand*{\si@true}{00} % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@tmp@bool} % A scratch switch % \begin{macrocode} \newcommand*{\si@tmp@bool}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\si@tempa} %\begin{macro}{\si@tempb} % Some private scratch macros. % \begin{macrocode} \newcommand*{\si@tempa}{} \newcommand*{\si@tempb}{} % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@tempcnt} % A count. % \begin{macrocode} \newcount\si@tempcnt % \end{macrocode} %\end{macro} %\begin{macro}{\si@tempbox} % A private box. % \begin{macrocode} \newsavebox\si@tempbox % \end{macrocode} %\end{macro} % %\begin{macro}{\si@log@error} %\begin{macro}{\si@log@info} %\begin{macro}{\si@log@warning} % To save some typing, the obvious abbreviations. % \begin{macrocode} \newcommand*{\si@log@error}{% \PackageError{siunitx}% } \newcommand*{\si@log@info}{% \PackageInfo{siunitx}% } \newcommand*{\si@log@warning}{% \PackageWarning{siunitx}% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\subsection{Utility macros} % % A series of tools which are used generally. A lot of this is inspired % by \LaTeX3: looping in particular is more reliable and efficient using % this system. % %\begin{macro}{\si@reseved@a} %\begin{macro}{\si@reseved@b} % Just for the utilities. % \begin{macrocode} \newcommand*{\si@reserved@a}{} \newcommand*{\si@reserved@b}{} % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@reserved@toks} % Also a toks. % \begin{macrocode} \newtoks\si@reserved@toks % \end{macrocode} %\end{macro} % %\begin{macro}{\si@add@left@N} %\begin{macro}{\si@add@left@O} % To add to a macro reliably. % \begin{macrocode} \newcommand*{\si@add@left@N}[2]{% \def\si@reserved@a{#2}% \edef#1{% \expandafter\unexpanded\expandafter{\si@reserved@a}% \expandafter\unexpanded\expandafter{#1}% }% } \newcommand*{\si@add@left@O}[2]{% \expandafter\si@add@left@N\expandafter#1\expandafter{#2}% } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@add@left@cs@N} %\begin{macro}{\si@add@left@cs@O} % Some name versions. % \begin{macrocode} \newcommand*{\si@add@left@cs@N}[1]{% \expandafter\si@add@left@N\csname #1\endcsname } \newcommand*{\si@add@left@cs@O}[1]{% \expandafter\si@add@left@O\csname #1\endcsname } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@add@right@N} %\begin{macro}{\si@add@right@O} % To add to a macro reliably. % \begin{macrocode} \newcommand*{\si@add@right@N}[2]{% \def\si@reserved@a{#2}% \edef#1{% \expandafter\unexpanded\expandafter{#1}% \expandafter\unexpanded\expandafter{\si@reserved@a}% }% } \newcommand*{\si@add@right@O}[2]{% \expandafter\si@add@right@N\expandafter#1\expandafter{#2}% } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@add@right@cs@N} %\begin{macro}{\si@add@right@cs@O} % Some name versions. % \begin{macrocode} \newcommand*{\si@add@right@cs@N}[1]{% \expandafter\si@add@right@N\csname #1\endcsname } \newcommand*{\si@add@right@cs@O}[1]{% \expandafter\si@add@right@O\csname #1\endcsname } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@bool@false} %\begin{macro}{\si@bool@new} %\begin{macro}{\si@bool@true} % For creating and manipulating \LaTeX3-style switches. % \begin{macrocode} \newcommand*{\si@bool@false}[1]{% \let#1\si@false } \newcommand*{\si@bool@new}[1]{% \newcommand*{#1}{}% \let#1\si@false } \newcommand*{\si@bool@true}[1]{% \let#1\si@true } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@bool@cs@false} %\begin{macro}{\si@bool@cs@new} %\begin{macro}{\si@bool@cs@true} % The same with names % \begin{macrocode} \newcommand*{\si@bool@cs@false}[1]{% \expandafter\si@bool@false\csname #1\endcsname } \newcommand*{\si@bool@cs@new}[1]{% \expandafter\si@bool@new\csname #1\endcsname } \newcommand*{\si@bool@cs@true}[1]{% \expandafter\si@bool@true\csname #1\endcsname } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@bool@if@F} %\begin{macro}{\si@bool@if@T} %\begin{macro}{\si@bool@if@TF} % To read and apply the \LaTeX3-style switches. % \begin{macrocode} \newcommand*{\si@bool@if@F}[1]{% \if#1\relax \expandafter\@gobble \else \expandafter\@firstofone \fi } \newcommand*{\si@bool@if@T}[1]{% \if#1\relax \expandafter\@firstofone \else \expandafter\@gobble \fi } \newcommand*{\si@bool@if@TF}[1]{% \if#1\relax \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@bool@cs@if@F} %\begin{macro}{\si@bool@cs@if@T} %\begin{macro}{\si@bool@cs@if@TF} % Also name versions % \begin{macrocode} \newcommand*{\si@bool@cs@if@F}[1]{% \expandafter\si@bool@if@F\csname #1\endcsname } \newcommand*{\si@bool@cs@if@T}[1]{% \expandafter\si@bool@if@T\csname #1\endcsname } \newcommand*{\si@bool@cs@if@TF}[1]{% \expandafter\si@bool@if@TF\csname #1\endcsname } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@clear@cs} %\begin{macro}{\si@clear@macro} % Quickly clear storage areas. % \begin{macrocode} \newcommand*{\si@clear@cs}[1]{% \si@let@cN{#1}\@empty } \newcommand*{\si@clear@macro}[1]{% \let#1\@empty } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@dowhile@bool@T} % A simple looping function. % \begin{macrocode} \newcommand*{\si@dowhile@bool@T}[2]{% #2% \si@bool@if@T#1{% \si@dowhile@bool@T#1{#2}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@empty@cs@if@F} %\begin{macro}{\si@empty@cs@if@T} %\begin{macro}{\si@empty@cs@if@TF} % Tests for empty macros by name. % \begin{macrocode} \newcommand*{\si@empty@cs@if@F}[1]{% \expandafter\si@empty@if@F\csname #1\endcsname } \newcommand*{\si@empty@cs@if@T}[1]{% \expandafter\si@empty@if@T\csname #1\endcsname } \newcommand*{\si@empty@cs@if@TF}[1]{% \expandafter\si@empty@if@TF\csname #1\endcsname } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@empty@if@F} %\begin{macro}{\si@empty@if@T} %\begin{macro}{\si@empty@if@TF} % Or directly. % \begin{macrocode} \newcommand*{\si@empty@if@F}[1]{% \si@meaning@eq@if@F#1\@empty } \newcommand*{\si@empty@if@T}[1]{% \si@meaning@eq@if@T#1\@empty } \newcommand*{\si@empty@if@TF}[1]{% \si@meaning@eq@if@TF#1\@empty } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@empty@tlist@if@F} %\begin{macro}{\si@empty@tlist@if@T} %\begin{macro}{\si@empty@tlist@if@TF} % For lists of tokens, things are kept nice and cautious. % \begin{macrocode} \newcommand*{\si@empty@tlist@if@F}[1]{% \expandafter\ifx\expandafter\si@nil\detokenize{#1}\si@nil \expandafter\@gobble \else \expandafter\@firstofone \fi } \newcommand*{\si@empty@tlist@if@T}[1]{% \expandafter\ifx\expandafter\si@nil\detokenize{#1}\si@nil \expandafter\@firstofone \else \expandafter\@gobble \fi } \newcommand*{\si@empty@tlist@if@TF}[1]{% \expandafter\ifx\expandafter\si@nil\detokenize{#1}\si@nil \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@elt@count} %\begin{macro}{\si@elt@count@aux} % To count the number of tokens in a macro quickly. % \begin{macrocode} \newcommand*{\si@elt@count}[1]{% \number\numexpr 0\si@loop@over@macro#1\si@elt@count@aux\relax } \newcommand*{\si@elt@count@aux}[1]{+1} % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@elt@count@cs} % The name version. % \begin{macrocode} \newcommand*{\si@elt@count@cs}[1]{% \expandafter\si@elt@count\csname #1\endcsname } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@expand@tlist} %\begin{macro}{\si@expand@tlist@cs} % Constructs a list of tokens by expanding each token in |#1| once. % Here, \cs{si@reserved@b} is used as the \cs{si@add@right@O} macro is % already using \cs{si@reserved@a}. % \begin{macrocode} \newcommand*{\si@expand@tlist}[2]{% \si@clear@macro#1% \def\si@reserved@b##1{% \si@add@right@O#1##1% }% \si@loop@over@macro@aux\si@reserved@b#2\si@loop@end\si@loop@stop } \newcommand*{\si@expand@tlist@cs}[1]{% \expandafter\si@expand@tlist\csname #1\endcsname } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@in@if@F} %\begin{macro}{\si@in@if@T} %\begin{macro}{\si@in@if@TF} % To test if a character is in a given variable. % \begin{macrocode} \newcommand*{\si@in@if@F}[2]{% \def\si@reserved@a##1#2##2\si@stop{% \si@no@value@if@T{##2}% }% \expandafter\si@reserved@a#1#2\si@no@value\si@stop } \newcommand*{\si@in@if@T}[2]{% \def\si@reserved@a##1#2##2\si@stop{% \si@no@value@if@F{##2}% }% \expandafter\si@reserved@a#1#2\si@no@value\si@stop } \newcommand*{\si@in@if@TF}[2]{% \def\si@reserved@a##1#2##2\si@stop{% \si@no@value@if@FT{##2}% }% \expandafter\si@reserved@a#1#2\si@no@value\si@stop } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@in@tlist@if@F} %\begin{macro}{\si@in@tlist@if@T} %\begin{macro}{\si@in@tlist@if@TF} % The same for lists of tokens. % \begin{macrocode} \newcommand*{\si@in@tlist@if@F}[2]{% \def\si@reserved@a##1#2##2\si@stop{% \si@no@value@if@T{##2}% }% \si@reserved@a#1#2\si@no@value\si@stop } \newcommand*{\si@in@tlist@if@T}[2]{% \def\si@reserved@a##1#2##2\si@stop{% \si@no@value@if@F{##2}% }% \si@reserved@a#1#2\si@no@value\si@stop } \newcommand*{\si@in@tlist@if@TF}[2]{% \def\si@reserved@a##1#2##2\si@stop{% \si@no@value@if@FT{##2}% }% \si@reserved@a#1#2\si@no@value\si@stop } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@in@cs@if@F} %\begin{macro}{\si@in@cs@if@T} %\begin{macro}{\si@in@cs@if@TF} % Also a character in a variable by name. % \begin{macrocode} \newcommand*{\si@in@cs@if@F}[1]{% \expandafter\si@in@if@F\csname #1\endcsname } \newcommand*{\si@in@cs@if@T}[1]{% \expandafter\si@in@if@T\csname #1\endcsname } \newcommand*{\si@in@cs@if@TF}[1]{% \expandafter\si@in@if@TF\csname #1\endcsname } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@let@cc} %\begin{macro}{\si@let@cN} %\begin{macro}{\si@let@Nc} % Clearer versions for \cs{let}ting a name. % \begin{macrocode} \newcommand*{\si@let@cc}[2]{% \expandafter\si@let@cN\expandafter{\expandafter#1\expandafter}% \csname #2\endcsname } \newcommand*{\si@let@cN}[1]{% \expandafter\let\csname #1\endcsname } \newcommand*{\si@let@Nc}[2]{% \expandafter\let\expandafter#1\csname #2\endcsname } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@loop@over@cs} % To loop over the name of a macro. % \begin{macrocode} \newcommand*{\si@loop@over@cs}[1]{% \expandafter\si@loop@over@macro\csname #1\endcsname } % \end{macrocode} %\end{macro} %\begin{macro}{\si@loop@over@macro} %\begin{macro}{\si@loop@over@macro@aux} % To loop over ever token inside a storage macro, expansion tricks % from \LaTeX3 keep things more reliable. % \begin{macrocode} \newcommand*{\si@loop@over@macro}[2]{% \expandafter\si@loop@over@macro@aux \expandafter#2#1\si@loop@end\si@loop@stop } \newcommand*{\si@loop@over@macro@aux}[2]{% \si@loop@end@if{#2}% #1{#2}% \si@loop@over@macro@aux#1% } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@loop@end@if} %\begin{macro}{\si@loop@exec@end@if} %\begin{macro}{\si@loop@end@if@aux} % To actually end the above loop. % \begin{macrocode} \newcommand*{\si@loop@end@if}[1]{% \expandafter\ifx\si@loop@end@if@aux#1?\si@nil\si@loop@end\si@loop@end \expandafter\si@loop@exit \fi } \newcommand*{\si@loop@exec@end@if}[2]{% \expandafter\ifx\si@loop@end@if@aux#1?\si@nil\si@loop@end\si@loop@end \expandafter\si@loop@exit@exec \else \expandafter\@gobble \fi {#2}% } \newcommand*{\si@loop@end@if@aux}{} \def\si@loop@end@if@aux#1#2\si@nil\si@loop@end{#1} % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@loop@exit} %\begin{macro}{\si@loop@exit@exec} % To stop the looping above. % \begin{macrocode} \newcommand*{\si@loop@exit}{} \def\si@loop@exit#1\si@loop@stop{} \newcommand*{\si@loop@exit@exec}{} \def\si@loop@exit@exec#1#2\si@loop@stop{#1} % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@loop@end} %\begin{macro}{\si@loop@stop} % The markers for the above % \begin{macrocode} \newcommand*{\si@loop@end}{\si@loop@end} \newcommand*{\si@loop@stop}{\si@loop@stop} % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@loop@over@three} %\begin{macro}{\si@loop@over@three@aux} %\begin{macro}{\si@loop@over@three@cs} % A special loop macro which uses three items at a time. % \begin{macrocode} \newcommand*{\si@loop@over@three}[2]{% \expandafter\si@loop@over@three@aux \expandafter#2#1\si@loop@end\si@loop@stop } \newcommand*{\si@loop@over@three@aux}[4]{% \si@loop@end@if{#2}% #1{#2#3#4}% \si@loop@over@three@aux#1% } \newcommand*{\si@loop@over@three@cs}[1]{% \expandafter\si@loop@over@three\csname #1\endcsname } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@meaning@eq@if@F} %\begin{macro}{\si@meaning@eq@if@T} %\begin{macro}{\si@meaning@eq@if@TF} % A wrapper around \cs{ifx}. % \begin{macrocode} \newcommand*{\si@meaning@eq@if@F}[2]{% \ifx#1#2% \expandafter\@gobble \else \expandafter\@firstofone \fi } \newcommand*{\si@meaning@eq@if@T}[2]{% \ifx#1#2% \expandafter\@firstofone \else \expandafter\@gobble \fi } \newcommand*{\si@meaning@eq@if@TF}[2]{% \ifx#1#2% \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@meaning@eq@cs@if@F} %\begin{macro}{\si@meaning@eq@cs@if@T} %\begin{macro}{\si@meaning@eq@cs@if@TF} % A wrapper around \cs{ifx}. % \begin{macrocode} \newcommand*{\si@meaning@eq@cs@if@F}[2]{% \expandafter\si@meaning@eq@if@F\csname #1\expandafter\endcsname \csname #2\endcsname } \newcommand*{\si@meaning@eq@cs@if@T}[2]{% \expandafter\si@meaning@eq@if@T\csname #1\expandafter\endcsname \csname #2\endcsname } \newcommand*{\si@meaning@eq@cs@if@TF}[2]{% \expandafter\si@meaning@eq@if@TF\csname #1\expandafter\endcsname \csname #2\endcsname } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@mode@maths@display@if@T} %\begin{macro}{\si@mode@maths@inline@if@T} %\begin{macro}{\si@mode@text@if@T} % \LaTeX\ wrappers on some \TeX\ tests, slightly altered to help with % the logical flow. % \begin{macrocode} \newcommand*{\si@mode@maths@display@if@T}{% \ifmmode \ifinner \expandafter\expandafter\expandafter\@gobble \else \expandafter\expandafter\expandafter\@firstofone \fi \else \expandafter\@gobble \fi } \newcommand*{\si@mode@maths@inline@if@T}{% \ifmmode \ifinner \expandafter\expandafter\expandafter\@firstofone \else \expandafter\expandafter\expandafter\@gobble \fi \else \expandafter\@gobble \fi } \newcommand*{\si@mode@text@if@T}{% \ifmmode \expandafter\@gobble \else \expandafter\@firstofone \fi } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@nameedef} % Pretty simple. % \begin{macrocode} \newcommand*{\si@nameedef}[1]{% \expandafter\edef\csname #1\endcsname } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@newcommand} % To create new commands which are \cs{protected} but which take % optional arguments, an adaptation from the \LaTeX\ kernel. Points to % note: (1) the new command is never \cs{long}, so no star is needed; % (2) the first argument of the new command is always optional; (3) % \cs{si@newcommand} \emph{requires} a number of arguments as its first % (mandatory) argument. % \begin{macrocode} \newcommand*{\si@newcommand}[3]{% \@ifdefinable{#1}{% \expandafter\protected\expandafter\def\expandafter#1\expandafter{% \expandafter\@testopt\csname\string#1\endcsname{}% }% \expandafter\@yargdef\csname\string#1\endcsname\tw@{#2}{#3}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@nil} %\begin{macro}{\si@stop} % Markers: do not \cs{edef}. % \begin{macrocode} \newcommand*{\si@nil}{\si@nil} \newcommand*{\si@stop}{\si@stop} % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@no@value} %\begin{macro}{\si@no@value@if@F} %\begin{macro}{\si@no@value@if@FT} %\begin{macro}{\si@no@value@if@T} %\begin{macro}{\si@no@value@if@TF} %\begin{macro}{\si@no@value@if@aux@i} %\begin{macro}{\si@no@value@if@aux@ii} %\begin{macro}{\si@no@value@if@aux@iii} %\begin{macro}{\si@no@value@if@aux@iv} % Empty value tests: a bit complicated. See \textsf{l3basics} for an % explanation of how this works (very clever). % \begin{macrocode} \newcommand*{\si@no@value}{\si@no@value} \newcommand*{\si@no@value@if@F}[1]{% \if\si@no@value@if@aux@i{#1}% \expandafter\@gobble \else \expandafter\@firstofone \fi } \newcommand*{\si@no@value@if@FT}[1]{% \if\si@no@value@if@aux@i{#1}% \expandafter\@secondoftwo \else \expandafter\@firstoftwo \fi } \newcommand*{\si@no@value@if@T}[1]{% \if\si@no@value@if@aux@i{#1}% \expandafter\@firstofone \else \expandafter\@gobble \fi } \newcommand*{\si@no@value@if@TF}[1]{% \if\si@no@value@if@aux@i{#1}% \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi } \newcommand*{\si@no@value@if@aux@i}[1]{% \if\expandafter\si@no@value@if@aux@ii\expandafter {\string\si@no@value\space}{\detokenize{#1}}% \si@true \else \si@false \fi } \newcommand*{\si@no@value@if@aux@ii}[1]{% \if\number\si@no@value@if@aux@iii{}{}#1\relax } \newcommand*{\si@no@value@if@aux@iii}[3]{% \if#3\relax \expandafter\si@no@value@if@aux@iv \fi \si@no@value@if@aux@iii{\if#3#1}{#2\fi}% } \newcommand*{\si@no@value@if@aux@iv}{} \def\si@no@value@if@aux@iv\si@no@value@if@aux@iii#1#2#3{% #1#3\relax'#213 \si@true \else \si@false \fi } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@if@F} %\begin{macro}{\si@num@if@T} %\begin{macro}{\si@num@if@TF} % Wrapper macros so that expansion happens first in all cases. These are % more basic than the \LaTeX3 versions, so occasionally the raw % \cs{ifnum} primitive is used in the code. % \begin{macrocode} \newcommand*{\si@num@if@F}[1]{% \ifnum#1\relax \expandafter\@gobble \else \expandafter\@firstofone \fi } \newcommand*{\si@num@if@T}[1]{% \ifnum#1\relax \expandafter\@firstofone \else \expandafter\@gobble \fi } \newcommand*{\si@num@if@TF}[1]{% \ifnum#1\relax \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@replace@all@in} %\begin{macro}{\si@replace@all@in@aux} %\begin{macro}{\si@replace@all@in@cs} % For searching and replacing. % \begin{macrocode} \newcommand*{\si@replace@all@in}[3]{% \si@reserved@toks{}% \def\si@tempa##1#2##2\si@stop{% \si@no@value@if@TF{##2}{% \si@replace@all@in@aux{##1}% }{% \si@replace@all@in@aux{##1#3}% \si@tempa\@empty##2\si@stop }% }% \@firstofone{\expandafter\si@tempa\expandafter\@empty}% #1#2\si@no@value\si@stop \edef#1{\the\si@reserved@toks}% } \newcommand*{\si@replace@all@in@aux}[1]{% \si@reserved@toks\expandafter\expandafter\expandafter{% \expandafter\the\expandafter\si@reserved@toks#1% }% } \newcommand*{\si@replace@all@in@cs}[1]{% \expandafter\si@replace@all@in\csname #1\endcsname } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@reverse@macro} %\begin{macro}{\si@reverse@cs} %\begin{macro}{\si@reverse@tlist} %\begin{macro}{\si@reverse@tlist@aux} % The tlist macro here is the same as in \LaTeX3, but the macro version % is simplified as \module{siunitx} does not expect to find % non-expandable content. % \begin{macrocode} \newcommand*{\si@reverse@macro}[1]{% \edef#1{% \expandafter\si@reverse@tlist\expandafter{#1}% }% } \newcommand*{\si@reverse@cs}[1]{% \expandafter\si@reverse@macro\csname #1\endcsname } \newcommand*{\si@reverse@tlist}[1]{% \si@reverse@tlist@aux{}#1\si@loop@end\si@loop@stop } \newcommand*{\si@reverse@tlist@aux}[2]{% \si@loop@exec@end@if{#2}{#1}% \si@reverse@tlist@aux{#2#1}% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@stop@if@F} %\begin{macro}{\si@stop@if@T} %\begin{macro}{\si@stop@if@TF} % Some quick tests. % \begin{macrocode} \newcommand*{\si@stop@if@F}[1]{% \si@meaning@eq@if@F#1\si@stop } \newcommand*{\si@stop@if@T}[1]{% \si@meaning@eq@if@T#1\si@stop } \newcommand*{\si@stop@if@TF}[1]{% \si@meaning@eq@if@TF#1\si@stop } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@whiledo@num@T} % A simple looping function. % \begin{macrocode} \newcommand*{\si@whiledo@num@T}[2]{% \si@num@if@T{#1}{% #2\si@whiledo@num@T{#1}{#2}% }% } % \end{macrocode} %\end{macro} %\begin{macro}{\si@whiledo@empty@F} %\begin{macro}{\si@whiledo@empty@T} % Similar for storage macros. % \begin{macrocode} \newcommand*{\si@whiledo@empty@F}[2]{% \si@empty@if@F#1{% #2\si@whiledo@empty@F#1{#2}% }% } \newcommand*{\si@whiledo@empty@T}[2]{% \si@empty@if@T#1{% #2\si@whiledo@empty@T#1{#2}% }% } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@whiledo@empty@cs@F} %\begin{macro}{\si@whiledo@empty@cs@T} % Name versions. % \begin{macrocode} \newcommand*{\si@whiledo@empty@cs@F}[2]{% \si@empty@cs@if@F{#1}{% #2\si@whiledo@empty@cs@F{#1}{#2}% }% } \newcommand*{\si@whiledo@empty@cs@T}[2]{% \si@empty@cs@if@T{#1}{% #2\si@whiledo@empty@cs@T{#1}{#2}% }% } % \end{macrocode} %\end{macro} %\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 \module{amstext} % package. By carrying out the changes outside maths mode, bold can % reliably be applied to maths output. % %\begin{macro}{\si@font@fam@mathsf} %\begin{macro}{\si@font@fam@mathtt} %\begin{macro}{\si@font@fam@detect@maths} % 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 % \module{fontspec} does (nasty errors arise otherwise). % \begin{macrocode} \newcommand*{\si@font@fam@mathsf}{} \newcommand*{\si@font@fam@mathtt}{} \newcommand*{\si@font@fam@detect@maths}[1]{% \begingroup \setbox\@tempboxa\hbox{% \ensuremath{% \csname math#1\endcsname{% \expandafter\global\expandafter\chardef \csname si@font@fam@math#1\endcsname\fam\relax }% }% }% \endgroup } \g@addto@macro{\document}{% \si@font@fam@detect@maths{sf}% \si@font@fam@detect@maths{tt}% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@font@fam@sfdefault} %\begin{macro}{\si@font@fam@ttdefault} %\begin{macro}{\si@font@fam@detect@text} % 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} \newcommand*{\si@font@fam@sfdefault}{} \newcommand*{\si@font@fam@ttfamily}{} \newcommand*{\si@font@fam@detect@text}[1]{% \si@nameedef{si@font@fam@#1default}{\@nameuse{#1default}}% } \AtBeginDocument{% \si@font@fam@detect@text{sf}% \si@font@fam@detect@text{tt}% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@font@det@b@bool} %\begin{macro}{\si@font@det@family@bool} %\begin{macro}{\si@font@det@maths@display@bool} %\begin{macro}{\si@font@det@maths@inline@bool} %\begin{macro}{\si@font@det@it@bool} %\begin{macro}{\si@font@det@mode@bool} % All of the choices here set switches, which need to be created. % \begin{macrocode} \si@bool@new\si@font@det@b@bool \si@bool@new\si@font@det@family@bool \si@bool@new\si@font@det@maths@display@bool \si@bool@new\si@font@det@maths@inline@bool \si@bool@new\si@font@det@it@bool \si@bool@new\si@font@det@mode@bool % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % The key definitions are not very exciting: almost all are Boolean % with variations in the naming. % \begin{macrocode} \si@keys@family{font/detect} \pgfkeys{ /siunitx/font/detect, all/.style = { /siunitx/font/detect/bold = true, /siunitx/font/detect/family = true, /siunitx/font/detect/italic = true, /siunitx/font/detect/mode = true }, bold/.is siunitx switch = {font@det@b}, display math/.is siunitx switch = {font@det@maths@display}, display maths/.is siunitx switch = {font@det@maths@display}, family/.is siunitx switch = {font@det@family}, inline bold/.is choice, inline bold/.cd, maths/.code = {\si@bool@true\si@font@det@maths@inline@bool}, math/.code = {\si@bool@true\si@font@det@maths@inline@bool}, text/.code = {\si@bool@false\si@font@det@maths@inline@bool}, /siunitx/font/detect, italic/.is siunitx switch = {font@det@it}, mode/.is siunitx switch = {font@det@mode}, none/.style = { /siunitx/font/detect/bold = false, /siunitx/font/detect/family = false, /siunitx/font/detect/italic = false, /siunitx/font/detect/mode = false }, bold = false, display maths = true, inline bold = text, italic = false, mode = false } % \end{macrocode} % %\begin{macro}{\si@font@set@bool} % To avoid testing more than once within an output group, a flag is % needed to indicate that everything is already done. % \begin{macrocode} \si@bool@new\si@font@set@bool % \end{macrocode} %\end{macro} %\begin{macro}{\si@font@set@bold} %\begin{macro}{\si@font@set@family} %\begin{macro}{\si@font@set@italic} % The detection system needs some storage areas for results. % \begin{macrocode} \newcommand*{\si@font@set@bold}{} \newcommand*{\si@font@set@family}{} \newcommand*{\si@font@set@italic}{} % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@font@set@text@bool} % A switch to show the mode. % \begin{macrocode} \si@bool@new\si@font@set@text@bool % \end{macrocode} %\end{macro} % %\begin{macro}{\si@font@det@set} % 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} \newcommand*{\si@font@det@set}{% \si@bool@if@F\si@font@set@bool{% \si@font@det@init \si@bool@if@T\si@font@det@b@bool{% \si@font@det@bold }% \si@bool@if@T\si@font@det@family@bool{% \si@font@det@family }% \si@bool@if@T\si@font@det@it@bool{% \si@font@det@italic }% \si@bool@if@T\si@font@det@mode@bool{% \si@font@det@mode }% }% } % \end{macrocode} %\end{macro} %\begin{macro}{\si@font@det@init} % Set up the basic macros on the assumption nothing happens. % \begin{macrocode} \newcommand*{\si@font@det@init}{% \si@bool@true\si@font@set@bool \def\si@font@set@bold{\unboldmath\mdseries}% \def\si@font@set@family{rm}% \si@bool@false\si@font@set@text@bool \def\si@font@set@italic{\upshape}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@font@det@bold} % The bold detection code depends on whether the current text is maths % or text, and also the type of maths (if appropriate). For inline % maths, there is a choice of what test to apply. % \begin{macrocode} \newcommand*{\si@font@det@bold}{% \si@mode@maths@display@if@T{% \si@bool@if@TF\si@font@det@maths@display@bool{% \si@font@det@bold@maths }{% \si@font@det@bold@text }% }% \si@mode@maths@inline@if@T{% \si@bool@if@TF\si@font@det@maths@inline@bool{% \si@font@det@bold@maths }{% \si@font@det@bold@text }% }% \si@mode@text@if@T{% \si@font@det@bold@text }% } % \end{macrocode} %\end{macro} %\begin{macro}{\si@font@det@bold@maths} %\begin{macro}{\si@font@det@bold@text} % The tests for bold depend on whether the module is testing text or % maths content. % \begin{macrocode} \newcommand*{\si@font@det@bold@maths}{% \def\si@tempa{bold}% \si@meaning@eq@if@T\si@tempa\math@version{% \def\si@font@set@bold{\boldmath\bfseries}% }% } \newcommand*{\si@font@det@bold@text}{% \def\si@tempa{b}% \edef\si@tempb{\expandafter\@car\f@series\@nil}% \si@meaning@eq@if@T\si@tempa\si@tempb{% \def\si@font@set@bold{\boldmath\bfseries}% }% } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@font@det@family} % Family detection usually picks up the surrounding text. However, for % display maths there are two options, and so a second test may be made. % \begin{macrocode} \newcommand*{\si@font@det@family}{% \si@font@det@fam@text \si@bool@if@T\si@font@det@maths@display@bool{% \si@mode@maths@display@if@T{% \si@font@det@fam@maths }% }% } % \end{macrocode} %\end{macro} %\begin{macro}{\si@font@det@fam@maths} %\begin{macro}{\si@font@det@fam@text} % The two detections routines check if the current font is sans serif or % monospaced. The method used depends on whether the current maths or % text font is of interest. The maths detection routine re-applies the % default (\texttt{rm}), as the text function is always called and may % have changed things. % \begin{macrocode} \newcommand*{\si@font@det@fam@maths}{% \def\si@font@set@family{rm}% \si@num@if@TF{\the\fam=\si@font@fam@mathsf}{% \def\si@font@set@family{sf}% }{% \si@num@if@T{\the\fam=\si@font@fam@mathtt}{% \def\si@font@set@family{tt}% }% }% } \newcommand*{\si@font@det@fam@text}{% \si@meaning@eq@if@T\f@family\si@font@fam@sfdefault{% \def\si@font@set@family{sf}% }% \si@meaning@eq@if@T\f@family\si@font@fam@ttdefault{% \def\si@font@set@family{tt}% }% } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@font@det@italic} % The italic test uses \cs{f@shape} as a handy indicator. % \begin{macrocode} \newcommand*{\si@font@det@italic}{% \def\si@tempa{it}% \si@meaning@eq@if@T\si@tempa\f@shape{% \def\si@font@set@italic{\itshape}% }% } % \end{macrocode} %\end{macro} %\begin{macro}{\si@font@det@mode} % The mode switch works from the fact that maths-mode output it the % standard. % \begin{macrocode} \newcommand*{\si@font@det@mode}{% \ifmmode\else \si@bool@true\si@font@set@text@bool \fi } % \end{macrocode} %\end{macro} % %\subsection{Font macros} % %\begin{macro}{\si@font@unit@maths@rm} %\begin{macro}{\si@font@unit@maths@sf} %\begin{macro}{\si@font@unit@maths@tt} %\begin{macro}{\si@font@unit@text@rm} %\begin{macro}{\si@font@unit@text@sf} %\begin{macro}{\si@font@unit@text@tt} %\begin{macro}{\si@font@num@maths@rm} %\begin{macro}{\si@font@num@maths@sf} %\begin{macro}{\si@font@num@maths@tt} %\begin{macro}{\si@font@num@text@rm} %\begin{macro}{\si@font@num@text@sf} %\begin{macro}{\si@font@num@text@tt} % 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{macrocode} \newcommand*{\si@font@unit@maths@rm}{} \newcommand*{\si@font@unit@maths@sf}{} \newcommand*{\si@font@unit@maths@tt}{} \newcommand*{\si@font@unit@text@rm}{} \newcommand*{\si@font@unit@text@sf}{} \newcommand*{\si@font@unit@text@tt}{} \newcommand*{\si@font@num@maths@rm}{} \newcommand*{\si@font@num@maths@sf}{} \newcommand*{\si@font@num@maths@tt}{} \newcommand*{\si@font@num@text@rm}{} \newcommand*{\si@font@num@text@sf}{} \newcommand*{\si@font@num@text@tt}{} % \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}{\si@font@unit@textmode@bool} %\begin{macro}{\si@font@num@textmode@bool} % Two switches for mode selection. % \begin{macrocode} \si@bool@new\si@font@unit@textmode@bool \si@bool@new\si@font@num@textmode@bool % \end{macrocode} %\end{macro} %\end{macro} % The font control keys are now created, all as unit and value variants. % \begin{macrocode} \si@keys@family{font} \si@keys@family{font/units} \si@keys@family{font/numbers} \pgfkeys{ /siunitx/font, maths rm/.style = { /siunitx/font/units/maths rm = #1, /siunitx/font/numbers/maths rm = #1 }, maths sf/.style = { /siunitx/font/units/maths sf = #1, /siunitx/font/numbers/maths sf = #1 }, maths tt/.style = { /siunitx/font/units/maths tt = #1, /siunitx/font/numbers/maths tt = #1 }, maths rm/.style = { /siunitx/font/units/maths rm = #1, /siunitx/font/numbers/maths rm = #1 }, maths sf/.style = { /siunitx/font/units/maths sf = #1, /siunitx/font/numbers/maths sf = #1 }, maths tt/.style = { /siunitx/font/units/maths tt = #1, /siunitx/font/numbers/maths tt = #1 }, mode/.is choice, mode/.cd, maths/.style = { /siunitx/font/units/mode = maths, /siunitx/font/numbers/mode = maths }, math/.style = { /siunitx/font/units/mode = maths, /siunitx/font/numbers/mode= maths }, text/.style = { /siunitx/font/units/mode = text, /siunitx/font/numbers/mode= text }, /siunitx/font, text rm/.style = { /siunitx/font/units/text rm = #1, /siunitx/font/numbers/text rm = #1 }, text sf/.style = { /siunitx/font/units/text sf = #1, /siunitx/font/numbers/text sf = #1 }, text tt/.style = { /siunitx/font/units/text tt = #1, /siunitx/font/numbers/text tt = #1 }, /siunitx/font/units, maths rm/.store in = \si@font@unit@maths@rm, maths sf/.store in = \si@font@unit@maths@sf, maths tt/.store in = \si@font@unit@maths@tt, maths rm/.store in = \si@font@unit@maths@rm, maths sf/.store in = \si@font@unit@maths@sf, maths tt/.store in = \si@font@unit@maths@tt, mode/.is choice, mode/.cd, maths/.code = {\si@bool@false\si@font@unit@textmode@bool}, math/.code = {\si@bool@false\si@font@unit@textmode@bool}, text/.code = {\si@bool@true\si@font@unit@textmode@bool}, /siunitx/font/units, text rm/.store in = \si@font@unit@text@rm, text sf/.store in = \si@font@unit@text@sf, text tt/.store in = \si@font@unit@text@tt, /siunitx/font/numbers, maths rm/.store in = \si@font@num@maths@rm, maths sf/.store in = \si@font@num@maths@sf, maths tt/.store in = \si@font@num@maths@tt, maths rm/.store in = \si@font@num@maths@rm, maths sf/.store in = \si@font@num@maths@sf, maths tt/.store in = \si@font@num@maths@tt, mode/.is choice, mode/.cd, maths/.code = {\si@bool@false\si@font@num@textmode@bool}, math/.code = {\si@bool@false\si@font@num@textmode@bool}, text/.code = {\si@bool@true\si@font@num@textmode@bool}, /siunitx/font/numbers, text rm/.store in = \si@font@num@text@rm, text sf/.store in = \si@font@num@text@sf, text tt/.store in = \si@font@num@text@tt, /siunitx/font, maths rm = \mathrm, maths sf = \mathsf, maths tt = \mathtt, mode = maths, text rm = \rmfamily, text sf = \sffamily, text tt = \ttfamily } % \end{macrocode} % %\subsection{Output control} % % The \module{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}{\si@print@type} % The type of output (\texttt{num} or \texttt{unit}) is always needed. % \begin{macrocode} \newcommand*{\si@print@type}{unit} % \end{macrocode} %\end{macro} % %\begin{macro}{\si@print} %\begin{macro}{\si@print@num} %\begin{macro}{\si@print@unit} % The main printing function does everything inside a group, as % there are category code and definition changes to make. First, there % is a check to see if the fonts have already been set. If not, it's % done now. Things are then placed inside \cs{text} and passed through % to the next part of the system. % \begin{macrocode} \newcommand*{\si@print}[2]{% \begingroup \si@bool@if@F\si@font@set@bool{% \si@font@det@set }% \def\si@print@type{#1}% \si@print@codes \text{\si@print@set{#2}}% \endgroup \check@mathfonts } \newcommand*{\si@print@num}{% \si@print{num}% } \newcommand*{\si@print@unit}{% \si@print{unit}% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@print@codes} % The various active characters for printing are set up and everything % is made safe for output. The definitions need the correct category % codes to apply for the \cs{let}, otherwise the dreaded % \cs{inaccessible} appears. % \begin{macrocode} \si@catcode@set{45}{13}% - \si@catcode@set{94}{13}% ^ \si@catcode@set{95}{13}% _ \newcommand*{\si@print@codes}{% \si@catcode@symbols \si@catcode@set{94}{13}% ^ \si@catcode@set{95}{13}% _ \endlinechar\m@ne\relax \everyeof{\noexpand}% \si@bool@if@TF\si@font@set@text@bool{% \si@catcode@set{45}{13}% - \let-\si@print@minus \let_\si@print@sb \let^\si@print@sp \let\textsubscript\si@print@sb \let\textsuperscript\si@print@sp }{% \si@catcode@set{45}{12}% - \let_\sb \let^\sp \let\textsubscript\sb \let\textsuperscript\sp }% } \si@catcode@set{45}{12}% - \si@catcode@set{94}{7}% ^ \si@catcode@set{95}{8}% _ % \end{macrocode} %\end{macro} % %\begin{macro}{\si@print@maths} %\begin{macro}{\si@print@text} % Actually printing is very easy for text, a little more involved for % maths. % \begin{macrocode} \newcommand*{\si@print@maths}[1]{% \ensuremath{% \@nameuse{si@font@\si@print@type @maths@\si@font@set@family}{#1}% }% } \newcommand*{\si@print@text}[1]{#1} % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@print@set} % The various font changes are set up, then the correct printing % function is called. The \cs{scantokens} primitive is here as this % avoids needing to re-\cs{edef} anything. % \begin{macrocode} \newcommand*{\si@print@set}[1]{% \si@font@set@bold \si@font@set@italic \@nameuse{si@font@\si@print@type @text@\si@font@set@family}% \si@bool@if@TF\si@font@set@text@bool{% \si@print@text{\scantokens{#1}}% }{% \si@print@maths{\scantokens{#1}}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@print@minus} % To allow the correct symbol to appear in text mode: this is the same % as \cs{textminus} from \module{textcomp}. % \begin{macrocode} \newcommand*{\si@print@minus}{} \DeclareTextSymbolDefault{\si@print@minus}{TS1} \DeclareTextSymbol{\si@print@minus}{TS1}{61} % \end{macrocode} %\end{macro} % %\begin{macro}{\si@print@sb} %\begin{macro}{\si@print@sp} % The appropriate macros for sub- and superscript in text mode ensure % the appearance is the same as maths mode. % \begin{macrocode} \newcommand*{\si@print@sb}[1]{% \ensuremath{_{\text{#1}}}% } \newcommand*{\si@print@sp}[1]{% \ensuremath{^{\text{#1}}}% } % \end{macrocode} %\end{macro} %\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}{\si@num@pre@product} %\begin{macro}{\si@num@pre@quotient} %\begin{macro}{\si@num@pre@tokens} % Storage for the tokens that need to be checked for. % \begin{macrocode} \newcommand*{\si@num@pre@product}{} \newcommand*{\si@num@pre@quotient}{} \newcommand*{\si@num@pre@tokens}{} % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % % The keys here are all considered as part of the input system. % \begin{macrocode} \si@keys@family{numbers/input} \pgfkeys{ /siunitx/numbers/input, product/.store in = \si@num@pre@product, quotient/.store in = \si@num@pre@quotient, protect tokens/.store in = \si@num@pre@tokens, product = x, quotient = /, protect tokens = \mp\pi\pm } % \end{macrocode} % %\begin{macro}{\si@num@pre@arg} %\begin{macro}{\si@num@pre@arg@den} %\begin{macro}{\si@num@pre@arg@held} %\begin{macro}{\si@num@pre@arg@num} % Storage areas for the various parts that may be found. % \begin{macrocode} \newcommand*{\si@num@pre@arg}{} \newcommand*{\si@num@pre@arg@den}{} \newcommand*{\si@num@pre@arg@held}{} \newcommand*{\si@num@pre@arg@num}{} % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@num@pre@error@bool} % An error flag. % \begin{macrocode} \si@bool@new\si@num@pre@error@bool % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@pre@process} % The pre-processor starts with the obvious: the most likely outcome is % that all of the argument is passed through unchanged. % \begin{macrocode} \newcommand*{\si@num@pre@process}[1]{% \si@num@pre@init \begingroup \si@num@pre@protect@tokens \protected@edef\@tempa{#1}% \expandafter\endgroup\expandafter \def\expandafter\si@num@pre@arg\expandafter{\@tempa}% \si@num@pre@sep@prod \si@num@pre@sep@quot } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@pre@error} % For when something is wrong. % \begin{macrocode} \newcommand*{\si@num@pre@error}{% \si@bool@true\si@num@pre@error@bool \si@log@error } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@pre@init} % The usual storage clearing. % \begin{macrocode} \newcommand*{\si@num@pre@init}{% \def\si@num@pre@arg{}% \def\si@num@pre@arg@den{}% \def\si@num@pre@arg@held{}% \def\si@num@pre@arg@num{}% \si@bool@false\si@num@pre@error@bool } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@pre@protect@tokens} %\begin{macro}{\si@num@pre@protect@tokens@aux} % Under some circumstances (for example when loading \module{breqn}) % some tokens do not behave safely under \cs{protected@edef}. To get % round this, they are redefined here. % \begin{macrocode} \newcommand*{\si@num@pre@protect@tokens}{% \si@loop@over@macro\si@num@pre@tokens\si@num@pre@protect@tokens@aux } \newcommand*{\si@num@pre@protect@tokens@aux}[1]{% \let#1\relax } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@pre@sep@prod} %\begin{macro}{\si@num@pre@sep@prod@aux} % Rather than search through the entire argument, we use the % delimited-argument trick. No error checks here as there can be an % arbitrary number of products (\emph{quel dommage}). % \begin{macrocode} \newcommand*{\si@num@pre@sep@prod}{% \si@loop@over@macro\si@num@pre@product\si@num@pre@sep@prod@aux } \newcommand*{\si@num@pre@sep@prod@aux}[1]{% \si@in@if@T\si@num@pre@arg{#1}{% \def\si@tempa##1#1##2\si@stop{% \def\si@num@pre@arg{##1}% \def\si@num@pre@arg@held{##2}% }% \expandafter\si@tempa\si@num@pre@arg\si@stop \si@empty@if@T\si@num@pre@arg{% \si@num@pre@error{Misplaced product token}{% A number cannot begin with a product token. }% }% \si@empty@if@T\si@num@pre@arg@held{% \si@num@pre@error{Misplaced product token}{% A number cannot end with a product token. }% }% \si@loop@exit }% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@pre@sep@quot} %\begin{macro}{\si@num@pre@sep@quot@aux} % For the quotient, only one token can appear in each part. So there % is an error check. % \begin{macrocode} \newcommand*{\si@num@pre@sep@quot}{% \si@loop@over@macro\si@num@pre@quotient\si@num@pre@sep@quot@aux } \newcommand*{\si@num@pre@sep@quot@aux}[1]{% \si@in@if@T\si@num@pre@arg{#1}{% \def\si@tempa##1#1##2\si@stop{% \def\si@num@pre@arg@num{##1}% \def\si@num@pre@arg@den{##2}% }% \expandafter\si@tempa\si@num@pre@arg\si@stop \si@empty@if@T\si@num@pre@arg@num{% \si@num@pre@error{Misplaced quotient token}{% A number cannot begin with a quotient token. }% }% \si@empty@if@T\si@num@pre@arg@den{% \si@num@pre@error{Misplaced quotient token}{% A number cannot end with a quotient token. }% }% \si@in@if@T\si@num@pre@arg@den{#1}{% \si@num@pre@error{Duplicate quotient token}{% Only one quotient token can appear in a single number. }% }% \si@loop@exit }% } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Parsing numbers} % % The number parser is designed to work with single numbers, which can % contain exponents, complex parts and uncertainties. In general, % looping over the input is avoided: instead, loops over the check % values are used as these will hopefully be shorter, on average. The % parser will report mathematically invalid numbers here: whether the % input is valid in the context required is left to the calling % function. % %\begin{macro}{\si@num@in@uncert@close} %\begin{macro}{\si@num@in@complex} %\begin{macro}{\si@num@in@decimal} %\begin{macro}{\si@num@in@digits} %\begin{macro}{\si@num@in@exponent} %\begin{macro}{\si@num@in@ignore} %\begin{macro}{\si@num@in@uncert@open} %\begin{macro}{\si@num@in@signs} %\begin{macro}{\si@num@in@symbols} % Storage areas for the various number components. % \begin{macrocode} \newcommand*{\si@num@in@uncert@close}{} \newcommand*{\si@num@in@complex}{} \newcommand*{\si@num@in@decimal}{} \newcommand*{\si@num@in@digits}{} \newcommand*{\si@num@in@exponent}{} \newcommand*{\si@num@in@signs}{} \newcommand*{\si@num@in@symbols}{} % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % The keys which control the package are all concerned with different % tokens to check for. The names are all hopefully obvious. % \begin{macrocode} \pgfkeys{ /siunitx/numbers/input, close uncertainty/.store in = \si@num@in@uncert@close, complex roots/.store in = \si@num@in@complex, decimal markers/.store in = \si@num@in@decimal, digits/.store in = \si@num@in@digits, exponent markers/.store in = \si@num@in@exponent, ignore/.store in = \si@num@in@ignore, open uncertainty/.store in = \si@num@in@uncert@open, signs/.store in = \si@num@in@signs, symbols/.store in = \si@num@in@symbols, %( close uncertainty = ), complex roots = ij, decimal markers = {.,}, digits = 0123456789, exponent markers = dDeE, ignore = {}, open uncertainty = (, %) signs = +-\mp\pm, symbols = \pi } % \end{macrocode} %\begin{macro}{\si@num@in@mant} %\begin{macro}{\si@num@in@mant@sign} %\begin{macro}{\si@num@in@mant@int} %\begin{macro}{\si@num@in@mant@dec} %\begin{macro}{\si@num@in@mant@uncert} %\begin{macro}{\si@num@in@mant@uncert@int} %\begin{macro}{\si@num@in@mant@uncert@dec} %\begin{macro}{\si@num@in@mant@comp} %\begin{macro}{\si@num@in@mant@comp@sign} %\begin{macro}{\si@num@in@mant@comp@int} %\begin{macro}{\si@num@in@mant@comp@dec} %\begin{macro}{\si@num@in@mant@comp@uncert} %\begin{macro}{\si@num@in@mant@comp@uncert@int} %\begin{macro}{\si@num@in@mant@comp@uncert@dec} % Storage areas for the various parts of a mantissa. % \begin{macrocode} \newcommand*{\si@num@in@mant}{} \newcommand*{\si@num@in@mant@sign}{} \newcommand*{\si@num@in@mant@int}{} \newcommand*{\si@num@in@mant@dec}{} \newcommand*{\si@num@in@mant@uncert}{} \newcommand*{\si@num@in@mant@uncert@int}{} \newcommand*{\si@num@in@mant@uncert@dec}{} \newcommand*{\si@num@in@mant@comp}{} \newcommand*{\si@num@in@mant@comp@sign}{} \newcommand*{\si@num@in@mant@comp@int}{} \newcommand*{\si@num@in@mant@comp@dec}{} \newcommand*{\si@num@in@mant@comp@uncert}{} \newcommand*{\si@num@in@mant@comp@uncert@int}{} \newcommand*{\si@num@in@mant@comp@uncert@dec}{} % \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} %\begin{macro}{\si@num@in@exp} %\begin{macro}{\si@num@in@exp@sign} %\begin{macro}{\si@num@in@exp@int} %\begin{macro}{\si@num@in@exp@dec} %\begin{macro}{\si@num@in@exp@uncert} %\begin{macro}{\si@num@in@exp@uncert@int} %\begin{macro}{\si@num@in@exp@uncert@dec} %\begin{macro}{\si@num@in@exp@comp} %\begin{macro}{\si@num@in@exp@comp@sign} %\begin{macro}{\si@num@in@exp@comp@int} %\begin{macro}{\si@num@in@exp@comp@dec} %\begin{macro}{\si@num@in@exp@comp@uncert} %\begin{macro}{\si@num@in@exp@comp@uncert@int} %\begin{macro}{\si@num@in@exp@comp@uncert@dec} % The same for an exponent. % \begin{macrocode} \newcommand*{\si@num@in@exp}{} \newcommand*{\si@num@in@exp@sign}{} \newcommand*{\si@num@in@exp@int}{} \newcommand*{\si@num@in@exp@dec}{} \newcommand*{\si@num@in@exp@uncert}{} \newcommand*{\si@num@in@exp@uncert@int}{} \newcommand*{\si@num@in@exp@uncert@dec}{} \newcommand*{\si@num@in@exp@comp}{} \newcommand*{\si@num@in@exp@comp@sign}{} \newcommand*{\si@num@in@exp@comp@int}{} \newcommand*{\si@num@in@exp@comp@dec}{} \newcommand*{\si@num@in@exp@comp@uncert}{} \newcommand*{\si@num@in@exp@comp@uncert@int}{} \newcommand*{\si@num@in@exp@comp@uncert@dec}{} % \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} %\begin{macro}{\si@num@in@mant@bool} %\begin{macro}{\si@num@in@mant@dec@bool} %\begin{macro}{\si@num@in@mant@uncert@dec@bool} %\begin{macro}{\si@num@in@mant@comp@bool} %\begin{macro}{\si@num@in@mant@comp@dec@bool} %\begin{macro}{\si@num@in@mant@comp@uncert@dec@bool} %\begin{macro}{\si@num@in@exp@bool} %\begin{macro}{\si@num@in@exp@dec@bool} %\begin{macro}{\si@num@in@exp@uncert@dec@bool} %\begin{macro}{\si@num@in@exp@comp@bool} %\begin{macro}{\si@num@in@exp@comp@dec@bool} %\begin{macro}{\si@num@in@exp@comp@uncert@dec@bool} % Flags for quick detection of parts; for complex numbers, this is % essential as you can just have the complex root ($\mathrm{i}$). % The \texttt{@dec} switches are used as the package may need to know % the difference between \texttt{1} and \texttt{1.}, for example. % \begin{macrocode} \si@bool@new\si@num@in@mant@bool \si@bool@new\si@num@in@mant@dec@bool \si@bool@new\si@num@in@mant@uncert@dec@bool \si@bool@new\si@num@in@mant@comp@bool \si@bool@new\si@num@in@mant@comp@dec@bool \si@bool@new\si@num@in@mant@comp@uncert@dec@bool \si@bool@new\si@num@in@exp@bool \si@bool@new\si@num@in@exp@dec@bool \si@bool@new\si@num@in@exp@uncert@dec@bool \si@bool@new\si@num@in@exp@comp@bool \si@bool@new\si@num@in@exp@comp@dec@bool \si@bool@new\si@num@in@exp@comp@uncert@dec@bool % \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}{\si@num@in@symbols@bool} % A flag is set if the input given contains ``symbolic'' tokens: this % information is useful later on. % \begin{macrocode} \si@bool@new\si@num@in@symbols@bool % \end{macrocode} %\end{macro} %\begin{macro}{\si@num@in@arg} % The argument given to the parser is stored and manipulated here. % \begin{macrocode} \newcommand*{\si@num@in@arg}{} % \end{macrocode} %\end{macro} %\begin{macro}{\si@num@in@error} % Errors are indicated using a numerical method, but this is done in % a slightly odd way (using a \LaTeX3 switch plus a negative value), % so a macro is used. % \begin{macrocode} \newcommand*{\si@num@in@error}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@in@parse} %\begin{macro}{\si@num@in@parse@O} % The master control for parsing numbers is mainly a list of functions % to carry out. Things are kept very simple here. A variant is also % provided for data which needs to be expanded once (\LaTeX3-inspired). % \begin{macrocode} \newcommand*{\si@num@in@parse}[1]{% \si@num@in@init \si@num@in@rescan{#1}% \si@empty@if@TF\si@num@in@arg{% \def\si@num@in@error{\m@ne}% }{% \si@num@in@arg@loop \si@num@in@try{\si@num@in@separate}% \si@num@in@try{\si@num@in@finalise}% }% } \newcommand*{\si@num@in@parse@O}[1]{% \expandafter\si@num@in@parse\expandafter{#1}% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@in@add} % For adding a token to one of the storage areas. % \begin{macrocode} \newcommand*{\si@num@in@add}[1]{% \si@add@right@cs@N{si@num@in@#1}% } % \end{macrocode} %\end{macro} %\begin{macro}{\si@num@in@arg@loop} %\begin{macro}{\si@num@in@arg@loop@aux} % The entire argument is looped over. Three tasks take place here, to % keep down the number of loops. First, a check is made that the input % token is valid. The input stream is re-written to remove ignored % tokens, and finally a check is made to see if ``symbolic'' tokens are % present in the input. % \begin{macrocode} \newcommand*{\si@num@in@arg@loop}{% \si@expand@tlist\si@tempa{% \si@num@in@signs \si@num@in@ignore \si@num@in@digits \si@num@in@decimal \si@num@in@exponent \si@num@in@complex \si@num@in@symbols \si@num@in@uncert@open \si@num@in@uncert@close }% \si@clear@macro\si@tempb \si@loop@over@macro\si@num@in@arg\si@num@in@arg@loop@aux \si@num@in@try{\let\si@num@in@arg\si@tempb}% } \newcommand*{\si@num@in@arg@loop@aux}[1]{% \si@in@if@F\si@tempa{#1}{% \si@num@in@throw{Invalid token `#1' in numerical input}{% Only the tokens: \MessageBreak \si@tempa \MessageBreak are valid for numerical input. }% \si@bool@true\si@num@in@error \si@loop@exit }% \si@in@if@F\si@num@in@ignore{#1}{% \si@add@right@N\si@tempb{#1}% }% \si@in@if@T\si@num@in@symbols{#1}{% \si@bool@true\si@num@in@symbols@bool }% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@in@finalise} %\begin{macro}{\si@num@in@final@check} % The finalisation system starts with a series of error checks for % invalid numbers. If they all pass, there are a few bits of tidying up % to do. % \begin{macrocode} \newcommand*{\si@num@in@finalise}{% \si@num@in@final@check \si@num@in@try{\si@num@in@final@tidy}% } \newcommand*{\si@num@in@final@check}{% \si@bool@true\si@num@in@mant@bool \si@empty@if@T\si@num@in@mant@dec{% \si@empty@if@T\si@num@in@mant@int{% \si@bool@false\si@num@in@mant@bool \si@empty@if@F\si@num@in@mant@uncert{% \si@num@in@throw{Uncertainty but no number}{% The mantissa contains only an uncertainty. }% }% }% }% \si@bool@if@T\si@num@in@mant@comp@bool{% \si@empty@if@T\si@num@in@mant@comp@dec{% \si@empty@if@T\si@num@in@mant@comp@int{% \si@empty@if@F\si@num@in@mant@comp@uncert{% \si@num@in@throw{Uncertainty but no number}{% The complex mantissa contains only an uncertainty. }% }% }% }% }% \si@bool@true\si@num@in@exp@bool \si@empty@if@T\si@num@in@exp@dec{% \si@empty@if@T\si@num@in@exp@int{% \si@bool@false\si@num@in@exp@bool \si@empty@if@F\si@num@in@exp@uncert{% \si@num@in@throw{Uncertainty but no number}{% The exponent contains only an uncertainty. }% }% \si@empty@if@F\si@num@in@exp@sign{% \si@num@in@throw{Sign but no exponent}{% The exponent contains only a sign. }% }% }% }% \si@bool@if@T\si@num@in@exp@comp@bool{% \si@empty@if@T\si@num@in@exp@comp@dec{% \si@empty@if@T\si@num@in@exp@comp@int{% \si@empty@if@F\si@num@in@exp@comp@uncert{% \si@num@in@throw{Uncertainty but no number}{% The complex exponent contains only an uncertainty. }% }% }% }% }% \si@bool@if@F\si@num@in@mant@bool{% \si@bool@if@F\si@num@in@mant@comp@bool{% \si@bool@if@F\si@num@in@exp@bool{% \si@bool@if@F\si@num@in@exp@comp@bool{% \si@num@in@throw{Empty numerical argument}{% The given `number' contains no information. }% }% }% }% }% } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@num@in@finalise@tidy} %\begin{macro}{\si@num@in@finalise@tidy@aux} % There are some minor bits of tidying up to do now. Two issues need to % be handled, both concerned with zero. % \begin{macrocode} \newcommand*{\si@num@in@final@tidy}{% \si@num@in@final@tidy@aux{mant}% \si@num@in@final@tidy@aux{exp}% } \newcommand*{\si@num@in@final@tidy@aux}[1]{% \si@num@in@remove@zeros{#1}% \si@num@in@remove@zeros{#1@comp}% \si@num@in@zero@sign{#1}% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@in@init} %\begin{macro}{\si@num@in@init@aux} %\begin{macro}{\si@num@in@init@names} % The various storage areas are all cleared \emph{en masse}. % \begin{macrocode} \newcommand*{\si@num@in@init}{% \si@bool@false\si@num@in@error \si@bool@false\si@num@in@symbols@bool \si@loop@over@macro\si@num@in@init@names\si@num@in@init@aux \si@bool@false\si@num@in@mant@bool \si@bool@false\si@num@in@mant@dec@bool \si@bool@false\si@num@in@mant@uncert@dec@bool \si@bool@false\si@num@in@mant@comp@bool \si@bool@false\si@num@in@mant@comp@dec@bool \si@bool@false\si@num@in@mant@comp@uncert@dec@bool \si@bool@false\si@num@in@exp@bool \si@bool@false\si@num@in@exp@dec@bool \si@bool@false\si@num@in@exp@uncert@dec@bool \si@bool@false\si@num@in@exp@comp@bool \si@bool@false\si@num@in@exp@comp@dec@bool \si@bool@false\si@num@in@exp@comp@uncert@dec@bool } \newcommand*{\si@num@in@init@aux}[1]{% \si@clear@cs{si@num@in@#1}% } \newcommand*{\si@num@in@init@names}{% {mant}% {mant@sign}% {mant@int}% {mant@dec}% {mant@uncert}% {mant@uncert@int}% {mant@uncert@dec}% {mant@comp}% {mant@comp@sign}% {mant@comp@int}% {mant@comp@dec}% {mant@comp@uncert}% {mant@comp@uncert@int}% {mant@comp@uncert@dec}% {exp}% {exp@sign}% {exp@int}% {exp@dec}% {exp@uncert}% {exp@uncert@int}% {exp@uncert@dec}% {exp@comp}% {exp@comp@sign}% {exp@comp@int}% {exp@comp@dec}% {exp@comp@uncert}% {exp@comp@uncert@int}% {exp@comp@uncert@dec}% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@in@protect@tokens} % The same as for the \texttt{pre} section, so a simple \cs{let}. % \begin{macrocode} \newcommand*{\si@num@in@protect@tokens}{} \let\si@num@in@protect@tokens\si@num@pre@protect@tokens % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@in@remove@zeros} % Here, any leading zeros are found in the integer part of the number. % By constructing the loop in this way, every character in the input % does not have to be tested. % \begin{macrocode} \newcommand*{\si@num@in@remove@zeros}[1]{% \si@in@cs@if@T{si@num@in@#1@int}{0}{% \def\si@tempa##10##2\si@stop{% \si@empty@tlist@if@TF{##1}{% \si@in@tlist@if@TF{##2}{0}{% \si@tempa##2\si@stop }{% \@namedef{si@num@in@#1@int}{##2}% }% }{% \@namedef{si@num@in@#1@int}{##10##2}% }% }% \si@let@Nc\si@tempb{si@num@in@#1@int}% \expandafter\si@tempa\si@tempb\si@stop \si@empty@cs@if@T{si@num@in@#1@int}{% \@namedef{si@num@in@#1@int}{0}% }% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@in@rescan} % The user input is re-scanned to ensure the correct category codes % and to remove spaces. Everything is done in the usual group so that % the changes are local, with the result ending up in % \cs{si@num@in@arg}. % \begin{macrocode} \newcommand*{\si@num@in@rescan}[1]{% \begingroup \si@catcode@symbols \si@catcode@set{9}{9}% tab ignored \si@catcode@set{32}{9}% space ignored \si@catcode@set{126}{9}% tilde ignored \everyeof{\noexpand}% \endlinechar\m@ne\relax \si@clear@macro{\,}% \si@num@in@protect@tokens \protected@edef\@tempa{\scantokens{#1}}% \expandafter\endgroup\expandafter \def\expandafter\si@num@in@arg\expandafter{\@tempa}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@in@separate} %\begin{macro}{\si@num@in@separate@aux} % The main separator macro divides the input into the various parts. % As everything is done for the mantissa and the exponent, an auxiliary % function is used to keep the code shorter. % \begin{macrocode} \newcommand*{\si@num@in@separate}{% \si@num@in@try{\si@num@in@sep@exp}% \si@num@in@separate@aux{mant}% \si@num@in@separate@aux{exp}% } \newcommand*{\si@num@in@separate@aux}[1]{% \si@num@in@try{\si@num@in@sep@sign{#1}}% \si@num@in@try{\si@num@in@sep@comp{#1}}% \si@num@in@try{\si@num@in@sep@dec{#1}}% \si@num@in@try{\si@num@in@sep@dec@comp{#1}}% \si@num@in@try{\si@num@in@sep@uncert{#1}}% \si@num@in@try{\si@num@in@sep@uncert{#1@comp}}% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@in@sep@comp} %\begin{macro}{\si@num@in@sep@comp@aux@i} %\begin{macro}{\si@num@in@sep@comp@aux@ii} %\begin{macro}{\si@num@in@sep@comp@aux@iii} %\begin{macro}{\si@num@in@sep@comp@aux@iiv} % Finding a valid complex number is a two stage process. The first part % is to look for a complex root at the end of the number. If one is % found, look for a sign dividing the real and imaginary parts. If % the number is not complex, then any sign tokens are invalid. % \begin{macrocode} \newcommand*{\si@num@in@sep@comp}[1]{% \si@empty@cs@if@F{si@num@in@#1}{% \si@empty@if@F\si@num@in@complex{% \si@let@Nc\si@tempa{si@num@in@#1}% \si@bool@false\si@tmp@bool \si@loop@over@macro\si@num@in@complex\si@num@in@sep@comp@aux@i \si@num@in@try{\si@num@in@sep@comp@aux@ii{#1}}% \si@num@in@try{\si@num@in@sep@comp@aux@iii{#1}}% }% }% } % \end{macrocode} % To avoid needing to use a second loop to check for the last letter, % a bit of trickery. If |##2| is \cs{si@no@value}, then the number does % not contain the root at all. If the root has been found, then |##3| % will be \cs{si@no@value} only if there is a misplaced root sign. % \begin{macrocode} \newcommand*{\si@num@in@sep@comp@aux@i}[1]{% \def\si@tempb##1#1##2##3\si@stop{% \si@no@value@if@F{##2}{% \si@no@value@if@TF{##3}{% \si@bool@true\si@tmp@bool \def\si@tempa{##1}% \si@loop@exit }{% \si@num@in@throw{Misplaced complex root}{% The complex root token `#1' can only come at \MessageBreak the end of a number. }% \si@loop@exit }% }% }% \expandafter\si@tempb\si@tempa#1\si@no@value\si@stop } % \end{macrocode} % The second part of the system has to look for a sign, then do some % tidying up. It starts by moving the data from the test above back to % the correct place. The start-off tests are done against the temporary % variables, as this keeps down the name use. % \begin{macrocode} \newcommand*{\si@num@in@sep@comp@aux@ii}[1]{% \si@let@cN{si@num@in@#1@comp@bool}\si@tmp@bool \si@let@cN{si@num@in@#1}\si@tempa \si@bool@if@T\si@tmp@bool{% \si@empty@if@F\si@tempa{% \def\si@tempb##1{% \si@in@if@TF\si@num@in@signs{##1}{% \si@bool@if@TF\si@tmp@bool{% \si@num@in@throw{Duplicate sign found}{% Only a single sign can be given \MessageBreak in the complex part of a number. }% \si@loop@exit }{% \si@num@in@add{#1@comp@sign}{##1}% \si@bool@true\si@tmp@bool }% }{% \si@bool@if@TF\si@tmp@bool{% \si@num@in@add{#1@comp}{##1}% }{% \si@num@in@add{#1}{##1}% }% }% }% \si@bool@false\si@tmp@bool \si@clear@cs{si@num@in@#1}% \si@loop@over@macro\si@tempa\si@tempb }% }% } % \end{macrocode} % A macro to tidy up the various possible combinations. If there is % a complex part, then a search will have occurred for a sign. It is % possible that no sign was found, in which case the entire number % should be complex. On the other hand, if there was no complex part % then a check is made for duplicated signs. % \begin{macrocode} \newcommand*{\si@num@in@sep@comp@aux@iii}[1]{% \si@bool@cs@if@TF{si@num@in@#1@comp@bool}{% \si@bool@if@F\si@tmp@bool{% \si@let@cc{si@num@in@#1@comp@sign}{si@num@in@#1@sign}% \si@clear@cs{si@num@in@#1@sign}% \si@let@cc{si@num@in@#1@comp}{si@num@in@#1}% \si@clear@cs{si@num@in@#1}% }% }{% \expandafter\si@loop@over@macro\csname si@num@in@#1\endcsname \si@num@in@sep@aux@iv }% } \newcommand*{\si@num@in@sep@aux@iv}[1]{% \si@in@if@T\si@num@in@signs{#1}{% \si@num@in@throw{Duplicate sign found}{% Only a single sign can be given \MessageBreak in the real part of a number. }% \si@loop@exit }% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@num@in@sep@dec} %\begin{macro}{\si@num@in@sep@dec@comp} %\begin{macro}{\si@num@in@sep@dec@aux@i} %\begin{macro}{\si@num@in@sep@dec@aux@ii} % The real and complex parts need a slightly different lead-off test % here. % \begin{macrocode} \newcommand*{\si@num@in@sep@dec}[1]{% \si@empty@cs@if@F{si@num@in@#1}{% \si@num@in@sep@dec@aux@i{#1}% }% } \newcommand*{\si@num@in@sep@dec@comp}[1]{% \si@bool@cs@if@T{si@num@in@#1@comp@bool}{% \si@empty@cs@if@TF{si@num@in@#1@comp}{% \si@let@cc{si@num@in@#1@comp@int}{si@num@in@#1@comp}% \si@let@cN{si@num@in@#1@comp}% }{% \si@num@in@sep@dec@aux@i{#1@comp}% }% }% } % \end{macrocode} % The main part of the integer--decimal separator avoids a loop. Only a % single token can be given, and this can be used to find the two parts % rapidly. If there is no marker, then \cs{si@tempb} is always empty and % so the decimal part ends up correct. % \begin{macrocode} \newcommand*{\si@num@in@sep@dec@aux@i}[1]{% \si@let@Nc\si@tempa{si@num@in@#1}% \si@clear@macro\si@tempb \si@bool@false\si@tmp@bool \si@clear@cs{si@num@in@#1}% \si@loop@over@macro\si@num@in@decimal\si@num@in@sep@dec@aux@ii \si@num@in@try{\si@let@cN{si@num@in@#1@int}\si@tempa}% \si@num@in@try{\si@let@cN{si@num@in@#1@dec}\si@tempb}% \si@num@in@try{\si@let@cN{si@num@in@#1@dec@bool}\si@tmp@bool}% } \newcommand*{\si@num@in@sep@dec@aux@ii}[1]{% \si@in@if@T\si@tempa{#1}{% \si@bool@true\si@tmp@bool \def\si@tempb##1#1##2\si@stop{% \def\si@tempa{##1}% \def\si@tempb{##2}% }% \expandafter\si@tempb\si@tempa\si@stop \si@in@if@T\si@tempb{#1}{% \si@num@in@throw{Duplicate decimal token found}{% Only a single decimal marker token can be given \MessageBreak in numerical input. }% }% \si@loop@exit }% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@num@in@sep@exp} %\begin{macro}{\si@num@in@sep@exp@aux} % The separation here follows the same path as the integer--decimal % part, except that the macro names are known and so the temporary % variables are not needed. % \begin{macrocode} \newcommand*{\si@num@in@sep@exp}{% \let\si@num@in@mant\si@num@in@arg \si@loop@over@macro\si@num@in@exponent\si@num@in@sep@exp@aux } \newcommand*{\si@num@in@sep@exp@aux}[1]{% \si@in@if@T\si@num@in@arg{#1}{% \def\si@tempa##1#1##2\si@stop{% \def\si@num@in@mant{##1}% \def\si@num@in@exp{##2}% }% \expandafter\si@tempa\si@num@in@arg\si@stop \si@in@if@T\si@num@in@exp{#1}{% \si@num@in@throw{Duplicate exponent token found}{% Only a single exponent marker token can be given \MessageBreak in numerical input. }% }% \si@loop@exit }% } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@num@in@sep@sign} %\begin{macro}{\si@num@in@sep@sign@aux} % Separating signs first converts ``\texttt{+-}'' to \cs{pm} and % ``\texttt{-+}'' to \cs{mp} before looking for a single-token sign. % This is done using the fact that only the very first token needs to be % examined. % \begin{macrocode} \newcommand*{\si@num@in@sep@sign}[1]{% \si@empty@cs@if@F{si@num@in@#1}{% \si@replace@all@in@cs{si@num@in@#1}{-+}{\mp}% \si@replace@all@in@cs{si@num@in@#1}{+-}{\pm}% \expandafter\expandafter\expandafter\si@num@in@sep@sign@aux \csname si@num@in@#1\endcsname\si@stop{#1}% }% } \newcommand*{\si@num@in@sep@sign@aux}{} \def\si@num@in@sep@sign@aux#1#2\si@stop#3{% \si@in@if@TF\si@num@in@signs{#1}{% \@namedef{si@num@in@#3@sign}{#1}% \@namedef{si@num@in@#3}{#2}% }{% \@namedef{si@num@in@#3}{#1#2}% }% } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@num@in@sep@uncert} %\begin{macro}{\si@num@in@sep@uncert@aux@i} %\begin{macro}{\si@num@in@sep@uncert@aux@ii} %\begin{macro}{\si@num@in@sep@uncert@aux@iii} %\begin{macro}{\si@num@in@sep@uncert@aux@iv} %\begin{macro}{\si@num@in@sep@uncert@aux@v} %\begin{macro}{\si@num@in@sep@uncert@aux@vi} % Finding any uncertainty depends on whether there is a decimal % part. % \begin{macrocode} \newcommand*{\si@num@in@sep@uncert}[1]{% \si@empty@cs@if@TF{si@num@in@#1@dec}{% \si@empty@cs@if@F{si@num@in@#1@int}{% \si@num@in@sep@uncert@aux@i{#1}{int}% }% }{% \si@num@in@sep@uncert@aux@i{#1}{dec}% \si@num@in@sep@uncert@check@int{#1}% }% } % \end{macrocode} % A check is made first for the closing symbol: it must be at the end of % the number, and so is relatively easy to find. % \begin{macrocode} \newcommand*{\si@num@in@sep@uncert@aux@i}[2]{% \si@let@Nc\si@tempa{si@num@in@#1@#2}% \si@loop@over@macro\si@num@in@uncert@close\si@num@in@sep@uncert@aux@ii \si@num@in@try{\si@num@in@sep@uncert@aux@iii{#1}{#2}}% } % \end{macrocode} % Here, |##2| will have a value if a marker has been found. Then, % |##3| will have no value if everything is correct. If |##3| has a % value, then the marker is misplaced (not at the end): this also % covers duplicated closing markers. % \begin{macrocode} \newcommand*{\si@num@in@sep@uncert@aux@ii}[1]{% \def\si@tempb##1#1##2##3\si@stop{% \si@no@value@if@F{##2}{% \si@no@value@if@TF{##3}{% \si@bool@true\si@tmp@bool \def\si@tempa{##1}% \si@loop@exit }{% \si@num@in@throw{Misplaced closing uncertainty token}{% The closing uncertainty token `#1' can only \MessageBreak come at the end of a number. }% \si@loop@exit }% }% }% \si@bool@false\si@tmp@bool \expandafter\si@tempb\si@tempa#1\si@no@value\si@stop \si@bool@if@T\si@tmp@bool{% \si@loop@exit }% } % \end{macrocode} % Now to look for the opening character, or perhaps make sure one is % not present. % \begin{macrocode} \newcommand*{\si@num@in@sep@uncert@aux@iii}[2]{% \si@bool@if@TF\si@tmp@bool{% \si@bool@false\si@tmp@bool \si@loop@over@macro\si@num@in@uncert@open \si@num@in@sep@uncert@aux@iv \si@num@in@try{\si@num@in@sep@uncert@aux@v{#1}{#2}}% }{% \si@loop@over@macro\si@num@in@uncert@open \si@num@in@sep@uncert@aux@vi }% } % \end{macrocode} % Here, |##1| contains the main part of the number, and |##2| should % contain the uncertainty. If there is a stray opening token, it will % appear in |##2|. % \begin{macrocode} \newcommand*{\si@num@in@sep@uncert@aux@iv}[1]{% \si@in@if@T\si@tempa{#1}{% \si@bool@true\si@tmp@bool \def\si@tempb##1#1##2\si@stop{% \def\si@tempa{##1}% \def\si@tempb{##2}% }% \expandafter\si@tempb\si@tempa\si@stop \si@in@if@T\si@tempb{#1}{% \si@num@in@throw{Duplicate opening uncertainty token found}{% Only a single opening uncertainty token can be \MessageBreak given in numerical input. }% }% \si@loop@exit }% } % \end{macrocode} % Two ``tidy up'' functions to make sure everything makes sense. % \begin{macrocode} \newcommand*{\si@num@in@sep@uncert@aux@v}[2]{% \si@bool@if@TF\si@tmp@bool{% \si@let@cN{si@num@in@#1@#2}\si@tempa \si@let@cN{si@num@in@#1@uncert}\si@tempb \si@empty@if@T\si@tempb{% \si@num@in@throw{Empty uncertainty given}{% The number given contains an empty uncertainty. }% }% }{% \si@num@in@throw{% Closing uncertainty token without matching opening% }{% The final token of a the number is a closing \MessageBreak uncertainty token, but no opening token was found \MessageBreak in this part of the number. }% }% } \newcommand*{\si@num@in@sep@uncert@aux@vi}[1]{% \si@in@if@T\si@tempa{#1}{% \si@num@in@throw{% Opening uncertainty token without matching closing% }{% The opening uncertainty token `#1' was found with no \MessageBreak matching closing token. }% \si@loop@exit }% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@num@in@sep@uncert@check@int} %\begin{macro}{\si@num@in@sep@uncert@check@int@aux} % For a number containing a decimal part, there is a need to check that % the integer part does not contain any error. % \begin{macrocode} \newcommand*{\si@num@in@sep@uncert@check@int}[1]{% \def\si@num@in@sep@uncert@check@int@aux##1{% \si@in@cs@if@T{si@num@in@#1@int}{##1}{% \si@num@in@throw{Uncertainty in integer part}{% The opening uncertainty token `##1' was found in the \MessageBreak integer part of the input, but a decimal part was also given. }% \si@loop@exit }% }% \si@loop@over@macro\si@num@in@uncert@open \si@num@in@sep@uncert@check@int@aux \si@loop@over@macro\si@num@in@uncert@close \si@num@in@sep@uncert@check@int@aux } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@in@throw} % Throw an error. % \begin{macrocode} \newcommand*{\si@num@in@throw}{% \let\si@num@in@error\si@true \si@log@error } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@in@try} % So that the parser stops on the first error, a guard macro is used. % \begin{macrocode} \newcommand*{\si@num@in@try}{% \si@bool@if@F\si@num@in@error } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@in@zero@sign} %\begin{macro}{\si@num@in@zero@sign@aux@i} %\begin{macro}{\si@num@in@zero@sign@aux@ii} % The number zero does not take a sign. The test is complicated by some % issues. First, the check for complex numbers needs to ensure that it % only fires if there is no real part. % \begin{macrocode} \newcommand*{\si@num@in@zero@sign}[1]{% \si@bool@cs@if@TF{si@num@in@#1@bool}{% \si@num@in@zero@sign@aux@i{#1}% }{% \si@num@in@zero@sign@aux@i{#1@comp}% }% } % \end{macrocode} % The integer part of the problem is easy: it will just be zero if there % is no value. However, the decimal part can be an arbitrary number of % zeros. % \begin{macrocode} \newcommand*{\si@num@in@zero@sign@aux@i}[1]{% \si@empty@cs@if@TF{si@num@in@#1@int}{% \si@num@in@zero@sign@aux@ii{#1}% }{% \def\si@tempa{0}% \si@meaning@eq@cs@if@T{si@tempa}{si@num@in@#1@int}{% \si@num@in@zero@sign@aux@ii{#1}% }% }% } \newcommand*{\si@num@in@zero@sign@aux@ii}[1]{% \si@empty@cs@if@TF{si@num@in@#1@dec}{% \si@clear@cs{si@num@in@#1@sign}% }{% \def\si@tempa{0}% \def\si@tempb##1{% \si@in@if@F\si@tempa{##1}{% \si@bool@false\si@tmp@bool }% }% \si@bool@true\si@tmp@bool \si@loop@over@cs{si@num@in@#1@dec}\si@tempb \si@bool@if@T\si@tmp@bool{% \si@clear@cs{si@num@in@#1@sign}% }% }% } % \end{macrocode} %\end{macro} %\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 ``formatting'': this is left for the output part of the system. % %\begin{macro}{\si@num@post@sign@token} % Storage for processing variables. % \begin{macrocode} \newcommand*{\si@num@post@sign@token}{} % \end{macrocode} %\end{macro} %\begin{macro}{\si@num@post@plus@bool} %\begin{macro}{\si@num@post@rnd@figures@bool} %\begin{macro}{\si@num@post@rnd@places@bool} %\begin{macro}{\si@num@post@sign@bool} %\begin{macro}{\si@num@post@zero@dec@bool} %\begin{macro}{\si@num@post@zero@exp@bool} %\begin{macro}{\si@num@post@zero@int@bool} % Flags for processing. % \begin{macrocode} \si@bool@new\si@num@post@plus@bool \si@bool@new\si@num@post@rnd@figures@bool \si@bool@new\si@num@post@rnd@places@bool \si@bool@new\si@num@post@sign@bool \si@bool@new\si@num@post@zero@dec@bool \si@bool@new\si@num@post@zero@exp@bool \si@bool@new\si@num@post@zero@int@bool % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@num@post@figures} %\begin{macro}{\si@num@post@places} % Rounding targets are stored as numbers. % \begin{macrocode} \newcount\si@num@post@figures \newcount\si@num@post@places % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@num@post@dec} %\begin{macro}{\si@num@rnd@int} % When carrying out the rounding procedures, a couple of storage % areas are needed. % \begin{macrocode} \newcommand*{\si@num@post@dec}{} \newcommand*{\si@num@post@int}{} % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@num@post@carry@bool} %\begin{macro}{\si@num@post@sig@bool} % For the rounding system. % \begin{macrocode} \si@bool@new\si@num@post@carry@bool \si@bool@new\si@num@post@sig@bool % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@num@post@rnd@tens} %\begin{macro}{\si@num@post@rnd@cnt} % The rounding system needs various storage areas. % \begin{macrocode} \newcommand*{\si@num@post@rnd@tens}{} \newcount\si@num@post@rnd@cnt % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@num@post@dec@cnt} %\begin{macro}{\si@num@post@uncert@cnt} % When separating out uncertainties there is a need to store the lengths % of various items. % \begin{macrocode} \newcount\si@num@post@dec@cnt \newcount\si@num@post@uncert@cnt % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@num@post@rnd@check} % A short validation macro. % \begin{macrocode} \newcommand*{\si@num@post@rnd@check}[2]{% \@nameuse{si@num@post@#1}#2\relax \expandafter\ifnum\csname si@num@post@#1\endcsname<\z@\relax \si@log@error{Invalid input for rounding digits}{% The input for option 'numbers/process/round #1' \MessageBreak must be a positive integer. }% \fi } % \end{macrocode} %\end{macro} % The options are set up. % \begin{macrocode} \si@keys@family{numbers/process} \pgfkeys{ /siunitx/numbers/process, add zero decimal/.is siunitx switch = {num@post@zero@dec}, add zero integer/.is siunitx switch = {num@post@zero@int}, explicit sign/.store in = \si@num@post@sign@token, include explicit sign/.is siunitx switch = {num@post@sign}, retain explicit plus/.is siunitx switch = {num@post@plus}, retain zero exponent/.is siunitx switch = {num@post@zero@exp}, round mode/.is choice, round mode/.cd, figures/.code = {% \si@bool@true\si@num@post@rnd@figures@bool \si@bool@false\si@num@post@rnd@places@bool }, off/.code = {% \si@bool@false\si@num@post@rnd@figures@bool \si@bool@false\si@num@post@rnd@places@bool }, places/.code = {% \si@bool@false\si@num@post@rnd@figures@bool \si@bool@true\si@num@post@rnd@places@bool }, /siunitx/numbers/process, round figures/.code = {\si@num@post@rnd@check{figures}{#1}}, round places/.code = {\si@num@post@rnd@check{places}{#1}}, add zero decimal = true, add zero integer = true, explicit sign = +, include explicit sign = false, retain explicit plus = false, retain zero exponent = false, round mode = off, round figures = 2, round places = 2 } % \end{macrocode} % %\begin{macro}{\si@num@post@process} % Post-processing is a series of small tasks. % \begin{macrocode} \newcommand*{\si@num@post@process}{% \si@bool@if@F\si@num@in@error{% \si@num@post@sign \si@num@post@zero@fill \si@num@post@exponent \si@bool@if@F\si@num@in@symbols@bool{% \si@num@post@round \si@bool@if@F\si@num@post@rnd@figures@bool{% \si@bool@if@F\si@num@post@rnd@places@bool{% \si@num@post@uncert }% }% }% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@post@add@sign} %\begin{macro}{\si@num@post@add@sign@aux} % Adding a sign to an existing number needs a couple of tests and % saves code with an auxiliary function. % \begin{macrocode} \newcommand*{\si@num@post@add@sign}[1]{% \si@bool@cs@if@TF{si@num@in@#1@bool}{% \si@num@post@add@sign@aux{#1}% }{% \si@bool@cs@if@T{si@num@in@#1@comp@bool}{% \si@num@post@add@sign@aux{#1@comp}% }% }% } \newcommand*{\si@num@post@add@sign@aux}[1]{% \si@empty@cs@if@T{si@num@in@#1@sign}{% \@namedef{si@num@in@#1@sign}{\si@num@post@sign@token}% }% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@post@exponent} % 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} \newcommand*{\si@num@post@exponent}{% \si@bool@if@F\si@num@post@zero@exp@bool{% \si@expand@tlist\si@tempa{% \si@num@in@exp@int \si@num@in@exp@dec \si@num@in@exp@comp@int \si@num@in@exp@comp@dec }% \si@in@if@T\si@tempa{0}{% \def\si@tempb##10000##2\si@stop{% \si@empty@tlist@if@T{##1}{% \def\si@num@in@exp@int{}% \def\si@num@in@exp@dec{}% \def\si@num@in@exp@comp@int{}% \def\si@num@in@exp@comp@dec{}% \si@bool@false\si@num@in@exp@bool \si@bool@false\si@num@in@exp@comp@bool }% }% \expandafter\si@tempb\si@tempa0000\si@stop }% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@post@plus} %\begin{macro}{\si@num@post@plus@aux} % Holding onto a plus works very much in the same way as adding a sign: % some quick tests and an assignment. % \begin{macrocode} \newcommand*{\si@num@post@plus}[1]{% \si@bool@cs@if@TF{si@num@in@#1@bool}{% \si@num@post@plus@aux{#1}% }{% \si@bool@cs@if@T{si@num@in@#1@comp@bool}{% \si@num@post@plus@aux{#1@comp}% }% }% } \newcommand*{\si@num@post@plus@aux}[1]{% \def\si@tempa{+}% \si@meaning@eq@cs@if@T{si@num@in@#1@sign}{si@tempa}{% \si@clear@cs{si@num@in@#1@sign}% }% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@post@sign} % Sorting out signs consists of two parts: retaining a plus if necessary % and adding an explicit sign. % \begin{macrocode} \newcommand*{\si@num@post@sign}{% \si@bool@if@F\si@num@post@plus@bool{% \si@num@post@plus{mant}% \si@num@post@plus{exp}% }% \si@bool@if@T\si@num@post@sign@bool{% \si@num@post@add@sign{mant}% \si@num@post@add@sign{exp}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@post@round} %\begin{macro}{\si@num@post@round@aux} % The lead-off for rounding is the same for decimal places and % significant figures. % \begin{macrocode} \newcommand*{\si@num@post@round}{% \si@num@post@round@aux{figures}% \si@num@post@round@aux{places}% } \newcommand*{\si@num@post@round@aux}[1]{% \si@bool@cs@if@T{si@num@post@rnd@#1@bool}{% \@nameuse{si@num@post@rnd@#1}{mant}% \@nameuse{si@num@post@rnd@#1}{mant@comp}% \@nameuse{si@num@post@rnd@#1}{exp}% \@nameuse{si@num@post@rnd@#1}{exp@comp}% }% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@post@rnd@dec} % The rounding routine for decimals is the same for figures and places. % \begin{macrocode} \newcommand*{\si@num@post@rnd@dec}[1]{% \si@num@if@F{\si@num@post@rnd@cnt>\@ne}{% \si@tempcnt\expandafter\@car\si@num@post@dec\@nil\relax \si@bool@if@T\si@num@post@carry@bool{% \advance\si@tempcnt\@ne\relax }% \si@bool@false\si@num@post@carry@bool \si@num@if@TF{\si@num@post@rnd@cnt=\@ne}{% \si@num@if@T{\si@tempcnt>4}{% \si@bool@true\si@num@post@carry@bool }% }{% \si@num@if@T{\si@tempcnt=10}{% \si@bool@true\si@num@post@carry@bool \si@tempcnt\z@\relax }% \si@nameedef{si@num@in@#1@dec}{% \the\si@tempcnt \@nameuse{si@num@in@#1@dec}% }% }% }% \advance\si@num@post@rnd@cnt\m@ne\relax \edef\si@num@post@dec{\expandafter\@cdr\si@num@post@dec\@nil}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@post@rnd@figures} %\begin{macro}{\si@num@post@rnd@figures@aux@i} %\begin{macro}{\si@num@post@rnd@figures@aux@ii} %\begin{macro}{\si@num@post@rnd@figures@aux@iii} % Rather than count figures to start with, a completely different % approach is used here. % \begin{macrocode} \newcommand*{\si@num@post@rnd@figures}[1]{% \si@num@post@rnd@cnt\z@\relax \si@bool@false\si@num@post@sig@bool \si@clear@macro\si@num@post@dec \si@clear@macro\si@num@post@int \si@whiledo@empty@cs@F{si@num@in@#1@int}{% \si@num@post@rnd@figures@aux@i{#1}{int}% }% \si@whiledo@empty@cs@F{si@num@in@#1@dec}{% \si@num@post@rnd@figures@aux@i{#1}{dec}% }% \si@bool@if@TF\si@num@post@sig@bool{% \si@num@if@TF{\si@num@post@rnd@cnt>\si@num@post@figures}{% \si@num@post@rnd@figures@aux@ii{#1}% }{% \si@num@post@rnd@figures@aux@iii{#1}% }% }{% \@namedef{si@num@in@#1@int}{0}% \si@clear@cs{si@num@in@#1@dec}% \si@bool@cs@false{si@num@in@#1@dec@bool}% }% } % \end{macrocode} % A counting macro so that the number of significant digits is known. % Reversal is done at the same time, to save needing another loop later. % \begin{macrocode} \newcommand*{\si@num@post@rnd@figures@aux@i}[2]{% \si@tempcnt\expandafter\expandafter\expandafter\@car \csname si@num@in@#1@#2\endcsname\@nil\relax \si@nameedef{si@num@post@#2}{% \the\si@tempcnt \@nameuse{si@num@post@#2}% }% \si@bool@if@F\si@num@post@sig@bool{% \si@num@if@F{\si@tempcnt=\z@}{% \si@bool@true\si@num@post@sig@bool }% }% \si@bool@if@T\si@num@post@sig@bool{% \advance\si@num@post@rnd@cnt\@ne\relax }% \si@nameedef{si@num@in@#1@#2}{% \expandafter\expandafter\expandafter\@cdr \csname si@num@in@#1@#2\endcsname\@nil }% } % \end{macrocode} % 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} \newcommand*{\si@num@post@rnd@figures@aux@ii}[1]{% \advance\si@num@post@rnd@cnt-\si@num@post@figures\relax \si@whiledo@empty@F\si@num@post@dec{% \si@num@post@rnd@dec{#1}% }% \si@whiledo@empty@F\si@num@post@int{% \si@num@post@rnd@figures@int{#1} }% \si@bool@if@T\si@num@post@carry@bool{% \si@nameedef{si@num@in@#1@int}{% 1% \@nameuse{si@num@in@#1@int}% }% \si@empty@cs@if@F{si@num@in@#1@dec}{% \si@reverse@cs{si@num@in@#1@dec}% \si@nameedef{si@num@in@#1@dec}{% \expandafter\expandafter\expandafter\@cdr \csname si@num@in@#1@dec\endcsname\@nil }% \si@reverse@cs{si@num@in@#1@dec}% }% }% } % \end{macrocode} % If the number is too short, then the reversal is undone and the % padding routine is called. % \begin{macrocode} \newcommand*{\si@num@post@rnd@figures@aux@iii}[1]{% \advance\si@num@post@rnd@cnt-\si@num@post@figures\relax \si@num@post@rnd@cnt-\si@num@post@rnd@cnt\relax \si@reverse@macro\si@num@post@dec \si@reverse@macro\si@num@post@int \si@let@cN{si@num@in@#1@dec}\si@num@post@dec \si@let@cN{si@num@in@#1@int}\si@num@post@int \si@num@post@rnd@pad{#1}% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@num@post@rnd@figures@int} % For figures, the integer part is a little complicated as zeros need % to be included. % \begin{macrocode} \newcommand*{\si@num@post@rnd@figures@int}[1]{% \si@num@if@T{\si@num@post@rnd@cnt>\z@}{% \si@nameedef{si@num@in@#1@int}{% 0% \@nameuse{si@num@in@#1@int}% }% }% \si@num@if@F{\si@num@post@rnd@cnt>\@ne}{% \si@tempcnt\expandafter\@car\si@num@post@int\@nil\relax \si@bool@if@T\si@num@post@carry@bool{% \advance\si@tempcnt\@ne\relax }% \si@bool@false\si@num@post@carry@bool \si@num@if@TF{\si@num@post@rnd@cnt=\@ne}{% \si@num@if@T{\si@tempcnt>4}{% \si@bool@true\si@num@post@carry@bool }% }{% \si@num@if@T{\si@tempcnt=10}{% \si@bool@true\si@num@post@carry@bool \si@tempcnt\z@\relax }% \si@nameedef{si@num@in@#1@int}{% \the\si@tempcnt \@nameuse{si@num@in@#1@int}% }% }% }% \advance\si@num@post@rnd@cnt\m@ne\relax \edef\si@num@post@int{\expandafter\@cdr\si@num@post@int\@nil}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@post@rnd@pad} % 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} \newcommand*{\si@num@post@rnd@pad}[1]{% \si@whiledo@num@T{\si@num@post@rnd@cnt>\z@}{% \si@nameedef{si@num@in@#1@dec}{% \@nameuse{si@num@in@#1@dec}% 0% }% \advance\si@num@post@rnd@cnt\m@ne\relax }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@post@rnd@places} %\begin{macro}{\si@num@post@rnd@places@aux@i} %\begin{macro}{\si@num@post@rnd@places@aux@ii} %\begin{macro}{\si@num@post@rnd@places@aux@iii} % When rounding to a number of places, the number of tokens in the % decimal parts is counted, as this is always needed. A check is then % made on the value of the number: if it is zero then a different % approach is used to that if there is a value. % \begin{macrocode} \newcommand*{\si@num@post@rnd@places}[1]{% \si@num@if@TF{\si@num@post@places=\z@}{% \si@clear@cs{si@num@in@#1@dec}% \si@bool@cs@false{si@num@in@#1@dec@bool}% }{% \si@num@post@rnd@places@aux@i{#1}% }% } \newcommand*{\si@num@post@rnd@places@aux@i}[1]{% \si@empty@cs@if@T{si@num@in@#1@dec}{% \@namedef{si@num@in@#1@dec}{0}% }% \si@num@post@rnd@cnt\si@elt@count@cs{si@num@in@#1@dec}\relax \expandafter\expandafter\expandafter\ifnum \csname si@num@in@#1@dec\endcsname=\z@\relax \si@num@post@rnd@cnt\si@num@post@places\relax \si@clear@cs{si@num@in@#1@dec}% \expandafter\si@num@post@rnd@pad \else \expandafter\si@num@post@rnd@places@aux@ii \fi {#1}% } % \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} \newcommand*{\si@num@post@rnd@places@aux@ii}[1]{% \advance\si@num@post@rnd@cnt-\si@num@post@places\relax \si@num@if@TF{\si@num@post@rnd@cnt<\z@}{% \si@num@post@rnd@cnt-\si@num@post@rnd@cnt\relax \si@num@post@rnd@pad{#1}% }{% \si@num@post@rnd@places@init{#1}% \si@num@post@rnd@places@aux@iii{#1}% }% } \newcommand*{\si@num@post@rnd@places@aux@iii}[1]{% \si@empty@if@TF\si@num@post@dec{% \si@whiledo@empty@F\si@num@post@int{% \si@num@post@rnd@places@int{#1}% }% \si@bool@if@T\si@num@post@carry@bool{% \si@nameedef{si@num@in@#1@int}{% 1% \@nameuse{si@num@in@#1@int}% }% }% }{% \si@num@post@rnd@dec{#1}% \si@num@post@rnd@places@aux@iii{#1}% }% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@num@post@rnd@places@int} % Rounding for integers is just a case of carrying digits. % \begin{macrocode} \newcommand*{\si@num@post@rnd@places@int}[1]{% \si@tempcnt\expandafter\@car\si@num@post@int\@nil\relax \edef\si@num@post@int{\expandafter\@cdr\si@num@post@int\@nil}% \si@bool@if@T\si@num@post@carry@bool{% \advance\si@tempcnt\@ne\relax }% \si@bool@false\si@num@post@carry@bool \si@num@if@T{\si@tempcnt=10}{% \si@bool@true\si@num@post@carry@bool \si@tempcnt\z@\relax }% \si@nameedef{si@num@in@#1@int}{% \the\si@tempcnt \@nameuse{si@num@in@#1@int}% }% } % \end{macrocode} %\end{macro} %\begin{macro}{\si@num@post@rnd@places@init} % To set up some rounding bits and pieces. % \begin{macrocode} \newcommand*{\si@num@post@rnd@places@init}[1]{% \si@let@Nc\si@num@post@dec{si@num@in@#1@dec}% \si@let@Nc\si@num@post@int{si@num@in@#1@int}% \si@reverse@macro\si@num@post@dec \si@reverse@macro\si@num@post@int \si@clear@cs{si@num@in@#1@dec}% \si@clear@cs{si@num@in@#1@int}% \si@bool@false\si@num@post@carry@bool } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@post@zero@fill} %\begin{macro}{\si@num@post@zero@fill@aux} % Checks for adding zeros to each component are carried out. % \begin{macrocode} \newcommand*{\si@num@post@zero@fill}{% \si@bool@if@T\si@num@post@zero@int@bool{% \si@num@post@zero@fill@aux{mant}{int}% \si@num@post@zero@fill@aux{mant@comp}{int}% \si@num@post@zero@fill@aux{exp}{int}% \si@num@post@zero@fill@aux{exp@comp}{int}% }% \si@bool@if@T\si@num@post@zero@dec@bool{% \si@num@post@zero@fill@aux{mant}{dec}% \si@num@post@zero@fill@aux{mant@comp}{dec}% \si@num@post@zero@fill@aux{exp}{dec}% \si@num@post@zero@fill@aux{exp@comp}{dec}% }% } \newcommand*{\si@num@post@zero@fill@aux}[2]{% \si@bool@cs@if@T{si@num@in@#1@dec@bool}{% \si@empty@cs@if@T{si@num@in@#1@#2}{% \@namedef{si@num@in@#1@#2}{0}% }% }% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@post@uncert} %\begin{macro}{\si@num@post@uncert@aux@i} %\begin{macro}{\si@num@post@uncert@aux@ii} % 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} \newcommand*{\si@num@post@uncert}{% \si@num@post@uncert@aux@i{mant}% \si@num@post@uncert@aux@i{exp}% } \newcommand*{\si@num@post@uncert@aux@i}[1]{% \si@num@post@uncert@aux@ii{#1}% \si@num@post@uncert@aux@ii{#1@comp}% } \newcommand*{\si@num@post@uncert@aux@ii}[1]{% \si@bool@cs@if@TF{si@num@in@#1@dec@bool}{% \si@num@post@uncert@dec{#1}% }{% \si@num@post@uncert@int{#1}% }% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@num@post@uncert@dec} %\begin{macro}{\si@num@post@uncert@dec@aux@i} %\begin{macro}{\si@num@post@uncert@dec@aux@ii} % 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} \newcommand*{\si@num@post@uncert@dec}[1]{% \si@empty@cs@if@F{si@num@in@#1@uncert}{% \si@bool@cs@true{si@num@in@#1@uncert@dec@bool}% \si@num@post@dec@cnt\si@elt@count@cs{si@num@in@#1@dec}\relax \si@num@post@uncert@cnt\si@elt@count@cs{si@num@in@#1@uncert}\relax \si@num@if@TF{\si@num@post@uncert@cnt>\si@num@post@dec@cnt}{% \si@num@post@uncert@dec@aux@i{#1}% }{% \si@num@post@uncert@dec@aux@ii{#1}% }% }% } \newcommand*{\si@num@post@uncert@dec@aux@i}[1]{% \def\si@tempa##1{% \si@num@if@TF{\si@num@post@uncert@cnt>\si@num@post@dec@cnt}{% \si@add@right@cs@N{si@num@in@#1@uncert@int}{##1}% }{% \si@add@right@cs@N{si@num@in@#1@uncert@dec}{##1}% }% \advance\si@num@post@uncert@cnt\m@ne\relax }% \si@loop@over@cs{si@num@in@#1@uncert}\si@tempa } \newcommand*{\si@num@post@uncert@dec@aux@ii}[1]{% \def\si@tempa{% \si@add@right@cs@N{si@num@in@#1@uncert@dec}{0}% \advance\si@num@post@uncert@cnt\@ne\relax }% \si@whiledo@num@T{\si@num@post@uncert@cnt<\si@num@post@dec@cnt}{% \si@tempa }% \def\si@tempa##1{% \si@add@right@cs@O{si@num@in@#1@uncert@dec}##1% }% \expandafter\si@tempa\expandafter {\csname si@num@in@#1@uncert\endcsname}% \si@bool@if@T\si@num@post@zero@int@bool{% \@namedef{si@num@in@#1@uncert@int}{0}% }% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@num@post@uncert@int} % Relatively easy: the uncertainty is in the integer part of the number, % and so there is no need to generate zeros. % \begin{macrocode} \newcommand*{\si@num@post@uncert@int}[1]{% \si@let@cc{si@num@in@#1@uncert@int}{si@num@in@#1@uncert}% } % \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{num@in} and % \texttt{num@out} storage areas is that the later can include % formatting such as hard spaces. % %\begin{macro}{\si@num@out@bracket@close} %\begin{macro}{\si@num@out@bracket@open} %\begin{macro}{\si@num@out@complex@root} %\begin{macro}{\si@num@out@decimal} %\begin{macro}{\si@num@out@exp@base} %\begin{macro}{\si@num@out@exp@prod} %\begin{macro}{\si@num@out@group@sep} %\begin{macro}{\si@num@out@uncert@close} %\begin{macro}{\si@num@out@uncert@open} %\begin{macro}{\si@num@out@uncert@space} % Storage areas for settings. % \begin{macrocode} \newcommand*{\si@num@out@bracket@close}{} \newcommand*{\si@num@out@bracket@open}{} \newcommand*{\si@num@out@complex@root}{} \newcommand*{\si@num@out@decimal}{} \newcommand*{\si@num@out@exp@base}{} \newcommand*{\si@num@out@exp@prod}{} \newcommand*{\si@num@out@group@sep}{} \newcommand*{\si@num@out@uncert@close}{} \newcommand*{\si@num@out@uncert@open}{} \newcommand*{\si@num@out@uncert@space}{} % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@out@bracket@use@bool} %\begin{macro}{\si@num@out@group@digits@bool} %\begin{macro}{\si@num@out@group@four@bool} %\begin{macro}{\si@num@out@tight@bool} %\begin{macro}{\si@num@out@uncert@sep@bool} % Switch storage for options. % \begin{macrocode} \si@bool@new\si@num@out@bracket@use@bool \si@bool@new\si@num@out@group@digits@bool \si@bool@new\si@num@out@group@four@bool \si@bool@new\si@num@out@tight@bool \si@bool@new\si@num@out@uncert@sep@bool % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@out@mant} %\begin{macro}{\si@num@out@mant@sign} %\begin{macro}{\si@num@out@mant@int} %\begin{macro}{\si@num@out@mant@dec} %\begin{macro}{\si@num@out@mant@uncert} %\begin{macro}{\si@num@out@mant@uncert@dec} %\begin{macro}{\si@num@out@mant@uncert@int} %\begin{macro}{\si@num@out@mant@comp} %\begin{macro}{\si@num@out@mant@comp@sign} %\begin{macro}{\si@num@out@mant@comp@int} %\begin{macro}{\si@num@out@mant@comp@dec} %\begin{macro}{\si@num@out@mant@comp@uncert} %\begin{macro}{\si@num@out@mant@comp@uncert@dec} %\begin{macro}{\si@num@out@mant@comp@uncert@int} % Storage areas for output mantissa. % \begin{macrocode} \newcommand*{\si@num@out@mant}{} \newcommand*{\si@num@out@mant@sign}{} \newcommand*{\si@num@out@mant@int}{} \newcommand*{\si@num@out@mant@dec}{} \newcommand*{\si@num@out@mant@uncert}{} \newcommand*{\si@num@out@mant@uncert@dec}{} \newcommand*{\si@num@out@mant@uncert@int}{} \newcommand*{\si@num@out@mant@comp}{} \newcommand*{\si@num@out@mant@comp@sign}{} \newcommand*{\si@num@out@mant@comp@int}{} \newcommand*{\si@num@out@mant@comp@dec}{} \newcommand*{\si@num@out@mant@comp@uncert}{} \newcommand*{\si@num@out@mant@comp@uncert@dec}{} \newcommand*{\si@num@out@mant@comp@uncert@int}{} % \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} %\begin{macro}{\si@num@out@exp} %\begin{macro}{\si@num@out@exp@sign} %\begin{macro}{\si@num@out@exp@int} %\begin{macro}{\si@num@out@exp@dec} %\begin{macro}{\si@num@out@exp@uncert} %\begin{macro}{\si@num@out@exp@uncert@dec} %\begin{macro}{\si@num@out@exp@uncert@int} %\begin{macro}{\si@num@out@exp@comp} %\begin{macro}{\si@num@out@exp@comp@sign} %\begin{macro}{\si@num@out@exp@comp@int} %\begin{macro}{\si@num@out@exp@comp@dec} %\begin{macro}{\si@num@out@exp@comp@uncert} %\begin{macro}{\si@num@out@exp@comp@uncert@dec} %\begin{macro}{\si@num@out@exp@comp@uncert@int} % And for exponents. % \begin{macrocode} \newcommand*{\si@num@out@exp}{} \newcommand*{\si@num@out@exp@sign}{} \newcommand*{\si@num@out@exp@int}{} \newcommand*{\si@num@out@exp@dec}{} \newcommand*{\si@num@out@exp@uncert}{} \newcommand*{\si@num@out@exp@uncert@dec}{} \newcommand*{\si@num@out@exp@uncert@int}{} \newcommand*{\si@num@out@exp@comp}{} \newcommand*{\si@num@out@exp@comp@sign}{} \newcommand*{\si@num@out@exp@comp@int}{} \newcommand*{\si@num@out@exp@comp@dec}{} \newcommand*{\si@num@out@exp@comp@uncert}{} \newcommand*{\si@num@out@exp@comp@uncert@dec}{} \newcommand*{\si@num@out@exp@comp@uncert@int}{} % \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} %\begin{macro}{\si@num@out@result} % The overall number is stored here, although it might not be used in % this form. % \begin{macrocode} \newcommand*{\si@num@out@result}{} % \end{macrocode} %\end{macro} %\begin{macro}{\si@num@out@mant@parts@bool} %\begin{macro}{\si@num@out@mant@comp@parts@bool} %\begin{macro}{\si@num@out@exp@parts@bool} %\begin{macro}{\si@num@out@exp@comp@parts@bool} % Flags to indicate that the input is in parts which may need brackets. % \begin{macrocode} \si@bool@new\si@num@out@mant@parts@bool \si@bool@new\si@num@out@mant@comp@parts@bool \si@bool@new\si@num@out@exp@parts@bool \si@bool@new\si@num@out@exp@comp@parts@bool % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@num@out@mant@comp@bool} %\begin{macro}{\si@num@out@exp@comp@bool} % Also for a number consisting of a real and complex part. % \begin{macrocode} \si@bool@new\si@num@out@mant@comp@bool \si@bool@new\si@num@out@exp@comp@bool % \end{macrocode} %\end{macro} %\end{macro} % The usual keys are created for output (appearance-only) settings. % \begin{macrocode} \si@keys@family{numbers/output} \pgfkeys{ /siunitx/numbers/output, close bracket/.store in = \si@num@out@bracket@close, close uncertainty/.store in = \si@num@out@uncert@close, complex root/.store in = \si@num@out@complex@root, decimal marker/.store in = \si@num@out@decimal, exponent base/.store in = \si@num@out@exp@base, exponent product/.store in = \si@num@out@exp@prod, group digits/.is siunitx switch = {num@out@group@digits}, group four digits/.is siunitx switch = {num@out@group@four}, group separator/.store in = \si@num@out@group@sep, open bracket/.store in = \si@num@out@bracket@open, open uncertainty/.store in = \si@num@out@uncert@open, separate uncertainty/.is siunitx switch = {num@out@uncert@sep}, tight spacing/.is siunitx switch = {num@out@tight}, uncertainty space/.store in = \si@num@out@uncert@space, %( use brackets/.is siunitx switch = {num@out@bracket@use}, close bracket = ),% ( close uncertainty = ), complex root = i, decimal marker = ., exponent base = 10, exponent product = \times, group digits = true, group four digits = false, group separator = {\,}, open bracket = (, %) open uncertainty = (, %) separate uncertainty = false, tight spacing = false, use brackets = true, uncertainty space = {}, } % \end{macrocode} % %\begin{macro}{\si@num@out@process} % The master control function for formatting output: the usual set up. % The number is put back together in stages. % \begin{macrocode} \newcommand*{\si@num@out@process}{% \si@num@out@init \si@num@out@core \si@num@out@complex \si@num@out@sign{mant}% \si@num@out@sign{exp}% \si@num@out@exponent } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@out@add} %\begin{macro}{\si@num@out@add@C} %\begin{macro}{\si@num@out@add@C@aux} % Adding to a store. % \begin{macrocode} \newcommand*{\si@num@out@add}[1]{% \si@add@right@cs@N{si@num@out@#1}% } \newcommand*{\si@num@out@add@C}[2]{% \expandafter\si@num@out@add@C@aux\expandafter {\csname si@num@out@#2\endcsname}{#1}% } \newcommand*{\si@num@out@add@C@aux}[2]{% \si@add@right@cs@O{si@num@out@#2}{#1}% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@num@out@add@maths} %\begin{macro}{\si@num@out@add@maths@aux} % To add something which requires maths mode to an output macro by name. % Done this way, the output ends up with the literal text stored (makes % debugging easier). A quick reversal of the input makes expansion % easier. % \begin{macrocode} \newcommand*{\si@num@out@add@maths}[2]{% \si@empty@if@F#2{% \expandafter\si@num@out@add@maths@aux\expandafter{#2}{#1}% }% } \newcommand*{\si@num@out@add@maths@aux}[2]{% \si@num@out@add{#2}{\ensuremath{#1}}% } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@num@out@add@pm} % To add \cs{pm}. % \begin{macrocode} \newcommand*{\si@num@out@add@pm}[1]{% \si@bool@if@TF\si@num@out@tight@bool{% \si@num@out@add@maths{#1}{{\pm}}% }{% \def\si@tempa{\pm}% \si@num@out@add@maths{#1}{\si@tempa}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@out@bracket@comp} %\begin{macro}{\si@num@out@bracket@parts} %\begin{macro}{\si@num@out@bracket@aux@i} %\begin{macro}{\si@num@out@bracket@aux@ii} % 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} \newcommand*{\si@num@out@bracket@comp}[1]{% \si@bool@cs@if@T{si@num@out@#1@comp@bool}{% \si@bool@cs@false{si@num@out@#1@parts@bool}% \si@bool@cs@false{si@num@out@#1@comp@parts@bool}% }% \si@num@out@brackets@aux@i{#1}{comp}% } \newcommand*{\si@num@out@bracket@parts}[1]{% \si@num@out@brackets@aux@i{#1}{parts}% } \newcommand*{\si@num@out@brackets@aux@i}[2]{% \si@empty@cs@if@F{si@num@out@#1}{% \si@bool@if@T\si@num@out@bracket@use@bool{% \si@bool@cs@if@T{si@num@out@#1@#2@bool}{% \si@num@out@bracket@aux@ii{#1}% \si@bool@cs@false{si@num@out@#1@#2@bool}% }% }% }% } \newcommand*{\si@num@out@bracket@aux@ii}[1]{% \si@add@left@cs@O{si@num@out@#1}\si@num@out@bracket@open \si@add@right@cs@O{si@num@out@#1}\si@num@out@bracket@close } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@out@complex} %\begin{macro}{\si@num@out@complex@aux} % The real and complex parts of each number are reassembled, with % brackets if needed. % \begin{macrocode} \newcommand*{\si@num@out@complex}{% \si@num@out@complex@aux{mant}% \si@num@out@complex@aux{exp}% } \newcommand*{\si@num@out@complex@aux}[1]{% \si@num@out@bracket@parts{#1@comp}% \si@bool@cs@if@T{si@num@in@#1@comp@bool}{% \si@num@out@add@maths{#1@comp}{\si@num@out@complex@root}% \si@num@out@bracket@parts{#1}% \si@empty@cs@if@F{si@num@out@#1}{% \si@num@out@sign{#1@comp}% \si@bool@cs@true{si@num@out@#1@comp@bool}% }% }% \si@num@out@add@C{#1}{#1@comp}% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@out@copy} %\begin{macro}{\si@num@out@copy@aux} % A short-cut, keeping down the need for \cs{edef}. % \begin{macrocode} \newcommand*{\si@num@out@copy}[1]{% \expandafter\si@num@out@copy@aux\csname si@num@in@#1\endcsname{#1}% } \newcommand*{\si@num@out@copy@aux}[2]{% \si@add@right@cs@O{si@num@out@#2}{#1}% } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@num@out@copy@maths} %\begin{macro}{\si@num@out@copy@maths@aux} % Similar but adding \cs{ensuremath}. % \begin{macrocode} \newcommand*{\si@num@out@copy@maths}[1]{% \expandafter\si@num@out@copy@maths@aux \csname si@num@in@#1\endcsname{#1}% } \newcommand*{\si@num@out@copy@maths@aux}[2]{% \si@num@out@add@maths{#2}#1% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@out@core} %\begin{macro}{\si@num@out@core@aux@i} %\begin{macro}{\si@num@out@core@aux@ii} % The integer, decimal and any uncertainty parts are put back together. % This gives a ``minimal'' unit which cannot need any brackets. % \begin{macrocode} \newcommand*{\si@num@out@core}{% \si@num@out@core@aux@i{mant}% \si@num@out@core@aux@i{exp}% } \newcommand*{\si@num@out@core@aux@i}[1]{% \si@num@out@core@aux@ii{#1}% \si@num@out@core@aux@ii{#1@comp}% } \newcommand*{\si@num@out@core@aux@ii}[1]{% \si@bool@cs@if@T{si@num@in@#1@bool}{% \si@num@out@group@digits{#1}% \si@empty@cs@if@F{si@num@in@#1@uncert}{% \si@num@out@uncert{#1}% }% }% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@out@exponent} % The exponent system starts by making sure that the mantissa contains % brackets if needed. A sign is then added to the exponent part, before % creating the full output (including the mantissa sign if needed). % \begin{macrocode} \newcommand*{\si@num@out@exponent}{% \si@empty@cs@if@F{si@num@out@mant}{% \si@empty@cs@if@F{si@num@out@exp}{% \si@num@out@bracket@comp{mant}% \si@num@out@bracket@parts{mant}% }% }% \si@num@out@add@C{result}{mant}% \si@empty@cs@if@F{si@num@out@mant}{% \si@empty@cs@if@F{si@num@out@exp}{% \si@bool@if@TF\si@num@out@tight@bool{% \expandafter\def\expandafter\si@tempa\expandafter {\expandafter{\si@num@out@exp@prod}}% \si@num@out@add@maths{result}\si@tempa }{% \si@num@out@add@maths{result}{\si@num@out@exp@prod}% }% }% }% \si@empty@cs@if@F{si@num@out@exp}{% \si@num@out@add@C{result}{exp@base}% \si@num@out@add{result}{^\bgroup}% \si@num@out@add@C{result}{exp}% \si@num@out@add{result}{\egroup}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@num@out@group@digits} %\begin{macro}{\si@num@out@group@digits@aux@i} %\begin{macro}{\si@num@out@group@digits@aux@ii} % Grouping digits only happens if there are no symbols in the input, and % of course if grouping has been requested. % \begin{macrocode} \newcommand*{\si@num@out@group@digits}[1]{% \si@num@out@copy{#1@dec}% \si@num@out@copy{#1@int}% \si@bool@if@T\si@num@out@group@digits@bool{% \si@bool@if@F\si@num@in@symbols@bool{% \si@num@out@group@digits@aux@i{#1}{dec}% \si@num@out@group@digits@aux@i{#1}{int}% }% }% \si@num@out@add@C{#1}{#1@int}% \si@bool@cs@if@T{si@num@in@#1@dec@bool}{% \si@num@out@add@maths{#1}{\si@num@out@decimal}% \si@num@out@add@C{#1}{#1@dec}% }% } \newcommand*{\si@num@out@group@digits@aux@i}[2]{% \si@empty@cs@if@F{si@num@in@#1@#2}{% \si@bool@if@TF\si@num@out@group@four@bool{% \si@num@out@group@digits@aux@ii{#1}{#2}% }{% \si@num@out@group@five@if@T{si@num@in@#1@#2}{% \si@num@out@group@digits@aux@ii{#1}{#2}% }% }% }% } % \end{macrocode} % The main formatter uses a loop to move through the input and convert % it to output. Branching for integer or decimal part is left until the % last possible moment. % \begin{macrocode} \newcommand*{\si@num@out@group@digits@aux@ii}[2]{% \si@clear@cs{si@num@out@#1@#2}% \@nameuse{si@num@out@group@#2}{#1}% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@num@out@group@dec} %\begin{macro}{\si@num@out@group@dec@aux} % Using the ``keep everything on the stack'' approach, a relatively % simple recursion is needed. % \begin{macrocode} \newcommand*{\si@num@out@group@dec}[1]{% \def\si@num@out@group@dec@aux##1##2##3##4{% \si@empty@tlist@if@TF{##2}{% \si@num@out@add{#1@dec}{##1}% }{% \si@empty@tlist@if@TF{##3}{% \si@num@out@add{#1@dec}{##1##2}% }{% \si@num@out@add{#1@dec}{##1##2##3}% \si@empty@tlist@if@F{##4}{% \si@num@out@add@maths{#1@dec}{\si@num@out@group@sep}% \si@num@out@group@dec@aux##4% }% }% }% }% \expandafter\expandafter\expandafter\si@num@out@group@dec@aux \csname si@num@in@#1@dec\endcsname{}{}{}% } \newcommand*{\si@num@out@group@dec@aux}{} % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@num@out@group@five@if@T} %\begin{macro}{\si@num@out@group@five@if@aux@i} % A check to see if there are five tokens in the input: this will always % be a name. The \cs{edef} in the auxiliary function here mops up the % \cs{@empty}s needed for the delimited argument. % \begin{macrocode} \newcommand*{\si@num@out@group@five@if@T}[1]{% \expandafter\expandafter\expandafter\si@num@out@group@five@if@aux \csname #1\endcsname\@empty\@empty\@empty\@empty\si@stop } \newcommand*{\si@num@out@group@five@if@aux}{} \def\si@num@out@group@five@if@aux#1#2#3#4#5\si@stop{% \edef\si@tempa{#5}% \si@empty@if@F\si@tempa } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\si@num@out@group@int} %\begin{macro}{\si@num@out@group@int@aux@i} %\begin{macro}{\si@num@out@group@int@aux@ii} %\begin{macro}{\si@num@out@group@int@aux@iii} % By keeping everything on the stack, recursion can occur quite % efficiently here. The rather odd order is needed because % \cs{si@num@out@group@int@aux@iii} needs |#1| to be available. % \begin{macrocode} \newcommand*{\si@num@out@group@int}[1]{% \def\si@num@out@group@int@aux@iii##1##2##3##4{% \si@num@out@add{#1@int}{##1##2##3}% \si@stop@if@F{##4}{% \si@num@out@add@maths{#1@int}{\si@num@out@group@sep}% \si@num@out@group@int@aux@iii##4% }% }% \expandafter\si@num@out@group@int@aux@i \csname si@num@in@#1@int\endcsname } \newcommand*{\si@num@out@group@int@aux@i}[1]{% \expandafter\si@num@out@group@int@aux@ii\expandafter {\expandafter}#1{}{}{}% } \newcommand*{\si@num@out@group@int@aux@ii}[4]{% \si@empty@tlist@if@TF{#2}{% \si@num@out@group@int@aux@iii#1\si@stop }{% \si@empty@tlist@if@TF{#3}{% \si@num@out@group@int@aux@iii{}{}#1#2\si@stop }{% \si@empty@tlist@if@TF{#4}{% \si@num@out@group@int@aux@iii{}#1#2#3\si@stop }{% \si@num@out@group@int@aux@ii{#1#2#3#4}% }% }% }% } \newcommand*{\si@num@out@group@int@aux@iii}{} % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@out@init} %\begin{macro}{\si@num@out@init@aux} % Clear out the storage for printing. % \begin{macrocode} \newcommand*{\si@num@out@init}{% \si@loop@over@macro\si@num@in@init@names\si@num@out@init@aux \si@clear@macro\si@num@out@result \si@bool@false\si@num@out@mant@parts@bool \si@bool@false\si@num@out@mant@comp@parts@bool \si@bool@false\si@num@out@exp@parts@bool \si@bool@false\si@num@out@exp@comp@parts@bool \si@bool@false\si@num@out@mant@comp@bool \si@bool@false\si@num@out@exp@comp@bool } \newcommand*{\si@num@out@init@aux}[1]{% \si@clear@cs{si@num@out@#1}% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@out@sign} %\begin{macro}{\si@num@out@sign@aux} % Some simple sign manipulation: for tight signs, a little shuffling. % \begin{macrocode} \newcommand*{\si@num@out@sign}[1]{% \si@bool@if@TF\si@num@out@tight@bool{% \si@let@Nc\si@tempa{si@num@in@#1@sign}% \expandafter\def\expandafter\si@tempa\expandafter {\expandafter{\si@tempa}}% \si@num@out@add@maths{#1@sign}\si@tempa }{% \si@num@out@copy@maths{#1@sign}% }% \si@num@out@sign@aux@i{#1}% } \newcommand*{\si@num@out@sign@aux@i}[1]{% \expandafter\si@num@out@sign@aux@ii \csname si@num@out@#1@sign\endcsname{si@num@out@#1}% } \newcommand*{\si@num@out@sign@aux@ii}[2]{% \si@add@left@cs@O{#2}{#1}% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@num@out@uncert} % Uncertainty output varies depending on whether there is a need to % separate the error form the number in the output. % \begin{macrocode} \newcommand*{\si@num@out@uncert}[1]{% \si@bool@if@TF\si@num@out@uncert@sep@bool{% \si@bool@cs@true{si@num@out@#1@parts@bool}% \si@num@out@group@digits{#1@uncert}% \si@num@out@add@pm{#1}% \si@num@out@add@C{#1}{#1@uncert}% }{% \si@num@out@add@maths{#1@uncert}{\si@num@out@uncert@open}% \si@num@out@copy{#1@uncert}% \si@num@out@add@maths{#1@uncert}{\si@num@out@uncert@close}% \si@num@out@add@maths{#1}{\si@num@out@uncert@space}% \si@num@out@add@C{#1}{#1@uncert}% }% } % \end{macrocode} %\end{macro} % %\subsection{Wrapper number macros} % % The \cs{num} macro needs some support macros to handle looping over % products and to handle quotients. % %\begin{macro}{\si@num@print} % \begin{macrocode} \newcommand*{\si@num@print}{% \expandafter\si@print@num\expandafter{\si@num@out@result}% TEMP } % \end{macrocode} %\end{macro} % %\subsection{Setting up tables} % % The \texttt{s} and \texttt{S} column types are both created using % the \module{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 \module{siunitx} % columns have to be listed first, as otherwise the optional % arguments do not work correctly. So they are added ``by hand'' to % the appropriate macro.\footnote{\cs{NC@list} is a toks, not a macro.} % \begin{macrocode} \edef\si@tempa{% \noexpand\NC@do S% \noexpand\NC@do s% \the\NC@list } \newcolumntype{S}{} \newcolumntype{s}{} \NC@list\expandafter{\si@tempa} % \end{macrocode} %\begin{macro}{\si@tab@rewrite@create} %\begin{macro}{\si@tab@rewrite@init} % There is now a slight problem with the \module{cellspace} package: % it also uses \texttt{S} for a column type Here, \texttt{S} seems to % make more sense for \module{siunitx}, with \texttt{C} used for % module{cellspace}. To enable this to work well, the column % rewriting code happens \cs{AtBeginDocument}. Note that \module{array} % uses \cs{@temptokena} to store the list of primitive columns. % \begin{macrocode} \newcommand*{\si@tab@rewrite@create}[1]{% \expandafter\renewcommand\expandafter*\expandafter{% \csname NC@rewrite@#1\endcsname }[1][]{% \edef\si@tempa{% \the\@temptokena >{\noexpand\si@tab@collect@begin[\unexpanded{##1}]{#1}}% c% <{\noexpand\si@tab@print@out}% }% \@temptokena\expandafter{\si@tempa}% \NC@find }% } \AtBeginDocument{% \si@tab@rewrite@create{s}% \si@tab@rewrite@create{S}% \@ifpackageloaded{cellspace}{% \newcolumntype{C}[1]{% >{\bcolumn #1\@nil}#1<{\ecolumn}% }% }{}% } % \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}{\si@tab@collect@after} %\begin{macro}{\si@tab@collect@before} %\begin{macro}{\si@tab@collect@body} % Three storage areas. % \begin{macrocode} \newcommand*{\si@tab@collect@after}{} \newcommand*{\si@tab@collect@before}{} \newcommand*{\si@tab@collect@body}{} % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\si@tab@collect@num} % To store the list of what is valid in a number. % \begin{macrocode} \newcommand*{\si@tab@collect@num}{} % \end{macrocode} %\end{macro} %\begin{macro}{\si@tab@collect@after@bool} %\begin{macro}{\si@tab@collect@before@bool} % Flags for having found a number in an \texttt{S} column. % \begin{macrocode} \si@bool@new\si@tab@collect@after@bool \si@bool@new\si@tab@collect@before@bool % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@tab@collect@begin} %\begin{macro}{\si@tab@collect@begin@s} %\begin{macro}{\si@tab@collect@begin@S} %\begin{macro}{\si@tab@collect@braced} % The collector starts by setting up local options, then clears and % initialises the storage and testing system. % \begin{macrocode} \newcommand*{\si@tab@collect@begin}[2][]{% \begingroup \pgfqkeys{/siunitx}{#1}% \def\si@tab@collect@body{}% \@nameuse{si@tab@collect@begin@#2}% \si@tab@collect@get } \newcommand*{\si@tab@collect@begin@s}{% \si@bool@false\si@tab@collect@before@bool \let\si@tab@collect@token\si@tab@collect@token@s \let\si@tab@print@out\si@tab@print@out@s \def\si@tab@collect@braced##1{% \si@add@right@N\si@tab@collect@body{{##1}}% \si@tab@collect@next }% } \newcommand*{\si@tab@collect@begin@S}{% \def\si@tab@collect@after{}% \def\si@tab@collect@before{}% \si@bool@true\si@tab@collect@before@bool \let\si@tab@collect@token\si@tab@collect@token@S \let\si@tab@print@out\si@tab@print@out@S \si@expand@tlist\si@tab@collect@num{% \si@num@in@ignore \si@num@in@signs \si@num@in@digits \si@num@in@decimal \si@num@in@exponent \si@num@in@complex \si@num@in@symbols \si@num@in@uncert@open \si@num@in@uncert@close }% \def\si@tab@collect@braced##1{% \si@bool@if@TF\si@tab@collect@before@bool{% \si@add@right@N\si@tab@collect@before{##1}% }{% \si@bool@false\si@tab@collect@before@bool \si@bool@true\si@tab@collect@after@bool \si@add@right@N\si@tab@collect@after{##1}% }% \si@tab@collect@next }% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % For items in braces, direct addition to the appropriate store can % occur. The definitions are column-type dependent, so occur in the % appropriate \texttt{begin} function. % \begin{macrocode} \newcommand*{\si@tab@collect@braced}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\si@tab@collect@expand} %\begin{macro}{\si@tab@collect@expand@aux@i} %\begin{macro}{\si@tab@collect@expand@aux@ii} % The idea here is to expand content if possible. There are a few % things to note. Only macros which are not \cs{long} or \cs{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 % Table~\ref{tab:xmpl:calc} in the user part of the documentation. % \begin{macrocode} \newcommand*{\si@tab@collect@expand}[1]{% \edef\si@tempa{% \expandafter\si@tab@collect@expand@aux@i\meaning#1:->\si@stop }% \si@meaning@eq@if@TF\si@tempa\si@tab@collect@expand@aux@ii{% \si@tab@collect@before \def\si@tab@collect@before{}% \expandafter\def\expandafter\si@tab@collect@next\expandafter{% \expandafter\si@tab@collect@get#1% }% }{% \si@bool@if@TF\si@tab@collect@before@bool{% \si@add@right@N\si@tab@collect@before{#1}% }{% \si@bool@true\si@tab@collect@after@bool \si@bool@false\si@tab@collect@before@bool \si@add@right@N\si@tab@collect@after{#1}% }% }% } \newcommand*{\si@tab@collect@expand@aux@i}{} \def\si@tab@collect@expand@aux@i#1:->#2\si@stop{#1} \newcommand*{\si@tab@collect@expand@aux@ii}{} \edef\si@tab@collect@expand@aux@ii{% \expandafter\si@tab@collect@expand@aux@i\meaning \si@tab@collect@expand@aux@ii:->\si@stop }% % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@tab@collect@get} %\begin{macro}{\si@tab@collect@get@aux} % 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} \newcommand*{\si@tab@collect@get}{% \let\si@tab@collect@next\si@tab@collect@get \futurelet\si@tempa\si@tab@collect@get@aux } \newcommand*{\si@tab@collect@get@aux}{% \si@meaning@eq@if@TF\si@tempa\bgroup{% \si@tab@collect@braced }{% \si@tab@collect@unbraced }% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si@tab@collect@newline} % The end macro needs to come before the new line is called. % \begin{macrocode} \newcommand*{\si@tab@collect@newline}{% \si@tab@print@out \tabularnewline } % \end{macrocode} %\end{macro} % %\begin{macro}{\si@tab@collect@next} % The tail recursion system is initialised. % \begin{macrocode} \newcommand*{\si@tab@collect@next}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\si@tab@collect@token} %\begin{macro}{\si@tab@collect@token@s} %\begin{macro}{\si@tab@collect@token@S} % For the \texttt{s} column, every token is added to the same storage % area, so life is simple. % \begin{macrocode} \newcommand*{\si@tab@collect@token}{} \newcommand*{\si@tab@collect@token@s}[1]{% \si@add@right@N\si@tab@collect@body{#1}% } % \end{macrocode} % 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} \newcommand*{\si@tab@collect@token@S}[1]{% \si@bool@if@TF\si@tab@collect@after@bool{% \si@add@right@N\si@tab@collect@after{#1}% }{% \si@in@if@TF\si@tab@collect@num{#1}{% \si@bool@false\si@tab@collect@before@bool \si@add@right@N\si@tab@collect@body{#1}% }{% \si@tab@collect@expand{#1}% }% }% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\si@tab@collect@unbraced} %\begin{macro}{\si@tab@collect@unbraced@aux} % A few macros are simply passed through to be executed; this is mainly % so that the table actually works. % \begin{macrocode} \newcommand*{\si@tab@collect@unbraced}[1]{% \si@meaning@eq@if@F{#1}\ignorespaces{% \si@meaning@eq@if@F{#1}\unskip{% \si@tab@collect@unbraced@aux{#1}% }% }% \si@tab@collect@next } \newcommand*{\si@tab@collect@unbraced@aux}[1]{% \def\si@tempa##1{% \si@meaning@eq@if@T{#1}##1{% \let\si@tab@collect@next##1% }% }% \si@tempa\csname \si@tempa\end \si@tempa\endtabular \si@tempa\si@tab@print@out \si@tempa\relax % \end{macrocode} % The newline function needs its own macro, which is picked up by hand. % \begin{macrocode} \si@meaning@eq@if@T\si@tab@collect@next\si@tab@collect@get{% \si@meaning@eq@if@TF{#1}\tabularnewline{% \let\si@tab@collect@next\si@tab@collect@newline }{% \si@tab@collect@token{#1}% }% }% } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Printing tables} % % The second part of creating tables is to print the results. Here, the % various alignment methods are implemented. % % \begin{macrocode} \si@keys@family{tables} \pgfkeys{ /siunitx/tables, align exponents/.is siunitx switch = {}, align uncertainties/.is siunitx switch = {}, number position/.is choice, number position/.cd, center/.code = {}, centre/.code = {}, decimal centred/.code = {}, decimal centered/.code = {}, left/.code = {}, right/.code = {}, /siunitx/tables, number format/.code = {}, position/.is choice, position/.cd, center/.style = { /siunitx/tables/number position = center, /siunitx/tables/text position = center, /siunitx/tables/unit position = center, }, centre/.style = { /siunitx/tables/number position = centre, /siunitx/tables/text position = centre, /siunitx/tables/unit position = centre, }, left/.style = { /siunitx/tables/number position = left, /siunitx/tables/text position = left, /siunitx/tables/unit position = left, }, right/.style = { /siunitx/tables/number position = right, /siunitx/tables/text position = right, /siunitx/tables/unit position = right, }, /siunitx/tables, text position/.is choice, text position/.cd, center/.code = {}, centre/.code = {}, none/.code = {}, left/.code = {}, right/.code = {}, /siunitx/tables, unit position/.is choice, unit position/.cd, center/.code = {}, centre/.code = {}, none/.code = {}, left/.code = {}, right/.code = {}, /siunitx/tables, number position = centre, text position = centre, unit position = centre } % \end{macrocode} % %\begin{macro}{\si@tab@print@out} %\begin{macro}{\si@tab@print@out@s} %\begin{macro}{\si@tab@print@out@S} % \begin{macrocode} \newcommand*{\si@tab@print@out}{} \newcommand*{\si@tab@print@out@s}{% \si@tab@collect@body \endgroup } \newcommand*{\si@tab@print@out@S}{% \si@tab@collect@before \si@tab@collect@body \si@tab@collect@after \endgroup } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\subsection{User macros} % % The user macros are all collected together here for ease: all of them % are \cs{protected}. % %\begin{macro}{\sisetup} % The set up macro simply moves to the correct path and executes % whatever has been passed. % \begin{macrocode} \newcommand*{\sisetup}{} \protected\def\sisetup#1{% \pgfqkeys{/siunitx}{#1}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\num} % \begin{macrocode} \si@newcommand{\num}{2}{% \begingroup \sisetup{#1}% \si@num@pre@process{#2}% \si@bool@if@F\si@num@pre@error@bool{% \si@num@in@parse@O{\si@num@pre@arg}% \si@num@post@process \si@num@out@process \si@num@print }% \endgroup } % \end{macrocode} %\end{macro} % %\begin{macro}{\SI} % \begin{macrocode} \si@newcommand{\SI}{3}{% TEMP \begingroup \sisetup{#1}% \num{#2}% \endgroup } % \end{macrocode} %\end{macro} % %\subsection{Finalisation} % % All done: any odd category codes can be restored. % \begin{macrocode} \si@catcode@restore % % \end{macrocode} % %\Finale