% \iffalse meta-comment % !TeX program = pdfLaTeX %<*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. % %<*internal> \fi \def\nameofplainTeX{plain} \ifx\fmtname\nameofplainTeX\else \expandafter\begingroup \fi % %<*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}} } \ifx\fmtname\nameofplainTeX \expandafter\endbatchfile \else \expandafter\endgroup \fi % %<*driver|package> \RequirePackage{expl3} \GetIdInfo$Id: siunitx.dtx 182 2009-11-23 06:58:25Z josephwright $ {A comprehensive (SI) units package} % %<*driver> %\fi \ProvidesFile{\filename.\filenameext} [\filedate\space v\fileversion\space\filedescription] %\iffalse \documentclass[full]{l3doc} \usepackage{booktabs,caption,csquotes,helvet,siunitx} \usepackage[final]{listings} \usepackage[osf]{mathpazo} \DeclareSIPower\quartic{4} \DeclareSIPower*\tothefourth{4} \DeclareSIQualifier\polymer{pol} \DeclareSIQualifier\catalyst{cat} \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % %\makeatletter % %^^A Some short cuts for the tables %\newcommand*\DescribePrefix[1]{^^A % \expandafter\SpecialUsageIndex\expandafter{\csname #1\endcsname} ^^A % #1 & \cs{#1} %} %\newcommand*\DescribeUnit[1]{^^A % \expandafter\SpecialUsageIndex\expandafter{\csname #1\endcsname} ^^A % #1 & % \cs{#1} & % \expandafter\si\expandafter{\csname #1\endcsname} %} % %^^A For creating examples with nice highlighting of code, and so %^^A on; based on the system used in the listings source (lstsample). %\lst@RequireAspects{writefile} %\newsavebox{\LaTeXdemo@box} %\lstnewenvironment{LaTeXdemo}[1][code and example] % {^^A % \global\let\lst@intname\@empty % \expandafter\let\expandafter\LaTeXdemo@end % \csname LaTeXdemo@#1@end\endcsname % \@nameuse{LaTeXdemo@#1}^^A % } % {\LaTeXdemo@end} %\newcommand*\LaTeXdemo@new[3]{^^A % \expandafter\newcommand\expandafter*\expandafter % {\csname LaTeXdemo@#1\endcsname}{#2}^^A % \expandafter\newcommand\expandafter*\expandafter % {\csname LaTeXdemo@#1@end\endcsname}{#3}^^A %} %\newcommand*\LaTeXdemo@common{^^A % \setkeys{lst} % { % basicstyle = \small\ttfamily, % basewidth = 0.51em, % gobble = 3, % keywordstyle = \color{blue}, % language = [LaTeX]{TeX}, % moretexcs = % { % ampere, % candela, % centi, % color, % cubic, % degree, % DeclareSIPrefix, % DeclareSIPower, % DeclareSIQualifier, % DeclareSIUnit, % farad, % gram, % gray, % henry, % hour, % joule, % kelvin, % kibi, % kilo, % kilogram, % litre, % lumen, % lux, % mathnormal, % metre, % milli, % mole, % num, % numrange, % pascal, % per, % raiseto, % second, % si, % SI, % sievert, % SIrange, % sisetup, % SIUnitSymbolDegree, % square, % squared, % texorpdfstring, % text, % tothe, % volt % } % }^^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} % {\LaTeXdemo@common}{} % %^^A Turning of the marginpar warnings is a bit awkward. %^^A It is achieved by temporarily disabling \@latex@warning@no@line %\let\latex@addmarginpar\@addmarginpar %\let\latex@warning@no@line\@latex@warning@no@line %\def\@addmarginpar{^^A % \let\@latex@warning@no@line\@gobble % \latex@addmarginpar % \let\@latex@warning@no@line\latex@warning@no@line %} % %\providecommand*\opt[1]{\texttt{#1}} % %\makeatother % %\GetIdInfo $Id: siunitx.dtx 182 2009-11-23 06:58:25Z josephwright $ % {A comprehensive (SI) units package} % %\title{^^A % \textsf{siunitx} --- A comprehensive (SI) units package\thanks{^^A % This file describes version v2.0 snapshot 3, last revised % \filedate\ (revision \fileversion).^^A % }^^A %} %\author{^^A % Joseph Wright\thanks{E-mail: joseph.wright@morningstar2.co.uk}^^A %} %\date{Released \filedate} % %\maketitle % %\changes{v0.6}{2008/02/18}{First public testing release (as \pkg{si})} %\changes{v1.0}{2008/06/15}{First official release} %\changes{v1.1}{2008/09/28}{Package extended to a greater range of unit % types} %\changes{v1.2}{2009/01/22}{Correct handling for ranges of numbers % added} %\changes{v1.3}{2009/09/20}{Better definition for micro symbol} %\changes{v2.0}{2009/11/22}{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 \pkg{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. %\end{abstract} %\tableofcontents % %\begin{documentation} % %\section{Introduction} % % The correct application of units of measurement is very important % in technical applications. For this reason, carefully-crafted % definitions of a coherent units system have been laid down by the % \emph{Conf\'erence G\'en\'erale des Poids et % Mesures} (CGPM): this has resulted in the \emph{Syst\`eme % International d'Unit\'es} (SI). At the same time, typographic % conventions for correctly displaying both numbers and units exist to % ensure that no loss of meaning occurs in printed matter. % % \pkg{siunitx} aims to provide a unified method for \LaTeX\ users to % typeset units and values correctly and easily. The design % philosophy of \pkg{siunitx} is to follow the agreed rules by % default, but to allow variation through option settings. In this way, % users can use \pkg{siunitx} to follow the requirements of % publishers, co-authors, universities, \emph{etc}.~without needing to % alter the input at all. % %\section{Installation} % % The package is supplied in \file{dtx} format and as a pre-extracted % zip file, \file{\jobname.tds.zip}. The later is most convenient for % most users: simply unzip this in your local texmf directory and % run \texttt{texhash} to update the database of file locations. If % you want to unpack the \file{dtx} yourself, running % \texttt{tex \jobname.dtx} will extract the package whereas % \texttt{latex \jobname.dtx} will extract it and also typeset the % documentation. % % The package requires \LaTeX3 support as provided in the % \pkg{expl3} and \pkg{xpackages} bundles. Both of these are available % on \href{http://www.ctan.org}{\textsc{ctan}} as ready-to-install % zip files. Suitable versions are available in MiK\TeX\ 2.8 and % \TeX\ Live 2009 (updating the relevant packages online may be % necessary). \LaTeX3, and so \pkg{siunitx}, requires the \eTeX\ % extensions: these are available on all modern \TeX\ systems. % %\section{\pkg{siunitx} for the impatient} % % The package provides the user macros: %\begin{itemize} % \item \cs{num}\oarg{options}\marg{number} % \item \cs{si}\oarg{options}\marg{unit} % \item \cs{SI}\oarg{options}\marg{value}\oarg{pre-unit}\marg{unit} % \item \cs{numrange}\oarg{options}\marg{number}\marg{number} % \item \cs{SIrange}\oarg{options}\marg{number}\marg{number}\marg{unit} % \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. % % Numbers are processed with understanding of exponents, complex numbers % and multiplication. %\begin{LaTeXdemo} % \num{12345,67890} \\ % \num{1+-2i} \\ % \num{.3e45} \\ % \num{1.654 x 2.34 x 3.430} %\end{LaTeXdemo} % % The unit system can interpret units given as text to be used directly % or as macro-based units. In the later case, different formatting is % possible. %\begin{LaTeXdemo} % \si{kg.m.s^{-1}} \\ % \si{\kilogram\metre\per\second} \\ % \si[per-mode=symbol] % {\kilogram\metre\per\second} %\end{LaTeXdemo} % % Simple ranges of numbers can be handled. %\begin{LaTeXdemo} % \numrange{10}{20} \\ % \SIrange{0.13}{0.67}{\milli\metre} %\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{detect-all}| will use the current font for typesetting. % %\section{Using the \pkg{siunitx} package} % %\subsection{Loading the package} % % The package should be loaded in the usual \LaTeXe\ way. %\begin{LaTeXdemo}[code only] % \usepackage{siunitx} %\end{LaTeXdemo} % %\subsection{Numbers} % %\DescribeMacro \num %\begin{syntax} % \cs{num}\oarg{options}\marg{number} %\end{syntax} % Numbers are automatically formatted by the \cs{num} macro. This % takes one optional argument, \meta{options}, and one mandatory one, % \meta{number}. The contents of \meta{number} are automatically % formatted. The formatter removes \enquote{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 \enquote{\texttt{.}} and \enquote{\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} % %\DescribeMacro \numrange %\begin{syntax} % \cs{numrange}\oarg{options}\marg{number1}\marg{number2} %\end{syntax} % Simple ranges of numbers can be handled using the \cs{numrange} % function. This acts in the same way as \cs{num}, but inserts a % phrase or other text between the two entries. This function will not % accept multi-part numbers. %\begin{LaTeXdemo} % \numrange{10}{30} %\end{LaTeXdemo} % %\subsection{Units} % %\DescribeMacro \si %\begin{syntax} % \cs{si}\oarg{options}\marg{unit} %\end{syntax} % The symbol for a unit can be typeset using the \cs{si} macro: this % provides full control over output format for the unit. Like the % \cs{num} macro, \cs{si} takes one optional and one mandatory % argument. The unit formatting system can accept two types of input. % When \meta{unit} contains one or more literal items, the output is % processed in the same manner as with the \pkg{sistyle} package. Sub- % and superscripts can be input without concern over maths mode, and % the tokens \texttt{.} and |~| are converted into inter-unit % separators. %\begin{LaTeXdemo} % \si{kg.m/s^2} \\ % \si{g_{polymer}~mol_{cat}.s^{-1}} %\end{LaTeXdemo} % The second operation mode for the \cs{si} macro is an % \enquote{interpreted} system, Here, each unit, SI multiple prefix and % power is given a macro name. These are entered in a method very % similar to the reading of the unit name in English. %\begin{LaTeXdemo} % \si{\kilo\gram\metre\per\square\second} \\ % \si{\gram\per\cubic\centi\metre} \\ % \si{\square\volt\cubic\lumen\per\farad} \\ % \si{\metre\squared\per\gray\cubic\lux} \\ % \si{\henry\second} %\end{LaTeXdemo} % On its own, this is less convenient than the direct method, although % it does use meaning rather than appearance for input. However, the % the package allows you to define new unit macros; a large number of % pre-defined abbreviations are also supplied. More importantly, by % defining macros for units, instead of literal values, new % functionality is made available. Units may be re-defined to give % different output, and handling of reciprocal values can be altered. % %\DescribeMacro \SI %\begin{syntax} % \cs{SI}\oarg{options}\marg{number}\oarg{preunit}\marg{unit} %\end{syntax} % Very often, numbers and values are given together. Mathematically, % these form a single entity, and should be separated by a non-breaking % space. The \cs{SI} macro combines the functionality of \cs{num} and % \cs{si}, and makes this both possible and easy. The \meta{number} and % \meta{unit} arguments work exactly like those for the \cs{num} and % \cs{si} macros, respectively. \meta{preunit} is a unit to be typeset % \emph{before} the numerical value (most likely to be a currency). %\begin{LaTeXdemo} % \SI[mode=text]{1.23}{J.mol^{-1}.K^{-1}} \\ % \SI{.23e7}{\candela} \\ % \SI[per-mode=symbol]{1.99}[\$]{\per\kilogram} \\ % \SI{70}{\metre\per\second} \\ % \SI[per-mode=fraction]{1,345}{\ampere\per\mole} %\end{LaTeXdemo} % % It is possible set up the unit macros to be available outside of % the \cs{SI} and \cs{si} functions. This is not the standard behaviour % as there is the risk of name clashes (for example, \cs{bar} is used % by other packages, and several packages define \cs{degree}). Full % details of using \enquote{stand alone} units are found in % Section~\ref{sec:units:creating}. % %\subsection{The unit macros} % % The package always defines the basic set of SI units with macro names. % This includes the base SI units, the derived units with special names % and the prefixes. A small number of powers are also given pre-defined % names. Full details of units in the SI are available % on-line~\cite{BIPM}. % %\DescribeMacro \meter % The seven base SI units are always defined % (Table~\ref{tab:unit:base}). In addition, the macro \cs{meter} is % available as an alias for \cs{metre}, for users of US spellings. % The full details of the base units are given in the SI % Brochure~\cite{SI:2.1}. The SI also lists a number of units which % have special names and symbols \cite{SI:2.2.2}: these are listed % in Table~\ref{tab:unit:derived}. %\begin{table} % \caption{SI base units} % \label{tab:unit:base} % \centering % \begin{tabular}{lll} % \toprule % \multicolumn{1}{c}{Unit} & % \multicolumn{1}{c}{Macro} & % \multicolumn{1}{c}{Symbol} \\ % \midrule % \DescribeUnit{ampere} \\ % \DescribeUnit{candela} \\ % \DescribeUnit{kelvin} \\ % \DescribeUnit{kilogram} \\ % \DescribeUnit{metre} \\ % \DescribeUnit{mole} \\ % \DescribeUnit{second} \\ % \bottomrule % \end{tabular} %\end{table} % %\begin{table} % \caption{Coherent derived units in the SI with special names and % symbols} % \label{tab:unit:derived} % \centering % \begin{tabular}{llllll} % \toprule % \multicolumn{1}{c}{Unit} & % \multicolumn{1}{c}{Macro} & % \multicolumn{1}{c}{Symbol} & % \multicolumn{1}{c}{Unit} & % \multicolumn{1}{c}{Macro} & % \multicolumn{1}{c}{Symbol} \\ % \midrule % \DescribeUnit{becquerel} & % \DescribeUnit{newton} \\ % \SpecialUsageIndex{\degreeCelsius}^^A % degree Celsius & \cs{degreeCelsius} & \si{\degreeCelsius} & % \DescribeUnit{ohm} \\ % \DescribeUnit{coulomb} & % \DescribeUnit{pascal} \\ % \DescribeUnit{farad} & % \DescribeUnit{radian} \\ % \DescribeUnit{gray} & % \DescribeUnit{siemens} \\ % \DescribeUnit{hertz} & % \DescribeUnit{sievert} \\ % \DescribeUnit{henry} & % \DescribeUnit{steradian} \\ % \DescribeUnit{joule} & % \DescribeUnit{tesla} \\ % \DescribeUnit{katal} & % \DescribeUnit{volt} \\ % \DescribeUnit{lumen} & % \DescribeUnit{watt} \\ % \DescribeUnit{lux} & % \DescribeUnit{weber} \\ % \bottomrule % \end{tabular} %\end{table} % % In addition to the official SI units, \pkg{siunitx} also provides % macros for a number of units which are accepted for use in the SI % although they are not SI units. Table~\ref{tab:unit:accepted} lists % the \enquote{accepted} units \cite{SI:4.1.T6}. Some units are % fundamental physical quantities, and these are non-SI but can be used % with in the SI (Table~\ref{tab:unit:physical}, \cite{SI:4.1.T7}). % There are also a set of non-SI units which are used in certain % defined circumstances (Table~\ref{tab:unit:other}), although they are % not necessarily official sanctioned \cite{SI:4.1.T8}. %\begin{table} % \caption{Non-SI units accepted for use with the % International System of Units} % \label{tab:unit:accepted} % \centering % \begin{tabular}{lll} % \toprule % \multicolumn{1}{c}{Unit} & % \multicolumn{1}{c}{Macro} & % \multicolumn{1}{c}{Symbol} \\ % \midrule % \DescribeUnit{day} \\ % \DescribeUnit{degree} \\ % \DescribeUnit{hectare} \\ % \DescribeUnit{hour} \\ % \DescribeUnit{litre} \\ % \SpecialUsageIndex{\liter}^^A % & \cs{liter} & \si{\liter} \\ % \SpecialUsageIndex{\arcminute}^^A % minute (plane angle) & \cs{arcminute} & \si{\arcminute} \\ % \SpecialUsageIndex{\minute}^^A % minute (time) & \cs{minute} & \si{\minute} \\ % \DescribeUnit{percent} \\ % \SpecialUsageIndex{\arcsecond}^^A % second (plane angle) & \cs{arcsecond} & \si{\arcsecond} \\ % \DescribeUnit{tonne} \\ % \bottomrule % \end{tabular} %\end{table} %\begin{table} % \caption{Non-SI units whose values in SI units must be obtained % experimentally} % \label{tab:unit:physical} % \centering % \begin{tabular}{lll} % \toprule % \multicolumn{1}{c}{Unit} & % \multicolumn{1}{c}{Macro} & % \multicolumn{1}{c}{Symbol} \\ % \midrule % \SpecialUsageIndex{\astronomicalunit}^^A % astronomical unit & \cs{astronomicalunit} % & \si{\astronomicalunit} \\ % \SpecialUsageIndex{\atomicmassunit}^^A % atomic mass unit & \cs{atomicmassunit} & % \si{\atomicmassunit} \\ % \DescribeUnit{bohr} \\ % \SpecialUsageIndex{\clight}^^A % speed of light & \cs{clight} & \si{\clight} \\ % \DescribeUnit{dalton} \\ % \SpecialUsageIndex{\electronmass}^^A % electron mass & \cs{electronmass} & \si{\electronmass} \\ % \DescribeUnit{electronvolt} \\ % \SpecialUsageIndex{\elementarycharge}^^A % elementary charge & \cs{elementarycharge} % & \si{\elementarycharge} \\ % \DescribeUnit{hartree} \\ % \SpecialUsageIndex{\planckbar}^^A % reduced Planck constant & \cs{planckbar} & \si{\planckbar} \\ % \bottomrule % \end{tabular} %\end{table} %\begin{table} % \caption{Other non-SI units} % \label{tab:unit:other} % \centering % \begin{tabular}{lll} % \toprule % \multicolumn{1}{c}{Unit} & % \multicolumn{1}{c}{Macro} & % \multicolumn{1}{c}{Symbol} \\ % \midrule % \SpecialUsageIndex{\angstrom}^^A % {\aa}ngstr{\"o}m & \cs{angstrom} & \si{\angstrom} \\ % \DescribeUnit{bar} \\ % \DescribeUnit{barn} \\ % \DescribeUnit{bel} \\ % \DescribeUnit{decibel} \\ % \DescribeUnit{knot} \\ % \SpecialUsageIndex{\mmHg}^^A % millimetre of mercury & \cs{mmHg} & \si{\mmHg} \\ % \SpecialUsageIndex{\nauticalmile}^^A % nautical mile & \cs{nauticalmile} & \si{\nauticalmile} \\ % \DescribeUnit{neper} \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeMacro \deka % In addition to the units themselves, \pkg{siunitx} provides % pre-defined macros for all of the SI prefixes % (Table~\ref{tab:unit:prefix}, \cite{SI:3.1}). The spelling % \enquote{\cs{deka}} is provided for US users as an alternative to % \cs{deca}. %\begin{table} % \caption{SI prefixes} % \label{tab:unit:prefix} % \centering % \begin{tabular}{llc>{$}l<{$}llc>{$}l<{$}} % \toprule % \multicolumn{1}{c}{Prefix} & % \multicolumn{1}{c}{Macro} & % \multicolumn{1}{c}{Symbol} & % \multicolumn{1}{c}{Power} & % \multicolumn{1}{c}{Prefix} & % \multicolumn{1}{c}{Macro} & % \multicolumn{1}{c}{Symbol} & % \multicolumn{1}{c}{Power} \\ % \midrule % \DescribePrefix{yocto} & y & -24 & % \DescribePrefix{deca} & da & 1 \\ % \DescribePrefix{zepto} & z & -21 & % \DescribePrefix{hecto} & h & 2 \\ % \DescribePrefix{atto} & a & -18 & % \DescribePrefix{kilo} & k & 3 \\ % \DescribePrefix{femto} & f & -15 & % \DescribePrefix{mega} & M & 6 \\ % \DescribePrefix{pico} & p & -12 & % \DescribePrefix{giga} & G & 9 \\ % \DescribePrefix{nano} & n & -9 & % \DescribePrefix{tera} & T & 12 \\ % \DescribePrefix{micro} & \SIUnitSymbolMicro & -6 & % \DescribePrefix{peta} & P & 15 \\ % \DescribePrefix{milli} & m & -3 & % \DescribePrefix{exa} & E & 18 \\ % \DescribePrefix{centi} & c & -2 & % \DescribePrefix{zetta} & Z & 21 \\ % \DescribePrefix{deci} & d & -1 & % \DescribePrefix{yotta} & Y & 24 \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeMacro \square %\DescribeMacro \squared %\DescribeMacro \cubic %\DescribeMacro \cubed % A small number of pre-defined powers are provided as macros. % \cs{square} and \cs{cubic} are intended for use before units, with % \cs{squared} and \cs{cubed} going after the unit. %\begin{LaTeXdemo} % \si{\square\becquerel} \\ % \si{\joule\squared\per\lumen} \\ % \si{\cubic\lux\volt\tesla\cubed} %\end{LaTeXdemo} %\DescribeMacro \tothe %\DescribeMacro \raiseto % Generic powers can be inserted on a one-off basis using the \cs{tothe} % and \cs{raiseto} macros. These are the only macros for units which % take an argument: %\begin{LaTeXdemo} % \si{\henry\tothe{5}} \\ % \si{\raiseto{4.5}\radian} %\end{LaTeXdemo} %\DescribeMacro \per % Reciprocal powers are indicated using the \cs{per} macro. This applies % to the next unit only, unless the \opt{sticky-per} option % is turned on. %\begin{LaTeXdemo} % \si{\joule\per\mole\per\kelvin} \\ % \si{\joule\per\mole\kelvin} \\ % \si{\per\henry\tothe{5}} \\ % \si{\per\square\becquerel} %\end{LaTeXdemo} % %\subsection{Creating new macros} % % The various macro components of a unit have to be defined before % they can be used. The package supplies a number of common definitions, % but new definitions are also possible. As the definition of a logical % unit should remain the same in a single document, these creation % functions are all preamble-only. % %\DescribeMacro \DeclareSIUnit %\begin{syntax} % \cs{DeclareSIUnit}\oarg{options}\marg{unit}\marg{symbol} %\end{syntax} % New units are produced using the \cs{DeclareSIUnit} macro. % \meta{symbol} can contain literal values, other units, multiple % prefixes, powers and \cs{per}, although literal text should not be % intermixed with unit macros. The \meta{options} argument can be % any suitable options, and applies the specific unit macro only. The % (first) optional argument to \cs{SI} and \cs{si} can be used to % override the settings for the unit. A typical example is the % \cs{degree} unit. %\begin{LaTeXdemo} % \SI{3.1415}{\degree} %\end{LaTeXdemo} % This is declared in the package as: %\begin{LaTeXdemo}[code only] % \DeclareSIUnit[number-unit-separator={}] % \degree{\SIUnitSymbolDegree} %\end{LaTeXdemo} % The spacing can still be altered at point of use: %\begin{LaTeXdemo} % \SI{67890}{\degree} \\ % \SI[number-unit-separator = \;]{67890}{\degree} %\end{LaTeXdemo} % %\DescribeMacro \DeclareSIPrefix %\DescribeMacro {\DeclareSIPrefix*} %\begin{syntax} % \cs{DeclareSIPrefix}\marg{prefix}\marg{symbol}\marg{powers-ten} % \cs{DeclareSIPrefix*}\marg{prefix}\marg{symbol}\marg{powers-two} %\end{syntax} % The standard SI powers of ten are defined by the package, and are % described above. However, the user can define new prefixes with % \cs{DeclareSIPrefix}. A % starred-version is also available for creating binary prefixes, with % the same syntax (\meta{powers-ten} being replaced by % \meta{powers-two}). For example, \cs{kilo} and \cs{kibi} are defined: %\begin{LaTeXdemo}[code only] % \DeclareSIPrefix\kilo{k}{3} % \DeclareSIPrefix*\kibi{Ki}{10} %\end{LaTeXdemo} % %\DescribeMacro \DeclareSIPower %\DescribeMacro {\DeclareSIPower*} %\begin{syntax} % \cs{DeclareSIPower}\marg{power}\marg{num} % \cs{DeclareSIPower*}\marg{power}\marg{num} %\end{syntax} % This creates a % power macro to appear before the unit it applies to. A starred version % of the macro creates powers to appear after the unit. For example, the % preamble to a document might contain: %\begin{LaTeXdemo}[code only] % \DeclareSIPower\quartic{4} % \DeclareSIPower*\tothefourth{4} %\end{LaTeXdemo} % with the functions then used in the document as: %\begin{LaTeXdemo} % \si{\kilogram\tothefourth}\\ % \si{\quartic\metre} %\end{LaTeXdemo} % %\DescribeMacro{\DeclareSIQualifier} % Following the syntax of the other macros, qualifiers are created % with the syntax \cs{DeclareSIQualifier}\marg{qualifier}\marg{symbol}. % In contrast to the other parts of a unit, there are no pre-defined % qualifiers. It is therefore entirely up to the user to create these. % For example, to identify the mass of a product created when using % a particular catalyst, the preamble could contain: %\begin{LaTeXdemo}[code only] % \DeclareSIQualifier\polymer{pol} % \DeclareSIQualifier*\catalyst{cat} %\end{LaTeXdemo} % and then in the body the document could read: %\begin{LaTeXdemo} % \SI{1.234}{\gram\polymer\per\mole\catalyst\per\hour} %\end{LaTeXdemo} % %\section{The key--value control system} % %\DescribeMacro{\sisetup} % The behaviour of the \pkg{siunitx} package is controlled by a % number of key--value options. These can be given globally using % the \cs{sisetup} function or locally as the optional argument to the % user macros. % % The package uses a range of different key types: %\begin{description} % \item[\texttt{Choice}] Takes a limited number of choices, which % are described separately for each key. % \item[\texttt{Literal}] A key which uses the value(s) given directly, % either to check input (for example the \texttt{input-digits} key) % or in output. % \item[\texttt{Maths}] Similar to a \texttt{literal} option, but the % input is always used in maths mode, irrespective of other % \pkg{siunitx} settings. Thus to text-mode only input must be % placed inside the argument of a \cs{text} macro. % \item[\texttt{Macro}] Requires a macro, which may need a single % argument. % \item[\texttt{Switch}] These are on--off switches, and recognise % \opt{true} and \opt{false}. Giving just the key name also % turns the key on. %\end{description} % The tables of option names use these descriptions to indicate how the % keys should be used. % % In all cases, UK and US English spellings are available for both % option names and for settings. Thus \opt{centre} and % \opt{center} can be used for alignment options, and \opt{maths} % or \opt{math} is valid in the names of font options. In the rest of % this document, UK English spelling is used. % %\subsection{Detecting fonts} % % The \pkg{siunitx} package controls the font used to print output % independently of the surrounding material. The standard method is to % ignore the surroundings entirely, and to use the current 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 summarised in % Table~\ref{tab:opt:font:det}. %\begin{table} % \centering % \caption{Font detection options.} % \label{tab:opt:font:det} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule % detect-all & Meta & \meta{none} \\ % detect-bold & Switch & false \\ % detect-display-maths & Switch & false \\ % detect-family & Switch & false \\ % detect-inline-bold & Choice & text \\ % detect-italic & Switch & false \\ % detect-mode & Switch & false \\ % detect-none & Meta & \meta{none} \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{detect-bold} %\DescribeOption{detect-family} %\DescribeOption{detect-italic} %\DescribeOption{detect-mode} % The options \opt{detect-bold} and \opt{detect-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 \opt{detect-family} % setting, while the current mode (text or maths) is detected using the % \opt{detect-mode} switch. % %\DescribeOption{detect-inline-bold} % Bold detection is influenced by the value of \opt{detect-inline-bold}, % which takes values \opt{text} and \opt{maths}. The package % can detect the local value of bold for either the surrounding text, % or the surrounding inline (|$|\ldots|$|) maths. %\begin{LaTeXdemo} % \sisetup{ % detect-bold = true, % detect-inline-bold = maths % }% % $\num{1234}$ \\ % { \boldmath $\num{1234}$ } \\ % { \bfseries $\num{1234}$ } \\ % \sisetup{detect-inline-bold = text} % { \boldmath $\num{1234}$ } \\ % { \bfseries $\num{1234}$ } %\end{LaTeXdemo} % %\DescribeOption{detect-display-maths} % The font detection system can treat displayed mathematical content % in two ways. This is controlled by the \opt{detect-display-maths} % option. When set \opt{true}, 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 % \opt{false}, display material is treated with the current running % text font. %\begin{LaTeXdemo} % \sffamily % Some text % \sisetup{ % detect-all, % detect-display-maths = true % } % \[ x = \SI{1.2e3}{\kilogram\kelvin\candela} \] % More text % \sisetup{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. % %\begin{table} % \centering % \caption{^^A % Font options (also available as \opt{number-\ldots} and % \opt{unit-\ldots} versions). % } % \label{tab:opt:font:set} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule % colour & Literal & \meta{none} \\ % 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{mode} % The \opt{mode} option determines whether \pkg{siunitx} uses % maths or text mode when printing output. The choices are % \opt{maths}, \opt{math} and \opt{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 \opt{detect-mode} switch is % \opt{true}. % %\DescribeOption{maths-rm} %\DescribeOption{text-rm} %\DescribeOption{maths-sf} %\DescribeOption{maths-tt} %\DescribeOption{text-sf} %\DescribeOption{text-tt} % If font family detection is inactive, \pkg{siunitx} uses the font % family stored in either \opt{maths-rm} or \opt{text-rm} for % output. The choice of \opt{maths} or \opt{text} depends on the % \opt{mode} setting. If font family detection is active, % \pkg{siunitx} may be using a sans serif or monospaced font for % output. In maths mode, these are stored in \opt{maths-sf} and % \opt{maths-tt}, and for text mode in \opt{text-sf} and \opt{text-tt}. % Notice that the detected and output font families can differ. %\begin{LaTeXdemo} % \sisetup{detect-family}% % \num{1234} \\ % { \sffamily \num{1234} } \\ % \SI{99}{\metre} \\ % \sisetup{maths-rm = \mathtt}% % \SI{99}{\metre} %\end{LaTeXdemo} % This can be used to good effect to change all output from % \pkg{siunitx} without needing to detect the font. For example, % when creating \pkg{beamer} presentations the settings %\begin{LaTeXdemo}[code only] % \sisetup{ % maths-rm = \mathsf, % text-rm = \sffamily % } %\end{LaTeXdemo} % given all output in sans serif font without font detection. % %\DescribeOption{colour} % The colour of printed output can be set using the \opt{colour} % option. When no colour is given, printing follows the surrounding % text. In contrast, when a specific colour is given, it is used % irrespective of the surroundings. As there are a number of different % colour models available, it is left to to user to load \pkg{color} or % a more powerful colour package. %\begin{LaTeXdemo} % \color{red} % Some text \\ % \SI{4}{\metre\per\sievert} \\ % More text \\ % \SI[colour = blue]{4}{\metre\per\sievert} \\ % Still red here! %\end{LaTeXdemo} % % Every one of the font options can be given independently for units % and number, with the prefixes \opt{unit-} and \opt{number-}, % respectively. This allows fine control of output. % %\subsection{Parsing numbers} % % The package uses a sophisticated parsing system to understand % numbers. This allows \pkg{siunitx} to carry out a range of % formatting, as described later. All of the input options take lists of % literal tokens, and are summarised in Table~\ref{tab:opt:num:in}. % %\begin{table} % \centering % \caption{Options for number parsing} % \label{tab:opt:num:in} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule ^^A ( % input-close-uncertainty & Literal & ) \\ % input-complex-roots & Literal & ij \\ % input-decimal-markers & Literal & ., \\ % input-digits & Literal & 0123456789 \\ % input-exponent-markers & Literal & dDeE \\ % input-ignore & Literal & \meta{none} \\ % input-open-uncertainty & Literal & ( \\ ^^A ) % input-protect-tokens & Literal & \verb=\mp\pi\pm= \\ % input-signs & Literal & +-\cs{pm}\cs{mp} \\ % input-symbols & Literal & \cs{pi} \\ % parse-numbers & Switch & true \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{input-digits} %\DescribeOption{input-decimal-markers} %\DescribeOption{input-signs} %\DescribeOption{input-exponent-markers} % The basic parts of a number are the digits, any sign and a separator % between the integer and decimal parts. These are stored in the input % options \opt{input-digits}, \opt{input-decimal-markers} and % \opt{input-signs}, respectively. More than one input decimal marker % can be used: it will be converted by the package to the appropriate % output marker. Numbers which include an exponent part also require % a marker for the exponent: this again is taken from the range of % tokens in the \opt{exponent markers} option. % %\DescribeOption{input-ignore} %\DescribeOption{input-symbols} % As well as \enquote{normal} digits, the package will interpret % symbolic \enquote{numbers} (such as \cs{pi}) correctly if they are % included in the \opt{input-symbols} list. Tokens given in the % \opt{input-ignore} list are totally passed over by \pkg{siunitx}: % they will be removed from the input with no further processing. % %\DescribeOption{input-open-uncertainty} %\DescribeOption{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 % \enquote{\num{1.234(5)}}. The opening and closing symbols used for % this type of input are set as \opt{input-open-uncertainty} and % \opt{input-close-uncertainty}. % %\DescribeOption{input-complex-roots} % When using complex numbers in input, the complex root ($\sqrt{-1}$) is % indicated by one of the tokens stored in \opt{input-complex-roots}. % %\DescribeOption{input-protect-tokens} % Some symbols can be problematic under expansion in \LaTeXe. To allow % these to be used in input without issue, the package can protect these % tokens while expanding input. Symbols to be protected in this way % should be listed in \opt{input-protect-tokens}. % %\DescribeOption{parse-numbers} % The \opt{parse-numbers} option turns the entire parsing system on % and off. The option is made available for two reasons. First, if % all of the numbers in a document are to be reproduced \enquote{as % given}, turning off the parser will represent a significant saving in % processing required. Second, it allows the use of arbitrary \TeX\ % code in numbers. If the parser is turned off, it is the users % responsibility to control maths/text mode selection (although % |^| and |_| can safely be used to give superscripts and subscripts, % respectively, even in text mode). %\begin{LaTeXdemo} % \num[parse-numbers = false]{\sqrt{2}} \\ % \SI[parse-numbers = false]{\sqrt{3}}{\metre} %\end{LaTeXdemo} % %\subsection{Post-processing numbers} % % Before typesetting numbers, various post-processing steps can be % carried out. These involve adding or removing information from the % number in a systematic way; the options are summarised in % Table~\ref{tab:opt:num:post}. % %\begin{table} % \centering % \caption{Number post-processing options} % \label{tab:opt:num:post} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule % add-zero-decimal & Switch & false \\ % add-zero-integer & Switch & false \\ % explicit-sign & Literal & \m{none} \\ % retain-explicit-plus & Switch & false \\ % retain-unity-mantissa & Switch & true \\ % retain-zero-exponent & Switch & false \\ % round-mode & Choice & off \\ % round-figures & Number & 2 \\ % round-places & Number & 2 \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{round-mode} %\DescribeOption{round-figures} %\DescribeOption{round-places} % The \pkg{siunitx} package can round numerical input to a fixed % number of significant figures or decimal places. This is controlled by % the \opt{round-mode} option, which takes the choices \opt{off}, % \opt{figures} and \opt{places}. When rounding is turned on, the % number of figures to use is determined by the \opt{round-figures} % and \opt{round-places} option: both of these options require a % number. %\begin{LaTeXdemo} % \num{1.23456} \\ % \num{14.23} \\ % \sisetup{ % round-mode = places, % round-places = 3 % }% % \num{1.23456} \\ % \num{14.23} \\ % \sisetup{ % round-mode = figures, % round-figures = 3 % }% % \num{1.23456} \\ % \num{14.23} %\end{LaTeXdemo} % %\DescribeOption{add-zero-decimal} %\DescribeOption{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 \opt{add-zero-decimal} and % \opt{add-zero-integer} allow the package to \enquote{fill in} the % missing zero. %\begin{LaTeXdemo} % \num{123.} \\ % \num{.456} \\ % \sisetup{ % add-zero-decimal = false, % add-zero-integer = false, % }% % \num{123.} \\ % \num{.456} %\end{LaTeXdemo} % %\DescribeOption{explicit-sign} %\DescribeOption{retain-explicit-plus} % The inclusion of a leading plus sign is usually unnecessary for % positive numbers, and so the \opt{retain-explicit-plus} option is % available to control whether these are printed. As the same time, it % may be useful to force all numbers to have a sign. This behaviour % is controlled by the \opt{explicit-sign} option: this is used if % given and if no sign was present in the input. %\begin{LaTeXdemo} % \num{+345} \\ % \num[retain-explicit-plus]{+345} \\ % \num[explicit-sign = -]{345} %\end{LaTeXdemo} % %\DescribeOption{retain-unity-mantissa} %\DescribeOption{retain-zero-exponent} % The retention of a zero exponent is controlled by the % \opt{retain-zero-exponent} option. The retention of a mantissa of one % is likewise controlled by the \opt{retain-unity-mantissa} option. %\begin{LaTeXdemo} % \num{1e4} \\ % \num[retain-unity-mantissa = false]{1e4} \\ % \num{444e0} \\ % \num[retain-zero-exponent = true]{444e0} %\end{LaTeXdemo} % %\subsection{Printing numbers} % % Actually printing numbers is controlled by a number of settings, % which apply ideas such as differing decimal markers, digit % grouping and so on. All of these options are concerned with the % appearance of output, rather than the data it conveys. The options are % summarised in Table~\ref{tab:opt:num:out}. % %\begin{table} % \centering % \caption{Output options for numbers} % \label{tab:opt:num:out} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule ^^A ( % close-bracket & Literal & ) \\ % exponent-base & Literal & 10 \\ % exponent-product & Maths & \cs{times} \\ % group-decimal-digits & Switch & true \\ % group-digits & Switch & true \\ % group-four-digits & Switch & false \\ % group-integer-digits & Switch & true \\ % group-separator & Maths & \cs{,} \\ % negative-colour & Literal & \meta{none} \\ % open-bracket & Literal & ( \\ ^^A ) ( % output-close-uncertainty & Literal & ) \\ % output-complex-root & Maths & i \\ % output-decimal-marker & Maths & . \\ % output-open-uncertainty & Literal & ( \\ ^^A ) % range-phrase & Literal & \verb*= to = \\ % separate-uncertainty & Switch & false \\ % tight-spacing & Switch & false \\ % uncertainty-separator & Maths & \meta{none} \\ % use-brackets & Switch & true \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{group-digits} %\DescribeOption{group-decimal-digits} %\DescribeOption{group-integer-digits} %\DescribeOption{group-four-digits} %\DescribeOption{group-separator} % Grouping digits into blocks of three is a common method to increase % the ease of reading of numbers. The \opt{group-digits} choice % turns this behaviour on and off, with grouping for numbers of exactly % four digits controlled by the \opt{group-four-digits} choice. Note % that the later only applies if \opt{group-digits} is turned on. % The separator used between groups of digits is stored by the % \opt{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[group-digits = false]{12345} \\ % \num{1234} \\ % \num[group-four-digits = true]{1234} \\ % \num{12345} \\ % \num[group-separator = {{,}}]{12345} \\ % \num[group-separator = \text{~}]{12345} %\end{LaTeXdemo} % Grouping can be activated separately for the integer and decimal % parts of a number using the \opt{group-integer-digits} and % \opt{group-decimal-digits} options. %\begin{LaTeXdemo} % \sisetup{group-digits = false}% % \num{12345.67890} \\ % \num[group-decimal-digits]{12345.67890} \\ % \num[group-integer-digits]{12345.67890} %\end{LaTeXdemo} % %\DescribeOption{output-complex-root} %\DescribeOption{output-decimal-marker} % The decimal marker used in output is set using the % \opt{output-decimal-marker} option. This can differ from the input % marker, as can the root of $\sqrt{-1}$, which is stored in the % \opt{output-complex-root} option. The later is always in maths mode, % but notice that \pkg{siunitx} uses \cs{mathrm} by default. To force % standard \TeX\ maths output to give $i$, the construction % |\text{\ensuremath{i}}| can be used. %\begin{LaTeXdemo} % \num{1.23} \\ % \num[output-decimal-marker = {{,}}]{1.23} \\ % \num{1+2i} \\ % \num[output-complex-root = \text{\ensuremath{i}}]{1+2i} %\end{LaTeXdemo} % %\DescribeOption{exponent-base} %\DescribeOption{exponent-product} % When exponents are present in the input, the % \opt{exponent-base} and \opt{exponent-product} options set the obvious % parts of the output. Notice that the base is in the current mode, but % the product sign is always in maths mode. %\begin{LaTeXdemo} % \num[exponent-product = \times]{1e2} \\ % \num[exponent-product = \cdot]{1e2} \\ % \num[exponent-base = 2]{1e2} %\end{LaTeXdemo} % %\DescribeOption{separate-uncertainty} %\DescribeOption{uncertainty-separator} %\DescribeOption{output-open-uncertainty} %\DescribeOption{output-close-uncertainty} % When input is given including an uncertainty in a value, it can be % printed either with the uncertainty in brackets or as a separate % number. This behaviour is controlled by the % \opt{separate-uncertainty} choice. If the uncertainty is given in % brackets, a space may be added between the main value and the % uncertainty: this is stored using the \opt{uncertainty-separator} % option. The opening and closing brackets used are stored % \opt{output-open-uncertainty} and % \opt{output-close-uncertainty}, respectively. %\begin{LaTeXdemo} % \num{1.234(5)} \\ % \num[separate-uncertainty = true]{1.234(5)} \\ % \sisetup{ % output-open-uncertainty = [, % output-close-uncertainty = ], % uncertainty-separator = {\,} % } % \num{1.234(5)} %\end{LaTeXdemo} % %\DescribeOption{use-brackets} %\DescribeOption{open-bracket} %\DescribeOption{close-bracket} % There are certain combinations of numerical input which can be % ambiguous. This can be corrected by adding brackets in the appropriate % place, and is controlled by the \opt{use-brackets} switch. The % opening and closing brackets used are stored \opt{open-bracket} and % \opt{close-bracket}, respectively. %\begin{LaTeXdemo} % \num{1+2i e10} \\ % \num[use-brackets = false]{1+2i e10} \\ % \sisetup{ % open-bracket = \{, % close-bracket = \}, % } % \num{1+2i e10} %\end{LaTeXdemo} % %\DescribeOption{negative-colour} % \pkg{siunitx} can detect negative mantissa values and alter print % colour accordingly. This is disabled by setting the option to an empty % value. %\begin{LaTeXdemo} % \num{-15673} \\ % \num[negative-colour = red]{-15673} %\end{LaTeXdemo} % %\DescribeOption{tight-spacing} % Under some circumstances is may be desirable to \enquote{squeeze} % the output spacing. This is turned on using the \opt{tight-spacing} % switch, which compresses spacing where possible. %\begin{LaTeXdemo} % \num{1 \pm 2i e3} \\ % \num[tight-spacing = true]{1 \pm 2i e3} %\end{LaTeXdemo} % %\DescribeOption{range-phrase} % Ranges of numbers can be given as input. These will have an % appropriate word or symbol inserted between the two entries: this % is stored using the \opt{range-phrase} option. The phrase should % include any necessary spaces: no extra space is added. %\begin{LaTeXdemo} % \numrange{5}{100} \\ % \numrange[range-phrase = --]{5}{100} %\end{LaTeXdemo} % %\subsection{Multi-part numbers} % % \pkg{siunitx} recognises the idea of products and quotients in % numbers, both with and without units. These multi-part numbers have % a number of options affecting how they are processed. The options are % summarised in Table~\ref{tab:opt:num:multi}. % %\begin{table} % \centering % \caption{Multi-part number options} % \label{tab:opt:num:multi} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule ^^A ( % input-product & Literal & x \\ % input-quotient & Literal & / \\ % output-product & Maths & \cs{times} \\ % output-quotient & Maths & / \\ % product-mode & Choice & symbol \\ % quotient-mode & Choice & symbol \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{input-product} %\DescribeOption{input-quotient} % The options \opt{input-product} and \opt{input-quotient} contain the % tokens used to determine if a number contains multiple parts. %\begin{LaTeXdemo} % \num{1 x 2 x 3} \\ % \num{1e4 x 2(3) x 3/4} \\ % \num[input-product=*]{4 * 5 * 6} \\ % \num{ 1 / 2e4 } %\end{LaTeXdemo} %\DescribeOption{output-product} %\DescribeOption{output-quotient} % The symbols used for printing products and quotients are stored using % the options \opt{output-product} and \opt{output-quotient}. %\begin{LaTeXdemo} % \num[output-product = \cdot]{4.87 x 5.321 x 6.90545} \\ % \num[output-quotient = \text{ div }]{1 / 2} %\end{LaTeXdemo} % %\DescribeOption{product-mode} %\DescribeOption{quotient-mode} % For quotients, there is the possibility to print output either using % a slash, or using the \cs{frac} macro. This is controlled by the % \opt{quotient} choice option, which takes values \opt{slash} and % \opt{fraction}. %\begin{LaTeXdemo} % \num{1 / 2e4} \\ % \num[quotient-mode = fraction]{1 / 2e4} %\end{LaTeXdemo} % %\subsection{Creating units} %\label{sec:units:creating} % % The various macro units are created at the start of the document. % These can be defined only inside the \cs{si} and \cs{SI} macros, or % can also be made available in the document body. There are a number of % settings which control this creation process % (Table~\ref{tab:opt:units:def}). As a result, these options all apply % in the preamble only. % %\begin{table} % \centering % \caption{Unit creation options} % \label{tab:opt:units:def} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule ^^A ( % free-standing-units & Switch & false \\ % overwrite-functions & Switch & false \\ % space-before-unit & Switch & false \\ % unit-optional-argument & Switch & false \\ % use-xspace & Switch & false \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{free-standing-units} %\DescribeOption{overwrite-functions} % The \opt{free-standing-units} option controls whether the unit macros % exist outside of the \cs{si} and \cs{SI} arguments. When this option % is \opt{true}, \pkg{siunitx} creates the macros for general use. % The standard method to achieve this does not overwrite any existing % macros: this behaviour can be altered using the % \opt{overwrite-functions} switch. % %\DescribeOption{space-before-unit} %\DescribeOption{unit-optional-argument} %\DescribeOption{use-xspace} % When \enquote{free standing} unit macros are created, their behaviour % can be adjusted by a number of options. These are mainly intended for % emulating the input syntax of older packages. The option % \opt{unit-optional-argument} gives the same behaviour for the % inputs %\begin{LaTeXdemo}[code only] % \SI{10}{\metre} %\end{LaTeXdemo} % and %\begin{LaTeXdemo}[code only] % \metre[10]. %\end{LaTeXdemo} % The \opt{space-before-unit} and \opt{use-xspace} options control % the behaviour at the \enquote{ends} of the unit macros. Activating % \opt{space-before-unit} inserts the number--unit space before the % unit is printed. This is suitable for the input syntax %\begin{LaTeXdemo}[code only] % 30\metre %\end{LaTeXdemo} % but does mean that the unit macros are incorrectly spaced in running % text. On the other hand, the \opt{use-xspace} option attempts to % correctly space input such as %\begin{LaTeXdemo}[code only] % \metre is the symbol for metres. %\end{LaTeXdemo} % %\subsection{Using units} % % Part of the power of \pkg{siunitx} is the ability to alter the output % format for units without changing the input. The behaviour of units % is therefore controlled by a number of options which alter either the % processing of units or the output directly. % %\begin{table} % \centering % \caption{Unit output options} % \label{tab:opt:num:out} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule ^^A ( % allow-literal-units & Switch & true \\ % inter-unit-separator & Maths & \cs{,} \\ % per-mode & Choice & reciprocal \\ % per-symbol & Maths & / \\ % prefixes-as-symbols & Switch & true \\ % qualifier-mode & Choice & subscript \\ % sticky-per & Switch & false \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{allow-literal-units} % Some users may prefer to completely disable the use of literal input % in units, for example to enforce consistency. This can be % accomplished by setting the \opt{allow-literal-units} switch. With % this option enabled, only macro-based units can be used in a document. % %\DescribeOption{inter-unit-separator} % The separator between each unit is stored using the % \opt{inter-unit-separator} option. The standard setting is a thin % space: another common choice is a centre dot. %\begin{LaTeXdemo} % \si{\farad\squared\lumen\candela} \\ % \si[inter-unit-separator=\cdot]{\farad\squared\lumen\candela} %\end{LaTeXdemo} % %\DescribeOption{per-mode} %\DescribeOption{per-symbol} % The handling of \cs{per} is altered using the \opt{per-mode} choice % option. The standard setting is \opt{reciprocal}, meaning that % \cs{per} generates reciprocal powers for units. Setting the option % to \opt{fraction} uses the \cs{frac} function to typeset the positive % and negative powers of a unit separately. %\begin{LaTeXdemo} % \si{\joule\per\mole\per\kelvin} \\ % \si{\metre\per\second\squared} \\ % \si[per-mode=fraction]{\joule\per\mole\per\kelvin} \\ % \si[per-mode=fraction]{\metre\per\second\squared} %\end{LaTeXdemo} % It is possible to use a symbol (usually \texttt{/}) to separate the % two parts of a unit by setting \opt{per-mode} to \opt{symbol}; the % symbol used is stored using the setting \opt{per-symbol}. This method % for displaying units can be ambiguous, and so brackets are added % unless \opt{use-brackets} is set to \opt{false}. The output % for \opt{per-symbol} is always made in maths mode, and so % \cs{text} will be needed to print textual information. %\begin{LaTeXdemo} % \sisetup{per-mode=symbol}% % \si{\joule\per\mole\per\kelvin} \\ % \si{\metre\per\second\squared} \\ % \si[per-symbol=\text{~div~}]{\joule\per\mole\per\kelvin} \\ % \si[use-brackets=false]{\joule\per\mole\per\kelvin} %\end{LaTeXdemo} % Finally, the often-requested (but mathematically invalid) % \opt{repeated-symbol} option is also available to repeat the symbol % for each \cs{per}. %\begin{LaTeXdemo} % \si[per-mode=repeated-symbol]{\joule\per\mole\per\kelvin} %\end{LaTeXdemo} % %\DescribeOption{sticky-per} % By default, \cs{per} applies only to the next unit % given.\footnote{This is the standard method of reading units in % English: for example, \si{\joule\per\mole\per\kelvin} is pronounced % \enquote{joules per mole per kelvin}.} By setting the % \opt{sticky-per} flag, this behaviour is changed so that \cs{per} % applies to all subsequent units. %\begin{LaTeXdemo} % \si{\pascal\per\gray\henry} \\ % \si[sticky-per]{\pascal\per\gray\henry} %\end{LaTeXdemo} % %\DescribeOption{qualifier-mode} % Unit qualifiers can be printed in three different formats, set by the % \opt{qualifier-mode} option. The standard setting is \opt{subscript}, % while the options \opt{brackets} and \opt{space} are also possible. % With the last settings, powers can lead to ambiguity and are % automatically detected and brackets added as appropriate. %\begin{LaTeXdemo} % \si{\kilogram\polymer\per\mole\catalyst\per\hour} \\ % \si[qualifier-mode=brackets] % {\kilogram\polymer\per\mole\catalyst\per\hour} \\ % \si[qualifier-mode=space] % {\kilogram\polymer\per\mole\catalyst\per\hour} %\end{LaTeXdemo} % %\DescribeOption{prefixes-as-symbols} % The unit prefixes (\cs{kilo}, \emph{etc.}) are normally given as % letters. However, the package can convert these into numerical powers. % This is controlled by the \opt{prefixes-as-symbols} switch option. %\begin{LaTeXdemo} % \si{\milli\litre} \\ % \SI{10}{\kilo\gram} \\ % \si[prefixes-as-symbols=false]{\milli\litre} \\ % \SI[prefixes-as-symbols=false]{10}{\kilo\gram} %\end{LaTeXdemo} % %\subsection{Symbols} % % Most units use letters as the symbol for the unit, and these are all % very easy to control. However, a small number of units use other % symbols, and matching these to the body text requires more work. % \pkg{siunitx} provides appropriate symbols for commonly-used units, % but the definitions may need adjustment depending on the body font % used in a document. % %\DescribeOption{redefine-symbols} % The package provides one general option for the handling of symbols. % If the packages \pkg{textcomp} or \pkg{upgreek} are loaded, symbols % can be taken from these for units, rather than using the % \pkg{siunitx} default values. The switch \opt{redefine-symbols} % can be used to turn this behaviour on or off: the standard setting % is \opt{true}. % % The individual symbols are set up independently for maths and text % output, and are summarised in Table~\ref{tab:opt:symbols}. Many of % the definitions are variations using \cs{text} or \cs{ensuremath} to % produce the correct output, as the symbols available in the document % may vary considerably. In the case of the micro symbol % (\SIUnitSymbolMicro), \pkg{sunitx} provides a suitable low-level % definition for the symbol. Depending on the fonts available, this % may need to be replaces by an alternative by the user. The % ohm symbol (\SIUnitSymbolOhm) is also set up using an internal value, % so that packages that redefine the standard \cs{Omega} symbol to be % italic do not lead to an italic ohm sign. % %\begin{table} % \centering % \caption{Symbol options} % \label{tab:opt:symbols} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule ^^A ( % maths-angstrom & Literal & \verb=\text{\AA}= \\ % maths-arcminute & Literal & \verb={}^{\prime}= \\ % maths-arcsecond & Literal & \verb={}^{\prime\prime}= \\ % maths-celsius & Literal & % \verb={}^{\circ}\kern -\scriptspace C= \\ % maths-degree & Literal & \verb={}^{\circ}= \\ % maths-micro & Literal & \meta{see text} \\ % maths-ohm & Literal & \meta{see text} \\ % redefine-symbols & Switch & true \\ % text-angstrom & Literal & \cs{AA} \\ % text-arcminute & Literal & \verb=\ensuremath{{}^{\prime}}= \\ % text-arcsecond & Literal & % \verb=\ensuremath{{}^{\prime\prime}}= \\ % text-celsius & Literal & % \verb=\ensuremath{{}^{\circ}\kern -\scriptspace C}= \\ % text-degree & Literal & \verb=\ensuremath{{}^{\circ}}= \\ % text-micro & Literal & \meta{see text} \\ % text-ohm & Literal & \meta{see text} \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeMacro{\SIUnitSymbolAngstrom} %\DescribeMacro{\SIUnitSymbolArcminute} %\DescribeMacro{\SIUnitSymbolArcsecond} %\DescribeMacro{\SIUnitSymbolCelsius} %\DescribeMacro{\SIUnitSymbolDegree} %\DescribeMacro{\SIUnitSymbolMicro} %\DescribeMacro{\SIUnitSymbolOhm} % The maths and text symbols defined above are wrapped up into mode % independent functions with user names. These are then used in the % definitions of the appropriate units. For example, the micro % symbol can be accessed using the macro \cs{SIUnitSymbolMicro}. % Notice that these names capitalise the unit name (to make reading % the macro name easier!).\footnote{The function % \cs{SIUnitSymbolAngstrom} uses the name without accents.} % %\section{Usage tips} % %\subsection{Ensuring text or maths output} % % The macros \cs{ensuremath} and \cs{text} should be used to ensure that % a particular item is always printed in the desired mode. Some % mathematical output does not work well in \cs{mathrm} (the standard % font used by \pkg{siunitx} for printing). The easiest way to solve % this is to use the construction |\text{\ensuremath{...}}|, which will % print the material in the standard mathematics font without affecting % the rest of the output. %\begin{LaTeXdemo} % \num[output-complex-root = i]{1+2i} \\ % \num[output-complex-root = \text{\ensuremath{i}}]{1+2i} %\end{LaTeXdemo} % In some circumstances, forcing \cs{mathnormal} may suffice, but this % deals less well with non-Latin characters. % %\subsection{Using units such as \si{\micro\metre\per\second} in % headings} % % The \pkg{siunitx} code is designed to work correctly with functions % in headings. They will print correctly in headings and in the table % of contents. As illustrated here, the standard behaviour is to ignore % font changes. When the \pkg{hyperref} package is loaded, the % functions automatically \enquote{degrade gracefully} to produce % useful information in PDF bookmarks. If you want more control over % the bookmark text, use the \cs{texorpdfstring} function from % \pkg{hyperref}, for example: %\begin{LaTeXdemo}[code only] % \section{Some text % \texorpdfstring % {\si{\joule\per\mole\per\kelvin}} % {J mol-1 K-1}% % } %\end{LaTeXdemo} % %\end{documentation} % %\begin{implementation} % %\section{Implementation} % %\subsection{Preliminaries} % % The usual preliminaries. % \begin{macrocode} %<*package> \ProvidesExplPackage {\filename}{\filedate}{\fileversion}{\filedescription} % \end{macrocode} % %\begin{macro}{\siunitx_load_check:} %\begin{macro}[aux]{\siunitx_load_check_aux:n} % There are also a number of packages that are incompatible with % \pkg{siunitx}. These are all checked for next. Some of the % incompatible packages will not raise an error if loaded after % \pkg{siunitx}. So a test is made at the beginning of the % document as well. The message for this may be needed immediately, so % it is created here not with the other messages. % \begin{macrocode} \msg_new:nnnn { siunitx } { incompatible-package } {Package `#1' incompatible.} {% The #1 package and siunitx are incompatible.\\% Use the `emulate=#1' package option when loading siunitx.% } \cs_new_nopar:Npn \siunitx_load_check: { \clist_map_function:nN { SIunits, sistyle, siunits, SIstyle } \siunitx_load_check_aux:n } \cs_new_nopar:Npn \siunitx_load_check_aux:n #1 { \group_begin: \@ifpackageloaded {#1} { \msg_error:nnx { siunitx } { incompatible-package } {#1} } { } \group_end: } \clist_map_function:nN { SIunits, sistyle, siunits, SIstyle, unitsdef, fancyunits } \siunitx_load_check_aux:n \AtBeginDocument { \siunitx_load_check: } % \end{macrocode} %\end{macro} %\end{macro} % % Now load the support packages. % \begin{macrocode} \RequirePackage{ amstext, array, xparse } % \end{macrocode} % %\begin{macro}{\siunitx_tmp:w} %\begin{macro}{\l_siunitx_tmp_bool} %\begin{macro}{\l_siunitx_tmp_int} %\begin{macro}{\l_siunitx_tmpa_tl} %\begin{macro}{\l_siunitx_tmpb_tl} % Scratch items. % \begin{macrocode} \cs_new:Npn \siunitx_tmp:w { } \bool_new:N \l_siunitx_tmp_bool \int_new:N \l_siunitx_tmp_int \tl_new:N \l_siunitx_tmpa_tl % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_error_bool} %\begin{macro}{\siunitx_error:nxx} %\begin{macro}{\siunitx_error:nx} %\begin{macro}{\siunitx_error:n} % General-purpose functions for throwing errors. % \begin{macrocode} \bool_new:N \l_siunitx_error_bool \cs_new:Npn \siunitx_error:nxx #1#2#3 { \bool_set_true:N \l_siunitx_error_bool \msg_error:nnxx { siunitx } {#1} {#2} {#3} } \cs_new:Npn \siunitx_error:nx #1#2 { \siunitx_error:nxx {#1} {#2} { } } \cs_new:Npn \siunitx_error:n #1 { \siunitx_error:nxx {#1} { } { } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_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} \cs_new_nopar:Npn \siunitx_encoding_ts_one: { \cs_if_free:cT { T@TS1 } { \DeclareFontEncoding { TS1 } { } { } \DeclareFontSubstitution { TS1 } { cmr } { m } { n } } } \AtBeginDocument { \siunitx_encoding_ts_one: } % \end{macrocode} %\end{macro} % %\begin{macro}{\c_siunitx_minus_tl} % To allow the correct symbol to appear in text mode: this is the same % as \cs{textminus} from \pkg{textcomp}. % \begin{macrocode} \DeclareTextSymbolDefault \c_siunitx_minus_tl { TS1 } \DeclareTextSymbol \c_siunitx_minus_tl { TS1 } { 61 } % \end{macrocode} %\end{macro} % %\begin{macro}{\c_siunitx_mu_tl} % The lack of an upright mu has to be sorted out. % \begin{macrocode} \DeclareTextSymbol \c_siunitx_mu_tl { TS1 } { 181 } \DeclareTextSymbolDefault \c_siunitx_mu_tl { TS1 } % \end{macrocode} %\end{macro} % %\begin{macro}{\c_siunitx_omega_tl} % Some package redefine \cs{Omega} to be slanted and move the original % symbol to \cs{upOmega}. This is handled here. % \begin{macrocode} \tl_new:Nn \c_siunitx_omega_tl { \Omega } \cs_new_nopar:Npn \siunitx_check_omega: { \cs_if_exist:NT \upOmega { \tl_set:Nn \c_siunitx_omega_tl { \upOmega } } } \AtBeginDocument { \siunitx_check_omega: } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_tl_put_left_maths:Nn} %\begin{macro}{\siunitx_tl_put_left_maths:NV} %\begin{macro}{\siunitx_tl_put_left_maths:cV} %\begin{macro}{\siunitx_tl_put_right_maths:Nn} %\begin{macro}{\siunitx_tl_put_right_maths:NV} %\begin{macro}{\siunitx_tl_put_right_maths:cV} % To add stuff in maths mode. % \begin{macrocode} \cs_new:Npn \siunitx_tl_put_left_maths:Nn #1#2 { \tl_put_left:Nn #1 { \ensuremath {#2} } } \cs_generate_variant:Nn \siunitx_tl_put_left_maths:Nn { NV, cV } \cs_new:Npn \siunitx_tl_put_right_maths:Nn #1#2 { \tl_put_right:Nn #1 { \ensuremath {#2} } } \cs_generate_variant:Nn \siunitx_tl_put_right_maths:Nn { NV, cV } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_option_deactivate_clist} %\begin{macro}{\siunitx_option_deactivate:n} %\begin{macro}{\siunitx_options_deactivate:} %\begin{macro}[aux]{\siunitx_option_deactivate_aux:n} % Some options need to be deactivated at the start of the document. % \begin{macrocode} \clist_new:N \l_siunitx_option_deactivate_clist \cs_new_nopar:Npn \siunitx_option_deactivate:n #1 { \clist_put_right:Nn \l_siunitx_option_deactivate_clist {#1} } \cs_new_nopar:Npn \siunitx_options_deactivate: { \clist_map_function:NN \l_siunitx_option_deactivate_clist \siunitx_options_deactivate_aux:n } \cs_new_nopar:Npn \siunitx_options_deactivate_aux:n #1 { \keys_define:nn { siunitx } { #1 .code:n = { \msg_warning:nnx { siunitx } { option-preamble-only } {#1} } } } \AtBeginDocument { \siunitx_options_deactivate: } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\tl_put_right:cv} %\begin{macro}{\tl_if_eq:nvTF} %\begin{macro}{\tl_replace_all_in:NnV} %\begin{macro}{\tl_set_rescan:NnV} % Variants needed which are not in \pkg{expl3}. % \begin{macrocode} \cs_generate_variant:Nn \tl_put_right:Nn { cv } \cs_generate_variant:Nn \tl_if_eq:nnTF { nv } \cs_generate_variant:Nn \tl_replace_all_in:Nnn { NnV } \cs_generate_variant:Nn \tl_set_rescan:Nnn { NnV } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_if_tl:NTF} %\begin{macro}[aux]{\siunitx_if_tl_aux:w} % This is basically a re-hash of stuff from \pkg{expl3}, but to test for % short macros only. % \begin{macrocode} \group_begin: \tl_map_inline:nn { \M \A \C \R \O } { \char_set_catcode:nn { `#1 } { \c_twelve } } \tl_map_inline:nn { \F \N \T } { \char_set_lccode:nn { `#1 } { `#1 } } \tl_to_lowercase:n { \group_end: \prg_new_conditional:Nnn \siunitx_if_tl:N { TF } { \exp_after:wN \siunitx_if_tl_aux:w \token_to_meaning:N #1 MACRO \q_nil } \cs_new_nopar:Npn \siunitx_if_tl_aux:w #1 MACRO #2 \q_nil { \tl_if_empty:nTF {#1} { \prg_return_true: } { \prg_return_false: } } } % \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 \pkg{amstext} % package. By carrying out the changes outside maths mode, bold can % reliably be applied to maths output. % %\begin{macro}{\c_siunitx_mathsf_int} %\begin{macro}{\c_siunitx_mathtt_int} %\begin{macro}{\siunitx_set_maths_fam:n} % The detection routine needs some basic data about the sans serif and % monospaced fonts in use. This is collected up at the start of the % document. The families used can change between here and the start of % the document. This is run as a hook onto \cs{document}, rather than % using \cs{AtBeginDocument} as it has to come after anything that % \pkg{fontspec} does (nasty errors arise otherwise). % \begin{macrocode} \cs_new_nopar:Npn \siunitx_set_maths_fam:n #1 { \group_begin: \hbox_set:Nn \l_tmpa_box { \ensuremath { \use:c { math #1 } { \exp_after:wN \pref_global:D \exp_after:wN \tex_chardef:D \cs:w c_siunitx_math #1 _int \cs_end: \fam \scan_stop: } } } \group_end: } \tl_put_right:Nn \document { \siunitx_set_maths_fam:n { sf } \siunitx_set_maths_fam:n { tt } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_font_set_text_fam:n} %\begin{macro}{\c_siunitx_textsf_tl} %\begin{macro}{\c_siunitx_texttt_tl} % The text families are done in a somewhat different manner: there are % no issues with \cs{AtBeginDocument}, luckily. The need to define % new macros here arises as \cs{sfdefault} and \cs{ttdefault} are % \cs{long}, whereas \cs{f@family} is not. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_set_text_fam:n #1 { \tl_new:c { c_siunitx_text #1 _tl } \tl_set:cx { c_siunitx_text #1 _tl } { \use:c { #1 default } } } \AtBeginDocument { \siunitx_set_text_fam:n { sf } \siunitx_set_text_fam:n { tt } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_detect_inline_bold_bool} % Used by the keys, but needs to be created here. % \begin{macrocode} \bool_new:N \l_siunitx_detect_inline_bold_bool % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_detect_bold_bool} %\begin{macro}{\l_siunitx_detect_display_maths_bool} %\begin{macro}{\l_siunitx_detect_family_bool} %\begin{macro}{\l_siunitx_detect_inline_bold_bool} %\begin{macro}{\l_siunitx_detect_italic_bool} %\begin{macro}{\l_siunitx_detect_mode_bool} % Font detection is all about creating switches, with just a little % gloss for \texttt{detect-all} and \texttt{detect-none}. % \begin{macrocode} \keys_define:nn { siunitx } { detect-all .choice:, detect-all .default:n = true, detect-all / false .meta:n = { detect-bold = false, detect-family = false, detect-italic = false, detect-mode = false }, detect-all / true .meta:n = { detect-bold = true, detect-family = true, detect-italic = true, detect-mode = true }, detect-bold .bool_set:N = \l_siunitx_detect_bold_bool, detect-display-math .bool_set:N = \l_siunitx_detect_display_maths_bool, detect-display-maths .bool_set:N = \l_siunitx_detect_display_maths_bool, detect-family .bool_set:N = \l_siunitx_detect_family_bool, detect-inline-bold .choice:, detect-inline-bold .value_required:, detect-inline-bold / math .code:n = { \bool_set_true:N \l_siunitx_detect_inline_bold_bool }, detect-inline-bold / maths .code:n = { \bool_set_true:N \l_siunitx_detect_inline_bold_bool }, detect-inline-bold / text .code:n = { \bool_set_false:N \l_siunitx_detect_inline_bold_bool }, detect-italic .bool_set:N = \l_siunitx_detect_italic_bool, detect-mode .bool_set:N = \l_siunitx_detect_mode_bool, detect-none .choice:, detect-none .default:n = true, detect-none / false .meta:n = { detect-bold = true, detect-family = true, detect-italic = true, detect-mode = true }, detect-none / true .meta:n = { detect-bold = false, detect-family = false, detect-italic = false, detect-mode = false } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_font_set_bool} %\begin{macro}{\l_siunitx_font_maths_mode_bool} % The internals of the package need a number of switches to track what % is happening. % \begin{macrocode} \bool_new:N \l_siunitx_font_set_bool \bool_new:N \l_siunitx_font_maths_mode_bool % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_font_family_tl} % Also some token storage. % \begin{macrocode} \tl_new:N \l_siunitx_font_family_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_font_bold:} %\begin{macro}{\siunitx_font_italic:} % These could be token lists or functions! % \begin{macrocode} \cs_new_nopar:Npn \siunitx_font_bold: { } \cs_new_nopar:Npn \siunitx_font_italic: { } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_detect_font:} % The main font-setting macro is a control point for the other % functions. Nesting font-control should not happen, so the first % test is to ensure this is not happening. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_detect_font: { \bool_if:NF \l_siunitx_font_set_bool { \siunitx_detect_font_init: \bool_if:NT \l_siunitx_detect_bold_bool { \siunitx_detect_font_bold: } \bool_if:NT \l_siunitx_detect_family_bool { \siunitx_detect_font_family: } \bool_if:NT \l_siunitx_detect_italic_bool { \siunitx_detect_font_italic: } \bool_if:NT \l_siunitx_detect_mode_bool { \siunitx_detect_font_mode: } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_detect_font_init:} % Set up the basic macros on the assumption nothing happens. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_detect_font_init: { \bool_set_true:N \l_siunitx_font_set_bool \cs_set:Npn \siunitx_font_bold: { \unboldmath \mdseries } \cs_set:Npn \siunitx_font_italic: { \upshape } \tl_set:Nn \l_siunitx_font_family_tl { rm } \bool_set_true:N \l_siunitx_font_maths_mode_bool } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_detect_font_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} \cs_new_nopar:Npn \siunitx_detect_font_bold: { \mode_if_math:TF { \mode_if_inner:TF { \bool_if:NTF \l_siunitx_detect_inline_bold_bool { \siunitx_detect_font_bold_maths: } { \siunitx_detect_font_bold_text: } } { \bool_if:NTF \l_siunitx_detect_display_maths_bool { \siunitx_detect_font_bold_maths: } { \siunitx_detect_font_bold_text: } } } { \siunitx_detect_font_bold_text: } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_detect_font_bold_maths:} %\begin{macro}{\siunitx_detect_font_bold_text:} % The tests for bold depend on whether the module is testing text or % maths content. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_detect_font_bold_maths: { \tl_if_eq:nVT { bold } \math@version { \cs_set:Npn \siunitx_font_bold: { \boldmath \bfseries } } } \cs_new_nopar:Npn \siunitx_detect_font_bold_text: { \tl_if_eq:nxT { b } { \exp_args:NV \tl_head_i:n \f@series } { \cs_set:Npn \siunitx_font_bold: { \boldmath \bfseries } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_detect_font_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} \cs_new_nopar:Npn \siunitx_detect_font_family: { \siunitx_detect_font_family_text: \bool_if:NT \l_siunitx_detect_display_maths_bool { \mode_if_math:T { \mode_if_inner:F { \siunitx_detect_font_family_maths: } } } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_detect_font_family_maths:} %\begin{macro}{\siunitx_detect_font_family_text:} % The two detections routines check if the current font is sans serif or % monospaced. The method used depends on whether the current 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} \cs_new_nopar:Npn \siunitx_detect_font_family_maths: { \tl_set:Nn \l_siunitx_font_family_tl { rm } \intexpr_compare:nT { \int_use:N \fam = \c_siunitx_mathsf_int } { \tl_set:Nn \l_siunitx_font_family_tl { sf } } \intexpr_compare:nT { \int_use:N \fam = \c_siunitx_mathtt_int } { \tl_set:Nn \l_siunitx_font_family_tl { tt } } } \cs_new_nopar:Npn \siunitx_detect_font_family_text: { \tl_if_eq:NNT \f@family \c_siunitx_textsf_tl { \tl_set:Nn \l_siunitx_font_family_tl { sf } } \tl_if_eq:NNT \f@family \c_siunitx_texttt_tl { \tl_set:Nn \l_siunitx_font_family_tl { tt } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_detect_font_italic:} % The italic test uses \cs{f@shape} as a handy indicator. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_detect_font_italic: { \tl_if_eq:nVT { it } \f@shape { \cs_nopar_set:Npn \siunitx_font_italic: { \itshape } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_detect_font_mode:} % The mode switch works from the fact that maths-mode output it the % standard. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_detect_font_mode: { \mode_if_math:F { \bool_set_false:N \l_siunitx_font_maths_mode_bool } } % \end{macrocode} %\end{macro} % %\subsection{Font macros} % % With the detection routines in place, the module can apply the result % to control the font used for output. This requires a series of font % names to be available. The appropriate storage areas will be selected % by name, based on output type (\texttt{unit} or \texttt{value}) and % the family selected by the detector. % %\begin{macro}{\l_siunitx_number_maths_mode_bool} %\begin{macro}{\l_siunitx_unit_maths_mode_bool} % Most of the variables are created by the keys system: these are not. % \begin{macrocode} \bool_new:N \l_siunitx_number_maths_mode_bool \bool_new:N \l_siunitx_unit_maths_mode_bool % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_number_colour_tl} %\begin{macro}{\siunitx_number_mathrm:} %\begin{macro}{\siunitx_number_mathsf:} %\begin{macro}{\siunitx_number_mathtt:} %\begin{macro}{\siunitx_number_textrm:} %\begin{macro}{\siunitx_number_textsf:} %\begin{macro}{\siunitx_number_texttt:} % The settings are actually created separately for numbers and units: % numbers first. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_mathrm: { } \cs_new_nopar:Npn \siunitx_number_mathsf: { } \cs_new_nopar:Npn \siunitx_number_mathtt: { } \cs_new_nopar:Npn \siunitx_number_textrm: { } \cs_new_nopar:Npn \siunitx_number_textsf: { } \cs_new_nopar:Npn \siunitx_number_texttt: { } \keys_define:nn { siunitx } { number-color .meta:n = { number-colour = #1 }, number-colour .tl_set:N = \l_siunitx_number_colour_tl, number-math-rm .code:n = { \cs_set_nopar:Npn \siunitx_number_mathrm: {#1} }, number-maths-rm .code:n = { \cs_set_nopar:Npn \siunitx_number_mathrm: {#1} }, number-math-sf .code:n = { \cs_set_nopar:Npn \siunitx_number_mathsf: {#1} }, number-maths-sf .code:n = { \cs_set_nopar:Npn \siunitx_number_mathsf: {#1} }, number-math-tt .code:n = { \cs_set_nopar:Npn \siunitx_number_mathtt: {#1} }, number-maths-tt .code:n = { \cs_set_nopar:Npn \siunitx_number_mathtt: {#1} }, number-mode .choice:, number-mode / math .code:n = { \bool_set_true:N \l_siunitx_number_maths_mode_bool }, number-mode / maths .code:n = { \bool_set_true:N \l_siunitx_number_maths_mode_bool }, number-mode / text .code:n = { \bool_set_false:N \l_siunitx_number_maths_mode_bool }, number-text-rm .code:n = { \cs_set_nopar:Npn \siunitx_number_textrm: {#1} }, number-text-sf .code:n = { \cs_set_nopar:Npn \siunitx_number_textsf: {#1} }, number-text-tt .code:n = { \cs_set_nopar:Npn \siunitx_number_texttt: {#1} } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_unit_colour_tl} %\begin{macro}{\siunitx_unit_mathrm:} %\begin{macro}{\siunitx_unit_mathsf:} %\begin{macro}{\siunitx_unit_mathtt:} %\begin{macro}{\siunitx_unit_textrm:} %\begin{macro}{\siunitx_unit_textsf:} %\begin{macro}{\siunitx_unit_texttt:} % Units look exactly the same. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_mathrm: { } \cs_new_nopar:Npn \siunitx_unit_mathsf: { } \cs_new_nopar:Npn \siunitx_unit_mathtt: { } \cs_new_nopar:Npn \siunitx_unit_textrm: { } \cs_new_nopar:Npn \siunitx_unit_textsf: { } \cs_new_nopar:Npn \siunitx_unit_texttt: { } \keys_define:nn { siunitx } { unit-color .meta:n = { unit-colour = #1 }, unit-colour .tl_set:N = \l_siunitx_unit_colour_tl, unit-math-rm .code:n = { \cs_set_nopar:Npn \siunitx_unit_mathrm: {#1} }, unit-maths-rm .code:n = { \cs_set_nopar:Npn \siunitx_unit_mathrm: {#1} }, unit-math-sf .code:n = { \cs_set_nopar:Npn \siunitx_unit_mathsf: {#1} }, unit-maths-sf .code:n = { \cs_set_nopar:Npn \siunitx_unit_mathsf: {#1} }, unit-math-tt .code:n = { \cs_set_nopar:Npn \siunitx_unit_mathtt: {#1} }, unit-maths-tt .code:n = { \cs_set_nopar:Npn \siunitx_unit_mathtt: {#1} }, unit-mode .choice:, unit-mode / math .code:n = { \bool_set_true:N \l_siunitx_unit_maths_mode_bool }, unit-mode / maths .code:n = { \bool_set_true:N \l_siunitx_unit_maths_mode_bool }, unit-mode / text .code:n = { \bool_set_false:N \l_siunitx_unit_maths_mode_bool }, unit-text-rm .code:n = { \cs_set_nopar:Npn \siunitx_unit_textrm: {#1} }, unit-text-sf .code:n = { \cs_set_nopar:Npn \siunitx_unit_textsf: {#1} }, unit-text-tt .code:n = { \cs_set_nopar:Npn \siunitx_unit_texttt: {#1} } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % % The general settings are all meta-keys. A few initial values are set % here as they are needed for everything to work. % \begin{macrocode} \keys_define:nn { siunitx } { color .meta:n = { number-color = #1, unit-color = #1 }, colour .meta:n = { number-colour = #1, unit-colour = #1 }, math-rm .meta:n = { number-math-rm = #1, unit-math-rm = #1 }, maths-rm .meta:n = { number-maths-rm = #1, unit-maths-rm = #1 }, math-sf .meta:n = { number-math-sf = #1, unit-math-sf = #1 }, maths-sf .meta:n = { number-maths-sf = #1, unit-maths-sf = #1 }, math-tt .meta:n = { number-math-tt = #1, unit-math-tt = #1 }, maths-tt .meta:n = { number-maths-tt = #1, unit-maths-tt = #1 }, mode .choice:, mode / math .meta:n = { number-mode = math, unit-mode = math }, mode / maths .meta:n = { number-mode = maths, unit-mode = maths }, mode / text .meta:n = { number-mode = text, unit-mode = text }, text-rm .meta:n = { number-text-rm = #1, unit-text-rm = #1 }, text-sf .meta:n = { number-text-sf = #1, unit-text-sf = #1 }, text-tt .meta:n = { number-text-tt = #1, unit-text-tt = #1 } } \keys_set:nn { siunitx } { maths-rm = \mathrm, maths-sf = \mathsf, maths-tt = \mathtt, number-mode = maths, text-rm = \rmfamily, text-sf = \sffamily, text-tt = \ttfamily } % \end{macrocode} % %\subsection{Output control} % % The \pkg{siunitx} output routine uses all of the font information % gathered earlier to print the text given in whatever font is required. % The low-level stuff is done here, with the calling routines expected % to have taken some steps first (this is to allow line breaks in the % appropriate places). % %\begin{macro}{\l_siunitx_print_arg_tl} % The text to print. % \begin{macrocode} \tl_new:N \l_siunitx_print_arg_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_print_type_tl} % The type of output (\texttt{number} or \texttt{unit}) is always % needed. % \begin{macrocode} \tl_new:N \l_siunitx_print_type_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_print:nn} %\begin{macro}{\siunitx_print:nV} % The main printing function does everything inside a group, as % there are category code and definition changes to make. First, set % the fonts. Then move on to printing mode, before moving to actual % printing. % \begin{macrocode} \cs_new:Npn \siunitx_print:nn #1#2 { \group_begin: \tl_set:Nn \l_siunitx_print_type_tl {#1} \tl_set:Nn \l_siunitx_print_arg_tl {#2} \siunitx_detect_font: \bool_if:NF \l_siunitx_detect_mode_bool { \bool_if:cTF { l_siunitx_ #1 _maths_mode_bool } { \bool_set_true:N \l_siunitx_font_maths_mode_bool } { \bool_set_false:N \l_siunitx_font_maths_mode_bool } } \siunitx_print_aux: \group_end: } \cs_generate_variant:Nn \siunitx_print:nn { nV } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}[aux]{\siunitx_print_aux:} % The various font changes are set up, then the correct printing % function is called. Everything is inside \cs{text} as this allows % proper setting of the various mode settings. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_print_aux: { \text { \siunitx_print_colour: \siunitx_font_bold: \siunitx_font_italic: \use:c { siunitx_ \l_siunitx_print_type_tl _ text \l_siunitx_font_family_tl : } \bool_if:NTF \l_siunitx_font_maths_mode_bool { \siunitx_print_maths: } { \siunitx_print_text: } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_print_colour:} %\begin{macro}{\siunitx_colour_check:} % The colour system checks if \pkg{color} is loaded, and only does % anything if it is. This will change when \LaTeX3 proper is available: % there will be colour out of the box! % \begin{macrocode} \cs_new_nopar:Npn \siunitx_print_colour: { \tl_if_empty:cF { l_siunitx_ \l_siunitx_print_type_tl _colour_tl } { \color { \tl_use:c { l_siunitx_ \l_siunitx_print_type_tl _colour_tl } } } } \cs_new_nopar:Npn \siunitx_colour_check: { \@ifpackageloaded { color } { } { \cs_set_eq:NN \siunitx_print_colour: \scan_stop: } } \AtBeginDocument { \siunitx_colour_check: } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_print_maths:} %\begin{macro}{\siunitx_print_text:} % Printing the text means replacing any awkward characters, which is % dependent on the output mode. The rest of the package uses |_| and % |^| to represent sub- and superscripts, respectively. In this way, % mode decisions can be delayed as long as possible. The % \pkg{underscore} package may make |_| active, or more likely % it will be a superscript character. Both are tested for here. % \begin{macrocode} \group_begin: \char_set_lccode:nn { `\@ } { `\_ } \char_make_math_subscript:N \@ \char_set_lccode:nn { `\! } { `\_ } \char_make_active:N \! \char_make_active:N \- \tl_to_lowercase:n { \group_end: \cs_new_nopar:Npn \siunitx_print_maths: { \ensuremath { \use:c { siunitx_ \l_siunitx_print_type_tl _ math \l_siunitx_font_family_tl : } \l_siunitx_print_arg_tl } } \cs_new_nopar:Npn \siunitx_print_text: { \group_begin: \char_make_active:N \- \cs_set:Npn - { \text { \c_siunitx_minus_tl } } \tl_set_rescan:NnV \l_siunitx_print_arg_tl { } \l_siunitx_print_arg_tl \tl_replace_all_in:Nnn \l_siunitx_print_arg_tl { @ } { \siunitx_print_text_sub:n } \tl_replace_all_in:Nnn \l_siunitx_print_arg_tl { ! } { \siunitx_print_text_sub:n } \tl_replace_all_in:Nnn \l_siunitx_print_arg_tl { ^ } { \siunitx_print_text_super:n } \l_siunitx_print_arg_tl \group_end: } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_print_text_sub:n} %\begin{macro}{\siunitx_print_text_super:n} % The appropriate macros for sub- and superscript in text mode ensure % the appearance is the same as maths mode. As |_| is a letter, there % is the need to do a category-code juggle. % \begin{macrocode} \group_begin: \char_set_lccode:nn { `\@ } { `\_ } \char_make_math_subscript:N \@ \tl_to_lowercase:n { \group_end: \cs_new:Npn \siunitx_print_text_sub:n #1 { \ensuremath { @ { \text {#1} } } } } \cs_new:Npn \siunitx_print_text_super:n #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}{\l_siunitx_input_product_tl} %\begin{macro}{\l_siunitx_input_quotient_tl} % There are a couple of settings which are created here as they are used % only for pre-processing. % \begin{macrocode} \keys_define:nn { siunitx } { input-product .tl_set:N = \l_siunitx_input_product_tl, input-quotient .tl_set:N = \l_siunitx_input_quotient_tl, } \keys_set:nn { siunitx } { input-product = x, input-quotient = / } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_number_arg_tl} %\begin{macro}{\l_siunitx_number_next_tl} % Storage for the pre-parsed material. The \texttt{arg} variable % contains the current argument, the \texttt{next} variable contains % anything held-over for the next round. % \begin{macrocode} \tl_new:N \l_siunitx_number_arg_tl \tl_new:N \l_siunitx_number_next_tl % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_number_multi_tl} % For products and quotients, a way of feeding information back. % \begin{macrocode} \tl_new:N \l_siunitx_number_multi_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_number_denominator_tl} %\begin{macro}{\l_siunitx_number_numerator_tl} % When searching for quotients, some more storage is needed. % \begin{macrocode} \tl_new:N \l_siunitx_number_denominator_tl \tl_new:N \l_siunitx_number_numerator_tl % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_preprocess:n} %\begin{macro}{\siunitx_number_preprocess:V} % The pre-processor starts with the obvious: the most likely outcome is % that all of the argument is passed through unchanged. % \begin{macrocode} \cs_new:Npn \siunitx_number_preprocess:n #1 { \siunitx_number_preprocess_init: \tl_set:Nn \l_siunitx_number_arg_tl {#1} \siunitx_number_preprocess_product: \tl_if_empty:NT \l_siunitx_number_multi_tl { \siunitx_number_preprocess_quotient: } } \cs_generate_variant:Nn \siunitx_number_preprocess:n { V } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_preprocess_init:} % A little initialisation as normal. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_preprocess_init: { \bool_set_false:N \l_siunitx_error_bool \tl_clear:N \l_siunitx_number_multi_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_preprocess_product:} %\begin{macro}[aux]{\siunitx_number_preprocess_product_aux:N} % Rather than search through the entire argument, we use the % delimited-argument trick. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_preprocess_product: { \tl_map_function:NN \l_siunitx_input_product_tl \siunitx_number_preprocess_product_aux:N } \cs_new:Npn \siunitx_number_preprocess_product_aux:N #1 { \tl_if_in:NnT \l_siunitx_number_arg_tl {#1} { \cs_set:Npn \siunitx_tmp:w ##1 #1 ##2 \q_stop { \tl_set:Nn \l_siunitx_number_arg_tl {##1} \tl_set:Nn \l_siunitx_number_next_tl {##2} \tl_set:Nn \l_siunitx_number_multi_tl { product } } \exp_after:wN \siunitx_tmp:w \l_siunitx_number_arg_tl \q_stop \tl_if_empty:NT \l_siunitx_number_arg_tl { \siunitx_error:n { starting-product-token } } \tl_if_empty:NT \l_siunitx_number_next_tl { \siunitx_error:n { ending-product-token } } \tl_map_break: } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_preprocess_quotient:} %\begin{macro}[aux]{\siunitx_number_preprocess_quotient_aux:N} % For the quotient, only one token can appear in each part. So there % is an additional error check. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_preprocess_quotient: { \tl_map_function:NN \l_siunitx_input_quotient_tl \siunitx_number_preprocess_quotient_aux:N } \cs_new:Npn \siunitx_number_preprocess_quotient_aux:N #1 { \tl_if_in:NnT \l_siunitx_number_arg_tl {#1} { \cs_set:Npn \siunitx_tmp:w ##1 #1 ##2 \q_stop { \tl_set:Nn \l_siunitx_number_numerator_tl {##1} \tl_set:Nn \l_siunitx_number_denominator_tl {##2} \tl_set:Nn \l_siunitx_number_multi_tl { quotient } } \exp_after:wN \siunitx_tmp:w \l_siunitx_number_arg_tl \q_stop \tl_if_empty:NT \l_siunitx_number_numerator_tl { \siunitx_error:n { starting-quotient-token } } \tl_if_empty:NT \l_siunitx_number_denominator_tl { \siunitx_error:n { ending-quotient-token } } \tl_if_in:NnT \l_siunitx_number_denominator_tl {#1} { \siunitx_error:n { duplicate-quotient-token } } \tl_map_break: } } % \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}{\l_siunitx_number_in_prop} % The number is split up into various parts, all stored here. % \begin{macrocode} \prop_new:N \l_siunitx_number_in_prop % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_number_valid_tl} % This list of valid tokens is set when parsing a number, so that it is % flexible. % \begin{macrocode} \tl_new:N \l_siunitx_number_valid_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\c_siunitx_number_parts_clist} % The parts of a number. % \begin{macrocode} \clist_new:N \c_siunitx_number_parts_clist \clist_put_right:Nn \c_siunitx_number_parts_clist { mantissa } \clist_put_right:Nn \c_siunitx_number_parts_clist { mantissa-complex } \clist_put_right:Nn \c_siunitx_number_parts_clist { exponent } \clist_put_right:Nn \c_siunitx_number_parts_clist { exponent-complex} % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_input_uncert_close_tl} %\begin{macro}{\l_siunitx_input_complex_tl} %\begin{macro}{\l_siunitx_input_decimal_tl} %\begin{macro}{\l_siunitx_input_digit_tl} %\begin{macro}{\l_siunitx_input_exponent_tl} %\begin{macro}{\l_siunitx_input_ignore_tl} %\begin{macro}{\l_siunitx_input_uncert_open_tl} %\begin{macro}{\l_siunitx_input_protect_tl} %\begin{macro}{\l_siunitx_input_sign_tl} %\begin{macro}{\l_siunitx_input_symbol_tl} % The various tokens to check against when parsing are all set up here. % These are valid inside a single number: the pre-processor has already % set up the appropriate things for products and quotients. % \begin{macrocode} \keys_define:nn { siunitx } { input-close-uncertainty .tl_set:N = \l_siunitx_input_uncert_close_tl, input-complex-roots .tl_set:N = \l_siunitx_input_complex_tl, input-decimal-markers .tl_set:N = \l_siunitx_input_decimal_tl, input-digits .tl_set:N = \l_siunitx_input_digit_tl, input-exponent-markers .tl_set:N = \l_siunitx_input_exponent_tl, input-ignore .tl_set:N = \l_siunitx_input_ignore_tl, input-open-uncertainty .tl_set:N = \l_siunitx_input_uncert_open_tl, input-protect-tokens .tl_set:N = \l_siunitx_input_protect_tl, input-signs .tl_set:N = \l_siunitx_input_sign_tl, input-symbols .tl_set:N = \l_siunitx_input_symbol_tl, } \keys_set:nn { siunitx } { % ( input-close-uncertainty = ), input-complex-roots = ij, input-decimal-markers = {.,}, input-digits = 0123456789, input-exponent-markers = dDeE, input-open-uncertainty = (, % ) input-protect-tokens = \mp\pi\pm, input-signs = +-\mp\pm, input-symbols = \pi, } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_parse:n} %\begin{macro}{\siunitx_number_in_parse:V} % The master control for parsing numbers is mainly a list of functions % to carry out. The rescanning allows full expansion of the input while % dealing with any hard spaces or awkward characters. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_parse:n #1 { \siunitx_number_in_init: \tl_set_rescan:Nnx \l_siunitx_number_arg_tl { \siunitx_number_in_protect: \char_make_ignore:N \~ \char_make_other:N \, \char_make_other:N \. \cs_set_eq:NN \, \prg_do_nothing: } {#1} \tl_if_empty:NF \l_siunitx_number_arg_tl { \siunitx_number_in_loop:V \l_siunitx_number_arg_tl \bool_if:NF \l_siunitx_error_bool { \siunitx_number_in_separate: } \bool_if:NF \l_siunitx_error_bool { \siunitx_number_in_tidy: } \bool_if:NF \l_siunitx_error_bool { \siunitx_number_in_check: } } } \cs_generate_variant:Nn \siunitx_number_in_parse:n { V } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_check:} %\begin{macro}[aux]{\siunitx_number_in_check_uncertainty:n} % Checks for invalid number combinations. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_check: { \clist_map_function:NN \c_siunitx_number_parts_clist \siunitx_number_in_check_uncertainty:n \prop_if_in:NnT \l_siunitx_number_in_prop { exponent } { \prop_if_in:NnF \l_siunitx_number_in_prop { exponent-integer } { \prop_if_in:NnF \l_siunitx_number_in_prop { exponent-decimal } { \prop_if_in:NnF \l_siunitx_number_in_prop { exponent-complex } { \siunitx_error:n { empty-exponent } } } } } } \cs_new_nopar:Npn \siunitx_number_in_check_uncertainty:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop { #1 -uncertainty } { \prop_if_in:NnF \l_siunitx_number_in_prop { #1 -integer } { \prop_if_in:NnF \l_siunitx_number_in_prop { #1 -decimal } { \siunitx_error:n { uncertainty-only } } } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_complex:n} %\begin{macro}[aux]{\siunitx_number_in_complex_aux:N} % 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} \cs_new_nopar:Npn \siunitx_number_in_complex:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop {#1} { \prop_get:NnN \l_siunitx_number_in_prop {#1} \l_siunitx_tmpa_tl \cs_set:Npn \siunitx_number_in_complex_aux:N ##1 { \tl_if_in:NnT \l_siunitx_tmpa_tl {##1} { \siunitx_number_in_complex_check:N ##1 \prop_put:Nnn \l_siunitx_number_in_prop { #1 -complex } { } \tl_map_break: } } \tl_map_function:NN \l_siunitx_input_complex_tl \siunitx_number_in_complex_aux:N \bool_if:NF \l_siunitx_error_bool { \prop_if_in:NnT \l_siunitx_number_in_prop { #1 -complex } { \prop_del:Nn \l_siunitx_number_in_prop {#1} \prop_del:Nn \l_siunitx_number_in_prop { #1 -complex } \siunitx_number_in_complex_separate:n {#1} \siunitx_number_in_complex_tidy:n {#1} } } \bool_if:NF \l_siunitx_error_bool { \siunitx_number_in_complex_check:n {#1} } } } \cs_new:Npn \siunitx_number_in_complex_aux:N #1 { } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_number_in_complex_check:N} % To avoid needing to use a second loop to check for the last letter, % a bit of trickery. The argument |##2| has to be empty for the % number to be valid. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_complex_check:N #1 { \cs_set:Npn \siunitx_tmp:w ##1 #1 ##2 \q_stop { \tl_if_empty:nTF {##2} { \tl_set:Nn \l_siunitx_tmpa_tl {##1} } { \siunitx_error:nx { misplaced-complex-root } {#1} } } \exp_after:wN \siunitx_tmp:w \l_siunitx_tmpa_tl \q_stop } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_in_complex_separate:n} %\begin{macro}[aux]{\siunitx_number_in_complex_separate_aux:N} %\begin{macro}[aux]{\siunitx_number_in_complex_separate_aux:n} % The second part of the system has to look for a sign. The complex % number is currently in \cs{l_siunitx_tmpa_tl}, so this does not need % to be recovered from the property list. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_complex_separate:n #1 { \cs_set:Npn \siunitx_number_in_complex_seperate_aux:N ##1 { \tl_if_in:NnT \l_siunitx_tmpa_tl {##1} { \cs_set:Npn \siunitx_tmp:w ####1 ##1 ####2 \q_stop { \tl_if_empty:nF {####1} { \prop_put:Nnn \l_siunitx_number_in_prop {#1} {####1} } \prop_put:Nnn \l_siunitx_number_in_prop { #1 -complex-sign } {##1} \prop_put:Nnn \l_siunitx_number_in_prop { #1 -complex } {####2} } \exp_after:wN \siunitx_tmp:w \l_siunitx_tmpa_tl \q_stop } } \tl_map_function:NN \l_siunitx_input_sign_tl \siunitx_number_in_complex_seperate_aux:N } \cs_new:Npn \siunitx_number_in_complex_seperate_aux:N #1 { } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_number_in_complex_tidy:n} % There is a need to check that the signs match up with the appropriate % parts of the number. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_complex_tidy:n #1 { \prop_if_in:NnF \l_siunitx_number_in_prop { #1 -complex } { \prop_put:NnV \l_siunitx_number_in_prop { #1 -complex } \l_siunitx_tmpa_tl \prop_if_in:NnT \l_siunitx_number_in_prop { #1 -sign } { \prop_get:NnN \l_siunitx_number_in_prop { #1 -sign } \l_siunitx_tmpa_tl \prop_del:Nn \l_siunitx_number_in_prop { #1 -sign } \prop_put:NnV \l_siunitx_number_in_prop { #1 -complex-sign } \l_siunitx_tmpa_tl } } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_in_complex_check:n} %\begin{macro}[aux]{\siunitx_number_in_complex_check_aux:n} %\begin{macro}[aux]{\siunitx_number_in_complex_check_aux:N} % Finally for complex numbers, make sure there are no stray tokens. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_complex_check:n #1 { \siunitx_number_in_complex_check_aux:n {#1} \siunitx_number_in_complex_check_aux:n { #1 -complex } } \cs_new_nopar:Npn \siunitx_number_in_complex_check_aux:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop {#1} { \prop_get:NnN \l_siunitx_number_in_prop {#1} \l_siunitx_tmpa_tl \cs_set:Npn \siunitx_number_in_complex_check_aux:N ##1 { \tl_if_in:NnT \l_siunitx_tmpa_tl {##1} { \siunitx_error:nx { misplaced-sign } {##1} \tl_map_break: } } \tl_map_function:NN \l_siunitx_input_sign_tl \siunitx_number_in_uncertainty_check_aux:N \cs_set:Npn \siunitx_number_in_complex_check_aux:N ##1 { \tl_if_in:NnT \l_siunitx_tmpa_tl {##1} { \siunitx_error:nx { misplaced-complex-root } {##1} \tl_map_break: } } \tl_map_function:NN \l_siunitx_input_complex_tl \siunitx_number_in_uncertainty_check_aux:N } } \cs_new:Npn \siunitx_number_in_complex_check_aux:N #1 { } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_decimal:n} % The real and complex parts need a slightly different lead-off test % here, as a valid complex number can have no digits at all. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_decimal:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop {#1} { \prop_get:NnN \l_siunitx_number_in_prop {#1} \l_siunitx_tmpa_tl \siunitx_number_in_decimal_aux:n {#1} } } \cs_new_nopar:Npn \siunitx_number_in_decimal_complex:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop { #1 -complex } { \prop_get:NnN \l_siunitx_number_in_prop { #1 -complex } \l_siunitx_tmpa_tl \tl_if_empty:NTF \l_siunitx_tmpa_tl { \prop_put:Nnn \l_siunitx_number_in_prop { #1 -complex-integer } { } } { \siunitx_number_in_decimal_aux:n { #1 -complex } } } } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{\siunitx_number_in_decimal_aux:n} %\begin{macro}[aux]{\siunitx_number_in_decimal_aux:N} % 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. The decimal token is also saved so that it will be available % later in the output routine (needed under certain circumstances). % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_decimal_aux:n #1 { \tl_if_empty:NF \l_siunitx_tmpa_tl { \prop_put:NnV \l_siunitx_number_in_prop { #1 -integer } \l_siunitx_tmpa_tl } \cs_set:Npn \siunitx_number_in_decimal_aux:N ##1 { \tl_if_in:NnT \l_siunitx_tmpa_tl {##1} { \cs_set:Npn \siunitx_tmp:w ####1 ##1 ####2 \q_stop { \tl_if_empty:nTF {####1} { \prop_del:Nn \l_siunitx_number_in_prop { #1 -integer } } { \prop_put:Nnn \l_siunitx_number_in_prop { #1 -integer } {####1} } \prop_put:Nnn \l_siunitx_number_in_prop { #1 -decimal } {####2} \prop_put:Nnn \l_siunitx_number_in_prop { #1 -decimal-symbol } {##1} } \exp_after:wN \siunitx_tmp:w \l_siunitx_tmpa_tl \q_stop \tl_map_break: } } \tl_map_function:NN \l_siunitx_input_decimal_tl \siunitx_number_in_decimal_aux:N \siunitx_number_in_decimal_check:n { #1 -integer } \siunitx_number_in_decimal_check:n { #1 -decimal } } \cs_new:Npn \siunitx_number_in_decimal_aux:N #1 { } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}[aux]{\siunitx_number_in_decimal_check:n} %\begin{macro}[aux]{\siunitx_number_in_decimal_check:N} % A short function which makes sure that there is only one decimal % marker. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_decimal_check:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop {#1} { \prop_get:NnN \l_siunitx_number_in_prop {#1} \l_siunitx_tmpa_tl \tl_map_function:NN \l_siunitx_input_decimal_tl \siunitx_number_in_decimal_check:N } } \cs_new:Npn \siunitx_number_in_decimal_check:N #1 { \tl_if_in:NnT \l_siunitx_tmpa_tl {#1} { \siunitx_error:n { duplicate-decimal-token } \tl_map_break: } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_exponent:} %\begin{macro}[aux]{\siunitx_number_in_exponent_aux:N} % Check for an exponent marker, and if it is there do the separation. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_exponent: { \tl_map_function:NN \l_siunitx_input_exponent_tl \siunitx_number_in_exponent_aux:N } \cs_new:Npn \siunitx_number_in_exponent_aux:N #1 { \prop_put:NnV \l_siunitx_number_in_prop { mantissa } \l_siunitx_number_arg_tl \tl_if_in:NnT \l_siunitx_number_arg_tl {#1} { \cs_set:Npn \siunitx_tmp:w ##1 #1 ##2 \q_stop { \prop_put:Nnn \l_siunitx_number_in_prop { mantissa } {##1} \prop_put:Nnn \l_siunitx_number_in_prop { exponent } {##2} \tl_set:Nn \l_siunitx_tmpa_tl {##2} \tl_if_empty:nT {##1} { \tl_if_empty:nT {##2} { \siunitx_error:n { empty-number } } } } \exp_after:wN \siunitx_tmp:w \l_siunitx_number_arg_tl \q_stop \tl_if_in:NnT \l_siunitx_tmpa_tl {#1} { \siunitx_error:n { duplicate-exponent-token } } \tl_map_break: } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_init:} % In the initialisation code, the token list % \cs{l_siunitx_number_valid_tl} is constructed for the checks. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_init: { \bool_set_false:N \l_siunitx_error_bool \prop_clear:N \l_siunitx_number_in_prop \group_begin: \siunitx_number_in_protect: \tl_set:Nx \l_siunitx_number_valid_tl { \l_siunitx_input_sign_tl \l_siunitx_input_ignore_tl \l_siunitx_input_digit_tl \l_siunitx_input_decimal_tl \l_siunitx_input_exponent_tl \l_siunitx_input_complex_tl \l_siunitx_input_symbol_tl \l_siunitx_input_uncert_open_tl \l_siunitx_input_uncert_close_tl } \exp_args:NNNV \group_end: \tl_set:Nn \l_siunitx_number_valid_tl \l_siunitx_number_valid_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_in_loop:n} %\begin{macro}{\siunitx_number_in_loop:V} %\begin{macro}[aux]{\siunitx_number_in_loop_aux:N} % 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 \enquote{symbolic} % tokens are present in the input. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_loop:n #1 { \tl_clear:N \l_siunitx_number_arg_tl \tl_map_function:nN {#1} \siunitx_number_in_loop_aux:N } \cs_generate_variant:Nn \siunitx_number_in_loop:n { V } \cs_new:Npn \siunitx_number_in_loop_aux:N #1 { \tl_if_in:NnF \l_siunitx_number_valid_tl {#1} { \siunitx_error:nxx { invalid-token-in-number } {#1} { \l_siunitx_number_valid_tl } \tl_map_break: } \tl_if_in:NnF \l_siunitx_input_ignore_tl {#1} { \tl_put_right:Nn \l_siunitx_number_arg_tl {#1} } \tl_if_in:NnT \l_siunitx_input_symbol_tl {#1} { \prop_put:Nnn \l_siunitx_number_in_prop { symbolic } { true } } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_protect:} %\begin{macro}[aux]{\siunitx_number_in_protect_aux:N} % Under some circumstances (for example when loading \pkg{breqn}) % some tokens do not behave safely under \texttt{x} expansion (at the % moment). To get round this, they are redefined here. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_protect: { \tl_map_function:NN \l_siunitx_input_protect_tl \siunitx_number_in_protect_aux:N } \cs_new:Npn \siunitx_number_in_protect_aux:N #1 { \cs_set_eq:NN #1 \scan_stop: } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_separate:} %\begin{macro}[aux]{\siunitx_number_in_separate_aux:n} % 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. At each stage where an % error might arise, a check is made for the error switch. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_separate: { \siunitx_number_in_exponent: \siunitx_number_in_separate_aux:n { exponent } \siunitx_number_in_separate_aux:n { mantissa } } \cs_new_nopar:Npn \siunitx_number_in_separate_aux:n #1 { \bool_if:NF \l_siunitx_error_bool { \siunitx_number_in_sign:n {#1} \siunitx_number_in_complex:n {#1} } \bool_if:NF \l_siunitx_error_bool { \siunitx_number_in_decimal:n {#1} \siunitx_number_in_decimal_complex:n {#1} } \bool_if:NF \l_siunitx_error_bool { \siunitx_number_in_uncertainty:n {#1} \siunitx_number_in_uncertainty:n { #1 -complex } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_sign:n} % Separating signs first converts \enquote{\texttt{+-}} to \cs{pm} and % \enquote{\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} \cs_new_nopar:Npn \siunitx_number_in_sign:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop {#1} { \prop_get:NnN \l_siunitx_number_in_prop {#1} \l_siunitx_tmpa_tl \tl_replace_all_in:Nnn \l_siunitx_tmpa_tl { -+ } { \mp } \tl_replace_all_in:Nnn \l_siunitx_tmpa_tl { +- } { \pm } \cs_set:Npn \siunitx_tmp:w ##1##2 \q_stop { \tl_if_in:NnTF \l_siunitx_input_sign_tl {##1} { \prop_put:Nnn \l_siunitx_number_in_prop { #1 -sign } { ##1 } \prop_put:Nnn \l_siunitx_number_in_prop {#1} { ##2 } } { \prop_put:Nnn \l_siunitx_number_in_prop {#1} { ##1 ##2 } } } \tl_if_empty:NF \l_siunitx_tmpa_tl { \exp_after:wN \siunitx_tmp:w \l_siunitx_tmpa_tl \q_stop } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_in_tidy:} % There are some minor bits of tidying up to do now. Two issues need to % be handled, both concerned with zero. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_tidy: { \clist_map_function:NN \c_siunitx_number_parts_clist \siunitx_number_in_tidy_zeros:n \prop_if_in:NnT \l_siunitx_number_in_prop { mantissa } { \prop_if_in:NnT \l_siunitx_number_in_prop { mantissa-sign } { \prop_get:NnN \l_siunitx_number_in_prop { mantissa } \l_siunitx_tmpa_tl \tl_if_empty:NT \l_siunitx_tmpa_tl { \prop_del:Nn \l_siunitx_number_in_prop { mantissa } \prop_get:NnN \l_siunitx_number_in_prop { mantissa-sign } \l_siunitx_tmpa_tl \prop_del:Nn \l_siunitx_number_in_prop { mantissa-sign } \prop_put:NnV \l_siunitx_number_in_prop { sign } \l_siunitx_tmpa_tl } } } \siunitx_number_in_tidy_sign:n { mantissa } \siunitx_number_in_tidy_sign:n { exponent } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_in_tidy_zeros:n} % 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} \cs_new_nopar:Npn \siunitx_number_in_tidy_zeros:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop { #1 -integer } { \prop_get:NnN \l_siunitx_number_in_prop { #1 -integer } \l_siunitx_tmpa_tl \tl_if_in:NnT \l_siunitx_tmpa_tl { 0 } { \cs_set:Npn \siunitx_tmp:w ##1 0 ##2 \q_stop { \tl_if_empty:nTF {##1} { \tl_if_in:nnTF {##2} { 0 } { \siunitx_tmp:w ##2 \q_stop } { \tl_set:Nn \l_siunitx_tmpa_tl {##2} \prop_put:Nnn \l_siunitx_number_in_prop { #1 -integer } {##2} } } { \prop_put:Nnn \l_siunitx_number_in_prop { #1 -integer } { ##1 0 ##2 } } } \exp_after:wN \siunitx_tmp:w \l_siunitx_tmpa_tl \q_stop \tl_if_empty:NT \l_siunitx_tmpa_tl { \prop_put:Nnn \l_siunitx_number_in_prop { #1 -integer } { 0 } } } } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_in_tidy_sign:n} %\begin{macro}[aux]{\siunitx_number_in_tidy_sign_aux_i:n} %\begin{macro}[aux]{\siunitx_number_in_tidy_sign_aux_ii:n} % 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. 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} \cs_new_nopar:Npn \siunitx_number_in_tidy_sign:n #1 { \prop_if_in:NnTF \l_siunitx_number_in_prop {#1} { \siunitx_number_in_tidy_sign_aux_i:n {#1} } { \siunitx_number_in_tidy_sign_aux_i:n { #1 -complex } } } \cs_new_nopar:Npn \siunitx_number_in_tidy_sign_aux_i:n #1 { \prop_if_in:NnTF \l_siunitx_number_in_prop { #1 -integer } { \prop_get:NnN \l_siunitx_number_in_prop { #1 -integer } \l_siunitx_tmpa_tl \tl_if_eq:nVTF { 0 } \l_siunitx_tmpa_tl { \siunitx_number_in_tidy_sign_aux_ii:n {#1} } { \tl_if_empty:NT \l_siunitx_tmpa_tl { \prop_if_in:NnT \l_siunitx_number_in_prop { #1 -decimal } { \siunitx_number_in_tidy_sign_aux_ii:n {#1} } } } } { \siunitx_number_in_tidy_sign_aux_ii:n {#1} } } \cs_new_nopar:Npn \siunitx_number_in_tidy_sign_aux_ii:n #1 { \prop_if_in:NnTF \l_siunitx_number_in_prop { #1 -decimal } { \prop_get:NnN \l_siunitx_number_in_prop { #1 -decimal } \l_siunitx_tmpa_tl \cs_set:Npn \siunitx_tmp:w ##1 { \tl_if_eq:nnF {##1} { 0 } { \tl_clear:N \l_siunitx_tmpa_tl \tl_map_break: } } \tl_reverse:N \l_siunitx_tmpa_tl \tl_map_function:NN \l_siunitx_tmpa_tl \siunitx_tmp:w \tl_if_empty:NF \l_siunitx_tmpa_tl { \prop_del:Nn \l_siunitx_number_in_prop { #1 -sign } } } { \prop_del:Nn \l_siunitx_number_in_prop { #1 -sign } } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_uncertainty:n} %\begin{macro}[aux]{\siunitx_number_in_uncertainty_close:nn} %\begin{macro}[aux]{\siunitx_number_in_uncertainty_close:N} % Finding any uncertainty depends on whether there is a decimal part. 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} \cs_new_nopar:Npn \siunitx_number_in_uncertainty:n #1 { \prop_if_in:NnTF \l_siunitx_number_in_prop { #1 -decimal } { \siunitx_number_in_uncertainty_close:nn {#1} { decimal } } { \prop_if_in:NnT \l_siunitx_number_in_prop { #1 -integer } { \siunitx_number_in_uncertainty_close:nn {#1} { integer } } } \siunitx_number_in_uncertainty_check:n {#1} } \cs_new_nopar:Npn \siunitx_number_in_uncertainty_close:nn #1#2 { \prop_get:NnN \l_siunitx_number_in_prop { #1 - #2 } \l_siunitx_tmpa_tl \cs_set:Npn \siunitx_number_in_uncertainty_close:N ##1 { \tl_if_in:NnT \l_siunitx_tmpa_tl {##1} { \cs_set:Npn \siunitx_tmp:w ####1 ##1 ####2 \q_stop { \tl_if_empty:nTF {####2} { \prop_put:Nnn \l_siunitx_number_in_prop { #1 -uncertainty } { } \tl_set:Nn \l_siunitx_tmpa_tl {####1} } { \siunitx_error:nx { misplaced-closing-uncertainty } {##1} } } \exp_after:wN \siunitx_tmp:w \l_siunitx_tmpa_tl \q_stop \tl_map_break: } } \tl_map_function:NN \l_siunitx_input_uncert_close_tl \siunitx_number_in_uncertainty_close:N \prop_if_in:NnT \l_siunitx_number_in_prop { #1 - uncertainty } { \siunitx_number_in_uncertainty_open:nn {#1} {#2} } } \cs_new:Npn \siunitx_number_in_uncertainty_close:N #1 { } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}[aux]{\siunitx_number_in_uncertainty_open:nn} %\begin{macro}[aux]{\siunitx_number_in_uncertainty_open:N} % Now to look for the opening character. This is done on the basis that % a search can always look first in the integer part. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_uncertainty_open:nn #1#2 { \cs_set:Npn \siunitx_number_in_uncertainty_open:N ##1 { \tl_if_in:NnT \l_siunitx_tmpa_tl {##1} { \cs_set:Npn \siunitx_tmp:w ####1 ##1 ####2 \q_stop { \prop_put:Nnn \l_siunitx_number_in_prop { #1 - #2 } {####1} \prop_put:Nnn \l_siunitx_number_in_prop { #1 -uncertainty } {####2} \tl_if_empty:nT {####2} { \siunitx_error:n { empty-uncertainty } } } \exp_after:wN \siunitx_tmp:w \l_siunitx_tmpa_tl \q_stop \tl_map_break: } } \tl_map_function:NN \l_siunitx_input_uncert_open_tl \siunitx_number_in_uncertainty_open:N } \cs_new:Npn \siunitx_number_in_uncertainty_open:N #1 { } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_number_in_uncertainty_check:n} %\begin{macro}{\siunitx_number_in_uncertainty_check_aux:n} %\begin{macro}{\siunitx_number_in_uncertainty_check_aux:N} % To make sure no stray tokens are about. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_uncertainty_check:n #1 { \siunitx_number_in_uncertainty_check_aux:n { #1 -integer } \siunitx_number_in_uncertainty_check_aux:n { #1 -decimal } \siunitx_number_in_uncertainty_check_aux:n { #1 -uncertainty } } \cs_new_nopar:Npn \siunitx_number_in_uncertainty_check_aux:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop {#1} { \prop_get:NnN \l_siunitx_number_in_prop {#1} \l_siunitx_tmpa_tl \tl_map_function:NN \l_siunitx_input_uncert_open_tl \siunitx_number_in_uncertainty_check_aux:N \tl_map_function:NN \l_siunitx_input_uncert_close_tl \siunitx_number_in_uncertainty_check_aux:N } } \cs_new:Npn \siunitx_number_in_uncertainty_check_aux:N #1 { \tl_if_in:NnT \l_siunitx_tmpa_tl {#1} { \siunitx_error:nx { misplaced-uncertainty } {#1} \tl_map_break: } } % \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 \enquote{formatting}: this is left for the output part of the % system. % %\begin{macro}{\l_siunitx_round_int} %\begin{macro}{\l_siunitx_round_tl} %\begin{macro}{\l_siunitx_round_bool} %\begin{macro}{\l_siunitx_round_decimal_in_tl} %\begin{macro}{\l_siunitx_round_decimal_out_tl} %\begin{macro}{\l_siunitx_round_integer_in_tl} %\begin{macro}{\l_siunitx_round_integer_out_tl} % The rounding system needs a number of variables. % \begin{macrocode} \int_new:N \l_siunitx_round_int \tl_new:N \l_siunitx_round_tl \bool_new:N \l_siunitx_round_bool \tl_new:N \l_siunitx_round_decimal_in_tl \tl_new:N \l_siunitx_round_decimal_out_tl \tl_new:N \l_siunitx_round_integer_in_tl \tl_new:N \l_siunitx_round_integer_out_tl % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_process_decimal_int} %\begin{macro}{\l_siunitx_process_uncertainty_int} %\begin{macro}{\l_siunitx_uncertainty_decimal_tl} %\begin{macro}{\l_siunitx_uncertainty_integer_tl} % The code to expand uncertainties needs to know numbers of digits, and % to store various data. % \begin{macrocode} \int_new:N \l_siunitx_process_decimal_int \int_new:N \l_siunitx_process_uncertainty_int \tl_new:N \l_siunitx_uncertainty_decimal_tl \tl_new:N \l_siunitx_uncertainty_integer_tl % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_process_decimal_zero_bool} %\begin{macro}{\l_siunitx_process_integer_zero_bool} %\begin{macro}{\l_siunitx_process_sign_tl} %\begin{macro}{\l_siunitx_process_plus_tl} %\begin{macro}{\l_siunitx_unity_mantissa_tl} %\begin{macro}{\l_siunitx_process_zero_exponent_bool} %\begin{macro}{\l_siunitx_process_figures_int} %\begin{macro}{\l_siunitx_process_places_int} % First, the options are set up. % \begin{macrocode} \keys_define:nn { siunitx } { add-zero-decimal .bool_set:N = \l_siunitx_process_decimal_zero_bool, add-zero-integer .bool_set:N = \l_siunitx_process_integer_zero_bool, explicit-sign .tl_set:N = \l_siunitx_process_sign_tl, retain-explicit-plus .bool_set:N = \l_siunitx_process_plus_tl, retain-unity-mantissa .bool_set:N = \l_siunitx_process_unity_mantissa_bool, retain-zero-exponent .bool_set:N = \l_siunitx_process_zero_exponent_bool, round-mode .choice: , round-mode / figures .code:n = { \tl_set:Nn \l_siunitx_round_tl { figures } }, round-mode / off .code:n = { \tl_clear:N \l_siunitx_round_tl }, round-mode / places .code:n = { \tl_set:Nn \l_siunitx_round_tl { places } }, round-figures .tl_set:N = \l_siunitx_process_figures_int, round-places .tl_set:N = \l_siunitx_process_places_int, } \keys_set:nn { siunitx } { add-zero-decimal = true, add-zero-integer = true, retain-unity-mantissa = true, round-figures = 2, round-places = 2 } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_process:} % Post-processing is a series of small tasks. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process: { \siunitx_number_process_sign: \siunitx_number_process_zero_fill: \siunitx_number_process_mantissa: \siunitx_number_process_exponent: \prop_if_in:NnF \l_siunitx_number_in_prop { symbolic } { \siunitx_number_process_round: \siunitx_number_process_uncertainty: } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_process_exponent:} %\begin{macro}[aux]{\siunitx_number_process_exponent_aux_i:n} %\begin{macro}[aux]{\siunitx_number_process_exponent_aux_ii:n} %\begin{macro}[aux]{\siunitx_number_process_exponent_clear:n} % To check for a totally zero exponent, the possibility that one or more % of the exponent storage areas is zero needs to be considered. This % means a bit of nesting and some slightly opaque clearing functions. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_exponent: { \bool_if:NF \l_siunitx_process_zero_exponent_bool { \prop_if_in:NnT \l_siunitx_number_in_prop { exponent } { \prop_if_in:NnF \l_siunitx_number_in_prop { symbolic } { \bool_set_false:N \l_siunitx_tmp_bool \siunitx_number_process_exponent_aux_i:n { } \siunitx_number_process_exponent_aux_i:n { complex- } \bool_if:NF \l_siunitx_tmp_bool { \prop_del:Nn \l_siunitx_number_in_prop { exponent } \siunitx_number_process_exponent_clear:n { } \siunitx_number_process_exponent_clear:n { complex- } } } } } } \cs_new_nopar:Npn \siunitx_number_process_exponent_aux_i:n #1 { \siunitx_number_process_exponent_aux_ii:n { #1 integer } \siunitx_number_process_exponent_aux_ii:n { #1 decimal } \siunitx_number_process_exponent_aux_ii:n { #1 uncertainty } } \cs_new_nopar:Npn \siunitx_number_process_exponent_aux_ii:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop { exponent- #1 } { \prop_get:NnN \l_siunitx_number_in_prop { exponent- #1 } \l_siunitx_tmpa_tl \intexpr_compare:nF { \l_siunitx_tmpa_tl = \c_zero } { \bool_set_true:N \l_siunitx_tmp_bool } } } \cs_new_nopar:Npn \siunitx_number_process_exponent_clear:n #1 { \prop_del:Nn \l_siunitx_number_in_prop { exponent- #1 sign } \prop_del:Nn \l_siunitx_number_in_prop { exponent- #1 integer } \prop_del:Nn \l_siunitx_number_in_prop { exponent- #1 decimal } \prop_del:Nn \l_siunitx_number_in_prop { exponent- #1 uncertainty } \prop_del:Nn \l_siunitx_number_in_prop { exponent- #1 complex } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_process_figures:n} %\begin{macro}[aux]{\siunitx_number_process_figures_aux:n} %\begin{macro}[aux]{\siunitx_number_process_figures_init:n} % Rather than count figures to start with, a completely different % approach is used here. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_figures:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop {#1} { \siunitx_number_process_figures_aux:n {#1} } } \cs_new_nopar:Npn \siunitx_number_process_figures_aux:n #1 { \siunitx_number_process_figures_init:n {#1} \siunitx_number_process_figures_count:n { integer } \siunitx_number_process_figures_count:n { decimal } \bool_if:NTF \l_siunitx_round_bool { \bool_set_false:N \l_siunitx_round_bool \intexpr_compare:nTF { \l_siunitx_round_int > \l_siunitx_process_figures_int } { \siunitx_number_process_figures_round: } { \siunitx_number_process_figures_pad:n {#1} } \siunitx_number_process_round_tidy:n {#1} } { \prop_put:Nnn \l_siunitx_number_in_prop { #1 -integer } { 0 } \prop_del:Nn \l_siunitx_number_in_prop { #1 -decimal } } } \cs_new_nopar:Npn \siunitx_number_process_figures_init:n #1 { \int_zero:N \l_siunitx_round_int \bool_set_false:N \l_siunitx_round_bool \prop_if_in:NnTF \l_siunitx_number_in_prop { #1 -decimal } { \prop_get:NnN \l_siunitx_number_in_prop { #1 -decimal } \l_siunitx_round_decimal_in_tl } { \tl_clear:N \l_siunitx_round_decimal_in_tl } \prop_if_in:NnTF \l_siunitx_number_in_prop { #1 -integer } { \prop_get:NnN \l_siunitx_number_in_prop { #1 -integer } \l_siunitx_round_integer_in_tl } { \tl_clear:N \l_siunitx_round_integer_in_tl } \tl_clear:N \l_siunitx_round_decimal_out_tl \tl_clear:N \l_siunitx_round_integer_out_tl } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_number_process_figures_count:n} %\begin{macro}[aux]{\siunitx_number_process_figures_count_aux:n} % The counting code has to check that characters are actually % significant. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_figures_count:n #1 { \tl_if_empty:cF { l_siunitx_round_ #1 _in_tl } { \prop_if_in:NnF \l_siunitx_number_in_prop { #1 -uncertainty } { \siunitx_number_process_figures_count_aux:n {#1} } } } \cs_new_nopar:Npn \siunitx_number_process_figures_count_aux:n #1 { \int_set:Nn \l_siunitx_tmp_int { \exp_args:Nv \tl_head_i:n { l_siunitx_round_ #1 _in_tl } } \tl_set:cx { l_siunitx_round_ #1 _in_tl } { \exp_args:Nv \tl_tail:n { l_siunitx_round_ #1 _in_tl } } \tl_put_left:cV { l_siunitx_round_ #1 _out_tl } \l_siunitx_tmp_int \bool_if:NF \l_siunitx_round_bool { \intexpr_compare:nF { \l_siunitx_tmp_int = \c_zero } { \bool_set_true:N \l_siunitx_round_bool } } \bool_if:NT \l_siunitx_round_bool { \int_incr:N \l_siunitx_round_int } \tl_if_empty:cTF { l_siunitx_round_ #1 _in_tl } { \tl_set_eq:cc { l_siunitx_round_ #1 _in_tl } { l_siunitx_round_ #1 _out_tl } \tl_clear:c { l_siunitx_round_ #1 _out_tl } } { \siunitx_number_process_figures_count_aux:n {#1} } } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_number_process_figures_round:} %\begin{macro}[aux]{\siunitx_number_process_figures_round_loop:} % The control macro for rounding to figures does the decimal part % then the integer part as loops. There is then some tidying up if a % digit is carried at the end. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_figures_round: { \int_set:Nn \l_siunitx_round_int { \l_siunitx_round_int - \l_siunitx_process_figures_int } \tl_if_empty:NF \l_siunitx_round_decimal_in_tl { \siunitx_number_process_figures_round_loop: } \tl_if_empty:NF \l_siunitx_round_integer_in_tl { \siunitx_number_process_figures_integer: } \bool_if:NT \l_siunitx_round_bool { \tl_put_left:Nn \l_siunitx_round_integer_out_tl { 1 } \tl_if_empty:NF \l_siunitx_round_decimal_out_tl { \tl_reverse:N \l_siunitx_round_decimal_out_tl \tl_set:Nx \l_siunitx_round_decimal_out_tl { \tl_tail:n \l_siunitx_round_decimal_out_tl } \tl_reverse:N \l_siunitx_round_decimal_out_tl } } } \cs_new_nopar:Npn \siunitx_number_process_figures_round_loop: { \siunitx_number_process_round_decimal: \tl_if_empty:NF \l_siunitx_round_decimal_in_tl { \siunitx_number_process_figures_round_loop: } } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_number_process_figures_integer:} % For figures, the integer part is a little complicated as zeros need % to be included. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_figures_integer: { \intexpr_compare:nT { \l_siunitx_round_int > \c_zero } { \tl_put_left:Nn \l_siunitx_round_integer_out_tl { 0 } } \intexpr_compare:nF { \l_siunitx_round_int > \c_one } { \int_set:Nn \l_siunitx_tmp_int { \exp_args:NV \tl_head_i:n \l_siunitx_round_integer_in_tl } \bool_if:NT \l_siunitx_round_bool { \int_incr:N \l_siunitx_tmp_int } \bool_set_false:N \l_siunitx_round_bool \intexpr_compare:nTF { \l_siunitx_round_int = \c_one } { \intexpr_compare:nT { \l_siunitx_tmp_int > \c_four } { \bool_set_true:N \l_siunitx_round_bool } } { \intexpr_compare:nT { \l_siunitx_tmp_int > \c_ten } { \bool_set_true:N \l_siunitx_round_bool \int_zero:N \l_siunitx_tmp_int } \tl_put_left:NV \l_siunitx_round_integer_out_tl \l_siunitx_tmp_int } } \int_decr:N \l_siunitx_round_int \tl_set:Nx \l_siunitx_round_integer_in_tl { \exp_args:NV \tl_tail:n \l_siunitx_round_integer_in_tl } \tl_if_empty:NF \l_siunitx_round_integer_in_tl { \siunitx_number_process_figures_integer: } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_process_figures_pad:n} % If the number is too short, then the reversal is undone and the % padding routine is called. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_figures_pad:n #1 { \prop_get:NnN \l_siunitx_number_in_prop { #1 -integer } \l_siunitx_round_integer_in_tl \prop_get:NnN \l_siunitx_number_in_prop { #1 -decimal } \l_siunitx_round_decimal_in_tl \int_set:Nn \l_siunitx_round_int { \l_siunitx_process_figures_int - \l_siunitx_round_int } \siunitx_number_process_pad:n {#1} } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_process_mantissa:} % A check for the mantissa consisting only of the token \texttt{1}, when % an exponent is also available. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_mantissa: { \bool_if:NF \l_siunitx_process_unity_mantissa_bool { \prop_if_in:NnT \l_siunitx_number_in_prop { exponent } { \prop_if_in:NnT \l_siunitx_number_in_prop { mantissa } { \prop_get:NnN \l_siunitx_number_in_prop { mantissa } \l_siunitx_tmpa_tl \tl_if_eq:nVT { 1 } \l_siunitx_tmpa_tl { \prop_del:Nn \l_siunitx_number_in_prop { mantissa } \prop_del:Nn \l_siunitx_number_in_prop { mantissa-integer } } } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_process_pad:n} % For padding a number by adding zero to the end repeatedly. This can % happen if the input was zero or if the number is too short. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_pad:n #1 { \prop_get:NnN \l_siunitx_number_in_prop { #1 -decimal } \l_siunitx_tmpa_tl \intexpr_while_do:nn { \l_siunitx_round_int > \c_zero } { \tl_put_right:Nn \l_siunitx_tmpa_tl { 0 } \int_decr:N \l_siunitx_round_int } \prop_put:NnV \l_siunitx_number_in_prop { #1 -decimal } \l_siunitx_tmpa_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_process_places:n} %\begin{macro}[aux]{\siunitx_number_process_places_aux_i:n} % For rounding to a fixed number of places, a check is made to see if % the decimal part is exactly zero. If it is, just create the % appropriate number of zeros in the padding routine. Otherwise, do the % real work. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_places:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop {#1} { \prop_if_in:NnF \l_siunitx_number_in_prop { #1 -uncertainty } { \siunitx_number_process_places_aux_i:n {#1} } } } \cs_new_nopar:Npn \siunitx_number_process_places_aux_i:n #1 { \intexpr_compare:nTF { \l_siunitx_process_places_int = \c_zero } { \prop_del:Nn \l_siunitx_number_in_prop { #1 -decimal } } { \prop_if_in:NnT \l_siunitx_number_in_prop { #1 -decimal } { \prop_get:NnN \l_siunitx_number_in_prop { #1 -decimal } \l_siunitx_tmpa_tl \tl_if_empty:NT \l_siunitx_tmpa_tl { \tl_set:Nn \l_siunitx_tmpa_tl { 0 } } \intexpr_compare:nTF { \l_siunitx_tmpa_tl = \c_zero } { \prop_put:Nnn \l_siunitx_number_in_prop { #1 -decimal } { } \int_set_eq:NN \l_siunitx_round_int \l_siunitx_process_places_int \siunitx_number_process_pad:n {#1} } { \int_set:Nn \l_siunitx_round_int { \tl_elt_count:N \l_siunitx_tmpa_tl } \siunitx_number_process_places_aux_ii:n {#1} } } } } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}[aux]{\siunitx_number_process_places_aux_ii:n} % For rounding to a fixed number of places, the package finds the % difference in length between what is present and what is required. % If the number is too short, there is some simple padding to do. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_places_aux_ii:n #1 { \int_sub:Nn \l_siunitx_round_int { \l_siunitx_process_places_int } \intexpr_compare:nTF { \l_siunitx_round_int < \c_zero } { \int_set:Nn \l_siunitx_round_int { - \l_siunitx_round_int } \siunitx_number_process_pad:n {#1} } { \siunitx_number_process_places_init:n {#1} \siunitx_number_process_places_loop:n {#1} \siunitx_number_process_round_tidy:n {#1} } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_process_places_init:n} % To keep the code a little clearer. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_places_init:n #1 { \prop_if_in:NnTF \l_siunitx_number_in_prop { #1 -integer } { \prop_get:NnN \l_siunitx_number_in_prop { #1 -integer } \l_siunitx_round_integer_in_tl } { \tl_clear:N \l_siunitx_round_integer_in_tl } \prop_get:NnN \l_siunitx_number_in_prop { #1 -decimal } \l_siunitx_round_decimal_in_tl \tl_reverse:N \l_siunitx_round_integer_in_tl \tl_reverse:N \l_siunitx_round_decimal_in_tl \tl_clear:N \l_siunitx_round_integer_out_tl \tl_clear:N \l_siunitx_round_decimal_out_tl \bool_set_false:N \l_siunitx_round_bool } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{\siunitx_number_process_places_loop:n} % If there is a decimal, do the decimal processing then come back here. % If there is an integer, do the same. Only if both are empty does the % loop stop. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_places_loop:n #1 { \tl_if_empty:NTF \l_siunitx_round_decimal_in_tl { \tl_if_empty:NF \l_siunitx_round_integer_in_tl { \siunitx_number_process_places_integer:n {#1} \siunitx_number_process_places_loop:n {#1} } \bool_if:NT \l_siunitx_round_bool { \tl_put_left:Nn \l_siunitx_round_integer_out_tl { 1 } \bool_set_false:N \l_siunitx_round_bool } } { \siunitx_number_process_round_decimal: \siunitx_number_process_places_loop:n {#1} } } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{\siunitx_number_process_places_integer:n} % Rounding for integers is just a case of carrying digits. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_places_integer:n #1 { \int_set:Nn \l_siunitx_tmp_int { \exp_args:NV \tl_head_i:n \l_siunitx_round_integer_in_tl } \tl_set:Nx \l_siunitx_round_integer_in_tl { \exp_args:NV \tl_tail:n \l_siunitx_round_integer_in_tl } \bool_if:NT \l_siunitx_round_bool { \int_incr:N \l_siunitx_tmp_int } \bool_set_false:N \l_siunitx_round_bool \intexpr_compare:nT { \l_siunitx_tmp_int = \c_ten } { \int_zero:N \l_siunitx_tmp_int \bool_set_true:N \l_siunitx_round_bool } \tl_put_left:NV \l_siunitx_round_integer_out_tl \l_siunitx_tmp_int } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_process_round:} % The lead-off for rounding is the same for decimal places and % significant figures. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_round: { \tl_if_empty:NF \l_siunitx_round_tl { \exp_args:NNc \clist_map_function:NN \c_siunitx_number_parts_clist { siunitx_number_process_ \l_siunitx_round_tl :n } } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_process_round_decimal:} %\begin{macro}[aux]{\siunitx_number_process_round_decimal_aux:} % The rounding routine for decimals is the same for figures and places, % so there is a generalised function here. Unfortunately, it is also % complicated! % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_round_decimal: { \intexpr_compare:nF { \l_siunitx_round_int > \c_one } { \siunitx_number_process_round_decimal_aux: } \tl_set:Nx \l_siunitx_round_decimal_in_tl { \exp_args:NV \tl_tail:n \l_siunitx_round_decimal_in_tl } \int_decr:N \l_siunitx_round_int } \cs_new_nopar:Npn \siunitx_number_process_round_decimal_aux: { \int_set:Nn \l_siunitx_tmp_int { \exp_args:NV \tl_head_i:n \l_siunitx_round_decimal_in_tl } \bool_if:NT \l_siunitx_round_bool { \int_incr:N \l_siunitx_tmp_int } \bool_set_false:N \l_siunitx_round_bool \intexpr_compare:nTF { \l_siunitx_round_int = \c_one } { \intexpr_compare:nT { \l_siunitx_tmp_int > \c_four } { \bool_set_true:N \l_siunitx_round_bool } } { \intexpr_compare:nT { \l_siunitx_tmp_int = \c_ten } { \bool_set_true:N \l_siunitx_round_bool \int_zero:N \l_siunitx_tmp_int } \tl_put_left:NV \l_siunitx_round_decimal_out_tl \l_siunitx_tmp_int } } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_number_process_round_tidy:n} % To put data back again. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_round_tidy:n #1 { \prop_put:NnV \l_siunitx_number_in_prop { #1 -integer } \l_siunitx_round_integer_out_tl \prop_put:NnV \l_siunitx_number_in_prop { #1 -decimal } \l_siunitx_round_decimal_out_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_process_sign:} % Sorting out signs consists of two parts: retaining a plus if necessary % and adding an explicit sign. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_sign: { \bool_if:NF \l_siunitx_process_plus_tl { \siunitx_number_process_sign_plus:n { exponent } \siunitx_number_process_sign_plus:n { mantissa } } \tl_if_empty:NF \l_siunitx_process_sign_tl { \siunitx_number_process_sign_add:n { exponent } \siunitx_number_process_sign_add:n { mantissa } } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_process_sign_add:n} %\begin{macro}[aux]{\siunitx_number_process_sign_add_aux:n} % Adding a sign to an existing number needs a couple of tests and % saves code with an auxiliary function. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_sign_add:n #1 { \prop_if_in:NnTF \l_siunitx_number_in_prop {#1} { \siunitx_number_process_sign_add_aux:n {#1} } { \prop_if_in:NnT \l_siunitx_number_in_prop { #1 -complex } { \siunitx_number_process_sign_add_aux:n { #1 -complex } } } } \cs_new_nopar:Npn \siunitx_number_process_sign_add_aux:n #1 { \prop_if_in:NnF \l_siunitx_number_in_prop { #1 -sign } { \prop_if_in:NnT \l_siunitx_number_in_prop {#1} { \prop_get:NnN \l_siunitx_number_in_prop {#1} \l_siunitx_tmpa_tl \tl_if_empty:NTF \l_siunitx_tmpa_tl { \prop_put:NnV \l_siunitx_number_in_prop { sign } \l_siunitx_process_sign_tl } { \prop_put:NnV \l_siunitx_number_in_prop { #1 -sign } \l_siunitx_process_sign_tl } } } } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_number_process_sign_plus:n} %\begin{macro}[aux]{\siunitx_number_process_sign_plus_aux:n} % Holding onto a plus works very much in the same way as adding a sign: % some quick tests and an assignment. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_sign_plus:n #1 { \prop_if_in:NnTF \l_siunitx_number_in_prop {#1} { \siunitx_number_process_sign_plus_aux:n {#1} } { \prop_if_in:NnT \l_siunitx_number_in_prop { #1 -complex } { \siunitx_number_process_sign_plus_aux:n { #1 -complex } } } } \cs_new_nopar:Npn \siunitx_number_process_sign_plus_aux:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop { #1 -sign } { \prop_get:NnN \l_siunitx_number_in_prop { #1 -sign } \l_siunitx_tmpa_tl \tl_if_eq:nVT { + } \l_siunitx_tmpa_tl { \prop_del:Nn \l_siunitx_number_in_prop { #1 -sign } } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_process_uncertainty:} %\begin{macro}[aux]{\siunitx_number_process_uncertainty_aux:n} % There may be a need to expand uncertainties into a decimal and integer % part. This is done here so that the core \texttt{in} code is faster. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_uncertainty: { \clist_map_function:NN \c_siunitx_number_parts_clist \siunitx_number_process_uncertainty_aux:n } \cs_new_nopar:Npn \siunitx_number_process_uncertainty_aux:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop { #1 -uncertainty } { \prop_if_in:NnTF \l_siunitx_number_in_prop { #1 -decimal } { \siunitx_number_process_uncertainty_decimal:n {#1} } { \siunitx_number_process_uncertainty_integer:n {#1} } } } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_number_process_uncertainty_decimal:n} %\begin{macro}[aux]{\siunitx_number_process_uncertainty_count:nn} % To deal with an error in the decimal part, care needs to be taken to % correctly pad with zeros and also to allow for the possibility that % the error crosses the decimal--integer boundary. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_uncertainty_decimal:n #1 { \siunitx_number_process_uncertainty_count:nn {#1} { decimal } \siunitx_number_process_uncertainty_count:nn {#1} { uncertainty } \tl_clear:N \l_siunitx_uncertainty_decimal_tl \tl_clear:N \l_siunitx_uncertainty_integer_tl \intexpr_compare:nTF { \l_siunitx_process_uncertainty_int > \l_siunitx_process_decimal_int } { \siunitx_number_process_uncertainty_separate: } { \siunitx_number_process_uncertainty_pad: } \tl_if_empty:NF \l_siunitx_uncertainty_integer_tl { \prop_put:NnV \l_siunitx_number_in_prop { #1 -uncertainty-integer } \l_siunitx_uncertainty_integer_tl } \prop_put:NnV \l_siunitx_number_in_prop { #1 -uncertainty-decimal } \l_siunitx_uncertainty_decimal_tl } \cs_new_nopar:Npn \siunitx_number_process_uncertainty_count:nn #1#2 { \prop_get:NnN \l_siunitx_number_in_prop { #1 - #2 } \l_siunitx_tmpa_tl \int_set:cn { l_siunitx_process_ #2 _int } { \tl_elt_count:N \l_siunitx_tmpa_tl } } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_number_process_uncertainty_pad:} % Uncertainty is short: add zeros. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_uncertainty_pad: { \intexpr_while_do:nn { \l_siunitx_process_uncertainty_int < \l_siunitx_process_decimal_int } { \tl_put_right:Nn \l_siunitx_uncertainty_decimal_tl {0} \int_incr:N \l_siunitx_process_uncertainty_int } \tl_put_right:NV \l_siunitx_uncertainty_decimal_tl \l_siunitx_tmpa_tl } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_process_uncertainty_separate:} %\begin{macro}{\siunitx_number_process_uncertainty_separate_aux:N} % Find the integer--decimal boundary and work appropriately. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_uncertainty_separate: { \tl_map_function:NN \l_siunitx_tmpa_tl \siunitx_number_process_uncertainty_separate_aux:N } \cs_new:Npn \siunitx_number_process_uncertainty_separate_aux:N #1 { \intexpr_compare:nTF { \l_siunitx_process_uncertainty_int > \l_siunitx_process_decimal_int } { \tl_put_right:Nn \l_siunitx_uncertainty_integer_tl {#1} } { \tl_put_right:Nn \l_siunitx_uncertainty_decimal_tl {#1} } \int_decr:N \l_siunitx_process_uncertainty_int } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_number_process_uncertainty_integer:n} % Relatively easy: the uncertainty is in the integer part of the number, % and so there is no need to generate zeros. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_uncertainty_integer:n #1 { \prop_get:NnN \l_siunitx_number_in_prop { #1 -uncertainty } \l_siunitx_tmpa_tl \prop_put:NnV \l_siunitx_number_in_prop { #1 -uncertainty-integer } \l_siunitx_tmpa_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_process_zero_fill:} %\begin{macro}[aux]{\siunitx_number_process_zero_fill_aux:n} %\begin{macro}[aux]{\siunitx_number_process_zero_fill_aux:nn} % Checks for adding zeros to each component are carried out. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_zero_fill: { \siunitx_number_process_zero_fill_aux:n { integer } \siunitx_number_process_zero_fill_aux:n { decimal } } \cs_new_nopar:Npn \siunitx_number_process_zero_fill_aux:n #1 { \bool_if:cT { l_siunitx_process_ #1 _zero_bool } { \siunitx_number_process_zero_fill_aux:nn { mantissa } {#1} \siunitx_number_process_zero_fill_aux:nn { mantissa-complex } {#1} \siunitx_number_process_zero_fill_aux:nn { exponent } {#1} \siunitx_number_process_zero_fill_aux:nn { exponent-complex } {#1} } } \cs_new_nopar:Npn \siunitx_number_process_zero_fill_aux:nn #1#2 { \prop_if_in:NnT \l_siunitx_number_in_prop { #1 -decimal } { \prop_if_in:NnTF \l_siunitx_number_in_prop { #1 - #2 } { \prop_get:NnN \l_siunitx_number_in_prop { #1 - #2 } \l_siunitx_tmpa_tl \tl_if_empty:NT \l_siunitx_tmpa_tl { \prop_put:Nnn \l_siunitx_number_in_prop { #1 - #2 } { 0 } } } { \prop_put:Nnn \l_siunitx_number_in_prop { #1 - #2 } { 0 } } } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\subsection{Formatting numbers for output} % % Getting numbers ready for printing requires the reconstruction of the % number from the various parts processed earlier. Spaces and brackets % are added back into the main numbers, as the various parts are also % correctly formatted. The difference between the \texttt{in} and % \texttt{out} store is that the later can include formatting such as % hard spaces. % %\begin{macro}{\l_siunitx_number_out_prop} % Like the \texttt{in} version! % \begin{macrocode} \prop_new:N \l_siunitx_number_out_prop % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_bracket_close_tl} %\begin{macro}{\l_siunitx_exponent_base_tl} %\begin{macro}{\l_siunitx_exponent_product_tl} %\begin{macro}{\l_siunitx_group_decimal_bool} %\begin{macro}{\l_siunitx_group_four_bool} %\begin{macro}{\l_siunitx_group_integer_bool} %\begin{macro}{\l_siunitx_group_sep_tl} %\begin{macro}{\l_siunitx_negative_colour_tl} %\begin{macro}{\l_siunitx_bracket_open_tl} %\begin{macro}{\l_siunitx_output_uncert_close_tl} %\begin{macro}{\l_siunitx_output_complex_tl} %\begin{macro}{\l_siunitx_output_decimal_tl} %\begin{macro}{\l_siunitx_output_uncert_open_tl} %\begin{macro}{\l_siunitx_uncert_sep_bool} %\begin{macro}{\l_siunitx_tight_bool} %\begin{macro}{\l_siunitx_uncert_sep_tl} %\begin{macro}{\l_siunitx_brackets_bool} % Lots of settings, some used only for numbers, some more widely. % \begin{macrocode} \keys_define:nn { siunitx } { close-bracket .tl_set:N = \l_siunitx_bracket_close_tl, %( exponent-base .tl_set:N = \l_siunitx_exponent_base_tl, exponent-product .tl_set:N = \l_siunitx_exponent_product_tl, group-decimal-digits .bool_set:N = \l_siunitx_group_decimal_bool, group-digits .meta:n = { group-decimal-digits = #1, group-integer-digits = #1 }, group-four-digits .bool_set:N = \l_siunitx_group_four_bool, group-integer-digits .bool_set:N = \l_siunitx_group_integer_bool, group-separator .tl_set:N = \l_siunitx_group_sep_tl, negative-color .meta:n = { negative-colour = #1 }, negative-colour .tl_set:N = \l_siunitx_negative_colour_tl, open-bracket .tl_set:N = \l_siunitx_bracket_open_tl, output-close-uncertainty .tl_set:N = \l_siunitx_output_uncert_close_tl, output-complex-root .tl_set:N = \l_siunitx_output_complex_tl, output-decimal-marker .tl_set:N = \l_siunitx_output_decimal_tl, output-open-uncertainty .tl_set:N = \l_siunitx_output_uncert_open_tl, separate-uncertainty .bool_set:N = \l_siunitx_uncert_sep_bool, tight-spacing .bool_set:N = \l_siunitx_tight_bool, uncertainty-separator .tl_set:N = \l_siunitx_uncert_sep_tl, use-brackets .bool_set:N = \l_siunitx_brackets_bool, } \keys_set:nn { siunitx } { % ( close-bracket = ), exponent-base = 10, exponent-product = \times, group-decimal-digits = true, group-integer-digits = true, group-separator = \,, open-bracket = (, % ) ( output-close-uncertainty = ), output-complex-root = i, output-decimal-marker = ., output-open-uncertainty = (, % ) use-brackets = true } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_format:} %\begin{macro}[aux]{\siunitx_number_format_aux:n} %\begin{macro}{\siunitx_number_format_parts:} % The master control function for formatting output: the usual set up. % The number is put back together in stages. The \texttt{parts} version % does not construct a full result, and so is faster and intended for % use with repeated units. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format: { \prop_if_empty:NF \l_siunitx_number_in_prop { \prop_clear:N \l_siunitx_number_out_prop \siunitx_number_format_reassemble: \siunitx_number_format_join_uncert: \siunitx_number_format_aux:n { mantissa } \siunitx_number_format_aux:n { exponent } \siunitx_number_format_colour: \siunitx_number_format_final: } } \cs_new_nopar:Npn \siunitx_number_format_aux:n #1 { \siunitx_number_format_complex:nn {#1} { } \siunitx_number_format_join_complex:n {#1} \siunitx_number_format_sign:n {#1} } \cs_new_nopar:Npn \siunitx_number_format_parts: { % TEMP \prop_if_empty:NF \l_siunitx_number_in_prop { \prop_clear:N \l_siunitx_number_out_prop \siunitx_number_format_reassemble: \siunitx_number_format_join_uncert:n { exponent } \siunitx_number_format_complex:nn { mantissa } { } \siunitx_number_format_complex:nn { mantissa } { -uncertainty } \siunitx_number_format_complex:nn { exponent } { } \siunitx_number_format_join_complex:n { exponent } \siunitx_number_format_sign:n { mantissa } \siunitx_number_format_sign:n { mantissa-complex } \siunitx_number_format_sign:n { exponent } { } \siunitx_number_format_colour: \siunitx_number_format_final_exponent: } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_format_brackets:n} %\begin{macro}{\siunitx_number_format_brackets_aux:n} % There are various points at which brackets might be added to % avoid ambiguity. The function here adds the appropriate tokens % around whatever is in the supplied named store. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_brackets:n #1 { \bool_if:NT \l_siunitx_brackets_bool { \prop_if_in:NnT \l_siunitx_number_out_prop { #1 -bracket } { \siunitx_number_format_brackets_aux:n {#1} \prop_del:Nn \l_siunitx_number_out_prop { #1 -bracket } } } } \cs_new_nopar:Npn \siunitx_number_format_brackets_aux:n #1 { \prop_if_in:NnTF \l_siunitx_number_out_prop { #1 -result } { \prop_get:NnN \l_siunitx_number_out_prop { #1 -result } \l_siunitx_tmpa_tl } { \prop_get:NnN \l_siunitx_number_out_prop {#1} \l_siunitx_tmpa_tl } \siunitx_tl_put_left_maths:NV \l_siunitx_tmpa_tl \l_siunitx_bracket_open_tl \siunitx_tl_put_right_maths:NV \l_siunitx_tmpa_tl \l_siunitx_bracket_close_tl \prop_put:NnV \l_siunitx_number_out_prop { #1 -result } \l_siunitx_tmpa_tl } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_format_colour:} %\begin{macro}{\siunitx_number_format_colour_aux:n} % If the mantissa is negative, then any colour for output might change. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_colour: { \tl_if_empty:NF \l_siunitx_negative_colour_tl { \siunitx_number_format_colour_aux:n { mantissa-sign } \siunitx_number_format_colour_aux:n { sign } } } \cs_new_nopar:Npn \siunitx_number_format_colour_aux:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop {#1} { \prop_get:NnN \l_siunitx_number_in_prop {#1} \l_siunitx_tmpa_tl \tl_if_eq:nVT { - } \l_siunitx_tmpa_tl { \prop_put:NnV \l_siunitx_number_out_prop { colour } \l_siunitx_negative_colour_tl } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_format_complex:nn} % The real and complex parts of each number are reassembled, with % brackets if needed. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_complex:nn #1#2 { \prop_if_in:NnT \l_siunitx_number_out_prop { #1 -complex #2 } { \siunitx_number_format_brackets:n { #1 -complex #2 } \prop_get:NnN \l_siunitx_number_out_prop { #1 -complex #2 } \l_siunitx_tmpa_tl \siunitx_tl_put_right_maths:NV \l_siunitx_tmpa_tl \l_siunitx_output_complex_tl \prop_put:NnV \l_siunitx_number_out_prop { #1 -complex #2 } \l_siunitx_tmpa_tl } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_format_copy:n} %\begin{macro}{\siunitx_number_format_copy:nn} % Just copy across. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_copy:n #1 { \prop_get:NnN \l_siunitx_number_in_prop {#1} \l_siunitx_tmpa_tl \prop_put:NnV \l_siunitx_number_out_prop {#1} \l_siunitx_tmpa_tl } \cs_new_nopar:Npn \siunitx_number_format_copy:nn #1#2 { \prop_get:NnN \l_siunitx_number_out_prop {#1} \l_siunitx_tmpa_tl \prop_put:NnV \l_siunitx_number_out_prop {#2} \l_siunitx_tmpa_tl } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_format_final:} % 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} \cs_new_nopar:Npn \siunitx_number_format_final: { \prop_if_in:NnTF \l_siunitx_number_out_prop { mantissa } { \prop_if_in:NnTF \l_siunitx_number_out_prop { exponent } { \siunitx_number_format_final_mantissa: \siunitx_number_format_final_exponent_aux: \siunitx_number_format_final_join_exp: } { \prop_if_in:NnTF \l_siunitx_number_out_prop { mantissa-result } { \siunitx_number_format_copy:nn { mantissa-result } { result } } { \siunitx_number_format_copy:nn { mantissa } { result } } } } { \siunitx_number_format_final_exponent: } \prop_if_in:NnT \l_siunitx_number_out_prop { mantissa-bracket } { \prop_put:Nnn \l_siunitx_number_out_prop { result-bracket } { true } \prop_del:Nn \l_siunitx_number_out_prop { mantissa-bracket } } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_format_final_exponent:} %\begin{macro}[aux]{\siunitx_number_format_final_exponent_aux:} %\begin{macro}[aux]{\siunitx_number_format_final_exponent_aux:n} % For tidying up the exponent part. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_final_exponent: { \siunitx_number_format_final_exponent_aux: \prop_if_in:NnTF \l_siunitx_number_in_prop { mantissa-sign } { \prop_get:NnN \l_siunitx_number_in_prop { mantissa-sign } \l_siunitx_tmpa_tl \tl_clear:N \l_siunitx_tmpb_tl \siunitx_tl_put_right_maths:NV \l_siunitx_tmpb_tl \l_siunitx_tmpa_tl \prop_put:NnV \l_siunitx_number_out_prop { result } \l_siunitx_tmpb_tl } { \prop_put:Nnn \l_siunitx_number_out_prop { result } { } } \siunitx_number_format_final_join_exp: } \cs_new_nopar:Npn \siunitx_number_format_final_exponent_aux: { \prop_if_in:NnTF \l_siunitx_number_out_prop { exponent-result } { \siunitx_number_format_final_exponent_aux:n { exponent-result } } { \prop_if_in:NnT \l_siunitx_number_out_prop { exponent } { \siunitx_number_format_final_exponent_aux:n { exponent } } } } \cs_new_nopar:Npn \siunitx_number_format_final_exponent_aux:n #1 { \prop_get:NnN \l_siunitx_number_out_prop {#1} \l_siunitx_tmpa_tl \tl_set:No \l_siunitx_tmpa_tl { \exp_after:wN ^ \exp_after:wN { \l_siunitx_tmpa_tl } } \tl_put_left:NV \l_siunitx_tmpa_tl \l_siunitx_exponent_base_tl \prop_if_in:NnT \l_siunitx_number_in_prop { sign } { \prop_get:NnN \l_siunitx_number_in_prop { sign } \l_siunitx_tmpb_tl \siunitx_tl_put_left_maths:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl } \prop_put:NnV \l_siunitx_number_out_prop { exponent } \l_siunitx_tmpa_tl } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_number_format_final_join_exp:} % If there is an exponent, this function is called to add it to the % result if necessary. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_final_join_exp: { \prop_if_in:NnT \l_siunitx_number_out_prop { result } { \prop_get:NnN \l_siunitx_number_out_prop { result } \l_siunitx_tmpb_tl \tl_put_left:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl \prop_put:NnV \l_siunitx_number_out_prop { result } \l_siunitx_tmpa_tl \prop_if_in:NnT \l_siunitx_number_out_prop { mantissa } { \prop_put:Nnn \l_siunitx_number_out_prop { result-bracket } { true } } } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_format_final_mantissa:} % Tidying up the mantissa, perhaps including adding a product sign % if there is an exponent to come. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_final_mantissa: { \siunitx_number_format_brackets:n { mantissa } \prop_if_in:NnTF \l_siunitx_number_out_prop { mantissa-result } { \prop_get:NnN \l_siunitx_number_out_prop { mantissa-result } \l_siunitx_tmpa_tl } { \prop_get:NnN \l_siunitx_number_out_prop { mantissa } \l_siunitx_tmpa_tl } \tl_set_eq:NN \l_siunitx_tmpb_tl \l_siunitx_exponent_product_tl \bool_if:NT \l_siunitx_tight_bool { \tl_set:No \l_siunitx_tmpb_tl { \exp_after:wN { \l_siunitx_tmpb_tl } } } \siunitx_tl_put_right_maths:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl \prop_put:NnV \l_siunitx_number_out_prop { result } \l_siunitx_tmpa_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_format_group:n} %\begin{macro}[aux]{\siunitx_number_format_group_aux:nn} % Grouping digits only happens if there are no symbols in the input, and % of course if grouping has been requested. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_group:n #1 { \siunitx_number_format_group_aux:nn {#1} { integer } \siunitx_number_format_group_aux:nn {#1} { decimal } \prop_if_in:NnTF \l_siunitx_number_out_prop { #1 -integer } { \siunitx_number_format_copy:nn { #1 -integer } {#1} } { \tl_clear:N \l_siunitx_tmpa_tl } \prop_if_in:NnT \l_siunitx_number_out_prop { #1 -decimal } { \prop_get:NnN \l_siunitx_number_out_prop { #1 -decimal } \l_siunitx_tmpb_tl \siunitx_tl_put_right_maths:NV \l_siunitx_tmpa_tl \l_siunitx_output_decimal_tl \tl_put_right:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl \prop_put:NnV \l_siunitx_number_out_prop {#1} \l_siunitx_tmpa_tl } } \cs_new_nopar:Npn \siunitx_number_format_group_aux:nn #1#2 { \prop_if_in:NnT \l_siunitx_number_in_prop { #1 - #2 } { \prop_if_in:NnTF \l_siunitx_number_in_prop { symbolic } { \siunitx_number_format_copy:n { #1 - #2 } } { \bool_if:cTF { l_siunitx_group_ #2 _bool } { \siunitx_number_format_group_four:nn {#1} {#2} } { \siunitx_number_format_copy:n { #1 - #2 } } } } } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_number_format_group_four:nn} %\begin{macro}[aux]{\siunitx_number_format_group_four_aux:nn} % The idea here is that grouping is only needed for items with at % least four tokens in them, and perhaps five if the grouping of % four-digit numbers is turned off. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_group_four:nn #1#2 { \prop_get:NnN \l_siunitx_number_in_prop { #1 - #2 } \l_siunitx_tmpa_tl \tl_if_empty:NTF \l_siunitx_tmpa_tl { \prop_put:Nnn \l_siunitx_number_in_prop { #1 - #2 } { } } { \bool_if:NTF \l_siunitx_group_four_bool { \siunitx_number_format_group_four_aux:nn {#1} {#2} } { \int_set:Nn \l_siunitx_tmp_int { \tl_elt_count:N \l_siunitx_tmpa_tl } \intexpr_compare:nTF { \l_siunitx_tmp_int > \c_four } { \siunitx_number_format_group_four_aux:nn {#1} {#2} } { \siunitx_number_format_copy:n {#1 - #2} } } } } \cs_new_nopar:Npn \siunitx_number_format_group_four_aux:nn #1#2 { \tl_clear:N \l_siunitx_tmpb_tl \use:c { siunitx_number_format_group_ #2 : } \prop_put:NnV \l_siunitx_number_out_prop { #1 - #2 } \l_siunitx_tmpb_tl } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_number_format_group_decimal:} %\begin{macro}[aux]{\siunitx_number_format_group_decimal_aux:} % Using the \enquote{keep everything on the stack} approach, relatively % simple recursion is needed. This trick is taken more or less directly % from \pkg{numprint}. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_group_decimal: { \tl_if_empty:NF \l_siunitx_tmpa_tl { \exp_after:wN \siunitx_number_format_group_decimal_aux:NNNN \l_siunitx_tmpa_tl { } { } { } } } \cs_new:Npn \siunitx_number_format_group_decimal_aux:NNNN #1#2#3#4 { \tl_if_empty:nTF {#2} { \tl_put_right:Nn \l_siunitx_tmpb_tl {#1} } { \tl_if_empty:nTF {#3} { \tl_put_right:Nn \l_siunitx_tmpb_tl { #1 #2 } } { \tl_put_right:Nn \l_siunitx_tmpb_tl { #1 #2 #3 } \tl_if_empty:nF {#4} { \siunitx_tl_put_right_maths:NV \l_siunitx_tmpb_tl \l_siunitx_group_sep_tl \siunitx_number_format_group_decimal_aux:NNNN #4 } } } } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_number_format_group_integer:} %\begin{macro}[aux]{\siunitx_number_format_group_integer_setup:n} %\begin{macro}[aux]{\siunitx_number_format_group_integer_setup:V} %\begin{macro}[aux]{\siunitx_number_format_group_integer_setup_aux:NNNN} %%\begin{macro}[aux]{\siunitx_number_format_group_integer_aux:NNNN} % By keeping everything on the stack, recursion can occur quite % efficiently here. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_group_integer: { \tl_if_empty:NF \l_siunitx_tmpa_tl { \siunitx_number_format_group_integer_setup:V \l_siunitx_tmpa_tl } } \cs_new:Npn \siunitx_number_format_group_integer_setup:n #1 { \siunitx_number_format_group_integer_setup_aux:NNNN { } #1 { } { } { } } \cs_generate_variant:Nn \siunitx_number_format_group_integer_setup:n { V } \cs_new:Npn \siunitx_number_format_group_integer_setup_aux:NNNN #1#2#3#4 { \tl_if_empty:nTF {#2} { \siunitx_number_format_group_integer_aux:NNNN #1 \q_nil } { \tl_if_empty:nTF {#3} { \siunitx_number_format_group_integer_aux:NNNN { } { } #1 #2 \q_nil } { \tl_if_empty:nTF {#4} { \siunitx_number_format_group_integer_aux:NNNN { } #1 #2 #3 \q_nil } { \siunitx_number_format_group_integer_setup_aux:NNNN { #1 #2 #3 #4 } } } } } \cs_new:Npn \siunitx_number_format_group_integer_aux:NNNN #1#2#3#4 { \tl_put_right:Nn \l_siunitx_tmpb_tl { #1 #2 #3 } \quark_if_nil:nF {#4} { \siunitx_tl_put_right_maths:NV \l_siunitx_tmpb_tl \l_siunitx_group_sep_tl \siunitx_number_format_group_integer_aux:NNNN #4 } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_format_join_complex:n} % For adding the complex part to the main part of a number. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_join_complex:n #1 { \prop_if_in:NnT \l_siunitx_number_out_prop {#1} { \prop_if_in:NnT \l_siunitx_number_out_prop { #1 -complex } { \siunitx_number_format_brackets:n {#1} \siunitx_number_format_sign:n { #1 -complex } \prop_if_in:NnTF \l_siunitx_number_out_prop { #1 -result } { \prop_get:NnN \l_siunitx_number_out_prop { #1 -result } \l_siunitx_tmpa_tl } { \prop_get:NnN \l_siunitx_number_out_prop {#1} \l_siunitx_tmpa_tl } \prop_get:NnN \l_siunitx_number_out_prop { #1 -complex } \l_siunitx_tmpb_tl \tl_put_right:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl \prop_put:NnV \l_siunitx_number_out_prop { #1 -result } \l_siunitx_tmpa_tl \prop_put:Nnn \l_siunitx_number_out_prop { #1 -bracket } { true } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_format_join_uncert:} %\begin{macro}{\siunitx_number_format_join_uncert:n} % For adding separated uncertainties to the main part of a number. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_join_uncert: { \clist_map_function:NN \c_siunitx_number_parts_clist \siunitx_number_format_join_uncert:n } \cs_new_nopar:Npn \siunitx_number_format_join_uncert:n #1 { \prop_if_in:NnT \l_siunitx_number_out_prop {#1} { \prop_if_in:NnT \l_siunitx_number_out_prop { #1 -uncertainty } { \prop_get:NnN \l_siunitx_number_out_prop {#1} \l_siunitx_tmpa_tl \prop_get:NnN \l_siunitx_number_out_prop { #1 -uncertainty } \l_siunitx_tmpb_tl \tl_put_right:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl \prop_put:NnV \l_siunitx_number_out_prop { #1 -result } \l_siunitx_tmpa_tl \prop_put:Nnn \l_siunitx_number_out_prop { #1 -bracket } { true } } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_format_reassemble:} %\begin{macro}[aux]{\siunitx_number_format_reassemble_aux:n} % The integer, decimal and any non-separated uncertainty parts are % put back together. This gives a \enquote{minimal} unit which cannot % need any brackets or repeated units (if applicable). If the % uncertainty is separate, it is stored at this stage pending later % re-attachment. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_reassemble: { \clist_map_function:NN \c_siunitx_number_parts_clist \siunitx_number_format_reassemble_aux:n } \cs_new_nopar:Npn \siunitx_number_format_reassemble_aux:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop {#1} { \siunitx_number_format_group:n {#1} \siunitx_number_format_uncertainty:n {#1} } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_format_sign:n} %\begin{macro}[aux]{\siunitx_number_format_sign_aux:n} % Some simple sign manipulation: for tight signs, a little shuffling. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_sign:n #1 { \prop_if_in:NnT \l_siunitx_number_out_prop {#1} { \prop_if_in:NnT \l_siunitx_number_in_prop { #1 -sign } { \prop_get:NnN \l_siunitx_number_in_prop { #1 -sign } \l_siunitx_tmpa_tl \bool_if:NT \l_siunitx_tight_bool { \tl_set:No \l_siunitx_tmpb_tl { \exp_after:wN { \l_siunitx_tmpa_tl } } } \tl_clear:N \l_siunitx_tmpb_tl \siunitx_tl_put_left_maths:NV \l_siunitx_tmpb_tl \l_siunitx_tmpa_tl \prop_put:NnV \l_siunitx_number_out_prop { #1 -sign } \l_siunitx_tmpb_tl \prop_get:NnN \l_siunitx_number_out_prop {#1} \l_siunitx_tmpa_tl \tl_put_right:NV \l_siunitx_tmpb_tl \l_siunitx_tmpa_tl \prop_put:NnV \l_siunitx_number_out_prop {#1} \l_siunitx_tmpb_tl } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_format_uncertainty:n} %\begin{macro}{\siunitx_number_format_uncertainty_joined:n} %\begin{macro}{\siunitx_number_format_uncertainty_sep:n} %\begin{macro}[aux]{\siunitx_number_format_uncertainty_pm:} % Uncertainty output varies depending on whether there is a need to % separate the error form the number in the output. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_uncertainty:n #1 { \prop_if_in:NnT \l_siunitx_number_in_prop { #1 -uncertainty } { \bool_if:NTF \l_siunitx_uncert_sep_bool { \siunitx_number_format_uncertainty_sep:n {#1} } { \siunitx_number_format_uncertainty_joined:n {#1} } } } \cs_new_nopar:Npn \siunitx_number_format_uncertainty_joined:n #1 { \prop_get:NnN \l_siunitx_number_in_prop { #1 -uncertainty } \l_siunitx_tmpa_tl \prop_del:Nn \l_siunitx_number_in_prop { #1 -uncertainty } \siunitx_tl_put_left_maths:NV \l_siunitx_tmpa_tl \l_siunitx_output_uncert_open_tl \siunitx_tl_put_left_maths:NV \l_siunitx_tmpa_tl \l_siunitx_uncert_sep_tl \siunitx_tl_put_right_maths:NV \l_siunitx_tmpa_tl \l_siunitx_output_uncert_close_tl \prop_get:NnN \l_siunitx_number_out_prop {#1} \l_siunitx_tmpb_tl \tl_put_right:NV \l_siunitx_tmpb_tl \l_siunitx_tmpa_tl \prop_put:NnV \l_siunitx_number_out_prop {#1} \l_siunitx_tmpb_tl } \cs_new_nopar:Npn \siunitx_number_format_uncertainty_sep:n #1 { \prop_if_in:NnT \l_siunitx_number_out_prop { #1 -integer } { \prop_if_in:NnF \l_siunitx_number_out_prop { #1 -uncertainty-integer } { \prop_put:Nnn \l_siunitx_number_out_prop { #1 -uncertainty-integer } { 0 } } } \siunitx_number_format_group:n { #1 -uncertainty } \siunitx_number_format_uncertainty_pm: \prop_put:NnV \l_siunitx_number_out_prop { #1 -uncertainty } \l_siunitx_tmpa_tl } \cs_new_nopar:Npn \siunitx_number_format_uncertainty_pm: { \bool_if:NTF \l_siunitx_tight_bool { \tl_put_left:Nn \l_siunitx_tmpa_tl { \ensuremath { { \pm } } } } { \tl_put_left:Nn \l_siunitx_tmpa_tl { \ensuremath { \pm } } } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\subsection{Numerical output} % % The outer level of number processing for actually printing things. % %\begin{macro}{\l_siunitx_number_out_tl} %\begin{macro}{\l_siunitx_number_out_saved_tl} % The final result, plus a version for loops. % \begin{macrocode} \tl_new:N \l_siunitx_number_out_tl \tl_new:N \l_siunitx_number_out_saved_tl % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_number_fraction_tl} % Fractions need to be build separately, so that there is no problem % with stack order. % \begin{macrocode} \tl_new:N \l_siunitx_number_fraction_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_number_compound_bool} % To help with brackets. % \begin{macrocode} \bool_new:N \l_siunitx_number_compound_bool % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_quotient_mode_tl} % The action for quotients is stored as a token list variable. % \begin{macrocode} \tl_new:N \l_siunitx_quotient_mode_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_calculate_product_bool} %\begin{macro}{\l_siunitx_calculate_quotient_bool} % Calculation mode needs some flags creating. % \begin{macrocode} \bool_new:N \l_siunitx_calculate_product_bool \bool_new:N \l_siunitx_calculate_quotient_bool % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_output_product_tl} %\begin{macro}{\l_siunitx_output_quotient_tl} %\begin{macro}{\l_siunix_number_parse_bool} % Some options related to numbers at the output stage. % \begin{macrocode} \keys_define:nn { siunitx } { output-product .tl_set:N = \l_siunitx_output_product_tl, output-quotient .tl_set:N = \l_siunitx_output_quotient_tl, parse-numbers .bool_set:N = \l_siunitx_number_parse_bool, product-mode .choice:, product-mode / calculate .code:n = { \bool_set_true:N \l_siunitx_calculate_product_bool }, product-mode / symbol .code:n = { \bool_set_false:N \l_siunitx_calculate_product_bool }, quotient-mode .choice:, quotient-mode / calculate .code:n = { \bool_set_true:N \l_siunitx_calculate_quotient_bool }, quotient-mode / fraction .code:n = { \bool_set_false:N \l_siunitx_calculate_quotient_bool \tl_set:Nn \l_siunitx_quotient_mode_tl { fraction } }, quotient-mode / symbol .code:n = { \bool_set_false:N \l_siunitx_calculate_quotient_bool \tl_set:Nn \l_siunitx_quotient_mode_tl { symbol } }, } \keys_set:nn { siunitx } { output-product = \times, output-quotient = /, parse-numbers = true, quotient-mode = symbol } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_output:n} % The control function for everything else. After pre-processing, % check if there are multiple parts. % \begin{macrocode} \cs_new:Npn \siunitx_number_output:n #1 { \bool_if:NTF \l_siunitx_number_parse_bool { \tl_clear:N \l_siunitx_number_out_tl \tl_clear:N \l_siunitx_number_out_saved_tl \bool_set_false:N \l_siunitx_number_compound_bool \siunitx_number_output_parse:n {#1} \siunitx_number_output_print: } { \siunitx_print:nn { number } {#1} } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_output_bracket:} % Compound numbers may need brackets adding. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_output_bracket: { \bool_if:NF \l_siunitx_error_bool { \bool_if:NT \l_siunitx_number_compound_bool { \siunitx_number_format_brackets:n { result } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_output_colour:} % If a colour needs to be set, it is recovered here and put into the % appropriate place. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_output_colour: { \prop_if_in:NnT \l_siunitx_number_out_prop { colour } { \prop_get:NnN \l_siunitx_number_out_prop { colour } \l_siunitx_number_colour_tl } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_output_compound:n} %\begin{macro}{\siunitx_number_output_compound:V} % Two possible choices if \cs{l_siunitx_number_multi_tl} is not empty: % either it is set to \texttt{product} or \texttt{quotient}. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_output_compound:n #1 { \bool_if:cTF { l_siunitx_calculate_ #1 _bool } { \siunitx_number_output_calculate:n {#1} } { \use:c { siunitx_number_output_ #1 : } } } \cs_generate_variant:Nn \siunitx_number_output_compound:n { V } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_output_parse:n} %\begin{macro}{\siunitx_number_output_parse:V} % The parsing system just has to check if there are multiple parts to % worry about. % \begin{macrocode} \cs_new:Npn \siunitx_number_output_parse:n #1 { \siunitx_number_preprocess:n {#1} \bool_if:NF \l_siunitx_error_bool { \tl_if_empty:NTF \l_siunitx_number_multi_tl { \siunitx_number_output_single: } { \siunitx_number_output_compound:V \l_siunitx_number_multi_tl } } } \cs_generate_variant:Nn \siunitx_number_output_parse:n { V } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_output_print:} % The final stage: print. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_output_print: { \bool_if:NF \l_siunitx_error_bool { \tl_if_eq:nVF { quotient } \l_siunitx_number_multi_tl { \tl_if_empty:NF \l_siunitx_number_out_saved_tl { \tl_put_left:NV \l_siunitx_number_out_tl \l_siunitx_number_out_saved_tl } } \siunitx_print:nV { number } \l_siunitx_number_out_tl } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_output_product:} % For a product, there could still be a quotient to worry about. So % first a second pass through the pre-processor. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_output_product: { \bool_set_true:N \l_siunitx_number_compound_bool \siunitx_number_preprocess:V \l_siunitx_number_arg_tl \bool_if:NF \l_siunitx_error_bool { \tl_if_empty:NTF \l_siunitx_number_multi_tl { \tl_set_eq:NN \l_siunitx_number_out_saved_tl \l_siunitx_number_out_tl \siunitx_number_output_single: \tl_put_left:NV \l_siunitx_number_out_tl \l_siunitx_number_out_saved_tl } { \siunitx_number_output_compound:n { quotient } } } \siunitx_tl_put_right_maths:NV \l_siunitx_number_out_tl \l_siunitx_output_product_tl \tl_set_eq:NN \l_siunitx_number_out_saved_tl \l_siunitx_number_out_tl \siunitx_number_output_parse:V \l_siunitx_number_next_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_output_quotient:} % For quotients, there are two options. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_output_quotient: { \use:c { siunitx_number_output_quotient_ \l_siunitx_quotient_mode_tl : } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_output_quotient_fraction:} % For fraction output, there are quite a lot of braces to construct, % unfortunately. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_output_quotient_fraction: { \bool_set_false:N \l_siunitx_number_compound_bool \siunitx_number_output_quotient_aux_i: \tl_set:No \l_siunitx_number_fraction_tl { \exp_after:wN { \l_siunitx_number_numerator_tl } } \tl_set:No \l_siunitx_tmpa_tl { \exp_after:wN { \l_siunitx_number_denominator_tl } } \tl_put_right:NV \l_siunitx_number_fraction_tl \l_siunitx_tmpa_tl \tl_put_left:Nn \l_siunitx_number_fraction_tl { \frac } \tl_set:No \l_siunitx_number_fraction_tl { \exp_after:wN \ensuremath \exp_after:wN { \l_siunitx_number_fraction_tl } } \tl_put_right:NV \l_siunitx_number_out_tl \l_siunitx_number_fraction_tl } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_output_quotient_symbol:} % If a symbol is used for the division, the build process is less % complex. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_output_quotient_symbol: { \bool_set_true:N \l_siunitx_number_compound_bool \siunitx_number_output_quotient_aux_i: \tl_put_right:NV \l_siunitx_number_out_tl \l_siunitx_number_numerator_tl \siunitx_tl_put_right_maths:NV \l_siunitx_number_out_tl \l_siunitx_output_quotient_tl \tl_put_right:NV \l_siunitx_number_out_tl \l_siunitx_number_denominator_tl } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{\siunitx_number_output_quotient_aux_i:} %\begin{macro}[aux]{\siunitx_number_output_quotient_aux_ii:} % The two parts of the number are parsed and formatted. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_output_quotient_aux_i: { \siunitx_number_in_parse:V \l_siunitx_number_numerator_tl \siunitx_number_output_quotient_aux_ii: \siunitx_number_output_colour: \prop_get:NnN \l_siunitx_number_out_prop { result } \l_siunitx_number_numerator_tl \siunitx_number_in_parse:V \l_siunitx_number_denominator_tl \siunitx_number_output_quotient_aux_ii: \prop_get:NnN \l_siunitx_number_out_prop { result } \l_siunitx_number_denominator_tl } \cs_new_nopar:Npn \siunitx_number_output_quotient_aux_ii: { \siunitx_number_process: \siunitx_number_format: \siunitx_number_output_bracket: } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_output_single:} % Printing a number with no multiple parts is easy. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_output_single: { \siunitx_number_in_parse:V \l_siunitx_number_arg_tl \bool_if:NF \l_siunitx_error_bool { \siunitx_number_process: \siunitx_number_format: \siunitx_number_output_colour: \siunitx_number_output_bracket: \prop_get:NnN \l_siunitx_number_out_prop { result } \l_siunitx_number_out_tl } } % \end{macrocode} %\end{macro} % %\subsection{Creating unit macros} % % Unit macros and related support are created here. To avoid cluttering % up the user name-space with a lot of short macro names, the standard % method only makes these available inside the unit-processing functions % (\cs{SI}, \cs{si} and the \texttt{S} column). % %\begin{macro}{\l_siunitx_declare_list_tl} % A list of all unit and related functions. % \begin{macrocode} \tl_new:Nn \l_siunitx_declare_list_tl { \per \raiseto \tothe } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_declare_power_after:Nn} %\begin{macro}{\siunitx_declare_power_before:Nn} % Creating powers is all about storing values. % \begin{macrocode} \cs_new:Npn \siunitx_declare_power_after:Nn #1#2 { \tl_put_right:Nn \l_siunitx_declare_list_tl {#1} \cs_set:cpn { siunitx_ \token_to_str:N #1 _literal:w } { \textsuperscript {#2} } \cs_set:cpn { siunitx_ \token_to_str:N #1 _function:w } { \siunitx_unit_parse_power_after:n {#2} } } \cs_new:Npn \siunitx_declare_power_before:Nn #1#2 { \tl_put_right:Nn \l_siunitx_declare_list_tl {#1} \cs_set:cpn { siunitx_ \token_to_str:N #1 _literal:w } ##1 { ##1 \textsuperscript {#2} } \cs_set:cpn { siunitx_ \token_to_str:N #1 _function:w } { \siunitx_unit_parse_power_before:n {#2} } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_declare_prefix:Nnnn} % Prefixes need to store both the symbol and the power they represent. % \begin{macrocode} \cs_new:Npn \siunitx_declare_prefix:Nnnn #1#2#3#4 { \tl_put_right:Nn \l_siunitx_declare_list_tl {#1} \cs_set:cpn { siunitx_ \token_to_str:N #1 _literal:w } {#2} \cs_set:cpn { siunitx_ \token_to_str:N #1 _function:w } { \bool_if:NTF \l_siunitx_prefix_symbols_bool { \siunitx_unit_parse_prefix:n {#2} } { \siunitx_unit_parse_prefix:nn {#3} {#4} } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_declare_qualifier:Nn} % Qualifiers just need storing. % \begin{macrocode} \cs_new:Npn \siunitx_declare_qualifier:Nn #1#2 { \tl_put_right:Nn \l_siunitx_declare_list_tl {#1} \cs_set:cpn { siunitx_ \token_to_str:N #1 _literal:w } { \text { ~ } ( #2 ) } \cs_set:cpn { siunitx_ \token_to_str:N #1 _function:w } { \siunitx_unit_parse_qualifier:n {#2} } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_declare_unit:Nnn} %\begin{macro}[aux]{\siunitx_unit_first_token:n} % Creating units requires various things to be stored. This is done % with several storage bins to keep the code clear. For the % \texttt{macro} definition, the test occurs at use so that there is no % problem with the creation order for units. % \begin{macrocode} \cs_new:Npn \siunitx_declare_unit:Nnn #1#2#3 { \tl_put_right:Nn \l_siunitx_declare_list_tl {#1} \cs_set:cpn { siunitx_ \token_to_str:N #1 _literal:w } {#2} \cs_set:cpn { siunitx_ \token_to_str:N #1 _function:w } { \cs_if_exist:cTF { siunitx_ \siunitx_unit_first_token:n {#2} _function:w } {#2} { \siunitx_unit_parse_unit:n {#2} } } \cs_if_free:cTF { l_siunitx_ \token_to_str:N #1 _options_tl } { \tl_new:cn { l_siunitx_ \token_to_str:N #1 _options_tl } {#3} } { \tl_set:cn { l_siunitx_ \token_to_str:N #1 _options_tl } {#3} } } \cs_new:Npn \siunitx_unit_first_token:n #1 { \exp_after:wN \token_to_str:N \tl_head_i:w #1 \q_nil } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\per} % The \cs{per} function is pretty simple. % \begin{macrocode} \cs_new:cpn { siunitx_ \token_to_str:N \per _literal:w } { / } \cs_new:cpn { siunitx_ \token_to_str:N \per _function:w } { \bool_set_true:N \l_siunitx_per_bool \siunitx_unit_parse_per: } % \end{macrocode} %\end{macro} % %\begin{macro}{\raiseto} %\begin{macro}{\tothe} % Generic versions of the pre-set powers. % \begin{macrocode} \cs_new:cpn { siunitx_ \token_to_str:N \raiseto _literal:w } #1#2 { #2 \textsuperscript {#1} } \cs_new:cpn { siunitx_ \token_to_str:N \raiseto _function:w } #1 { \siunitx_unit_parse_power_before:n {#1} } \cs_new:cpn { siunitx_ \token_to_str:N \tothe _literal:w } #1 { \textsuperscript {#1} } \cs_new:cpn { siunitx_ \token_to_str:N \tothe _function:w } #1 { \siunitx_unit_parse_power_after:n {#1} } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Creating body unit macros} % % The user might have asked for the unit macros to be available in the % document body. If so, then these are created at the start of the % document body. % %\begin{macro}{\l_siunitx_create_free_bool} %\begin{macro}{\l_siunitx_create_overwrite_bool} %\begin{macro}{\l_siunitx_create_prespace_bool} %\begin{macro}{\l_siunitx_create_optional_bool} %\begin{macro}{\l_siunitx_create_xspace_bool} % There are a few options which control this behaviour: these are all % preamble-only. % \begin{macrocode} \keys_define:nn { siunitx } { free-standing-units .bool_set:N = \l_siunitx_create_free_bool, overwrite-functions .bool_set:N = \l_siunitx_create_overwrite_bool, space-before-unit .bool_set:N = \l_siunitx_create_prespace_bool, unit-optional-argument .bool_set:N = \l_siunitx_create_optional_bool, use-xspace .bool_set:N = \l_siunitx_create_xspace_bool } \siunitx_option_deactivate:n { free-standing-units, overwrite-functions, space-before-unit, unit-optional-argument, use-xspace } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_create_check:} % The master control macro which occurs at the start of the document. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_create_check: { \bool_if:NT \l_siunitx_create_free_bool { \siunitx_unit_create_functions: } } \AtBeginDocument { \siunitx_unit_create_check: } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_unit_create_functions:} % Creation of macros essentially involves picking up a couple of loops. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_create_functions: { \bool_if:NT \l_siunitx_create_overwrite_bool { \tl_map_function:NN \l_siunitx_declare_list_tl \cs_gundefine:N } \bool_if:NTF \l_siunitx_create_optional_bool { \tl_map_function:NN \l_siunitx_declare_list_tl \siunitx_unit_create_with_arg:N } { \tl_map_function:NN \l_siunitx_declare_list_tl \siunitx_unit_create:N } \bool_if:NT \l_siunitx_create_xspace_bool { \RequirePackage { xspace } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_unit_create:N} %\begin{macro}{\siunitx_unit_create_with_arg:N} % The creation functions expand everything as far as possible so that % there is less to do in the document. % \begin{macrocode} \cs_new:Npn \siunitx_unit_create:N #1 { \cs_if_free:NT #1 { \cs_set:Npx \siunitx_tmp:w { \DeclareDocumentCommand \exp_not:N #1 { } { \bool_if:NT \l_siunitx_create_prespace_bool { \exp_not:n { \ensuremath { \l_siunitx_number_unit_sep_tl } } } \exp_not:n { \siunitx_unit_in:nn {#1} { } } \bool_if:NT \l_siunitx_create_xspace_bool { \exp_not:N \xspace } } } \siunitx_tmp:w } } \cs_new:Npn \siunitx_unit_create_with_arg:N #1 { \cs_if_free:NT #1 { \cs_set:Npx \siunitx_tmp:w { \DeclareDocumentCommand \exp_not:N #1 { o } { \exp_not:N \IfNoValueTF {####1} { \exp_not:n { \siunitx_unit_in:nn {#1} { } } } { \bool_if:NT \l_siunitx_create_prespace_bool { \exp_not:n { \ensuremath { \l_siunitx_number_unit_sep_tl } } } \SI {####1} { \exp_not:N #1 } } \bool_if:NT \l_siunitx_create_xspace_bool { \exp_not:N \xspace } } } \siunitx_tmp:w } } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Initial unit processing} % % The unit processor has to convert the input (which may be all macros % or may contain literal input) into formatted text for output. The % input part of the process is used to sort out parsed or literal units. % %\begin{macro}{\l_siunitx_unit_allow_literal_bool} % One option is related to how units are pre-processed. % \begin{macrocode} \keys_define:nn { siunitx } { allow-literal-units .bool_set:N = \l_siunitx_unit_allow_literal_bool, } \keys_set:nn { siunitx } { allow-literal-units = true } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_unit_in:nn} %\begin{macro}{\siunitx_unit_in:Vn} % The master function does a very simple checks then hands off. % \begin{macrocode} \cs_new:Npn \siunitx_unit_in:nn #1#2 { \siunitx_unit_if_literal:nTF {#1} { \bool_if:NTF \l_siunitx_unit_allow_literal_bool { \siunitx_unit_format_literal:n {#1} } { \msg_error:nnx { siunitx } { literal-unit } {#1} } } { \siunitx_unit_parse:nn {#1} {#2} \siunitx_unit_format: } } \cs_generate_variant:Nn \siunitx_unit_in:nn { Vn } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_if_literal:nTF} %\begin{macro}[aux]{\siunitx_unit_if_literal_aux:N} % A test is needed to see if the input only contains unit macros. This % is done by altering setting all of the unit macros to expand to % nothing at all. Thus there will only be anything left if there is % a literal in the unit. % \begin{macrocode} \cs_new:Npn \siunitx_unit_if_literal:nTF #1#2#3 { \group_begin: \tl_map_function:NN \l_siunitx_declare_list_tl \siunitx_unit_if_literal_aux:N \cs_set_eq:NN \raiseto \use_none:n \cs_set_eq:NN \tothe \use_none:n \protected@edef \l_siunitx_tmpa_tl {#1} \exp_args:NNNV \group_end: \tl_set:Nn \l_siunitx_tmpa_tl \l_siunitx_tmpa_tl \tl_if_empty:NTF \l_siunitx_tmpa_tl {#3} {#2} } \cs_new:Npn \siunitx_unit_if_literal_aux:N #1 { \cs_set_eq:NN #1 \prg_do_nothing: } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Parsing macro units} % % For macro-based units, the macros are converted into literal text, % which is then passed on for printing. The code reads through the % input to collect up the units, before re-combining everything into % a single block at the end of the process. % %\begin{macro}{\l_siunitx_unit_int} %\begin{macro}{\l_siunitx_unit_prop} % Parsed units are stored in a property list, to keep things compact. % An integer is also needed to count up units. % \begin{macrocode} \int_new:N \l_siunitx_unit_int \prop_new:N \l_siunitx_unit_prop % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_per_bool} % To allow \cs{per} to be \enquote{sticky}. % \begin{macrocode} \bool_new:N \l_siunitx_per_bool % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_prefix_symbols_bool} %\begin{macro}{\l_siunitx_sticky_per_bool} % Some options are directly related to how units are handled at this % stage, so need be created before the reconstruction part of the code. % \begin{macrocode} \keys_define:nn { siunitx } { prefixes-as-symbols .bool_set:N = \l_siunitx_prefix_symbols_bool, sticky-per .bool_set:N = \l_siunitx_sticky_per_bool, } \keys_set:nn { siunitx } { prefixes-as-symbols = true } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_parse:nn} % The unit to be parsed is received here along with any options given. % The later are needed so that the user can override any saved options % on a one-off basis. % \begin{macrocode} \cs_new:Npn \siunitx_unit_parse:nn #1#2 { \siunitx_unit_parse_init: \siunitx_unit_parse_options:nn {#1} {#2} #1 } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_unit_parse_init:} %\begin{macro}[aux]{\siunitx_unit_parse_init_aux:N} % As always, the initialisation is a separate routine to make life a % little clearer. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_parse_init: { \prop_clear:N \l_siunitx_unit_prop \int_zero:N \l_siunitx_unit_int \bool_set_false:N \l_siunitx_per_bool \tl_map_function:NN \l_siunitx_declare_list_tl \siunitx_unit_parse_init_aux:N } \cs_new:Npn \siunitx_unit_parse_init_aux:N #1 { \cs_set_eq:Nc #1 { siunitx_ \token_to_str:N #1 _function:w } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_parse_options:n} % Any unit-specific options are loaded, followed by re-applying any % options given for this particular macro. The second call to % \cs{keys_set:nn} is needed to allow the local overriding of settings. % \begin{macrocode} \cs_new:Npn \siunitx_unit_parse_options:nn #1#2 { \cs_if_free:cF { l_siunitx_ \siunitx_unit_first_token:n {#1} _options_tl } { \keys_set:nv { siunitx } { l_siunitx_ \siunitx_unit_first_token:n {#1} _options_tl } \keys_set:nn { siunitx } {#2} } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_unit_parse_power_before:n} %\begin{macro}{\siunitx_unit_parse_power_after:n} % Storing powers depends on whether they are given before or after % the unit. % \begin{macrocode} \cs_new:Npn \siunitx_unit_parse_power_before:n #1 { \tl_set:Nx \l_siunitx_tmpa_tl { power- \intexpr_eval:n { \l_siunitx_unit_int + 1 } } \prop_put:NVn \l_siunitx_unit_prop \l_siunitx_tmpa_tl {#1} } \cs_new:Npn \siunitx_unit_parse_power_after:n #1 { \tl_set:Nx \l_siunitx_tmpa_tl { power- \int_use:N \l_siunitx_unit_int } \prop_put:NVn \l_siunitx_unit_prop \l_siunitx_tmpa_tl {#1} } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_parse_prefix:n} %\begin{macro}{\siunitx_unit_parse_prefix:nn} % Saving prefixes always increments the counter. For non-symbolic % mode, the base needs to be saved along with the power. % \begin{macrocode} \cs_new:Npn \siunitx_unit_parse_prefix:n #1 { \int_incr:N \l_siunitx_unit_int \tl_set:Nx \l_siunitx_tmpa_tl { prefix- \int_use:N \l_siunitx_unit_int } \prop_put:NVn \l_siunitx_unit_prop \l_siunitx_tmpa_tl {#1} } \cs_new:Npn \siunitx_unit_parse_prefix:nn #1#2 { \siunitx_unit_parse_prefix:n {#2} \tl_set:Nx \l_siunitx_tmpa_tl { prefix-base- \int_use:N \l_siunitx_unit_int } \prop_put:NVn \l_siunitx_unit_prop \l_siunitx_tmpa_tl {#1} } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_parse_per:} % The \cs{per} function always applies to the next unit seen, so % the counter has to be advanced by one. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_parse_per: { \tl_set:Nx \l_siunitx_tmpa_tl { per- \intexpr_eval:n { \l_siunitx_unit_int + 1 } } \prop_put:NVn \l_siunitx_unit_prop \l_siunitx_tmpa_tl { true } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_unit_parse_qualifier:n} % Qualifiers never alter the number of units. % \begin{macrocode} \cs_new:Npn \siunitx_unit_parse_qualifier:n #1 { \tl_set:Nx \l_siunitx_tmpa_tl { symbol- \int_use:N \l_siunitx_unit_int } \prop_if_in:NVF \l_siunitx_unit_prop \l_siunitx_tmpa_tl { \msg_error:nn { siunitx } { qualifier-before-unit } } \tl_set:Nx \l_siunitx_tmpa_tl { qualifier- \int_use:N \l_siunitx_unit_int } \prop_put:NVn \l_siunitx_unit_prop \l_siunitx_tmpa_tl {#1} } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_unit_parse_unit:n} %\begin{macro}[aux]{\siunitx_unit_parse_unit_per:} % For units, there is a check in case a prefix is present (which will % have incremented the counter). With the counter correct, simply add % the literal to the property list. There is also a check to see if % there is a \enquote{sticky} \cs{per} to think about. % \begin{macrocode} \cs_new:Npn \siunitx_unit_parse_unit:n #1 { \tl_set:Nx \l_siunitx_tmpa_tl { prefix- \int_use:N \l_siunitx_unit_int } \prop_if_in:NVTF \l_siunitx_unit_prop \l_siunitx_tmpa_tl { \tl_set:Nx \l_siunitx_tmpa_tl { symbol- \int_use:N \l_siunitx_unit_int } \prop_if_in:NVT \l_siunitx_unit_prop \l_siunitx_tmpa_tl { \int_incr:N \l_siunitx_unit_int } } { \int_incr:N \l_siunitx_unit_int } \tl_set:Nx \l_siunitx_tmpa_tl { symbol- \int_use:N \l_siunitx_unit_int } \prop_put:NVn \l_siunitx_unit_prop \l_siunitx_tmpa_tl {#1} \siunitx_unit_parse_unit_per: } \cs_new_nopar:Npn \siunitx_unit_parse_unit_per: { \bool_if:NT \l_siunitx_sticky_per_bool { \bool_if:NT \l_siunitx_per_bool { \tl_set:Nx \l_siunitx_tmpa_tl { per- \int_use:N \l_siunitx_unit_int } \prop_put:NVn \l_siunitx_unit_prop \l_siunitx_tmpa_tl { true } } } } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Unit formatting} % %\begin{macro}{\l_siunitx_unit_tl} %\begin{macro}{\l_siunitx_unit_current_tl} %\begin{macro}{\l_siunitx_unit_denominator_tl} %\begin{macro}{\l_siunitx_unit_numerator_tl} % Storage space for creating unit output. % \begin{macrocode} \tl_new:N \l_siunitx_unit_tl \tl_new:N \l_siunitx_unit_current_tl \tl_new:N \l_siunitx_unit_denominator_tl \tl_new:N \l_siunitx_unit_numerator_tl % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_unit_denominator_int} %\begin{macro}{\l_siunitx_unit_numerator_int} % For tracking in case brackets are needed. % \begin{macrocode} \int_new:N \l_siunitx_unit_denominator_int \int_new:N \l_siunitx_unit_numerator_int % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_unit_prefix_int} %\begin{macro}{\l_siunitx_unit_prefix_base_int} %\begin{macro}{\l_siunitx_unit_prefix_current_tl} % Used to calculate the overall prefix value. % \begin{macrocode} \int_new:N \l_siunitx_unit_prefix_int \int_new:N \l_siunitx_unit_prefix_base_int \tl_new:N \l_siunitx_unit_prefix_current_tl % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_per_fraction_bool} %\begin{macro}{\l_siunitx_per_mode_tl} %\begin{macro}{\l_siunitx_qualifier_mode_tl} % For saving settings. % \begin{macrocode} \bool_new:N \l_siunitx_per_fraction_bool \tl_new:N \l_siunitx_per_mode_tl \tl_new:N \l_siunitx_qualifier_mode_tl % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_unit_separator_tl} %\begin{macro}{\l_siunitx_per_symbol_tl} % At this stage, output formatting options are created. % \begin{macrocode} \keys_define:nn { siunitx } { inter-unit-separator .tl_set:N = \l_siunitx_unit_separator_tl , per-mode .choice:, per-mode / fraction .code:n = { \bool_set_true:N \l_siunitx_per_fraction_bool \tl_set:Nn \l_siunitx_per_mode_tl { fraction } }, per-mode / power .code:n = { \bool_set_false:N \l_siunitx_per_fraction_bool \tl_clear:N \l_siunitx_per_mode_tl }, per-mode / repeated-symbol .code:n = { \bool_set_false:N \l_siunitx_per_fraction_bool \tl_set:Nn \l_siunitx_per_mode_tl { repeat } }, per-mode / symbol .code:n = { \bool_set_true:N \l_siunitx_per_fraction_bool \tl_set:Nn \l_siunitx_per_mode_tl { symbol } }, per-symbol .tl_set:N = \l_siunitx_per_symbol_tl, qualifier-mode .choice:, qualifier-mode / brackets .code:n = { \tl_set:Nn \l_siunitx_qualifier_mode_tl { brackets } }, qualifier-mode / space .code:n = { \tl_set:Nn \l_siunitx_qualifier_mode_tl { space } }, qualifier-mode / subscript .code:n = { \tl_set:Nn \l_siunitx_qualifier_mode_tl { subscript } }, } \keys_set:nn { siunitx } { inter-unit-separator = \,, per-mode = power, per-symbol = /, qualifier-mode = subscript } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_format:} % Most of the work is done by the loop, with a little tidying up for % fraction-like output. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_format: { \siunitx_unit_format_init: \intexpr_compare:nT { \l_siunitx_unit_int > \c_zero } {\siunitx_unit_format_loop: } \bool_if:NT \l_siunitx_per_fraction_bool { \siunitx_unit_format_fraction: } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_unit_format_add:} %\begin{macro}[aux]{\siunitx_unit_format_add_aux:n} % Adding the current unit to the output means checking where it goes. % The odd code when adding a space is to pick up repeated per symbols, % which need to suppress the space. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_format_add: { \bool_if:NTF \l_siunitx_per_fraction_bool { \tl_set:Nx \l_siunitx_tmpb_tl { per- \int_use:N \l_siunitx_unit_int } \prop_if_in:NVTF \l_siunitx_unit_prop \l_siunitx_tmpb_tl { \siunitx_unit_format_add_aux:n { _denominator } \int_incr:N \l_siunitx_unit_denominator_int } { \siunitx_unit_format_add_aux:n { _numerator } \int_incr:N \l_siunitx_unit_numerator_int } } { \siunitx_unit_format_add_aux:n { } } \tl_clear:N \l_siunitx_unit_current_tl } \cs_new_nopar:Npn \siunitx_unit_format_add_aux:n #1 { \tl_if_empty:cF { l_siunitx_unit #1 _tl } { \tl_if_eq:nVTF { repeat } \l_siunitx_per_mode_tl { \tl_set:Nx \l_siunitx_tmpa_tl { per- \intexpr_eval:n { \l_siunitx_unit_int + 1 } } \prop_if_in:NVF \l_siunitx_unit_prop \l_siunitx_tmpa_tl { \siunitx_tl_put_right_maths:NV \l_siunitx_unit_current_tl \l_siunitx_unit_separator_tl } } { \siunitx_tl_put_right_maths:NV \l_siunitx_unit_current_tl \l_siunitx_unit_separator_tl } } \tl_put_left:cV { l_siunitx_unit #1 _tl } \l_siunitx_unit_current_tl } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_format_fraction:} %\begin{macro}[aux]{\siunitx_unit_format_fraction:} %\begin{macro}[aux]{\siunitx_unit_format_symbol:} %\begin{macro}[aux]{\siunitx_unit_format_symbol_aux:n} % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_format_fraction: { \intexpr_compare:nTF { \l_siunitx_unit_denominator_int > \c_zero } { \use:c { siunitx_unit_format_fraction_ \l_siunitx_per_mode_tl : } } { \tl_set_eq:NN \l_siunitx_unit_tl \l_siunitx_unit_numerator_tl } } \cs_new_nopar:Npn \siunitx_unit_format_fraction_fraction: { \tl_if_empty:NT \l_siunitx_unit_numerator_tl { \tl_set:Nn \l_siunitx_unit_numerator_tl { 1 } } \tl_set:No \l_siunitx_unit_numerator_tl { \exp_after:wN { \l_siunitx_unit_numerator_tl } } \tl_put_left:Nn \l_siunitx_unit_numerator_tl { \PrintSIUnit } \tl_set:No \l_siunitx_unit_numerator_tl { \exp_after:wN { \l_siunitx_unit_numerator_tl } } \tl_set:No \l_siunitx_unit_denominator_tl { \exp_after:wN { \l_siunitx_unit_denominator_tl } } \tl_put_left:Nn \l_siunitx_unit_denominator_tl { \PrintSIUnit } \tl_set:No \l_siunitx_unit_denominator_tl { \exp_after:wN { \l_siunitx_unit_denominator_tl } } \tl_set:Nn \l_siunitx_unit_tl { \frac } \tl_put_right:NV \l_siunitx_unit_tl \l_siunitx_unit_numerator_tl \tl_put_right:NV \l_siunitx_unit_tl \l_siunitx_unit_denominator_tl \tl_set:No \l_siunitx_unit_tl { \exp_after:wN \ensuremath \exp_after:wN { \l_siunitx_unit_tl } } } \cs_new_nopar:Npn \siunitx_unit_format_fraction_symbol: { \siunitx_unit_format_fraction_symbol_aux:n { numerator } \siunitx_unit_format_fraction_symbol_aux:n { denominator } \tl_set_eq:NN \l_siunitx_unit_tl \l_siunitx_unit_numerator_tl \siunitx_tl_put_right_maths:NV \l_siunitx_unit_tl \l_siunitx_per_symbol_tl \tl_put_right:NV \l_siunitx_unit_tl \l_siunitx_unit_denominator_tl } \cs_new_nopar:Npn \siunitx_unit_format_fraction_symbol_aux:n #1 { \intexpr_compare:nT { \int_use:c { l_siunitx_unit_ #1 _int } > \c_one } { \bool_if:NT \l_siunitx_brackets_bool { \siunitx_tl_put_left_maths:cV { l_siunitx_unit_ #1 _tl } \l_siunitx_bracket_open_tl \siunitx_tl_put_right_maths:cV { l_siunitx_unit_ #1 _tl } \l_siunitx_bracket_close_tl } } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_format_init:} % The normal initialisation stuff. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_format_init: { \tl_clear:N \l_siunitx_unit_tl \tl_clear:N \l_siunitx_unit_current_tl \tl_clear:N \l_siunitx_unit_denominator_tl \tl_clear:N \l_siunitx_unit_numerator_tl \int_zero:N \l_siunitx_unit_prefix_base_int \int_zero:N \l_siunitx_unit_prefix_int \int_zero:N \l_siunitx_unit_denominator_int \int_zero:N \l_siunitx_unit_numerator_int } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_unit_format_literal:n} %\begin{macro}{\siunitx_unit_format_literal_aux:N} % If the unit given contains anything which is not a unit macro, then % any unit macros that are there simply dump literal meanings. There is % then a little work to do sorting out |~| and |.| characters at the % outer level. % \begin{macrocode} \char_make_active:N \~ \cs_new:Npn \siunitx_unit_format_literal:n #1 { \int_zero:N \l_siunitx_unit_prefix_int \tl_map_function:NN \l_siunitx_declare_list_tl \siunitx_unit_print_literal_aux:N \tl_set:Nn \l_siunitx_unit_tl {#1} \tl_set:No \l_sunitx_tmpa_tl { \exp_after:wN \ensuremath \exp_after:wN { \l_siunitx_unit_separator_tl } } \tl_replace_all_in:NnV \l_siunitx_unit_tl { . } \l_sunitx_tmpa_tl \tl_replace_all_in:NnV \l_siunitx_unit_tl { ~ } \l_sunitx_tmpa_tl } \cs_new:Npn \siunitx_unit_print_literal_aux:N #1 { \cs_set_eq:Nc #1 { siunitx_ \token_to_str:N #1 _literal:w } } \char_make_ignore:N \~ % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_format_loop:} % The unit components are examined and reconstructed. This is done on % a unit-by-unit basis as there is the possibility that brackets will be % needed to be added. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_format_loop: { \siunitx_unit_format_prefix: \siunitx_unit_format_symbol: \siunitx_unit_format_qualifier: \siunitx_unit_format_power: \siunitx_unit_format_add: \int_decr:N \l_siunitx_unit_int \intexpr_compare:nT { \l_siunitx_unit_int > \c_zero } { \siunitx_unit_format_loop: } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_unit_format_power:} %\begin{macro}[aux]{\siunitx_unit_format_power_aux:} % To format powers, there are a few issues: are brackets needed, is % the power reciprocal and is fraction-formatting in operation. Repeated % per symbols make life a little more complex, as they have to be % handled here as well. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_format_power: { \tl_set:Nx \l_siunitx_tmpa_tl { power- \int_use:N \l_siunitx_unit_int } \prop_if_in:NVTF \l_siunitx_unit_prop \l_siunitx_tmpa_tl { \prop_get:NVN \l_siunitx_unit_prop \l_siunitx_tmpa_tl \l_siunitx_tmpa_tl \siunitx_unit_format_power_aux: } { \tl_set:Nx \l_siunitx_tmpa_tl { per- \int_use:N \l_siunitx_unit_int } \prop_if_in:NVT \l_siunitx_unit_prop \l_siunitx_tmpa_tl { \tl_set:Nn \l_siunitx_tmpa_tl { 1 } \siunitx_unit_format_power_aux: } } } % \end{macrocode} % The auxiliary function needs to make sure that the printing routine % prints the power as a number, not as text: the two modes may be % different. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_format_power_aux: { \tl_if_eq:nVTF { repeat } \l_siunitx_per_mode_tl { \siunitx_unit_format_power_repeat: } { \siunitx_unit_format_power_per: } \tl_if_eq:nVF { 1 } \l_siunitx_tmpa_tl { \siunitx_unit_format_power_brackets: \tl_put_right:Nx \l_siunitx_unit_current_tl { ^ { \PrintNumber { \exp_not:V \l_siunitx_tmpa_tl } } } } } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}[aux]{\siunitx_unit_format_power_brackets:} % A check is made for a qualifier with a space, which needs brackets % if there is also a power. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_format_power_brackets: { \tl_set:Nx \l_siunitx_tmpb_tl { bracket- \int_use:N \l_siunitx_unit_int } \prop_if_in:NVT \l_siunitx_unit_prop \l_siunitx_tmpb_tl { \bool_if:NT \l_siunitx_brackets_bool { \siunitx_tl_put_left_maths:NV \l_siunitx_unit_current_tl \l_siunitx_bracket_open_tl \siunitx_tl_put_right_maths:NV \l_siunitx_unit_current_tl \l_siunitx_bracket_close_tl } } } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{\siunitx_unit_format_power_per:} %\begin{macro}[aux]{\siunitx_unit_format_power_repeat:} % For dealing with \cs{per} and repeated \cs{per} symbols. The sign % change does not use any numbers, as this makes life easier with % non-integer values. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_format_power_per: { \tl_set:Nx \l_siunitx_tmpb_tl { per- \int_use:N \l_siunitx_unit_int } \prop_if_in:NVT \l_siunitx_unit_prop \l_siunitx_tmpb_tl { \bool_if:NF \l_siunitx_per_fraction_bool { \tl_if_in:NnTF \l_siunitx_tmpa_tl { - } { \cs_set:Npn \siunitx_tmp:w ##1 - ##2 \q_stop { \tl_set:Nn \l_siunitx_tmpa_tl {##2} } \exp_afer:wN \siunitx_tmp:w \l_siunitx_tmpa_tl \q_stop } { \tl_put_left:Nn \l_siunitx_tmpa_tl { - } } } } } \cs_new_nopar:Npn \siunitx_unit_format_power_repeat: { \tl_set:Nx \l_siunitx_tmpb_tl { per- \int_use:N \l_siunitx_unit_int } \prop_if_in:NVT \l_siunitx_unit_prop \l_siunitx_tmpb_tl { \siunitx_tl_put_left_maths:NV \l_siunitx_unit_current_tl \l_siunitx_per_symbol_tl } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_format_prefix:} %\begin{macro}[aux]{\siunitx_unit_format_prefix_number:} %\begin{macro}[aux]{\siunitx_unit_format_prefix_number_calc:} %\begin{macro}[aux]{\siunitx_unit_format_prefix_symbol:} % If there is a prefix, it is added to the output. When using numerical % output, some conversion is needed instead. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_format_prefix: { \tl_set:Nx \l_siunitx_tmpa_tl { prefix- \int_use:N \l_siunitx_unit_int } \prop_if_in:NVT \l_siunitx_unit_prop \l_siunitx_tmpa_tl { \prop_get:NVN \l_siunitx_unit_prop \l_siunitx_tmpa_tl \l_siunitx_unit_prefix_current_tl \bool_if:NTF \l_siunitx_prefix_symbols_bool { \siunitx_unit_format_prefix_symbol: } { \siunitx_unit_format_prefix_number: } } } \cs_new_nopar:Npn \siunitx_unit_format_prefix_number: { \tl_set:Nx \l_siunitx_tmpa_tl { prefix-base- \int_use:N \l_siunitx_unit_int } \prop_get:NVN \l_siunitx_unit_prop \l_siunitx_tmpa_tl \l_siunitx_tmpa_tl \intexpr_compare:nT { \l_siunitx_unit_prefix_base_int = \c_zero } { \int_set:Nn \l_siunitx_unit_prefix_base_int { \l_siunitx_tmpa_tl } } \intexpr_compare:nTF { \l_siunitx_unit_prefix_base_int = \l_siunitx_tmpa_tl } { \siunitx_unit_format_prefix_number_calc: } { \msg_error:nn { siunitx } { prefix-base-mismatch } } } \cs_new_nopar:Npn \siunitx_unit_format_prefix_number_calc: { \tl_set:Nx \l_siunitx_tmpa_tl { power- \int_use:N \l_siunitx_unit_int } \prop_if_in:NVTF \l_siunitx_unit_prop \l_siunitx_tmpa_tl { \prop_get:NVN \l_siunitx_unit_prop \l_siunitx_tmpa_tl \l_siunitx_tmpa_tl } { \tl_set:Nn \l_siunitx_tmpa_tl { 1 } } \tl_set:Nx \l_siunitx_unit_prefix_current_tl { \intexpr_eval:n { \l_siunitx_unit_prefix_current_tl * \l_siunitx_tmpa_tl } } \tl_set:Nx \l_siunitx_tmpa_tl { per- \int_use:N \l_siunitx_unit_int } \prop_if_in:NVTF \l_siunitx_unit_prop \l_siunitx_tmpa_tl { \int_set:Nn \l_siunitx_unit_prefix_int { \l_siunitx_unit_prefix_int - \l_siunitx_unit_prefix_current_tl } } { \int_set:Nn \l_siunitx_unit_prefix_int { \l_siunitx_unit_prefix_int + \l_siunitx_unit_prefix_current_tl } } } \cs_new_nopar:Npn \siunitx_unit_format_prefix_symbol: { \tl_set_eq:NN \l_siunitx_unit_current_tl \l_siunitx_unit_prefix_current_tl } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_format_qualifier:} %\begin{macro}{\siunitx_unit_format_qualifier_brackets:} %\begin{macro}{\siunitx_unit_format_qualifier_space:} %\begin{macro}{\siunitx_unit_format_qualifier_subscript:} % Three methods for showing qualifiers, each with its own sub-function. % For the \texttt{space} methods, a warning is set in the property list % as if there is a power then some brackets will be needed. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_format_qualifier: { \tl_set:Nx \l_siunitx_tmpa_tl { qualifier- \int_use:N \l_siunitx_unit_int } \prop_if_in:NVT \l_siunitx_unit_prop \l_siunitx_tmpa_tl { \prop_get:NVN \l_siunitx_unit_prop \l_siunitx_tmpa_tl \l_siunitx_tmpa_tl \use:c { siunitx_unit_format_qualifier_ \l_siunitx_qualifier_mode_tl : } } } \cs_new_nopar:Npn \siunitx_unit_format_qualifier_brackets: { \siunitx_tl_put_right_maths:NV \l_siunitx_unit_current_tl \l_siunitx_bracket_open_tl \tl_put_right:NV \l_siunitx_unit_current_tl \l_siunitx_tmpa_tl \siunitx_tl_put_right_maths:NV \l_siunitx_unit_current_tl \l_siunitx_bracket_close_tl } \char_make_active:N \~ \cs_new_nopar:Npn \siunitx_unit_format_qualifier_space: { \tl_put_right:Nn \l_siunitx_unit_current_tl { \text { ~ } } \tl_put_right:NV \l_siunitx_unit_current_tl \l_siunitx_tmpa_tl \tl_set:Nx \l_siunitx_tmpa_tl { bracket- \int_use:N \l_siunitx_unit_int } \prop_put:NVn \l_siunitx_unit_prop \l_siunitx_tmpa_tl { true } } \char_make_space:N \~ \group_begin: \char_set_lccode:nn { `\@ } { `\_ } \char_make_math_subscript:N \@ \tl_to_lowercase:n { \group_end: \cs_new_nopar:Npn \siunitx_unit_format_qualifier_subscript: { \tl_put_right:No \l_siunitx_unit_current_tl { \exp_after:wN @ \exp_after:wN { \l_siunitx_tmpa_tl } } } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_format_symbol:} % If there is no symbol, something is wrong! % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_format_symbol: { \tl_set:Nx \l_siunitx_tmpa_tl { symbol- \int_use:N \l_siunitx_unit_int } \prop_if_in:NVTF \l_siunitx_unit_prop \l_siunitx_tmpa_tl { \prop_get:NVN \l_siunitx_unit_prop \l_siunitx_tmpa_tl \l_siunitx_tmpa_tl \tl_put_right:NV \l_siunitx_unit_current_tl \l_siunitx_tmpa_tl } { \msg_error:nn { siunitx } { prefix-only } } } % \end{macrocode} %\end{macro} % %\subsection{Unit output} % % A collection of the internal parts of various user functions. % %\begin{macro}{\l_siunitx_number_unit_power_bool} %\begin{macro}{\l_siunitx_number_unit_repeat_bool} % Some storage for options. % \begin{macrocode} \bool_new:N \l_siunitx_number_unit_power_bool \bool_new:N \l_siunitx_number_unit_repeat_bool % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_number_unit_breaks_bool} %\begin{macro}{\l_siunitx_number_unit_separator_tl} % Options for printing units or units with numbers. % \begin{macrocode} \keys_define:nn { siunitx } { allow-number-unit-breaks .bool_set:N = \l_siunitx_number_unit_breaks_bool, number-unit-separator .tl_set:N = \l_siunitx_number_unit_separator_tl, repeated-units .choice:, repeated-units / false .code:n = { \bool_set_false:N \l_siunitx_number_unit_power_bool \bool_set_false:N \l_siunitx_number_unit_repeat_bool }, repeated-units / power .code:n = { \bool_set_true:N \l_siunitx_number_unit_power_bool \bool_set_false:N \l_siunitx_number_unit_repeat_bool }, repeated-units / true .code:n = { \bool_set_false:N \l_siunitx_number_unit_power_bool \bool_set_true:N \l_siunitx_number_unit_repeat_bool }, repeated-units .default:n = { true } } \keys_set:nn { siunitx } { number-unit-separator = \,, repeated-units = true } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_output:nn} % For typesetting a unit directly: used by \cs{si} and the \texttt{s} % column. The second argument is any options to set locally. % \begin{macrocode} \cs_new:Npn \siunitx_unit_output:nn #1#2 { \siunitx_unit_in:nn {#1} {#2} \intexpr_compare:nF { \l_siunitx_unit_prefix_int = \c_zero } { \tl_set:Nx \l_siunitx_tmpa_tl { \int_use:N \l_siunitx_unit_prefix_base_int ^ { \int_use:N \l_siunitx_unit_prefix_int } } \siunitx_print:nV { number } \l_siunitx_tmpa_tl \siunitx_unit_output_number_sep: } \siunitx_print:nV { unit } \l_siunitx_unit_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_unit_output_number_sep:} % For printing the number separator. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_output_number_sep: { \bool_if:NTF \l_siunitx_number_unit_breaks_bool { \allowbreak } { \nobreak } \ensuremath { \l_siunitx_number_unit_separator_tl } } % \end{macrocode} %\end{macro} % %\subsection{Numbers with units} % % Numbers with units have to be formatted in a more complex way than % simply sticking the two together. % %\begin{macro}{\l_siunitx_pre_unit_tl} % When there is a pre-unit, it gets stored here. % \begin{macrocode} \tl_new:N \l_siunitx_pre_unit_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_number_product_int} % Used to count up the number of product tokens in a number. % \begin{macrocode} \int_new:N \l_siunitx_number_product_int % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_combined:nnnn} % Setting up for printing numbers with units is a more complex operation % than it first appears. First, the pre-unit is set up: this is easy. % The main unit is a bit more complex, so is handled separately. The % number part is then handed off. % \begin{macrocode} \cs_new:Npn \siunitx_combined:nnnn #1#2#3#4 { \IfNoValueTF {#3} { \tl_clear:N \l_siunitx_pre_unit_tl } { \siunitx_unit_in:nn {#3} {#1} \cs_set_eq:NN \l_siunitx_pre_unit_tl \l_siunitx_unit_tl } \siunitx_combined_unit:nnn {#2} {#4} {#1} \siunitx_combined_loop:n {#2} } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_combined_loop:n} %\begin{macro}{\siunitx_combined_loop:V} % Printing is controlled here. There are a number of tasks to carry out, % hence needing to work in this way. % \begin{macrocode} \cs_new:Npn \siunitx_combined_loop:n #1 { \intexpr_compare:nTF { \l_siunitx_unit_prefix_int = \c_zero } { \siunitx_number_output:n {#1} } { \tl_set:Nn \l_siunitx_tmpa_tl { #1 e } \tl_put_right:NV \l_siunitx_tmpa_tl \l_siunitx_unit_prefix_int \exp_args:NV \siunitx_number_output:n \l_siunitx_tmpa_tl } \siunitx_unit_output_number_sep: \siunitx_print:nV { unit } \l_siunitx_unit_tl } \cs_generate_variant:Nn \siunitx_combined_loop:n { V } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_combined_number:n} % \begin{macrocode} \cs_new:Npn \siunitx_combined_number:n #1 { \bool_if:NTF \l_siunitx_number_parse_bool { \tl_clear:N \l_siunitx_number_out_tl \tl_clear:N \l_siunitx_number_out_saved_tl \bool_set_false:N \l_siunitx_number_compound_bool \siunitx_number_output_parse:n {#1} \siunitx_number_output_print: } { \siunitx_print:nn { number } {#1} } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_combined_unit:nnn} % In most cases, sorting out the main unit is easy: simply set up for % printing using \cs{siunitx_unit_in:nn}. However, if there are multiple % parts to the number, and they are to be combined into the unit, then % there is more work to do. In either case, the result is the % correctly-prepared unit stored in \cs{l_siunitx_unit_tl}. % \begin{macrocode} \cs_new:Npn \siunitx_combined_unit:nnn #1#2#3 { \bool_if:NTF \l_siunitx_number_unit_power_bool { \siunitx_combined_product_count:n {#1} \intexpr_compare:nTF { \l_siunitx_number_product_int > \c_zero } { \int_incr:N \l_siunitx_number_product_int \tl_set:Nn \l_siunitx_tmpa_tl {#2} \tl_set:No \l_siunitx_tmpb_tl { \exp_after:wN \tothe \exp_after:wN { \int_use:N \l_siunitx_number_product_int } } \tl_put_right:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl \siunitx_unit_in:Vn \l_siunitx_tmpa_tl {#3} } { \siunitx_unit_in:nn {#2} {#3} } } { \siunitx_unit_in:nn {#2} {#3} } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_combined_product_count:n} %\begin{macro}[aux]{\siunitx_combined_product_count_aux:n} % \begin{macrocode} \cs_new:Npn \siunitx_combined_product_count:n #1 { \int_zero:N \l_siunitx_number_product_int \tl_set:Nn \l_siunitx_tmpa_tl {#1} \tl_map_function:NN \l_siunitx_input_product_tl \siunitx_combined_product_count_aux:N } \cs_new:Npn \siunitx_combined_product_count_aux:N #1 { \tl_if_in:NnT \l_siunitx_tmpa_tl {#1} { \int_incr:N \l_siunitx_number_product_int \tl_remove_in:Nn \l_siunitx_tmpa_tl {#1} \siunitx_combined_product_count_aux:N #1 } } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Ranges} % %\begin{macro}{\l_siunitx_range_phrase_tl} % Simple settings for ranges. % \begin{macrocode} \keys_define:nn { siunitx } { range-phrase .tl_set:N = \l_siunitx_range_phrase_tl, } \keys_set:nn { siunitx } { range-phrase = { ~ to ~ } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_range_numbers:nn} %\begin{macro}{\siunitx_range_numbers_aux:n} % A range of numbers. This is more restrictive than the \cs{num} % function: nothing compound. % \begin{macrocode} \cs_new:Npn \siunitx_range_numbers:nn #1#2 { \siunitx_range_numbers_aux:n {#1} \text { \l_siunitx_range_phrase_tl } \siunitx_range_numbers_aux:n {#2} } \cs_new:Npn \siunitx_range_numbers_aux:n #1 { \bool_if:NTF \l_siunitx_number_parse_bool { \tl_clear:N \l_siunitx_number_out_tl \tl_clear:N \l_siunitx_number_out_saved_tl \bool_set_false:N \l_siunitx_number_compound_bool \siunitx_number_output_parse:n {#1} \bool_if:NTF \l_siunitx_number_compound_bool { \msg_error:nnx { siunitx } { multi-part-range } {#1} } { \siunitx_number_output_print: } } { \siunitx_print:nn { number } {#1} } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_range_unit:nnnn} % Unit printing is also simple: basically a past-up job. % \begin{macrocode} \cs_new:Npn \siunitx_range_unit:nnnn #1#2#3#4 { \siunitx_unit_in:nn {#1} {#2} \siunitx_range_numbers_aux:n {#3} \siunitx_unit_output_number_sep: \siunitx_print:nV { unit } \l_siunitx_unit_tl \text { \l_siunitx_range_phrase_tl } \siunitx_range_numbers_aux:n {#4} \siunitx_unit_output_number_sep: \siunitx_print:nV { unit } \l_siunitx_unit_tl } % \end{macrocode} %\end{macro} % %\subsection{Setting up tables} % %\begin{macro}{\siunitx_table_rewrite_cellspace:} % There is a slight problem with the \pkg{cellspace} package: it also % uses \texttt{S} for a column type Here, \texttt{S} seems to make % more sense for \pkg{siunitx}, with \texttt{C} used for % \pkg{cellspace}. To enable this to work well, the column % rewriting code happens \cs{AtBeginDocument}. The \texttt{S} column % is deleted from \cs{NC@list} so that no warning appears. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_rewrite_cellspace: { \@ifpackageloaded { cellspace } { \newcolumntype { C } [1] { > { \bcolumn ##1 \@nil } ##1 < { \ecolumn } } \cs_set:Npn \siunitx_tmp:w ##1 \NC@do~S ##2 \q_stop { \toks_set:N \NC@list { ##1 ##2 } } \exp_after:wN \siunitx_tmp:w \toks_use:N \NC@list \q_stop \cs_gundefine:N \NC@find@S } { } } \AtBeginDocument { \siunitx_table_rewrite_cellspace: } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_table_rewrite_create:N} % The \texttt{s} and \texttt{S} column types are both created using % the \pkg{array} package, but with the internal macros redefined % to work with optional argument. First, there is a need to do a % quick shuffle with the \cs{NC@list} macro. The \pkg{siunitx} % columns have to be listed first, as otherwise the optional % arguments do not work correctly. So they are added \enquote{by hand} % to the appropriate macro. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_rewrite_create:N #1 { \tl_set:Nn \l_siunitx_tmpa_tl { \NC@do ~ #1 } \tl_put_right:NV \l_siunitx_tmpa_tl \NC@list \newcolumntype {#1} { } \toks_set:NV \NC@list \l_siunitx_tmpa_tl \exp_args:NNc \renewcommand * { NC@rewrite@ #1 } [1] [ ] { \toks_put_right:Nn \@temptokena { > { \siunitx_table_collect_begin:Nn #1 {##1} } c < { \siunitx_table_print: } } \use:c { siunitx_table_column_start_ #1 : } \NC@find } } \AtBeginDocument { \siunitx_table_rewrite_create:N S } \AtBeginDocument { \siunitx_table_rewrite_create:N s } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_table_column_start_S:} %\begin{macro}{\siunitx_table_column_start_s:} %\begin{macro}{\siunitx_table_column_start_s_aux} % There is a slight issue with the \texttt{s} column: \TeX\ attempts to % expand material in columns \emph{before} using the template to wrap % material up (this allows \cs{omit} and \cs{span} to be inside other % macros). The result is that the unit macros have to be defined when % the column starts if they are to work correctly. Everything needs to % be unexpandable, hence the \cs{protected} definition used. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_column_start_S: { } \cs_new_nopar:Npn \siunitx_table_column_start_s: { \group_execute_after:N \siunitx_table_column_start_s_aux: } \cs_new_nopar:Npn \siunitx_table_column_start_s_aux: { \bool_if:NF \l_siunitx_create_free_bool { \tl_map_inline:Nn \l_siunitx_declare_list_tl { \cs_set_protected_nopar:Npn ##1 { \ERROR } } } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\subsection{Collecting tokens in tables} % % The table system is in two parts, collecting tokens and typesetting % the result. The collection routine tries to ensure that the % typesetting part only receives real cell contents. % %\begin{macro}{\l_siunitx_table_collect_tl} %\begin{macro}{\l_siunitx_table_collect_pre_tl} %\begin{macro}{\l_siunitx_table_collect_post_tl} % Three storage areas. % \begin{macrocode} \tl_new:N \l_siunitx_table_collect_tl \tl_new:N \l_siunitx_table_collect_pre_tl \tl_new:N \l_siunitx_table_collect_post_tl % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_table_collect_pre_bool} %\begin{macro}{\l_siunitx_table_collect_post_bool} % Flags for having found a number in an \texttt{S} column. % \begin{macrocode} \bool_new:N \l_siunitx_table_collect_pre_bool \bool_new:N \l_siunitx_table_collect_post_bool % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_table_collect_begin:Nn} % The collector starts by setting up local options, then clears and % initialises the storage and testing system. % \begin{macrocode} \cs_new:Npn \siunitx_table_collect_begin:Nn #1#2 { \group_begin: \keys_set:nn { siunitx } {#2} \cs_set_eq:Nc \siunitx_table_collect_token:N { siunitx_table_collect_token_ #1 :N } \cs_set_eq:Nc \siunitx_table_print: { siunitx_table_print_ #1 : } \use:c { siunitx_table_collect_init_ #1 : } \siunitx_table_collect_get: } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_table_collect_braced:n} % The collection of braced items depends on the column type. So we % start of with an empty definition. % \begin{macrocode} \cs_new:Npn \siunitx_table_collect_braced:n #1 { } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_table_collect_expand:N} % 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} \cs_new:Npn \siunitx_table_collect_expand:N #1 { \siunitx_if_tl:NTF #1 { \tl_use:N \siunitx_table_collect_pre_tl \tl_clear:N \siunitx_table_collect_pre_tl \cs_set_nopar:Npx \siunitx_table_collect_next: { \exp_not:N \siunitx_table_collect_get: \exp_not:V #1 } } { \bool_if:NTF \siunitx_table_collect_pre_bool { \tl_put_right:Nn \siunitx_table_collect_pre_tl {#1} } { \bool_set_true:N \siunitx_table_collect_post_bool \bool_set_false:N \siunitx_table_collect_pre_bool \tl_put_right:Nn \siunitx_table_collect_post_tl {#1} } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_table_collect_get:} % The token collection system first has to check that the next argument % does not start with an opening-brace character. If it does, the % testing is skipped and the braced token is stored. Otherwise, a check % is made against various ignored tokens. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_collect_get: { \cs_set_eq:NN \siunitx_table_collect_next: \siunitx_table_collect_get: \peek_charcode:NTF \c_group_begin_token { \siunitx_table_collect_braced:n } { \siunitx_table_collect_not_braced:N } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_table_collect_init:} % The usual spin-out of basics. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_collect_init: { \tl_clear:N \l_siunitx_table_collect_tl \tl_clear:N \l_siunitx_table_collect_pre_tl \tl_clear:N \l_siunitx_table_collect_post_tl \bool_set_false:N \l_siunitx_table_collect_post_bool } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_table_collect_init_s:} %\begin{macro}{\siunitx_table_collect_init_S:} % Some type-specific definitions. In the \texttt{S} case, the % initialisation function for numbers is used to set % \cs{l_siunitx_number_valid_tl} correctly. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_collect_init_s: { \bool_set_false:N \l_siunitx_table_collect_pre_bool \cs_set:Npn \siunitx_table_collect_braced:n ##1 { \tl_put_right:Nn \l_siunitx_table_collect_tl { {##1} } \siunitx_table_collect_next: } } \cs_new_nopar:Npn \siunitx_table_collect_init_S: { \siunitx_number_in_init: \bool_set_true:N \l_siunitx_table_collect_pre_bool \cs_set:Npn \siunitx_table_collect_braced:n ##1 { \bool_if:NTF \l_siunitx_table_collect_pre_bool { \tl_put_right:Nn \l_siunitx_table_collect_pre_tl { {##1} } } { \bool_set_true:N \l_siunitx_table_collect_post_bool \tl_put_right:Nn \l_siunitx_table_collect_post_tl { {##1} } } \siunitx_table_collect_next: } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_table_collect_next:} % A holder for the next thing to do. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_collect_next: { } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_table_collect_newline:} % The end macro needs to come before the new line is called. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_collect_newline: { \siunitx_table_print: \tabularnewline } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_table_collect_not_braced:N} %\begin{macro}[aux]{\siunitx_table_collect_not_braced_aux_i:N} %\begin{macro}[aux]{\siunitx_table_collect_not_braced_aux_ii:N} % A few macros are simply passed through to be executed; this is mainly % so that the table actually works. The newline function needs its own % function, which is picked up by hand. % \begin{macrocode} \cs_new:Npn \siunitx_table_collect_not_braced:N #1 { \token_if_eq_meaning:NNF #1 \ignorespaces { \token_if_eq_meaning:NNF #1 \unskip { \siunitx_table_collect_not_braced_aux_i:N #1 } } \siunitx_table_collect_next: } \cs_new:Npn \siunitx_table_collect_not_braced_aux_i:N #1 { \cs_set:Npn \siunitx_table_collect_not_braced_aux_ii:N ##1 { \token_if_eq_meaning:NNT #1 ##1 { \cs_set_eq:NN \siunitx_table_collect_next: ##1 } } \tl_map_function:nN { \csname \end \endtabular \relax \siunitx_table_print: } \siunitx_table_collect_not_braced_aux_ii:N \token_if_eq_meaning:NNT \siunitx_table_collect_next: \siunitx_table_collect_get: { \token_if_eq_meaning:NNTF #1 \tabularnewline { \cs_set_eq:NN \siunitx_table_collect_next: \siunitx_table_collect_newline: } { \siunitx_table_collect_token:N #1 } } } \cs_new:Npn \siunitx_table_collect_not_braced_aux_ii:N #1 { } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_table_collect_token:N} %\begin{macro}{\siunitx_table_collect_token_s:N} % For the \texttt{s} column, every token is added to the same storage % area, so life is simple. % \begin{macrocode} \cs_new:Npn \siunitx_table_collect_token:N #1 { } \cs_new:Npn \siunitx_table_collect_token_s:N #1 { \tl_put_right:Nn \l_siunitx_table_collect_tl {#1} } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_table_collect_token_S:N} % Not so easy for the \texttt{S} column type. If the content is after % a number, things are easy. On the other hand, if the token might be % a number, then a check is made. It the token is still unmatched, then % it is passed on to the expansion handler. % \begin{macrocode} \cs_new:Npn \siunitx_table_collect_token_S:N #1 { \bool_if:NTF \l_siunitx_table_collect_post_bool { \tl_put_right:Nn \l_siunitx_table_collect_post_tl {#1} } { \tl_if_in:NnTF \l_siunitx_number_valid_tl {#1} { \bool_set_false:N \l_siunitx_table_collect_pre_tl \tl_put_right:Nn \l_siunitx_table_collect_tl {#1} } { \siunitx_table_collect_expand:N #1 } } } % \end{macrocode} %\end{macro} % %\subsection{Symbols} % % Not all units use letters alone for their symbol. This raises two % problems. First, the symbols need to work in maths and in text mode. % Second, the user needs to be able to adjust each symbol. % %\begin{macro}{\l_siunitx_redefine_symbols_bool} % Only one setting applies here! % \begin{macrocode} \keys_define:nn { siunitx } { redefine-symbols .bool_set:N = \l_siunitx_redefine_symbols_bool, } \keys_set:nn { siunitx } { redefine-symbols = true } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_redefine_symbols:} % The redefinition of symbols has to do a number of checks to ensure % that there are no clashes. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_redefine_symbols: { \bool_if:NT \l_siunitx_redefine_symbols_bool { \@ifpackageloaded { textcomp } { \keys_set:nn { siunitx } { maths-degree = \text { \textdegree }, text-degree = \textdegree, } \@ifpackageloaded { mathptmx } { } { \keys_set:nn { siunitx } { text-micro = \textmu, text-ohm = \textohm } } \tl_if_eq:nVT { OT1 } \encodingdefault { \keys_set:nn { siunitx } { maths-angstrom = \text { \capitalring { A } }, text-angstrom = \capitalring { A } } } } { } \@ifpackageloaded { upgreek } { \keys_set:nn { siunitx } { maths-ohm = \Upomega } } { } } } \AtBeginDocument { \siunitx_redefine_symbols: } % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_angstrom_maths_tl} %\begin{macro}{\l_siunitx_arcminute_maths_tl} %\begin{macro}{\l_siunitx_arcsecond_maths_tl} %\begin{macro}{\l_siunitx_celsius_maths_tl} %\begin{macro}{\l_siunitx_degree_maths_tl} %\begin{macro}{\l_siunitx_micro_maths_tl} %\begin{macro}{\l_siunitx_ohm_maths_tl} % The symbol storage macros are created separately for maths and text % mode, although this is all pretty similar. The default definitions use % what is generally available, except for those for micro, where % Computer Modern does not have the appropriate symbol at all. For the % maths mode omega option, the |\text{\ensuremath{...}}| construction % deals with the case where \cs{mathnormal} has the wrong symbol. % \begin{macrocode} \keys_define:nn { siunitx } { math-angstrom .tl_set:N = \l_siunitx_angstrom_maths_tl, maths-angstrom .tl_set:N = \l_siunitx_angstrom_maths_tl, math-arcminute .tl_set:N = \l_siunitx_arcminute_maths_tl, maths-arcminute .tl_set:N = \l_siunitx_arcminute_maths_tl, math-arcsecond .tl_set:N = \l_siunitx_arcsecond_maths_tl, maths-arcsecond .tl_set:N = \l_siunitx_arcsecond_maths_tl, math-celsius .tl_set:N = \l_siunitx_celsius_maths_tl, maths-celsius .tl_set:N = \l_siunitx_celsius_maths_tl, math-degree .tl_set:N = \l_siunitx_degree_maths_tl, maths-degree .tl_set:N = \l_siunitx_degree_maths_tl, math-micro .tl_set:N = \l_siunitx_micro_maths_tl, maths-micro .tl_set:N = \l_siunitx_micro_maths_tl, math-ohm .tl_set:N = \l_siunitx_ohm_maths_tl, maths-ohm .tl_set:N = \l_siunitx_ohm_maths_tl, } \keys_set:nn { siunitx } { maths-angstrom = \text { \AA }, maths-arcminute = { } ^ { \prime }, maths-arcsecond = { } ^ { \prime \prime }, maths-celsius = { } ^ { \circ } \kern - \scriptspace C, maths-degree = { } ^ { \circ }, maths-micro = \text { \c_siunitx_mu_tl }, maths-ohm = \text { \ensuremath { \c_siunitx_omega_tl } }, } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\l_siunitx_angstrom_text_tl} %\begin{macro}{\l_siunitx_arcminute_text_tl} %\begin{macro}{\l_siunitx_arcsecond_text_tl} %\begin{macro}{\l_siunitx_celsius_text_tl} %\begin{macro}{\l_siunitx_degree_text_tl} %\begin{macro}{\l_siunitx_micro_text_tl} %\begin{macro}{\l_siunitx_ohm_text_tl} % Text versions are similar. % \begin{macrocode} \keys_define:nn { siunitx } { text-angstrom .tl_set:N = \l_siunitx_angstrom_text_tl, text-arcminute .tl_set:N = \l_siunitx_arcminute_text_tl, text-arcsecond .tl_set:N = \l_siunitx_arcsecond_text_tl, text-celsius .tl_set:N = \l_siunitx_celsius_text_tl, text-degree .tl_set:N = \l_siunitx_degree_text_tl, text-micro .tl_set:N = \l_siunitx_micro_text_tl, text-ohm .tl_set:N = \l_siunitx_ohm_text_tl, } \keys_set:nn { siunitx } { text-angstrom = \AA, text-arcminute = \ensuremath { { } ^ { \prime } }, text-arcsecond = \ensuremath { { } ^ { \prime \prime } }, text-celsius = \ensuremath { { } ^ { \circ } \kern - \scriptspace C }, text-degree = \ensuremath { { } ^ { \circ } }, text-micro = \c_siunitx_mu_tl , text-ohm = \ensuremath { \c_siunitx_omega_tl }, } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_symbol_new:n} % For creating the outer symbol macro. % \begin{macrocode} \cs_new:Npn \siunitx_symbol_new:n #1 { \exp_args:Nc \NewDocumentCommand { SIUnitSymbol #1 } { } { \mode_if_math:TF { \tl_to_lowercase:n { \use:c { l_siunitx_ #1 _maths_tl } } } { \tl_to_lowercase:n { \use:c { l_siunitx_ #1 _text_tl } } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\SIUnitSymbolAngstrom} %\begin{macro}{\SIUnitSymbolArcminute} %\begin{macro}{\SIUnitSymbolArcsecond} %\begin{macro}{\SIUnitSymbolCelsius} %\begin{macro}{\SIUnitSymbolDegree} %\begin{macro}{\SIUnitSymbolMicro} %\begin{macro}{\SIUnitSymbolOhm} % The wrapper macros are created. % \begin{macrocode} \siunitx_symbol_new:n { Angstrom } \siunitx_symbol_new:n { Arcminute } \siunitx_symbol_new:n { Arcsecond } \siunitx_symbol_new:n { Celsius } \siunitx_symbol_new:n { Degree } \siunitx_symbol_new:n { Micro } \siunitx_symbol_new:n { Ohm } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\subsection{Messages} % % Lots of messages, all of them together in one block to make life % easier. % \begin{macrocode} \msg_new:nnnn { siunitx } { duplicate-decimal-token } {Duplicate decimal token.} {Only one decimal token can appear in a single number.} \msg_new:nnnn { siunitx } { duplicate-exponent-token } {Duplicate exponent token found.} {Only one exponent token can appear in a single number.} \msg_new:nnnn { siunitx } { duplicate-quotient-token } {Duplicate quotient token.} {Only one quotient token can appear in a single number.} \msg_new:nnnn { siunitx } { empty-exponent } {Empty exponent.} {The exponent contains no number.} \msg_new:nnnn { siunitx } { empty-number } {Empty numerical argument.} {The given `number' contains no information.} \msg_new:nnnn { siunitx } { empty-uncertainty } {Empty uncertainty given.} {The number given contains an empty uncertainty.} \msg_new:nnnn { siunitx } { ending-product-token } {Misplaced product token.} {A number cannot end with a product token.} \msg_new:nnnn { siunitx } { ending-quotient-token } {Misplaced quotient token.} {A number cannot end with a quotient token.} \msg_new:nnnn { siunitx } { invalid-token-in-number } {Invalid token `#1' in numerical input.} {% Only the tokens\\% \msg_space: \msg_space: #2\\% are valid for numerical input.% } \msg_new:nnnn { siunitx } { literal-unit } {Literal units disabled.} {% You gave the literal input `\exp_not:n {#1}'\\% but literal unit output is disabled.% } \msg_new:nnnn { siunitx } { multi-part-range } {Numerical range with multiple parts.} {% The input `#1' is a number which has more than one part.\\ Ranges can only contain one number in each part.% } \msg_new:nnnn { siunitx } { misplaced-complex-root } {Misplaced complex root.} {The complex root token `#1' can only come at the end of a number.} \msg_new:nnnn { siunitx } { misplaced-closing-uncertainty } {Misplaced closing uncertainty token.} {% The closing uncertainty token `#1' can only come at the end of a number.% } \msg_new:nnnn { siunitx } { misplaced-sign } {Misplaced sign token.} {The sign token `#1' can only come at the beginning of a number.} \msg_new:nnnn { siunitx } { misplaced-uncertainty } {Misplaced uncertainty token.} {The uncertainty token `#1' does not properly match another token.} \msg_new:nnn { siunitx } { option-preamble-only } {Option `#1' only available in the preamble.} \msg_new:nnnn { siunitx } { prefix-base-mismatch } {Prefix bases do not match.} {% You have asked for prefixes to be converted into a power,\\% but the bases do not match.% } \msg_new:nnn { siunitx } { prefix-only } {Prefix with no unit.} \msg_new:nnnn { siunitx } { qualifier-before-unit } {Qualifier before unit.} {Unit qualifiers have to follow after units, not before them.} \msg_new:nnnn { siunitx } { starting-product-token } {Misplaced product token.} {A number cannot begin with a product token.} \msg_new:nnnn { siunitx } { starting-quotient-token } {Misplaced quotient token.} {A number cannot begin with a quotient token.} \msg_new:nnnn { siunitx } { uncertainty-only } {Uncertainty but no number.} {A number contains an uncertainty part with no main value.} % \end{macrocode} % %\subsection{Design-level macros} % %\begin{macro}{\DeclareSIPower} %\begin{macro}{\DeclareSIPrefix} %\begin{macro}{\DeclareSIQualifier} %\begin{macro}{\DeclareSIUnit} % The macros for creating units and so on are in design name space. % Basically, a set of shuffles for arguments. % \begin{macrocode} \DeclareDocumentCommand \DeclareSIPower { s m m } { \IfBooleanTF #1 { \siunitx_declare_power_after:Nn #2 {#3} } { \siunitx_declare_power_before:Nn #2 {#3} } } \DeclareDocumentCommand \DeclareSIPrefix { s m m m } { \IfBooleanTF #1 { \siunitx_declare_prefix:Nnnn #2 {#3} { 2 } {#4} } { \siunitx_declare_prefix:Nnnn #2 {#3} { 10 } {#4} } } \DeclareDocumentCommand \DeclareSIQualifier { m m } { \siunitx_declare_qualifier:Nn #1 {#2} } \DeclareDocumentCommand \DeclareSIUnit { o m m } { \IfNoValueTF {#1} { \siunitx_declare_unit:Nnn #2 {#3} { } } { \siunitx_declare_unit:Nnn #2 {#3} {#1} } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % % None of this should be done after the preamble. % \begin{macrocode} \@onlypreamble \DeclareSIPower \@onlypreamble \DeclareSIPrefix \@onlypreamble \DeclareSIQualifier \@onlypreamble \DeclareSIUnit % \end{macrocode} % %\subsection{Document macros} % % The user document macros are all collected together here for ease. % %\begin{macro}{\num} % The \cs{num} macro is quite simple: read the number, check it is % correct then print it. % \begin{macrocode} \DeclareDocumentCommand \num { o m } { \group_begin: \IfNoValueF {#1} { \keys_set:nn { siunitx } {#1} } \siunitx_number_output:n {#2} \group_end: } % \end{macrocode} %\end{macro} % %\begin{macro}{\numrange} % A very simple approach is taken here: this is not intended for % anything complicated. % \begin{macrocode} \DeclareDocumentCommand \numrange { o m m } { \group_begin: \IfNoValueF {#1} { \keys_set:nn { siunitx } {#1} } \siunitx_range_numbers:nn {#2} {#3} \group_end: } % \end{macrocode} %\end{macro} % %\begin{macro}{\PrintNumber} %\begin{macro}{\PrintSIUnit} % There are some places where a macro to print numbers is needed with % user category codes. For consistency, there is also one for printing % units. In neither case is there any processing at all. These functions % are given design-like names to indicate that they are not intended % for general use. % \begin{macrocode} \NewDocumentCommand \PrintNumber { m } { \siunitx_print:nn { number } {#1} } \NewDocumentCommand \PrintSIUnit { m } { \siunitx_print:nn { unit } {#1} } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\si} % The \cs{si} macro needs to pass options through to the internal % function as well as setting them here. This is used so that options % set for a unit can be overridden on a one-off basis. % \begin{macrocode} \DeclareDocumentCommand \si { o m } { \group_begin: \IfNoValueTF {#1} { \siunitx_unit_output:nn {#2} { } } { \keys_set:nn { siunitx } {#1} \siunitx_unit_output:nn {#2} {#1} } \group_end: } % \end{macrocode} %\end{macro} % %\begin{macro}{\SIrange} % Printing unit ranges is a lot less complex than printing single % numbers with units, as we insist that everything is kept simple. % \begin{macrocode} \DeclareDocumentCommand \SIrange { o m m m } { \group_begin: \IfNoValueTF {#1} { \siunitx_range_unit:nnnn {#4} { } {#2} {#3} } { \keys_set:nn { siunitx } {#1} \siunitx_range_unit:nnnn {#4} {#1} {#2} {#3} } \group_end: } % \end{macrocode} %\end{macro} % %\begin{macro}{\SI} % \begin{macrocode} \DeclareDocumentCommand \SI { o m o m } { \group_begin: \IfNoValueTF {#1} { \siunitx_combined:nnnn { } {#2} {#3} {#4} } { \keys_set:nn { siunitx } {#1} \siunitx_combined:nnnn {#1} {#2} {#3} {#4} } \group_end: } % \end{macrocode} %\end{macro} % %\begin{macro}{\sisetup} % The set up macro simply moves to the correct path and executes % whatever has been passed. % \begin{macrocode} \DeclareDocumentCommand \sisetup { m } { \keys_set:nn { siunitx } {#1} } % \end{macrocode} %\end{macro} % %\subsection{Precautions for section headings} % % There are two issues to be handled for section headings, \emph{etc}. % First, within the \cs{addcontentline} macro the various unit functions % need to be \cs{protected}. Secondly, there is a need to worry about % \pkg{hyperref}, and ensure that everything works cleanly and with % no unnecessary warnings. % %\begin{macro}{\siunitx_contents_add_setup:} %\begin{macro}{\siunitx_contents_add:nnn} %\begin{macro}{\siunitx_contents_add_aux:N} % An updated version of \cs{addtocontents} which will ensure that % everything works properly. Using \cs{token_to_str:N} means that % there is no problem with the asynchronous nature of \TeX's writing % mechanism. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_contents_add_setup: { \cs_set:Npn \addtocontents ##1##2 { \protected@write \@auxout { \cs_set_eq:NN \label \use_none:n \cs_set_eq:NN \index \use_none:n \cs_set_eq:NN \glossary\use_none:n \tl_map_function:NN \l_siunitx_declare_list_tl \siunitx_contents_add_aux:N } { \token_to_str:N \@writefile {##1} {##2} } } } \cs_new_nopar:Npn \siunitx_contents_add_aux:N #1 { \cs_set_nopar:Npn #1 { \token_to_str:N #1 } } \AtBeginDocument { \siunitx_contents_add_setup: } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_contents_bookmarks:} % The idea here is two-fold. First, all of the unit macros are set % up to simply print their literal interpretation: this is hopefully % good enough for most bookmark situations. Secondly, the document % commands are made expandable. This allows a bit of re-arrangement % of the input, removes any set up options (which are being ignored) % and stops \pkg{hyperref} issuing a warning. The \pkg{xparse} warning % about redefining commands is also silenced. To save a few % expansions, the expandable commands which do not need any optional % arguments are redefined using \cs{cs_set_nopar:Npn} rather than % using \pkg{xparse}. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_contents_bookmarks: { \tl_map_function:NN \l_siunitx_declare_list_tl \siunitx_unit_print_literal_aux:N \msg_redirect_name:nnn { LaTeX / xparse } { redefine-command } { none } \DeclareExpandableDocumentCommand \num { o m } {##2} \DeclareExpandableDocumentCommand \numrange { o m m } { ##2 \l_siunitx_range_phrase_tl ##3 } \DeclareExpandableDocumentCommand \si { o m } {##2} \DeclareExpandableDocumentCommand \SI { o m o m } { \IfNoValueF {##3} {##3} ##2~##4 } \DeclareExpandableDocumentCommand \SIrange { o m m m } { ##2~##4 \l_siunitx_range_phrase_tl ##3~##4 } \cs_set_nopar:Npn \SIUnitSymbolAngstrom { \AA } \cs_set_nopar:Npn \SIUnitSymbolArcminute { ' } \cs_set_nopar:Npn \SIUnitSymbolArcsecond { '' } \cs_set_nopar:Npn \SIUnitSymbolCelsius { \textcelsius } \cs_set_nopar:Npn \SIUnitSymbolDegree { \textdegree } \cs_set_nopar:Npn \SIUnitSymbolMicro { \textmu } \cs_set_nopar:Npn \SIUnitSymbolOhm { [ohm] } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_hyperref_check:} % A short check to get things working. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_hyperref_check: { \@ifpackageloaded { hyperref } { \pdfstringdefDisableCommands { \siunitx_contents_bookmarks: } } { } } \AtBeginDocument { \siunitx_hyperref_check: } % \end{macrocode} %\end{macro} % %\subsection{Physical units} % %\begin{macro}{\kilogram} %\begin{macro}{\metre} %\begin{macro}{\meter} %\begin{macro}{\mole} %\begin{macro}{\kelvin} %\begin{macro}{\candela} %\begin{macro}{\second} %\begin{macro}{\ampere} % The basic SI units are always defined, including both variants for % metre. % \begin{macrocode} \DeclareSIUnit \kilogram { \kilo \gram } \DeclareSIUnit \metre { m } \DeclareSIUnit \meter { \metre } \DeclareSIUnit \mole { mol } \DeclareSIUnit \second { s } \DeclareSIUnit \ampere { A } \DeclareSIUnit \kelvin { K } \DeclareSIUnit \candela { cd } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\gram} % The gram is an odd unit as it is needed for the base unit kilogram. % \begin{macrocode} \DeclareSIUnit \gram { g } % \end{macrocode} %\end{macro} % %\begin{macro}{\yocto} %\begin{macro}{\zepto} %\begin{macro}{\atto} %\begin{macro}{\femto} %\begin{macro}{\pico} %\begin{macro}{\nano} %\begin{macro}{\micro} %\begin{macro}{\milli} %\begin{macro}{\centi} %\begin{macro}{\deci} % The various SI multiple prefixes are defined here: first the small % ones. % \begin{macrocode} \DeclareSIPrefix \yocto { y } { -24 } \DeclareSIPrefix \zepto { z } { -21 } \DeclareSIPrefix \atto { a } { -18 } \DeclareSIPrefix \femto { f } { -15 } \DeclareSIPrefix \pico { p } { -12 } \DeclareSIPrefix \nano { n } { -9 } \DeclareSIPrefix \micro { \SIUnitSymbolMicro } { -6 } \DeclareSIPrefix \milli { m } { -3 } \DeclareSIPrefix \centi { c } { -2 } \DeclareSIPrefix \deci { d } { -1 } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\deca} %\begin{macro}{\deka} %\begin{macro}{\hecto} %\begin{macro}{\kilo} %\begin{macro}{\mega} %\begin{macro}{\giga} %\begin{macro}{\tera} %\begin{macro}{\peta} %\begin{macro}{\exa} %\begin{macro}{\zetta} %\begin{macro}{\yotta} % Now the large ones. % \begin{macrocode} \DeclareSIPrefix \deca { da } { 1 } \DeclareSIPrefix \deka { da } { 1 } \DeclareSIPrefix \hecto { h } { 2 } \DeclareSIPrefix \kilo { k } { 3 } \DeclareSIPrefix \mega { M } { 6 } \DeclareSIPrefix \giga { G } { 9 } \DeclareSIPrefix \tera { T } { 12 } \DeclareSIPrefix \peta { P } { 15 } \DeclareSIPrefix \exa { E } { 18 } \DeclareSIPrefix \zetta { Z } { 21 } \DeclareSIPrefix \yotta { Y } { 24 } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\becquerel} %\begin{macro}{\degreeCelsius} %\begin{macro}{\coulomb} %\begin{macro}{\farad} %\begin{macro}{\gray} %\begin{macro}{\hertz} %\begin{macro}{\henry} %\begin{macro}{\joule} %\begin{macro}{\katal} %\begin{macro}{\lumen} %\begin{macro}{\lux} % A number of derived units with defined names and symbols. % \begin{macrocode} \DeclareSIUnit \becquerel { Bq } \DeclareSIUnit \degreeCelsius { \SIUnitSymbolCelsius } \DeclareSIUnit \coulomb { C } \DeclareSIUnit \farad { F } \DeclareSIUnit \gray { Gy } \DeclareSIUnit \hertz { Hz } \DeclareSIUnit \henry { H } \DeclareSIUnit \joule { J } \DeclareSIUnit \katal { kat } \DeclareSIUnit \lumen { lm } \DeclareSIUnit \lux { lx } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\newton} %\begin{macro}{\ohm} %\begin{macro}{\pascal} %\begin{macro}{\radian} %\begin{macro}{\siemens} %\begin{macro}{\sievert} %\begin{macro}{\steradian} %\begin{macro}{\tesla} %\begin{macro}{\volt} %\begin{macro}{\watt} %\begin{macro}{\weber} % More units. % \begin{macrocode} \DeclareSIUnit \newton { N } \DeclareSIUnit \ohm { \SIUnitSymbolOhm } \DeclareSIUnit \pascal { Pa } \DeclareSIUnit \radian { rad } \DeclareSIUnit \siemens { S } \DeclareSIUnit \sievert { Sv } \DeclareSIUnit \steradian { sr } \DeclareSIUnit \tesla { T } \DeclareSIUnit \volt { V } \DeclareSIUnit \watt { W } \DeclareSIUnit \weber { Wb } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\arcminute} %\begin{macro}{\arcsecond} %\begin{macro}{\day} %\begin{macro}{\degree} %\begin{macro}{\hectare} %\begin{macro}{\hour} %\begin{macro}{\litre} %\begin{macro}{\liter} %\begin{macro}{\minute} %\begin{macro}{\percent} %\begin{macro}{\tonne} % Non-SI, but accepted for general use. % \begin{macrocode} \DeclareSIUnit[ number-unit-separator = ] \arcmin { \arcminute } \DeclareSIUnit[ number-unit-separator = ] \arcminute { \SIUnitSymbolArcminute } \DeclareSIUnit[ number-unit-separator = ] \arcsecond { \SIUnitSymbolArcsecond } \DeclareSIUnit \day { d } \DeclareSIUnit[ number-unit-separator = ] \degree { \SIUnitSymbolDegree } \DeclareSIUnit \hectare { ha } \DeclareSIUnit \hour { h } \DeclareSIUnit \litre { l } \DeclareSIUnit \liter { L } \DeclareSIUnit \minute { min } \DeclareSIUnit \percent { \char 37 } \DeclareSIUnit \tonne { t } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\astronomicalunit} %\begin{macro}{\atomicmassunit} %\begin{macro}{\electronvolt} %\begin{macro}{\dalton} % A few units based on physical measurements exist. % \begin{macrocode} \DeclareSIUnit \astronomicalunit { ua } \DeclareSIUnit \atomicmassunit { u } \DeclareSIUnit \electronvolt { eV } \DeclareSIUnit \dalton { Da } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\clight} %\begin{macro}{\electronmass} %\begin{macro}{\planckbar} % A set of \enquote{natural units}. % \begin{macrocode} \group_begin: \char_set_lccode:nn { `\@ } { `\_ } \char_make_math_subscript:N \@ \tl_to_lowercase:n { \group_end: \DeclareSIUnit \clight { \text { \ensuremath { c @ { 0 } } } } \DeclareSIUnit \electronmass { \text { \ensuremath { m @ { \text { e } } } } } } \DeclareSIUnit \planckbar {\text{\ensuremath{\hbar}}} % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\elementarycharge} %\begin{macro}{\bohr} %\begin{macro}{\hartree} % A set of \enquote{atomic units}. % \begin{macrocode} \DeclareSIUnit \elementarycharge { \text { \ensuremath { e } } } \group_begin: \char_set_lccode:nn { `\@ } { `\_ } \char_make_math_subscript:N \@ \tl_to_lowercase:n { \group_end: \DeclareSIUnit \bohr { \text { \ensuremath { a @ { 0 } } } } \DeclareSIUnit \hartree { \text { \ensuremath { E @ { \textup { h } } } } } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\angstrom} %\begin{macro}{\bar} %\begin{macro}{\barn} %\begin{macro}{\bel} %\begin{macro}{\bel} %\begin{macro}{\knot} %\begin{macro}{\mmHg} %\begin{macro}{\nauticalmile} %\begin{macro}{\neper} % There are then some day-to-day units which are accepted for use % with SI, but are not part of the official specification. % \begin{macrocode} \DeclareSIUnit \angstrom { \SIUnitSymbolAngstrom } \DeclareSIUnit \bar { bar } \DeclareSIUnit \barn { b } \DeclareSIUnit \bel { B } \DeclareSIUnit \decibel { \deci \bel } \DeclareSIUnit \knot { kn } \DeclareSIUnit \mmHg { mmHg } \DeclareSIUnit \nauticalmile { M } \DeclareSIUnit \neper { Np } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\square} %\begin{macro}{\squared} %\begin{macro}{\cubic} %\begin{macro}{\cubed} % The basic powers are also defined. % \begin{macrocode} \DeclareSIPower \square { 2 } \DeclareSIPower* \squared { 2 } \DeclareSIPower \cubic { 3 } \DeclareSIPower* \cubed { 3 } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\subsection{Support for version one} % % The re-arrangements made to the code in version two, and in particular % the new option names, mean that support for version one needs to be % included explicitly. Looking forward, this code is unlikely to be % taken forward to a stand-alone \LaTeX3 version of \pkg{siunitx}. % However, that is likely to be some way off. % % \begin{macrocode} \keys_define:nn { siunitx } { addsign .choice: , addsign / false .meta:n = { explicit-sign = }, addsign / true .meta:n = { explicit-sign = + }, allowlitunits .meta:n = { free-standing-units = #1 }, allowoptarg .meta:n = { unit-optional-argument = #1 }, allowzeroexp .meta:n = { retain-zero-exponent = #1 }, % angformat & List & Conversion of angle format \\ % anglesep & List or literal & Space between angle components \\ % astroang & Boolean & Astronomy-style angles \\ closeerr .meta:n = { close-bracket = #1 }, closefrac .meta:n = { close-bracket = #1 }, closerange .meta:n = { close-bracket = #1 }, colorall .code:n = , colourall .code:n = , colorneg .code:n = , colourneg .code:n = , colorunits .meta:n = , colourunits .meta:n = , colorvalues .meta:n = , colourvalues .meta:n = , decimalsymbol .choice: , decimalsymbol / cdot .code:n = { output-decimal-marker = { } \cdot { } }, decimalsymbol fullstop .code:n = { output-decimal-marker = { { . } } }, decimalsymbol / period .code:n = { output-decimal-marker = { { . } } }, decimalsymbol / stop .code:n = { output-decimal-marker = { { . } } }, decimalsymbol / tightcdot .code:n = { output-decimal-marker = \bgroup \cdot \egroup }, decimalsymbol / unknown .code:n = { output-decimal-marker = #1 }, debug .code:n = , detectdisplay .meta:n = { detect-display-maths = #1 }, digitsep .choice:, digitsep / cdot .code:n = { group-separator = { } \cdot { } }, digitsep / comma .code:n = { group-separator = { {,} } }, digitsep / fullstop .code:n = { group-separator = { { . } } }, digitsep / med .code:n = { group-separator = \: }, digitsep / medium .code:n = { group-separator = \: }, digitsep / none .code:n = { group-separator = }, digitsep / period .code:n = { group-separator = { { . } } }, digitsep / space .code:n = { group-separator = \text { ~ } }, digitsep / stop .code:n = { group-separator = { { . } } }, digitsep / thick .code:n = { group-separator = \; }, digitsep / thin .code:n = { group-separator = \, }, digitsep / tightcdot .code:n = { group-separator = \bgroup \cdot \egroup }, digitsep / tighttimes .code:n = { group-separator = \bgroup \times \egroup }, digitsep / times .code:n = { group-separator = \times }, digitsep / unknown .code:n = { group-separator = #1 }, dp .meta:n = { round-mode = places, round-places = #1, }, emulate .code:n = , errspace .choice: , errspace / med .code:n = { uncertainty-separator = \: }, errspace / medium .code:n = { uncertainty-separator = \: }, errspace / none .code:n = { uncertainty-separator = }, errspace / space .code:n = { uncertainty-separator = \text { ~ } }, errspace / thick .code:n = { uncertainty-separator = \; }, errspace / thin .code:n = { uncertainty-separator = \, }, errspace / unknown .code:n = { uncertainty-separator = #1 }, eVcorra .code:n = , eVcorrb .code:n = , expbase .choice: , expbase / ten .code:n = { exponent-base = 10 }, expbase / two .code:n = { exponent-base = 2 }, expbase / unknown .code:n = { exponent-base = #1 }, expproduct / cdot .code:n = { exponent-product = { } \cdot { } }, expproduct / tightcdot .code:n = { exponent-product = \bgroup \cdot \egroup }, expproduct / tighttimes .code:n = { exponent-product = \bgroup \times \egroup }, expproduct / times .code:n = { exponent-product = \times }, expproduct / unknown .code:n = { exponent-product = #1 }, fixdp .choice:, fixdp / false .meta:n = { round-mode = none }, fixdp / true .meta:n = { round-mode = places }, fixsf .choice: , fixsf / false .meta:n = { round-mode = none }, fixsf / true .meta:n = { round-mode = figures }, % fraction & List & Method used when setting \opt{per=frac} \\ inlinebold .meta:n = { detect-inline-bold = #1 }, % load & Modules & Modules to load \\ % locale & Modules & Locale to follow \\ % loctolang & Special & Associate locale with \pkg{babel} % language \\ % log & List & Amount of data added to log \\ mathOmega .meta:n = { math-ohm = #1 }, mathcelsius .meta:n = { math-celsius = #1 }, mathdegree .meta:n = { math-degree = #1 }, mathminute .meta:n = { math-arcminute = #1 }, mathmu .meta:n = { math-micro = #1 }, mathringA .meta:n = { math-angstrom = #1 }, mathrm .meta:x = { math-rm = \exp_not:c {#1} }, mathsOmega .meta:n = { maths-ohm = #1 }, mathscelsius .meta:n = { maths-celsius = #1 }, mathsdegree .meta:n = { maths-degree = #1 }, mathsecond .meta:n = { math-arcsecond = #1 }, mathsf .meta:x = { math-sf = \exp_not:c {#1} }, mathsminute .meta:n = { maths-arcminute = #1 }, mathsmu .meta:n = { maths-micro = #1 }, mathsringA .meta:n = { maths-angstrom = #1 }, mathssecond .meta:n = { maths-arcsecond = #1 }, mathssf .meta:x = { maths-sf = \exp_not:c {#1} }, mathstt .meta:x = { maths-tt = \exp_not:c {#1} }, mathtt .meta:x = { math-tt = \exp_not:c {#1} }, negcolor .meta:n = { negative-color = #1 }, negcolour .meta:n = { negative-colour = #1 }, % noload & Modules & Modules not to load \\ numaddn .meta:n = { input-symbols = #1 }, numcloseerr .meta:n = { input-close-uncertainty = #1 }, numdecimal .meta:n = { input-decimal-markers = #1 }, numdigits .meta:n = { input-digits = #1 }, numdiv .meta:n = { input-quotient = #1 }, numexp .meta:n = { input-exponent-markers = #1 }, numgobble .meta:n = { input-ignore = #1 }, numopenerr .meta:n = { input-open-uncertainty = #1 }, numprod .meta:n = { input-product = #1 }, numsign .meta:n = { input-signs = #1 }, obeyall .meta:n = { detect-all = #1 }, obeybold .meta:n = { detect-bold = #1 }, obeyitalic .meta:n = { detect-italic = #1 }, obeymode .meta:n = { detect-mode = #1 }, openerr .meta:n = { open-bracket = #1 }, openfrac .meta:n = { open-bracket = #1 }, openrange .meta:n = { open-bracket = #1 }, % padangle & List & Add zeros to blank parts of angles \\ % padnumber & List & Add zeros to blank parts of numbers \\ per .choice: , per / fraction .code:n = { per-mode = fraction }, per / reciprocal .code:n = { per-mode = reciprocal }, per / slash .code:n = { per-mode = symbol }, % prefixbase & List or literal & Base used when making prefixes \\ % & & numerical \\ % prefixproduct & List or literal & Product sign for prefixes \\ prefixsymbolic .meta:n = { prefixes-as-symbols = #1 }, prespace .meta:n = { space-before-unit = #1 }, redefsymbols .meta:n = { redefine-symbols = #1 }, % repeatunits & List & Repeat units with separated errors, \\ % & & products and in ranges \\ retainplus .meta:n = { retain-explicit-plus = #1 }, seperr .meta:n = { separate-uncertainty = #1 }, seperr .meta:n = { separate-uncertainty = #1 }, sepfour .meta:n = { group-four-digits = true }, sf .meta:n = { round-mode = figures, round-places = #1, }, sign .meta:n = { explicit-sign = #1 }, slash .choice: , slash / slash .code:n = { per-symbol = / }, slash / unknown .code:n = { per symbol = #1 }, stickyper .meta:n = { sticky-per = #1 }, % strict & Boolean & Obey the rules strictly \\ % strictarc & Boolean & Require exactly zero or \\ % & & two semi-colons \\ % tabalign & List & Positioning of all column data \\ % tabalignexp & Boolean & Alignment of exponents in tables \\ % tabautofit & Boolean & Switch for rounding numbers to \\ % & & length given by \opt{tabformat} \\ % tabformat & Number & Space reserved in table for numbers \\ % tabnumalign & List & Alignment of |S| column numbers \\ % tabparseonly & Boolean & Do not align |S| columns \\ % & & on decimal marker \\ % tabtextalign & List & Positioning of text in |S| columns \\ % tabunitalign & List & Positioning of units in |s| columns \\ textOmega .meta:n = { text-ohm = #1 }, textcelsius .meta:n = { text-celsius = #1 }, textdegree .meta:n = { text-degree = #1 }, textminute .meta:n = { text-arcminute = #1 }, textmode .choice: , textmode / true .meta:n = { mode = text }, textmode / false .meta:n = { mode = maths }, textmode .default:n = { true }, textmu .meta:n = { text-micro = #1 }, textringA .meta:n = { text-angstrom = #1 }, textrm .meta:x = { text-rm = \exp_not:c {#1} }, textsecond .meta:n = { text-arcsecond = #1 }, textsf .meta:x = { text-sf = \exp_not:c {#1} }, texttt .meta:x = { text-tt = \exp_not:c {#1} }, tightpm .meta:n = { tight-spacing = #1 }, tophrase .meta:n = { range-phrase = #1 }, % trapambigerr & Boolean & Check for ambiguous errors \\ % trapambigfrac & Boolean & Check for ambiguous fractions \\ % trapambigrange & Boolean & Check for ambiguous ranges \\ unitcolor .meta:n = { unit-color = #1 }, unitcolour .meta:n = { unit-colour = #1 }, unitmathrm .meta:x = { unit-math-rm = \exp_not:c {#1} }, unitmathsf .meta:x = { unit-math-sf = \exp_not:c {#1} }, unitmathsrm .meta:x = { unit-maths-rm = \exp_not:c {#1} }, unitmathssf .meta:x = { unit-maths-sf = \exp_not:c {#1} }, unitmathstt .meta:x = { unit-maths-tt = \exp_not:c {#1} }, unitmathtt .meta:x = { unit-math-tt = \exp_not:c {#1} }, unitmode .meta:n = { unit-mode = #1 }, unitsep .choice: , unitsep / cdot .code:n = { inter-unit-separator = { } \cdot { } }, unitsep / comma .code:n = { inter-unit-separator = { {,} } }, unitsep / fullstop .code:n = { inter-unit-separator = { { . } } }, unitsep / med .code:n = { inter-unit-separator = \: }, unitsep / medium .code:n = { inter-unit-separator = \: }, unitsep / none .code:n = { inter-unit-separator = }, unitsep / period .code:n = { inter-unit-separator = { { . } } }, unitsep / space .code:n = { inter-unit-separator = \text { ~ } }, unitsep / stop .code:n = { inter-unit-separator = { { . } } }, unitsep / thick .code:n = { inter-unit-separator = \; }, unitsep / thin .code:n = { inter-unit-separator = \, }, unitsep / tightcdot .code:n = { inter-unit-separator = \bgroup \cdot \egroup }, unitsep / tighttimes .code:n = { inter-unit-separator = \bgroup \times \egroup }, unitsep / times .code:n = { inter-unit-separator = \times }, unitsep / unknown .code:n = { inter-unit-separator = #1 }, unitspace .choice: , unitspace / med .code:n = { inter-unit-separator = \: }, unitspace / medium .code:n = { inter-unit-separator = \: }, unitspace / none .code:n = { inter-unit-separator = }, unitspace / space .code:n = { inter-unit-separator = \text { ~ } }, unitspace / thick .code:n = { inter-unit-separator = \; }, unitspace / thin .code:n = { inter-unit-separator = \, }, unitspace / unknown .code:n = { inter-unit-separator = #1 }, valuecolor .meta:n = { number-color = #1 }, valuecolour .meta:n = { number-colour = #1 }, valuemathrm .meta:x = { number-math-rm = \exp_not:c {#1} }, valuemathsf .meta:x = { number-math-sf = \exp_not:c {#1} }, valuemathsrm .meta:x = { number-maths-rm = \exp_not:c {#1} }, valuemathssf .meta:x = { number-maths-sf = \exp_not:c {#1} }, valuemathstt .meta:x = { number-maths-tt = \exp_not:c {#1} }, valuemathtt .meta:x = { number-math-tt = \exp_not:c {#1} }, valuemode .meta:n = { number-mode = #1 }, valuesep .choice: , valuesep / cdot .code:n = { unit-value-separator = { } \cdot { } }, valuesep / comma .code:n = { unit-value-separator = { {,} } }, valuesep / fullstop .code:n = { unit-value-separator = { { . } } }, valuesep / med .code:n = { unit-value-separator = \: }, valuesep / medium .code:n = { unit-value-separator = \: }, valuesep / none .code:n = { unit-value-separator = }, valuesep / period .code:n = { unit-value-separator = { { . } } }, valuesep / space .code:n = { unit-value-separator = \text { ~ } }, valuesep / stop .code:n = { unit-value-separator = { { . } } }, valuesep / thick .code:n = { unit-value-separator = \; }, valuesep / thin .code:n = { unit-value-separator = \, }, valuesep / tightcdot .code:n = { unit-value-separator = \bgroup \cdot \egroup }, valuesep / tighttimes .code:n = { unit-value-separator = \bgroup \times \egroup }, valuesep / times .code:n = { unit-value-separator = \times }, valuesep / unknown .code:n = { unit-value-separator = #1 }, xspace .meta:n = { use-xspace = #1 } } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % %\end{implementation} % %\begin{thebibliography}{1} % % \bibitem{BIPM} % \emph{The International System of Units (SI)}, % \url{http://www.bipm.org/en/si/}. % % \bibitem{SI:2.1} % \emph{SI base units}, % \url{http://www.bipm.org/en/si/si_brochure/chapter2/2-1/}. % % \bibitem{SI:2.2.2} % \emph{Units with special names and symbols; units that % incorporate special names and symbols}, % \url{http://www.bipm.org/en/si/si_brochure/chapter2/2-2/2-2-2.html}. % % \bibitem{SI:3.1} % \emph{SI Prefixes}, % \url{http://www.bipm.org/en/si/si_brochure/chapter3/prefixes.html}. % % \bibitem{SI:4.1.T6} % \emph{Non-SI units accepted for use with the International % System of Units}, % \url{http://www.bipm.org/en/si/si_brochure/chapter4/table6.html}. % % \bibitem{SI:4.1.T7} % \emph{Non-SI units whose values in SI units must be obtained % experimentally}, % \url{http://www.bipm.org/en/si/si_brochure/chapter4/table7.html}. % % \bibitem{SI:4.1.T8} % \emph{Other non-SI units}, % \url{http://www.bipm.org/en/si/si_brochure/chapter4/table8.html}. % %\end{thebibliography} % %\PrintChanges % %\PrintIndex