% \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. Installation ------------ The package is supplied in dtx format and as a pre-extracted zip file, siunitx.tds.zip. The later is most convenient for most users: simply unzip this in your local texmf directory and run texhash to update the database of file locations. If you want to unpack the dtx yourself, running 'tex siunitx.dtx' will extract the package whereas 'latex siunitx.dtx will extract it and also typeset the documentation. The package requires LaTeX3 support as provided in the expl3 and xpackages bundles. Both of these are available on CTAN (http://www.ctan.org/) as ready-to-install zip files. Suitable versions are available in MiKTeX 2.8 and TeX Live 2009 (updating the relevant packages online may be necessary). LaTeX3, and so siunitx, requires the e-TeX extensions: these are available on all modern TeX systems. Typesetting the documentation requires a number of packages in addition to those needed to use the package. This is mainly because of the number of demonstration items included in the text. To compile the documentation without error, you will need the packages: - amsmath - booktabs - caption - cleveref - csquotes - datatool - helvet - mathpazo - listings - pgfplots - xcolor The xfrac package is also loaded if available, but is not required to typeset the documentation. % %<*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-2010 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}} } \usedir{tex/latex/siunitx/config} \generate{ \file{siunitx-abbreviations.cfg} {\from{\jobname.dtx}{config,abbreviations}} \file{siunitx-astronomy.cfg}{\from{\jobname.dtx}{config,astronomy}} \file{siunitx-binary.cfg}{\from{\jobname.dtx}{config,binary}} \file{siunitx-chemical-engineering.cfg} {\from{\jobname.dtx}{config,chemical-engineering}} \file{siunitx-chemistry.cfg}{\from{\jobname.dtx}{config,chemistry}} \file{siunitx-geophysics.cfg}{\from{\jobname.dtx}{config,geophysics}} \file{siunitx-version-1.cfg}{\from{\jobname.dtx}{config,version-1}} } % %\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} % %<*config|driver|package> \GetIdInfo$Id: siunitx.dtx 352 2010-01-31 13:51:42Z josephwright $ {A comprehensive (SI) units package} \edef\fileversion{2.0alpha (revision \fileversion)} % %<*driver> %\fi \ProvidesFile{\filename.\filenameext} [\filedate\space \fileversion\space\filedescription] %\iffalse \documentclass[full]{l3doc} \usepackage{amsmath,booktabs,caption,csquotes,datatool,helvet,pgfplots} \usepackage{siunitx,xcolor,xtab} \IfFileExists{xfrac.sty} {\usepackage{xfrac}} {% \PackageWarningNoLine{siunitx} {% xfrac unavailable: \string\sfrac\space fraction \MessageBreak will have wrong appearance% } } \providecommand*\sfrac[2]{\frac{#1}{#2}} \usepackage[capitalise]{cleveref} \usepackage[final]{listings} \usepackage[osf]{mathpazo} \pgfplotsset{compat = newest} \sisetup{ load-configurations = { abbreviations, astronomy, binary, chemical-engineering, chemistry, geophysics } } \DeclareSIPrePower\quartic{4} \DeclareSIPostPower\tothefourth{4} \DeclareSIQualifier\polymer{pol} \DeclareSIQualifier\catalyst{cat} %\DisableImplementation \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} & \expandafter\si\expandafter{\csname #1\endcsname} %} %\newcommand*\DescribeUnit[1]{^^A % \expandafter\SpecialUsageIndex\expandafter{\csname #1\endcsname}^^A % #1 & % \cs{#1} & % \expandafter\si\expandafter{\csname #1\endcsname} %} %\newcommand*\DescribeNamedUnit[2]{^^A % \expandafter\SpecialUsageIndex\expandafter{\csname #2\endcsname}^^A % #1 & % \cs{#2} & % \expandafter\si\expandafter{\csname #2\endcsname} %} % %^^A For creating examples with nice highlighting of code, and so %^^A on; based on the system used in the listings source (lstsample). %\lst@RequireAspects{writefile} %\newsavebox{\LaTeXdemo@box} %\lstnewenvironment{LaTeXdemo}[1][code and example] % {^^A % \global\let\lst@intname\@empty % \expandafter\let\expandafter\LaTeXdemo@end % \csname LaTeXdemo@#1@end\endcsname % \@nameuse{LaTeXdemo@#1}^^A % } % {\LaTeXdemo@end} %\newcommand*\LaTeXdemo@new[3]{^^A % \expandafter\newcommand\expandafter*\expandafter % {\csname LaTeXdemo@#1\endcsname}{#2}^^A % \expandafter\newcommand\expandafter*\expandafter % {\csname LaTeXdemo@#1@end\endcsname}{#3}^^A %} %\newcommand*\LaTeXdemo@common{^^A % \setkeys{lst} % { % basicstyle = \small\ttfamily, % basewidth = 0.51em, % gobble = 3, % keywordstyle = \color{blue}, % language = [LaTeX]{TeX}, % moretexcs = % { % ampere, % ang, % angstrom, % becquerel, % bit, % bottomrule, % byte, % candela, % centi, % color, % coulomb, % cubed, % cubic, % deci, % decibel, % degree, % DeclareBinaryPrefix, % DeclareRobustCommand, % DeclareSIPostPower, % DeclareSIPrefix, % DeclareSIPrePower, % DeclareSIQualifier, % DeclareSIUnit, % DeclareSIUnitWithOptions, % DTLdisplaydb, % DTLforeach, % DTLiffirstrow, % DTLmul, % DTLnewdb, % DTLnewdbentry, % DTLnewrow, % farad, % gram, % gray, % henry, % hour, % Hz, % joule, % kelvin, % kibi, % kilo, % kilogram, % litre, % lumen, % lux, % mathnormal, % metre, % mebi, % micro, % midrule, % milli, % mole, % num, % numrange, % pascal, % per, % protected, % radian, % raiseto, % robustify, % second, % si, % SI, % sievert, % SIrange, % sisetup, % SIUnitSymbolDegree, % square, % squared, % tesla, % texorpdfstring, % text, % toprule, % 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 and float}{^^A % \lst@BeginAlsoWriteFile{siunitx.tmp}^^A % \LaTeXdemo@common %}{^^A % \lst@EndWriteFile % \LaTeXdemo@input %} %\LaTeXdemo@new{code only} % {\LaTeXdemo@common}{} % %^^A Turning of the marginpar warnings is a bit awkward. %^^A It is achieved by temporarily disabling \@latex@warning@no@line %\let\latex@addmarginpar\@addmarginpar %\let\latex@warning@no@line\@latex@warning@no@line %\def\@addmarginpar{^^A % \let\@latex@warning@no@line\@gobble % \latex@addmarginpar % \let\@latex@warning@no@line\latex@warning@no@line %} % %\providecommand*\opt[1]{\texttt{#1}} % %\makeatother % %\title{^^A % \textsf{siunitx} --- A comprehensive (SI) units package\thanks{^^A % This file describes v\fileversion, last revised \filedate.^^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}{\filedate}{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. % % Typesetting the documentation requires a number of packages in % addition to those needed to use the package. This is mainly % because of the number of demonstration items included in the text. To % compile the documentation without error, you will need the packages: %\begin{itemize} % \item \pkg{amsmath} % \item \pkg{booktabs} % \item \pkg{caption} % \item \pkg{cleveref} % \item \pkg{csquotes} % \item \pkg{helvet} % \item \pkg{mathpazo} % \item \pkg{listings} % \item \pkg{pgfplots} % \item \pkg{xcolor} %\end{itemize} % The \pkg{xfrac} package is also loaded if available, but is not % required to typeset the documentation. % %\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{number1}\marg{number2} % \item \cs{SIrange}\oarg{options}\marg{number1}\marg{number2}^^A % \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} \\ % \si[per-mode=symbol] % {\kilogram\metre\per\ampere\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} % The key--value options described later in this document can be used % when loading the package, for example %\begin{LaTeXdemo}[code only] % \usepackage[load-configuration = version-1]{siunitx} %\end{LaTeXdemo} % to use options from version 1 of the package. % %\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}, \texttt{E}, \texttt{d} 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} % Note that numbers are parsed before typesetting, which does % have a performance overhead (only obvious with very large amounts % of numerical input). The parser understands a range of input syntaxes, % as demonstrated above. % %\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} % %\DescribeMacro{\ang} %\begin{syntax} % \cs{ang}\oarg{options}\marg{angle} %\end{syntax} % Angles can be typeset using the \cs{ang} command. The % \meta{angle} can be given either as a decimal number or as a % semi-colon separated list of degrees, minutes and seconds, which % is called \enquote{arc format} in this document. The numbers which % make up an angle are processed using the same system as other numbers. %\begin{LaTeXdemo} % \ang{10} \\ % \ang{12.3} \\ % \ang{4,5} \\ % \ang{1;2;3} \\ % \ang{;;1} \\ % \ang{+10;;} \\ % \ang{-0;1;} %\end{LaTeXdemo} % %\subsection{Units} % %\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[per-mode=fraction]{1,345}{\coulomb\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 % \cref{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 % (\cref{tab:unit:base}). In addition, the macro \cs{meter} is % available as an alias for \cs{metre}, for users of US spellings. % The full details of the base units are given in the SI % Brochure~\cite{SI:2.1}. %\begin{table} % \caption{SI base units.} % \label{tab:unit:base} % \centering % \begin{tabular}{lll} % \toprule % \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} % %\DescribeMacro{\celsius} % The SI also lists a number of units which have special names and % symbols \cite{SI:2.2.2}: these are listed in % \cref{tab:unit:derived}. As a short-cut for the degree Celsius, % the unit \cs{celius} is defined equivalent to \cs{degreeCelsius} . %\begin{table} % \caption{Coherent derived units in the SI with special names and % symbols.} % \label{tab:unit:derived} % \centering % \begin{tabular}{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} \\ % \DescribeNamedUnit{degree Celsius}{degreeCelsius} & % \DescribeUnit{ohm} \\ % \DescribeUnit{coulomb} & % \DescribeUnit{pascal} \\ % \DescribeUnit{farad} & % \DescribeUnit{radian} \\ % \DescribeUnit{gray} & % \DescribeUnit{siemens} \\ % \DescribeUnit{hertz} & % \DescribeUnit{sievert} \\ % \DescribeUnit{henry} & % \DescribeUnit{steradian} \\ % \DescribeUnit{joule} & % \DescribeUnit{tesla} \\ % \DescribeUnit{katal} & % \DescribeUnit{volt} \\ % \DescribeUnit{lumen} & % \DescribeUnit{watt} \\ % \DescribeUnit{lux} & % \DescribeUnit{weber} \\ % \bottomrule % \end{tabular} %\end{table} % % In addition to the official SI units, \pkg{siunitx} also provides % macros for a number of units which are accepted for use in the SI % although they are not SI units. \cref{tab:unit:accepted} lists % the \enquote{accepted} units \cite{SI:4.1.T6}. Some units are % fundamental physical quantities, and these are non-SI but can be used % with in the SI (\cref{tab:unit:physical}, \cite{SI:4.1.T7}). % There are also a set of non-SI units which are used in certain % defined circumstances (\cref{tab:unit:other}), although they are % not necessarily 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} \\ % \DescribeNamedUnit{minute (plane angle)}{arcminute} \\ % \DescribeNamedUnit{minute (time)}{minute} \\ % \DescribeNamedUnit{second (plane angle)}{arcsecond} \\ % \DescribeNamedUnit{second (time)}{second} \\ % \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 % \DescribeNamedUnit{astronomical unit}{astronomicalunit} \\ % \DescribeNamedUnit{atomic mass unit}{atomicmassunit} \\ % \DescribeUnit{bohr} \\ % \DescribeNamedUnit{speed of light}{clight} \\ % \DescribeUnit{dalton} \\ % \DescribeNamedUnit{electron mass}{electronmass} \\ % \DescribeUnit{electronvolt} \\ % \DescribeNamedUnit{elementary charge}{elementarycharge} \\ % \DescribeUnit{hartree} \\ % \DescribeNamedUnit{reduced Planck constant}{planckbar} \\ % \bottomrule % \end{tabular} %\end{table} %\begin{table} % \caption{Other non-SI units.} % \label{tab:unit:other} % \centering % \begin{tabular}{lll} % \toprule % \multicolumn{1}{c}{Unit} & % \multicolumn{1}{c}{Macro} & % \multicolumn{1}{c}{Symbol} \\ % \midrule % \DescribeNamedUnit{{\aa}ngstr{\"o}m}{angstrom} \\ % \DescribeUnit{bar} \\ % \DescribeUnit{barn} \\ % \DescribeUnit{bel} \\ % \DescribeUnit{decibel} \\ % \DescribeUnit{knot} \\ % \DescribeNamedUnit{millimetre of mercury}{mmHg} \\ % \DescribeNamedUnit{nautical mile}{nauticalmile} \\ % \DescribeUnit{neper} \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeMacro{\deka} % In addition to the units themselves, \pkg{siunitx} provides % pre-defined macros for all of the SI prefixes % (\cref{tab:unit:prefix}, \cite{SI:3.1}). The spelling % \enquote{\cs{deka}} is provided for US users as an alternative to % \cs{deca}. %\begin{table} % \caption{SI prefixes.} % \label{tab:unit:prefix} % \centering % \begin{tabular}{llc>{$}l<{$}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} & -24 & % \DescribePrefix{deca} & 1 \\ % \DescribePrefix{zepto} & -21 & % \DescribePrefix{hecto} & 2 \\ % \DescribePrefix{atto} & -18 & % \DescribePrefix{kilo} & 3 \\ % \DescribePrefix{femto} & -15 & % \DescribePrefix{mega} & 6 \\ % \DescribePrefix{pico} & -12 & % \DescribePrefix{giga} & 9 \\ % \DescribePrefix{nano} & -9 & % \DescribePrefix{tera} & 12 \\ % \DescribePrefix{micro} & -6 & % \DescribePrefix{peta} & 15 \\ % \DescribePrefix{milli} & -3 & % \DescribePrefix{exa} & 18 \\ % \DescribePrefix{centi} & -2 & % \DescribePrefix{zetta} & 21 \\ % \DescribePrefix{deci} & -1 & % \DescribePrefix{yotta} & 24 \\ % \bottomrule % \end{tabular} %\end{table} % %\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} % % When using the unit macros, the package is able to validate the % input given. As part of this, stand-alone unit prefixes can be used % with the \cs{si} macro %\begin{LaTeXdemo} % \si{\kilo} \\ % \si{\micro} %\end{LaTeXdemo} % However, the package only allows a single prefix to be used in this % way: multiple prefixes will give an error, as will trying to give % a number without a unit. So the following will raise errors: %\begin{LaTeXdemo}[code only] % \si{\kilo\gram\micro} \\ % \SI{10}{\micro} %\end{LaTeXdemo} % %\subsection{Creating new macros} % % The various macro components of a unit have to be defined before % they can be used. The package supplies a number of common definitions, % but new definitions are also possible. As the definition of a logical % unit should remain the same in a single document, these creation % functions are all preamble-only. % %\DescribeMacro{\DeclareSIUnit} %\DescribeMacro{\DeclareSIUnitWithOptions} %\begin{syntax} % \cs{DeclareSIUnit}\oarg{options}\marg{unit}\marg{symbol} % \cs{DeclareSIUnitWithOptions}\marg{unit}\marg{symbol}\marg{options} %\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. Units can be created with options % using the \cs{DeclareSIUnitWithOptions} function, where 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] % \DeclareSIUnitWithOptions\degree{\SIUnitSymbolDegree} % {number-unit-separator={}} %\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{\DeclareBinaryPrefix} %\begin{syntax} % \cs{DeclareSIPrefix}\marg{prefix}\marg{symbol}\marg{powers-ten} % \cs{DeclareBinaryPrefix}\marg{prefix}\marg{symbol}\marg{powers-two} %\end{syntax} % The standard SI powers of ten are defined by the package, and are % described above. However, the user can define new prefixes with % \cs{DeclareSIPrefix}. The \cs{DeclareBinaryPrefix} function is also % available for creating binary prefixes, with the same syntax % (\meta{powers-ten} being replaced by \meta{powers-two}). For % example, \cs{kilo} and \cs{kibi} are defined: %\begin{LaTeXdemo}[code only] % \DeclareSIPrefix\kilo{k}{3} % \DeclareBinaryPrefix\kibi{Ki}{10} %\end{LaTeXdemo} % %\DescribeMacro{\DeclareSIPostPower} %\DescribeMacro{\DeclareSIPrePower} %\begin{syntax} % \cs{DeclareSIPostPower}\marg{power}\marg{num} % \cs{DeclareSIPrePower}\marg{power}\marg{num} %\end{syntax} % These create power macros to appear before or after the unit they % apply to. For example, the preamble to a document might contain: %\begin{LaTeXdemo}[code only] % \DeclareSIPrePower\quartic{4} % \DeclareSIPostPower\tothefourth{4} %\end{LaTeXdemo} % with the functions then used in the document as: %\begin{LaTeXdemo} % \si{\kilogram\tothefourth}\\ % \si{\quartic\metre} %\end{LaTeXdemo} % %\DescribeMacro{\DeclareSIQualifier} % Following the syntax of the other macros, qualifiers are created % with the syntax \cs{DeclareSIQualifier}\marg{qualifier}\marg{symbol}. % In contrast to the other parts of a unit, there are no pre-defined % qualifiers. It is therefore entirely up to the user to create these. % For example, to identify the mass of a product created when using % a particular catalyst, the preamble could contain: %\begin{LaTeXdemo}[code only] % \DeclareSIQualifier\polymer{pol} % \DeclareSIQualifier\catalyst{cat} %\end{LaTeXdemo} % and then in the body the document could read: %\begin{LaTeXdemo} % \SI{1.234}{\gram\polymer\per\mole\catalyst\per\hour} %\end{LaTeXdemo} % %\subsection{Tabular material} % % Centring numbers in tabular content is handled by a new column % type, the \texttt{S} column. This new column type can align material % using a number of different strategies, with the aim of flexibility % of output without needing to alter the input. The method used % as standard is to place the decimal marker in the number at the % centre of the cell and to align the material appropriately % (\cref{tab:S:standard}). % %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Standard behaviour of the \texttt{S} column type.} % \label{tab:S:standard} % \centering % \begin{tabular}{S} % \toprule % {Some Values} \\ % \midrule % 2.3456 \\ % 34.2345 \\ % -6.7835 \\ % 90.473 \\ % 5642.5 \\ % 1.2e3 \\ % e4 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % % The \texttt{S} column will attempt to automatically detect % material which should be placed before or after a number, and will % maintain the alignment of the numerical data % (\cref{tab:S:extras}). If the material could be mistaken for % part of a number, it should be protected by braces. %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Detection of surrounding material in an \texttt{S} % column.} % \label{tab:S:extras} % \centering % \begin{tabular}{S} % \toprule % {Some Values} \\ % \midrule % 12.34 \\ % \color{purple} 975,31 \\ % 44.268 \textsuperscript{\emph{a}} \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % % As a complement to the \texttt{S} column, \pkg{siunitx} also provides % a second column type, \texttt{s}. This is intended for producing % columns of units. The letters chosen are intended to be similar to % \cs{SI} and \cs{si}, respectively. This allows both macro-based and % explicit units to be printed easily (\cref{tab:s:demo}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{Number and units in tables.} % \label{tab:s:demo} % \begin{tabular}{s} % \toprule % \multicolumn{1}{c}{Unit} \\ % \midrule % \metre\squared\per\second \\ % \pascal \\ % m.s^{-1} \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % % As the \cs{si} macro can take literal or macro input, the \texttt{s} % column cannot validate the input. \emph{Everything} in an \texttt{s} % column is therefore passed to the \cs{si} macro for processing. To % prevent this, you have to use \cs{multicolumn}, as is shown in % \cref{tab:s:processing}. Notice that the braces do not prevent % processing and colouring of the cell contents. %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{The \texttt{s} column processes everything.} % \label{tab:s:processing} % \sisetup{colour = orange} % \begin{tabular}{ss} % \toprule % {Unit} & \multicolumn{1}{c}{Unit}\\ % \midrule % {\si{m^3}} & \multicolumn{1}{c}{\si{m^3}} \\ % \kilogram & \kilogram \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\section{The key--value control system} % %\DescribeMacro{\sisetup} % The behaviour of the \pkg{siunitx} package is controlled by a % number of key--value options. These can be given globally using % the \cs{sisetup} function or locally as the optional argument to the % user macros. % % The package uses a range of different key types: %\begin{description} % \item[\texttt{Choice}] Takes a limited number of choices, which % are described separately for each key. % \item[\texttt{Integer}] Requires a number as the argument. % \item[\texttt{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 body fonts. % However, the package can detect and follow surrounding bold, italic % and font family changes. The font detection options are summarised in % \cref{tab:opt:font:det}. %\begin{table} % \centering % \caption{Font detection options.} % \label{tab:opt:font:det} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule % detect-all & Meta & \meta{none} \\ % detect-display-maths & Switch & false \\ % detect-family & Switch & false \\ % detect-inline-weight & Choice & text \\ % detect-italic & Switch & false \\ % detect-mode & Switch & false \\ % detect-none & Meta & \meta{none} \\ % detect-weight & Switch & false \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{detect-weight} %\DescribeOption{detect-family} %\DescribeOption{detect-italic} %\DescribeOption{detect-mode} % The options \opt{detect-weight} and \opt{detect-italic} set detection % of the prevailing font weight 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-weight} % Font weight detection is influenced by the value of % \opt{detect-inline-weight}, which takes values \opt{text}, \opt{maths} % and \opt{combined}. The package can detect the local value of font % weight for either the surrounding text, or the surrounding inline % (|$|\ldots|$|) maths. The \opt{combined} option checks both and uses % the prevailing weight if either test is true. %\begin{LaTeXdemo} % \sisetup{ % detect-weight = true, % detect-inline-weight = maths % }% % $\num{1234}$ \\ % { \boldmath $\num{1234}$ } \\ % { \bfseries $\num{1234}$ } \\ % \sisetup{detect-inline-weight = 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} % %\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} % %\DescribeOption{number-colour} %\DescribeOption{unit-colour} % Every one of the font options can be given independently for units % and number, with the prefixes \opt{unit-} and \opt{number-}, % respectively. This allows fine control of output. %\begin{LaTeXdemo} % \SI{4}{\angstrom} \\ % \SI[number-colour=green]{4}{\angstrom} \\ % \SI[unit-colour=green]{4}{\angstrom} %\end{LaTeXdemo} % %\subsection{Parsing numbers} % % The package uses a sophisticated parsing system to understand % numbers. This allows \pkg{siunitx} to carry out a range of % formatting, as described later. All of the input options take lists of % literal tokens, and are summarised in \cref{tab:opt:num:in}. % %\begin{table} % \centering % \caption{Options for number parsing.} % \label{tab:opt:num:in} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{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}. % The parser understands complex root symbols given either before % or after the associated number (but will detect any invalid % arrangement): %\begin{LaTeXdemo} % \num{9.99 + 88.8i} \\ % \num{9.99 + i88.8} %\end{LaTeXdemo} % %\DescribeOption{input-protect-tokens} % Some symbols can be problematic under expansion in \LaTeXe. To allow % these to be used in input without issue, the package can protect these % tokens while expanding input. Symbols to be protected in this way % should be listed in \opt{input-protect-tokens}. % %\DescribeOption{parse-numbers} % The \opt{parse-numbers} option turns the entire parsing system on % and off. The option is made available for two reasons. First, if % all of the numbers in a document are to be reproduced \enquote{as % given}, turning off the parser will represent a significant saving in % processing required. Second, it allows the use of arbitrary \TeX\ % code in numbers. If the parser is turned off, the input will be % printed in maths mode (requiring \cs{text} to protect any text % in the number). %\begin{LaTeXdemo} % \num[parse-numbers = false]{\sqrt{2}} \\ % \SI[parse-numbers = false]{\sqrt{3}}{\metre} %\end{LaTeXdemo} % %\subsection{Post-processing numbers} % % Before typesetting numbers, various post-processing steps can be % carried out. These involve adding or removing information from the % number in a systematic way; the options are summarised in % \cref{tab:opt:num:post}. % %\begin{table} % \centering % \caption{Number post-processing options.} % \label{tab:opt:num:post} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule % add-decimal-zero & Switch & true \\ % add-integer-zero & Switch & true \\ % 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 & Integer & 2 \\ % round-places & Integer & 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. No rounding will take place if the number contains an % uncertainty component. %\begin{LaTeXdemo} % \num{1.23456} \\ % \num{14.23} \\ % \num{0.12345(9)} \\ % \sisetup{ % round-mode = places, % round-places = 3 % }% % \num{1.23456} \\ % \num{14.23} \\ % \num{0.12345(9)} \\ % \sisetup{ % round-mode = figures, % round-figures = 3 % }% % \num{1.23456} \\ % \num{14.23} \\ % \num{0.12345(9)} %\end{LaTeXdemo} % %\DescribeOption{add-decimal-zero} %\DescribeOption{add-integer-zero} % It is possible to give real (floating point) numbers as input omitting % the decimal or the integer parts of the number (for example \num{.123} % or \num{123.}). The options \opt{add-decimal-zero} and % \opt{add-integer-zero} allow the package to \enquote{fill in} the % missing zero. %\begin{LaTeXdemo} % \num{123.} \\ % \num{456} \\ % \num{.789} \\ % \sisetup{ % add-decimal-zero = false, % add-integer-zero = false, % }% % \num{123.} \\ % \num{456} \\ % \num{.789} %\end{LaTeXdemo} % %\DescribeOption{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 \cref{tab:opt:num:out}. % %\begin{table} % \centering % \caption{Output options for numbers.} % \label{tab:opt:num:out} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule ^^A ( % close-bracket & Literal & ) \\ % complex-root-after-number & Switch & true \\ % copy-decimal-marker & Choice & false \\ % 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 & \verb=\mathrm{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} %\DescribeOption{copy-decimal-marker} % The decimal marker used in output is set using the % \opt{output-decimal-marker} option. This can differ from the input % marker, as can the root of $\sqrt{-1}$, which is stored in the % \opt{output-complex-root} option. The later is always in maths mode, % but the standard setting uses \cs{mathrm} to give an upright % \enquote{i}: this can easily be altered. The decimal marker from % the input can be used in the output by setting the % \opt{copy-decimal-marker} option. %\begin{LaTeXdemo} % \num{1.23} \\ % \num[output-decimal-marker = {,}]{1.23} \\ % \num{1+2i} \\ % \num[output-complex-root = \text{\ensuremath{i}}]{1+2i} \\ % \num[output-complex-root = j]{1+2i} \\ % \num[copy-decimal-marker]{555,555} %\end{LaTeXdemo} % %\DescribeOption{complex-root-after-number} % The position of the complex root can be adjusted to place it % either before or after the associated numeral in a complex number % using the \opt{complex-root-after-number} option. %\begin{LaTeXdemo} % \num{67-0.9i} \\ % \num[complex-root-after-number = false]{67-0.9i} %\end{LaTeXdemo} % %\DescribeOption{exponent-base} %\DescribeOption{exponent-product} % When exponents are present in the input, the % \opt{exponent-base} and \opt{exponent-product} options set the obvious % parts of the output. Notice that the base is in the current mode, but % the product sign is always in 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 \cref{tab:opt:num:multi}. % %\begin{table} % \centering % \caption{Multi-part number options.} % \label{tab:opt:num:multi} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule ^^A ( % fraction-function & Macro & \cs{frac} \\ % 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 } \\ % \num{ 1e2 / 3e4 } %\end{LaTeXdemo} %\DescribeOption{output-product} %\DescribeOption{output-quotient} % The symbols used for printing products and quotients are stored using % the options \opt{output-product} and \opt{output-quotient}. %\begin{LaTeXdemo} % \num[output-product = \cdot]{4.87 x 5.321 x 6.90545} \\ % \num[output-quotient = \text{ div }]{1 / 2} %\end{LaTeXdemo} % %\DescribeOption{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} % %\DescribeOption{fraction-function} % The function used when \opt{quotient-mode = fraction} is set is % determin ed by the \opt{fraction-function} option. This should % be set to a function which takes two arguments, and presumably % creates some type of fraction. Most alternatives to the standard % \cs{frac} function will involve loading addition packages: the % demonstrations here need \pkg{amsmath} and % \pkg{xfrac}.\footnote{If \pkg{xfrac} is not available when typesetting % this document, the demonstration of \cs{sfrac} will have the wrong % appearance.} %\begin{LaTeXdemo} % \sisetup{quotient-mode = fraction} % \num{1 / 1} % \num[fraction-function = \dfrac]{1 / 2} % \num[fraction-function = \sfrac]{1 / 3} % \num[fraction-function = \tfrac]{1 / 4} %\end{LaTeXdemo} % %\subsection{Angles} % % Angle processing provided by the \cs{ang} has a set of options which % apply in addition to the general ones set up for number processing % (\cref{tab:opt:ang}) % %\begin{table} % \centering % \caption{Angle options.} % \label{tab:opt:ang} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule % add-arc-degree-zero & Switch & false \\ % add-arc-minute-zero & Switch & false \\ % add-arc-second-zero & Switch & false \\ % angle-symbol-over-decimal & Switch & false \\ % arc-separator & Maths & false \\ % number-angle-separator & Maths & \meta{empty} \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{number-angle-separator} % The separator between the number and angle symbol (degrees, minutes % or seconds) can be set using the \opt{number-angle-separator} % option, independent of the related \opt{number-unit-separator} % option used by the \cs{SI} function. %\begin{LaTeXdemo} % \ang{2.67} \\ % \ang[number-angle-separator = \,]{2.67} %\end{LaTeXdemo} % %\DescribeOption{arc-separator} % When angles are printed in arc format, the separation of the different % pars is set up using the \opt{arc-separator} option. %\begin{LaTeXdemo} % \ang{6;7;6.5} \\ % \ang[arc-separator = \,]{6;7;6.5} %\end{LaTeXdemo} % %\DescribeOption{add-arc-degree-zero} %\DescribeOption{add-arc-minute-zero} %\DescribeOption{add-arc-second-zero} % Zero-filling for the degree, minute or second parts of an arc is % controlled using the \opt{add-arc-degree-zero}, % \opt{add-arc-minute-zero} and \opt{add-arc-second-zero} options. % All are off as standard. %\begin{LaTeXdemo} % \ang{-1;;} \\ % \ang{;-2;} \\ % \ang{;;-3} \\ % \sisetup{add-arc-degree-zero} % \ang{-1;;} \\ % \ang{;-2;} \\ % \ang{;;-3} \\ % \sisetup{add-arc-minute-zero} % \ang{-1;;} \\ % \ang{;-2;} \\ % \ang{;;-3} \\ % \sisetup{add-arc-second-zero} % \ang{-1;;} \\ % \ang{;-2;} \\ % \ang{;;-3} %\end{LaTeXdemo} % %\DescribeOption{angle-symbol-over-decimal} % In some subject areas, most notably astronomy, the angle symbols % are given over the decimal marker, rather than at the end of the % number. This behaviour is available using the % \opt{angle-symbol-over-decimal} option. %\begin{LaTeXdemo} % \ang{45.697} \\ % \ang{6;7;6.5} \\ % \ang[angle-symbol-over-decimal]{45.697} \\ % \ang[angle-symbol-over-decimal]{6;7;6.5} %\end{LaTeXdemo} % %\subsection{Creating units} %\label{sec:units:creating} % % The various macro units are created at the start of the document. % 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 % (\cref{tab:opt:units:def}). As a result, these options all apply % in the preamble only. % %\begin{table} % \centering % \caption{Unit creation options.} % \label{tab:opt:units:def} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{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{Loading additional units} % %\DescribeOption{load-configurations} % There are a number of additional unit definitions supplied with % \pkg{siunitx} that are not loaded as standard. Some of these are % specialist units for certain subject areas, others are not % accepted with the SI and some are for the users convenience. % A comma-separated list of configurations to load should be % given as the argument to the \opt{load-configurations} option. % % The first group of add-on units are those which provide % convenient abbreviations (\cref{tab:unit:abbr}). The standard % \pkg{siunitx} settings only create these abbreviations within the % scope of the \cs{si} and \cs{SI} functions, meaning that no clashes % should occur (for example with the standard \cs{pm} symbol). % %\begin{center} % \tablecaption{Abbreviated units \endgraf % (\opt{load-configurations=abbreviations})} % \label{tab:unit:abbr} % \tablefirsthead{^^A % \toprule % \multicolumn{1}{c}{Unit} & % \multicolumn{1}{c}{Abbreviation} & % \multicolumn{1}{c}{Symbol} \\ % \midrule % } % \tablehead{^^A % \multicolumn{3}{l}{\emph{Continued from previous page}} \\ % \toprule % \multicolumn{1}{c}{Unit} & % \multicolumn{1}{c}{Abbreviation} & % \multicolumn{1}{c}{Symbol} \\ % \midrule % } % \tabletail{^^A % \bottomrule % \multicolumn{3}{r}{\emph{Continued on next page}} \\ % } % \tablelasttail{\bottomrule} % \begin{xtabular}{lcc} % \DescribeNamedUnit{femtogram}{fg} \\ % \DescribeNamedUnit{picogram}{pg} \\ % \DescribeNamedUnit{nanogram}{ng} \\ % \DescribeNamedUnit{microgram}{ug} \\ % \DescribeNamedUnit{milligram}{mg} \\ % \DescribeNamedUnit{gram}{g} \\ % \DescribeNamedUnit{kilogram}{kg} \\ % \DescribeNamedUnit{atomic mass unit}{amu} \\ % % \midrule % % \DescribeNamedUnit{picometre}{pm} \\ % \DescribeNamedUnit{nanometre}{nm} \\ % \DescribeNamedUnit{micrometre}{um} \\ % \DescribeNamedUnit{millimetre}{mm} \\ % \DescribeNamedUnit{centimetre}{cm} \\ % \DescribeNamedUnit{decimetre}{dm} \\ % \DescribeNamedUnit{kilometre}{km} \\ % % \midrule % % \DescribeNamedUnit{attosecond}{as} \\ % \DescribeNamedUnit{femtosecond}{fs} \\ % \DescribeNamedUnit{picosecond}{ps} \\ % \DescribeNamedUnit{nanosecond}{ns} \\ % \DescribeNamedUnit{microsecond}{us} \\ % \DescribeNamedUnit{millisecond}{ms} \\ % \DescribeNamedUnit{second}{s} \\ % % \midrule % % \DescribeNamedUnit{femtomole}{fmol} \\ % \DescribeNamedUnit{picomole}{pmol} \\ % \DescribeNamedUnit{nanomole}{nmol} \\ % \DescribeNamedUnit{micromole}{umol} \\ % \DescribeNamedUnit{millimole}{mmol} \\ % \DescribeNamedUnit{kilomole}{kmol} \\ % % \midrule % % \DescribeNamedUnit{picoampere}{pA} \\ % \DescribeNamedUnit{nanoampere}{nA} \\ % \DescribeNamedUnit{microampere}{uA} \\ % \DescribeNamedUnit{milliampere}{mA} \\ % \DescribeNamedUnit{kiloampere}{kA} \\ % % \midrule % % \DescribeNamedUnit{microlitre}{ul} \\ % \DescribeNamedUnit{millilitre}{ml} \\ % \DescribeNamedUnit{microliter}{uL} \\ % \DescribeNamedUnit{milliliter}{mL} \\ % % \midrule % % \DescribeNamedUnit{millihertz}{mHz} \\ % \DescribeNamedUnit{hertz}{Hz} \\ % \DescribeNamedUnit{kilohertz}{kHz} \\ % \DescribeNamedUnit{megahertz}{MHz} \\ % \DescribeNamedUnit{gigahertz}{GHz} \\ % \DescribeNamedUnit{terahertz}{THz} \\ % % \midrule % % \DescribeNamedUnit{millivolt}{mV} \\ % \DescribeNamedUnit{kilovolt}{kV} \\ % % \midrule % % \DescribeNamedUnit{kilojoule}{kJ} \\ % \DescribeNamedUnit{electronvolt}{eV} \\ % \DescribeNamedUnit{millielectronvolt}{meV} \\ % \DescribeNamedUnit{kiloelectronvolt}{keV} \\ % \DescribeNamedUnit{megaelectronvolt}{MeV} \\ % \DescribeNamedUnit{gigaelectronvolt}{GeV} \\ % \DescribeNamedUnit{teraelectronvolt}{TeV} \\ % \DescribeNamedUnit{kilowatt hour}{kWh} \\ % % \end{xtabular} %\end{center} % %\DescribeMacro{\bit} %\DescribeMacro{\byte} % Binary data requires the units bits and bites, and the special % prefixes which use powers of two rather than of ten % (\cref{tab:unit:binary}) have been defined for this purpose. % Appropriate unit prefixes, along with the units \cs{bit} and % \cs{byte} are available for use in the computing field. %\begin{LaTeXdemo} % \SI{100}{\mebi\byte} \\ % \SI[prefixes-as-symbols=false]{30}{\kibi\bit} %\end{LaTeXdemo} % %\begin{table} % \caption{Binary prefixes \protect \\ % (\opt{load-configurations=binary}).} % \label{tab:unit:binary} % \centering % \begin{tabular}{llc>{$}l<{$}} % \toprule % \multicolumn{1}{c}{Prefix} & % \multicolumn{1}{c}{Macro} & % \multicolumn{1}{c}{Symbol} & % \multicolumn{1}{c}{Power} \\ % \midrule % \DescribePrefix{kibi} & 10 \\ % \DescribePrefix{mebi} & 20 \\ % \DescribePrefix{gibi} & 30 \\ % \DescribePrefix{tebi} & 40 \\ % \DescribePrefix{pebi} & 50 \\ % \DescribePrefix{exbi} & 60 \\ % \DescribePrefix{zebi} & 70 \\ % \DescribePrefix{yobi} & 80 \\ % \bottomrule % \end{tabular} %\end{table} % % Units for specialist areas are given in % \cref{tab:unit:astro,tab:unit:chemeng,tab:unit:chem,tab:unit:geophys}. % These are not SI units, but are defined here as they are in common % usage in the subject areas concerned. % %\begin{table} % \caption{Astronomy-related units \protect \\ % (\opt{load-configurations=astronomy}).} % \label{tab:unit:astro} % \centering % \begin{tabular}{lll} % \toprule % \multicolumn{1}{c}{Unit} & % \multicolumn{1}{c}{Macro} & % \multicolumn{1}{c}{Symbol} \\ % \midrule % \DescribeUnit{parsec} \\ % \DescribeUnit{lightyear} \\ % \bottomrule % \end{tabular} %\end{table} % %\begin{table} % \caption{Chemical engineering units \protect \\ % (\opt{load-configurations=chemical-engineering}).} % \label{tab:unit:chemeng} % \centering % \begin{tabular}{lll} % \toprule % \multicolumn{1}{c}{Unit} & % \multicolumn{1}{c}{Macro} & % \multicolumn{1}{c}{Symbol} \\ % \midrule % \DescribeNamedUnit{gram-mole}{gmol} \\ % \DescribeNamedUnit{kilogram-mole}{kgmol} \\ % \DescribeNamedUnit{pound-mole}{lbmol} \\ % \bottomrule % \end{tabular} %\end{table} % %\begin{table} % \caption{Chemistry-related units \protect \\ % (\opt{load-configurations=chemistry}).} % \label{tab:unit:chem} % \centering % \begin{tabular}{lll} % \toprule % \multicolumn{1}{c}{Unit} & % \multicolumn{1}{c}{Macro} & % \multicolumn{1}{c}{Symbol} \\ % \midrule % \DescribeUnit{molar} \\ % \SpecialUsageIndex{\Molar}^^A % & \cs{Molar} & \si{\Molar} \\ % \DescribeUnit{torr} \\ % \bottomrule % \end{tabular} %\end{table} % %\begin{table} % \caption{Geophysics-related units \protect \\ % (\opt{load-configurations=geophysics}).} % \label{tab:unit:geophys} % \centering % \begin{tabular}{lll} % \toprule % \multicolumn{1}{c}{Unit} & % \multicolumn{1}{c}{Macro} & % \multicolumn{1}{c}{Symbol} \\ % \midrule % \DescribeUnit{gon} \\ % \bottomrule % \end{tabular} %\end{table} % %\subsection{Using units} % % Part of the power of \pkg{siunitx} is the ability to alter the output % format for units without changing the input. The behaviour of units % is therefore controlled by a number of options which alter either the % processing of units or the output directly % (\cref{tab:opt:units:out}). % %\begin{table} % \centering % \caption{Unit output options.} % \label{tab:opt:units:out} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule ^^A ( % forbid-literal-units & Switch & false \\ % inter-unit-separator & Maths & \cs{,} \\ % parse-units & Switch & true \\ % 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{forbid-literal-units} % Some users may prefer to completely disable the use of literal input % in units, for example to enforce consistency. This can be % accomplished by setting the \opt{forbid-literal-units} switch. With % this option enabled, only macro-based units can be used in a document. % %\DescribeOption{inter-unit-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 centred dot. To get the correct % spacing it is necessary to use |{}\cdot{}| in the later case. %\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} % The closely-related \opt{reciprocal-positive-first} setting acts in % the same way but places all of the positive powers before any negative % ones. %\begin{LaTeXdemo} % \si{\ampere\per\mole\second} \\ % \si[per-mode = reciprocal-positive-first] % {\ampere\per\mole\second} %\end{LaTeXdemo} % It is possible to use a symbol (usually \texttt{/}) to separate the % two parts of a unit by setting \opt{per-mode} to \opt{symbol}; the % symbol used is stored using the setting \opt{per-symbol}. This method % for displaying units can be ambiguous, and so brackets are added % unless \opt{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} % The often-requested (but mathematically invalid) % \opt{repeated-symbol} option is also available to repeat the symbol % for each \cs{per}. %\begin{LaTeXdemo} % \si[per-mode=repeated-symbol]{\joule\per\mole\per\kelvin} %\end{LaTeXdemo} % Finally, it is possible for the behaviour of the \cs{per} function % to depend on the surrounding environment. Setting the option to % \opt{symbol-or-fraction}, causes the same behaviour as % \opt{symbol} when the surroundings are in line, and the same % behaviour as \opt{fraction} when in a display context. %\begin{LaTeXdemo} % \sisetup{per-mode = symbol-or-fraction}% % \( \si{\joule\per\mole\per\kelvin} \) % \[ \si{\joule\per\mole\per\kelvin} \] % \si{\joule\per\mole\per\kelvin} %\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\squared\per\mole\catalyst\per\hour} \\ % \si[qualifier-mode=brackets] % {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ % \si[qualifier-mode=space] % {\kilogram\polymer\squared\per\mole\catalyst\per\hour} %\end{LaTeXdemo} % %\DescribeOption{prefixes-as-symbols} % The unit prefixes (\cs{kilo}, \emph{etc.}) are normally given as % letters. However, the package can convert these into numerical powers. % This is controlled by the \opt{prefixes-as-symbols} switch option. %\begin{LaTeXdemo} % \si{\milli\litre\per\mole\deci\ampere} \\ % \SI{10}{\kilo\gram\squared\deci\second} \\ % \si[prefixes-as-symbols=false]{\milli\litre\per\mole\deci\ampere} \\ % \SI[prefixes-as-symbols=false]{10}{\kilo\gram\squared\deci\second} %\end{LaTeXdemo} % %\DescribeOption{parse-units} % Normally, \pkg{siunitx} is used with the unit parse enabled, and % only prints units directly if there is literal input. However, if % the input is known to be essentially consistent and high performance % is desired, then the parser can be turned off using the % \opt{parse-units} switch. %\begin{LaTeXdemo} % \SI{300}{\MHz} \\ % \SI[parse-units = false]{300}{\MHz} %\end{LaTeXdemo} % %\subsection{Numbers with units} % % Some options apply to the combination of units and numbers, rather % than to units or numbers alone (\cref{tab:opt:units:numbers}). % %\begin{table} % \centering % \caption{Options for numbers with units.} % \label{tab:opt:units:numbers} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule ^^A ( % allow-number-unit-breaks & Switch & false \\ % number-unit-separator & Maths & \cs{,} \\ % repeat-units & Switch & true \\ % unit-product-to-power & Switch & false \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{allow-number-unit-breaks} % Usually, the combination of a number and unit is regards as a single % mathematical entity which should not be split across lines. However, % there are cases (very long units, narrow columns, \emph{etc}.) where % breaks may be needed. This can be turned on using the % \opt{allow-number-unit-breaks} option. %\begin{LaTeXdemo} % \begin{minipage}{2.55 cm} % % Gives an underfull hbox % Some filler text \SI{10}{\metre} \\ % \sisetup{allow-number-unit-breaks} % Some filler text \SI{10}{\metre} % \end{minipage} %\end{LaTeXdemo} % %\DescribeOption{number-unit-separator} % The separator between the number and unit is set using the % \opt{number-unit-separator} option. %\begin{LaTeXdemo} % \SI{2.67}{\farad} \\ % \SI[number-unit-separator=\text{~}]{2.67}{\farad} \\ % \SI[number-unit-separator=]{2.67}{\farad} %\end{LaTeXdemo} % %\DescribeOption{repeat-units} %\DescribeOption{unit-product-to-power} % When brackets are not in use to make the meaning of number--unit % combinations clear, it may be necessary to repeat units to maintain % the mathematical meaning of the output. This is handled by the % \opt{repeat-units} option, which may be \opt{true} or \opt{false}. % At the same time, \emph{simple} products (areas and volumes) may be % given with the repetition of the unit converted into a power. This % behaviour is set by the \opt{unit-product-to-power} option, which % will only act if units are not being printed repeatedly. %\begin{LaTeXdemo} % \SI{10 x 20 x 30}{\metre} \\ % \SI[unit-product-to-power]{10 x 20 x 30}{\metre} \\ % % \sisetup{use-brackets = false} % \SI{10 x 20 x 30}{\metre} \\ % \SI[unit-product-to-power]{10 x 20 x 30}{\metre} \\ % \SI[repeat-units=false]{10 x 20 x 30}{\metre} \\ % \SI[repeat-units=false,unit-product-to-power] % {10 x 20 x 30}{\metre} \\ % % \sisetup{ % separate-uncertainty, % use-brackets = false % } % \SI{12.3(4)}{\kilo\gram} \\ % \SI[repeat-units=false]{12.3(4)}{\kilo\gram} %\end{LaTeXdemo} % %\subsection{Tabular material} % % Processing of material in tables obeys the same settings as described % for the functions already described. However, there are some settings % which apply only to the layout of tabular material. % %\begin{table} % \centering % \caption{Options for tabular material.} % \label{tab:opt:tables} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{c}{Option name} & % \multicolumn{1}{c}{Type} & % \multicolumn{1}{c}{Default} \\ % \midrule ^^A ( % table-align-numbers & Choice & centre \\ % table-align-text & Choice & centre \\ % table-align-units & Choice & centre \\ % table-auto-round & Switch & false \\ % table-figures-decimal & Integer & 2 \\ % table-figures-exponent & Integer & 0 \\ % table-figures-integer & Integer & 3 \\ % table-figures-uncertainty & Integer & 0 \\ % table-parse-only & Switch & false \\ % table-space-text-pre & Literal & \m{empty} \\ % table-space-text-post & Literal & \m{empty} \\ % table-sign-exponent & Switch & false \\ % table-sign-mantissa & Switch & false \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{table-parse-only} % The main use of the \texttt{S} column is to control the alignment of % the resulting output. However, it is possible to turn off alignment % entirely and only use the number parser of \pkg{siunitx}. This is % achieved using the \opt{table-parse-only} switch, as illustrated % in \cref{tab:S:parse} %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{Parsing without aligning in an \texttt{S} column.} % \label{tab:S:parse} % \begin{tabular} % { % S % S[table-parse-only] % } % \toprule % {Decimal-centred} & % {Simple centring} \\ % \midrule % 12.345 & 12.345 \\ % 6,78 & 6,78 \\ % -88.8(9) & -88.8(9) \\ % 4.5e3 & 4.5e3 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{table-align-numbers} % The alignment of numbers with the boundaries of the \texttt{S} % column is controlled using the \opt{table-align-numbers} option, % which takes the values \opt{centre-decimal-marker}, \opt{centre}, % \opt{left} and \opt{right}. The \opt{centre-decimal-marker} places the % decimal marker for the number at the centre of the column. This does % not need any information in advance, and so is the standard setting. % It works best for approximately symmetrical input (equal numbers of % digits before and after the decimal). On the other hand, the % \opt{centre}, \opt{left} and \opt{right} options require space to be % reserved for the numbers, and then use this fixed space to align with % the edges of the column. The different alignment choices are % illustrated in \cref{tab:S:align}, which uses somewhat % exaggerated column headings to show the relative position of the % cell contents. %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Aligning the \texttt{S} column.} % \label{tab:S:align} % \centering % \sisetup{ % table-figures-integer = 2, % table-figures-decimal = 4 % } % \begin{tabular}{ % S % S[table-align-numbers = centre] % S[table-align-numbers = left] % S[table-align-numbers = right] % } % \toprule % {Some Values} & {Some Values} & {Some Values} & {Some Values} \\ % \midrule % 2.3456 & 2.3456 & 2.3456 & 2.3456 \\ % 34.2345 & 34.2345 & 34.2345 & 34.2345 \\ % 56.7835 & 56.7835 & 56.7835 & 56.7835 \\ % 90.473 & 90.473 & 90.473 & 90.473 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % Many of the other table options do not apply when % \opt{table-align-numbers = centre-decimal-marker} is set, as this % mode always centres the marker at the expense of any other % choices. % %\DescribeOption{table-figures-decimal} %\DescribeOption{table-figures-exponent} %\DescribeOption{table-figures-integer} %\DescribeOption{table-figures-uncertainty} % The space reserved by \pkg{siunitx} for a number is controlled by % two families of options. The first family cover the number of digits % allowed for in different parts of the number, for example % \opt{table-figures-integer} controls the space for integer digits in % the mantissa. If the number of figures is set to \num{0}, then no % space is reserved and some output will either be out of position % or not printed at all (although a warning will result). Reserving % space for a given part of number will automatically include space % for any associated items (for example the \enquote{\(\times\)} symbol % for exponents). %\DescribeOption{table-sign-exponent} %\DescribeOption{table-sign-mantissa} % The second family of options are switches which govern whether % space is reserved for a sign: \opt{table-sign-exponent} and % \opt{table-sign-mantissa}. The effect of altering some of these % settings is shown in \cref{tab:S:space}. %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Reserving space in \texttt{S} columns.} % \label{tab:S:space} % \sisetup{ % table-align-numbers = centre, % table-figures-integer = 2 % } % \centering % \begin{tabular}{ % S % S[table-align-numbers = right] % S[table-figures-uncertainty = 1] % S[ % separate-uncertainty, % table-figures-uncertainty = 1 % ] % S[table-sign-mantissa] % S[table-figures-exponent = 1] % } % \toprule % {Values} % & {Values} % & {Values} % & {Values} % & {Values} % & {Values} \\ % \midrule % 2.3 & 2.3 & 2.3(5) & 2.3(5) & 2.3 & 2.3e8 \\ % 34.23 & 34.23 & 34.23(4) & 34.23(4) & 34.23 & 34.23 \\ % 56.78 & 56.78 & 56.78(3) & 56.78(3) & -56.78 & 56.78e3 \\ % 3,76 & 3,76 & 3,76(2) & 3.76(2) & +-3.76 & e6 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{table-space-text-pre} %\DescribeOption{table-space-text-post} % Space for material before and after the \texttt{S} column can % be reserved by giving model text for the options % \opt{table-space-text-pre} and \opt{\ldots -post}. % This is then used to provide the necessary gap while maintaining % alignment (\cref{tab:S:ends}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Text before and after numbers.} % \label{tab:S:ends} % \centering % \sisetup{ % table-figures-integer = 2, % table-figures-decimal = 4, % table-space-text-pre = $ > $, % table-space-text-post = % \textsuperscript{\emph{a}} % } % \begin{tabular}{S} % \toprule % {Values} \\ % \midrule % 2.3456 \\ % 34.2345 \textsuperscript{\emph{a}}\\ % 56.7835 \\ % $ > $ 90.473 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{table-auto-round} % The contents of table cells can automatically be rounded or % zero-filled to the number of decimal digits given for the % \opt{table-figures-decimal} option. This mode is activated using % the \opt{table-auto-round} switch, as illustrated in % \cref{tab:S:auto}. %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{The \opt{table-auto-round} option.} % \label{tab:S:auto} % \sisetup{ % table-align-numbers = centre, % table-figures-integer = 1, % table-figures-decimal = 3 % } % % Notice the overfull hbox which results with % % the first column % \begin{tabular}{ % S % S[table-auto-round] % } % \toprule % {Header} & {Header} \\ % \midrule % 1.2 & 1.2 \\ % 1.2345 & 1.2345 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{parse-numbers} % When the \opt{parse-numbers} option is set to \opt{false}, then % the alignment code for tables takes a different approach. The % output is always set in maths mode, and alignment takes place % at the first decimal marker. This is achieved by making it % active in maths mode. When reserving space for content only % the integer and decimal values for the mantissa are considered % (\cref{tab:S:nonparsed}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Aligning without parsing.} % \label{tab:S:nonparsed} % \sisetup{ % parse-numbers = false, % table-figures-integer = 2, % table-figures-decimal = 3 % } % \centering % \begin{tabular}{ % S % S[table-align-numbers = centre] % S[table-align-numbers = right] % S[table-align-numbers = left] % } % \toprule % \multicolumn{1}{c}{Some values} % & \multicolumn{1}{c}{Some values} % & \multicolumn{1}{c}{Some values} % & \multicolumn{1}{c}{Some values} \\ % \midrule % 2.35 & 2.35 & 2.35 & 2.35 \\ % 34.234 & 34.234 & 34.234 & 34.234 \\ % 56.783 & 56.783 & 56.783 & 56.783 \\ % 3,762 & 3,762 & 3,762 & 3.762 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{table-align-text} % Cell contents which are not part of of a number can be protected % using braces, as illustrated. Cells which contain no numerical data % at all are aligned using the setting specified by the % \opt{table-align-text} option, which recognises the values % \opt{centre}, \opt{left} and \opt{right} (\cref{tab:S:text}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Aligning text in \texttt{S} columns.} % \label{tab:S:text} % \sisetup{ % table-align-numbers = centre, % table-figures-integer = 4, % table-figures-decimal = 4 % } % \centering % \begin{tabular}{ % S % S[table-align-text = left] % S[table-align-text = right] % } % \toprule % {Values} % & {Values} % & {Values} \\ % \midrule % 992.435 & 992.435 & 992.435 \\ % 7734.2344 & 7734.2344 & 7734.2344 \\ % 56.7834 & 56.7834 & 56.7834 \\ % 3,7462 & 3,7462 & 3,7462 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{table-align-units} % The contents of \texttt{s} columns can be centred or aligned to the % left or right using the \opt{table-align-units} option. As for the % other alignment options, this recognises the choices \opt{centre}, % \opt{left} and \opt{right}. %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{Alignment options in \texttt{s} columns.} % \label{tab:s:align} % \begin{tabular} % { % s[table-align-units = right] % s % s[table-align-units = left] % } % \toprule % \multicolumn{1}{c}{Left-aligned} & % \multicolumn{1}{c}{Centred text} & % \multicolumn{1}{c}{Right-aligned} \\ % \midrule % \metre\per\second & \metre\per\second & \metre\per\second \\ % \kilogram & \kilogram & \kilogram \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\subsection{Symbols} % % Most units use letters as the symbol for the unit, and these are all % very easy to control. However, a small number of units use other % symbols, and matching these to the body text requires more work. % \pkg{siunitx} provides appropriate symbols for commonly-used units, % but the definitions may need adjustment depending on the body font % used in a document. % %\DescribeOption{redefine-symbols} % The package provides one general option for the handling of symbols. % If the packages \pkg{textcomp} or \pkg{upgreek} are loaded, symbols % can be taken from these for units, rather than using the % \pkg{siunitx} default values. The switch \opt{redefine-symbols} % can be used to turn this behaviour on or off: the standard setting % is \opt{true}. % % The individual symbols are set up independently for maths and text % output, and are summarised in \cref{tab:opt:symbols}. Many of % the definitions are variations using \cs{text} or \cs{ensuremath} to % produce the correct output, as the symbols available in the document % may vary considerably. In the case of the micro symbol % (\SIUnitSymbolMicro), \pkg{sunitx} provides a suitable low-level % definition for the symbol. Depending on the fonts available, this % may need to be replaced by an alternative by the user. The % ohm symbol (\SIUnitSymbolOhm) is usually set to \cs{Omega}, but % will check that this has not been redefined as a slanted letter. If % \cs{Omega} has been redefined, an alternative definition is used. % %\begin{table} % \centering % \caption{Symbol options.} % \label{tab:opt:symbols} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{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}= \\ % & & \verb=\kern -\scriptspace \mathrm{C}= \\ % maths-degree & Literal & \verb={}^{\circ}= \\ % maths-micro & Literal & \meta{see text} \\ % maths-ohm & Literal & \cs{Omega} \\ % redefine-symbols & Switch & true \\ % text-angstrom & Literal & \cs{AA} \\ % text-arcminute & Literal & \verb=\ensuremath{{}^{\prime}}= \\ % text-arcsecond & Literal & % \verb=\ensuremath{{}^{\prime\prime}}= \\ % text-celsius & Literal & \verb=\ensuremath{{}^{\circ}= \\ % & & \verb=\kern -\scriptspace \text{C}}= \\ % text-degree & Literal & \verb=\ensuremath{{}^{\circ}}= \\ % text-micro & Literal & \meta{see text} \\ % text-ohm & Literal & \verb=\ensuremath{\Omega}= \\ % \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.} % %\subsection{Other options} % %\DescribeOption{strict} % Some users will want to stick closely to the official rules for % typesetting units. This could be made complicated if the options % for non-standards behaviour could not be turned off. The % preamble-only option \opt{strict} resets package behaviour to % follow the rules closely, and disables options which deviate from % this. If the package is loaded with the \opt{strict} option, all % output is made using the upright serif font. % %\section{Hints for using \pkg{siunitx}} % %\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. In some cases, simply forcing \cs{mathnormal} % will suffice, but this is less reliable with non-Latin characters. % %\subsection{Expanding content in tables} % % When processing tables, \pkg{siunitx} will expand anything stored % inside a macro, unless it is long or protected. \LaTeXe\ robust % commands are also detected and are not expanded % (\cref{tab:xmpl:macro}). Values which would otherwise be expanded % can be protected by wrapping them in a set of braces. As \TeX\ itself % will expand the first token in a table cell before \pkg{siunitx} % can act on it, using the \eTeX\ protected mechanism is the % recommended course of action to prevent expansion of macros in % table cells. (As is shown in the table, \TeX's expansion of % \LaTeXe\ robust commands can lead to unexpected results.) %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{Values as macros in \texttt{S} columns.} % \label{tab:xmpl:macro} % \newcommand*\myvaluea{1234} % \newcommand\myvalueb{1234} % \DeclareRobustCommand*\myvaluec{1234} % \protected\def\myvalued{1234} % \begin{tabular}{S} % \toprule % {Some Values} \\ % \midrule % \myvaluea 8.8 \myvaluea \\ % Both expanded % \myvalueb 8.8 \myvalueb \\ % First expanded by TeX % % to numbers % \myvaluec 8.8 \myvaluec \\ % First expanded by TeX % % but not to numbers! % \myvalued 8.8 \myvalued \\ % Neither expanded % {\myvaluea\ 8.8 \myvaluea} \\ % Neither expanded % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % % It is possible to use calculated values in tables. For this to % work, the calculation must take place before attempting to parse % the number. An added complication is that \TeX\ itself will % expand the first macro in a table cell until it finds % something unexpandable. The \eTeX\ protected mechanism can be % used to prevent this; using the \pkg{etoolbox} package provides % a convenient way to apply this protection to existing functions. % The general approach is illustrated in \cref{tab:xmpl:calc}. % The macro \cs{DTLmul} is made robust inside the table using % the \cs{robustify} command from \pkg{etoolbox}, before % constructing the table using an extra column to contain the % calculation. %\begin{LaTeXdemo}[code and float] % \DTLnewdb{data} % \DTLnewrow{data}\DTLnewdbentry{data}{value}{66.7012} % \DTLnewrow{data}\DTLnewdbentry{data}{value}{66.0212} % \DTLnewrow{data}\DTLnewdbentry{data}{value}{64.9026} % \begin{table} % \caption{Calculated values.} % \label{tab:xmpl:calc} % \centering % \robustify\DTLmul % \sisetup{ % table-align-numbers = centre, % table-figures-integer = 2, % table-figures-decimal = 4 % } % \begin{tabular}{ % S % S[table-figures-integer = 3] % @{}l % } % \toprule % {Value} & {Doubled} & % \DTLforeach{data}{\myvalue=value}{% % \DTLiffirstrow {\\ \midrule}{\\}% % \myvalue & % First column % \DTLmul{\myvalue}{\myvalue}{2} \myvalue % second column % & }\\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\subsection{Using \pkg{siunitx} with \pkg{datatool}} % % As illustrated in \cref{tab:xmpl:calc}, \pkg{siunitx} can be used % to typeset data stored using \pkg{datatool}. For quickly displaying % the contents of tables, \pkg{datatool} offers the \cs{DTLshowtable} % macro. This will only work with \texttt{S} columns if number parsing % is turned off (\cref{tab:xmpl:datatool}). %\begin{LaTeXdemo}[code and float] % \DTLnewdb{moredata} % \DTLnewrow{moredata}\DTLnewdbentry{moredata}{value}{ 6.7012} % \DTLnewrow{moredata}\DTLnewdbentry{moredata}{value}{66.0212} % \DTLnewrow{moredata}\DTLnewdbentry{moredata}{value}{64.902 } % \begin{table} % \caption{Displaying a \textsf{datatool} table.} % \label{tab:xmpl:datatool} % \centering % \sisetup{ % parse-numbers = false, % table-align-numbers = centre, % table-figures-integer = 2, % table-figures-decimal = 4 % } % \renewcommand*\dtlrealalign{S} % \DTLdisplaydb{moredata} % \end{table} %\end{LaTeXdemo} % %\subsection{Using units such as \si{\micro\metre\per\second} in % headings} % % The \pkg{siunitx} code is designed to work correctly with functions % in headings. They will print correctly in headings and in the table % of contents. As illustrated here, the standard behaviour is to ignore % font changes. When the \pkg{hyperref} package is loaded, the % functions automatically \enquote{degrade gracefully} to produce % useful information in PDF bookmarks. If you want more control over % the bookmark text, use the \cs{texorpdfstring} function from % \pkg{hyperref}, for example: %\begin{LaTeXdemo}[code only] % \section{Some text % \texorpdfstring % {\si{\joule\per\mole\per\kelvin}} % {J mol-1 K-1}% % } %\end{LaTeXdemo} % %\subsection{Symbols and \texorpdfstring{\XeTeX}{XeTeX}} % % A small number of non-Latin symbols are needed by \pkg{siunitx}, % notably \SIUnitSymbolOhm\ and \SIUnitSymbolMicro. The package picks % glyphs for these which are correct in the sense that they are upright % (not italic) symbols, and match the \LaTeX\ standard Computer Modern % font. However, this does not make them the best choice if other % fonts are in use, which is particularly common when \XeTeX\ is % being used. % % \XeTeX\ users will probably need to choose appropriate symbols % themselves. The correct choice depends on the fonts in use, but many % system fonts include Greek letters and other symbols (which is not % the case with most \TeX-specific fonts). An appropriate setting % could then be to use the text \SIUnitSymbolMicro\ symbol in all % cases: %^^A This document cannot be UTF-8, as it has to work correctly with %^^A PDFLaTeX. So there is a bit of work to do here to get the right %^^A output. %\begin{flushleft} % \ttfamily % \textbackslash \textcolor{blue}{sisetup}\{\\ % \ \ maths-micro = \textbackslash % \textcolor{blue}{text}\{\SIUnitSymbolMicro\}, \\ % \ \ text-micro \ = \SIUnitSymbolMicro \\ % \} %\end{flushleft} % %\subsection{Scaled document fonts with \texorpdfstring{\XeTeX}{XeTeX}} % % The \pkg{fontspec} package makes it possible to scale the document % body font. This can lead to unexpected problems with printing % for \pkg{siunitx}, as some symbols will not scale while numbers % and text will. The problem is best avoided by forcing \pkg{siunitx} % to use the default maths font for all output: %\begin{LaTeXdemo}[code only] % \sisetup{ % mode = maths, % maths-rm = \ensuremath % } %\end{LaTeXdemo} % This will cause all \pkg{siunitx} output \emph{not} to scale at all, % consistent with other mathematical content. % %\subsection{Maximising performance} % % Both the number and unit parsers require significant effort in % terms of \TeX\ programming. For input that does not require % such processing, the maximum performance for \pkg{siunitx} can % therefore be obtained by turning off both systems: %\begin{LaTeXdemo} % \SI{7.3}{\Hz} \\ % \SI[parse-units = false]{7.3}{\Hz} \\ % \SI[ % parse-numbers = false, % parse-units = false % ]{7.3}{\Hz} %\end{LaTeXdemo} % %\section{Correct application of (SI) units} % % Consistent and logical units are a necessity for scientific work, % and have applicability everywhere. Historically, a number of % systems have been used for physical units. SI units were % introduced by the \emph{Conf{\'e}rence G{\'e}n{\'e}rale des Poids et % Mesures} (CGPM) in 1960. SI units are a coherent system based on % seven base units, from which all other units may be derived. % % At the same time, physical quantities with units are mathematical % entities, and as such way that they are typeset is important. In % mathematics, changes of type (such as using bold, italic, sans % serif typeface and so on) convey information. This means that % rules exist not only for the type of units to be used under the SI % system, but also the way they should appear in print. Advice on % best practice has been made available by the \emph{National % Institute of Standards and Technology} (NIST) \cite{NIST}. % % As befits an agreed international standard, the full rules are % detailed. It is not appropriate to reproduce these in totality % here; instead, a useful summary of the key points is provided. The % full details are available from the \emph{Bureau International des % Poids et Mesures} \cite{BIPM}. % % \pkg{siunitx} takes account of the information given here, so far as % is possible. Thus the package defaults follow the recommendations % made for typesetting units and values. Spacing and so forth is % handled in such a way as to make implementing the rules % (relatively) easy. % %\subsection{Units} % % There are seven base SI units, listed in \cref{tab:unit:base}. % Apart from the kilogram, these are defined in terms of a measurable % physical quantity needing the definition alone.\footnote{Some base % units need others defined first; there is therefore a required % order of definition.} The base units have been chosen such that % all physical quantities can be expressed using an appropriative % combination of these units, needing no others and with no % redundancy. The kilogram is slightly different from the other base % units as it is still defined in terms of a \enquote{prototype} held in % Paris. % % All other units within the SI system are regarded as \enquote{derived} % from the seven base units. At the most basic, all other SI units % can be expressed as combinations of the base units. However, many % units (listed in \cref{tab:unit:derived,tab:unit:accepted}) have a % special name and symbol. Most of these units are simple combinations % of one or more base units (raised to powers as appropriate). A small % number of units derived from experimental data are allowed as SI % units (\cref{tab:unit:physical}). % % A series of SI prefixes for decimal multiples and sub-multiples are % provided, and can be used as modifiers for any SI unit (either base % or derived units) with the exception of the kilogram. The prefixes % are listed in \cref{tab:unit:prefix}. No space should be used % between a prefix and the unit, and only a single prefix should be % used. Even the degree Celsius can be given a prefix, for example % \SI{1}{\milli\degreeCelsius}. % % It is important to note that the kilogram is the only SI unit with % a prefix as part of its name and symbol. Only single prefix may % be used, and so in the case of the kilogram prefix names are used % with the unit name \enquote{gram} and the prefix symbols are used with % the unit symbol \si{\gram}. For example \( \SI{1e-6}{\kilo\gram} = % \SI{1}{\milli\gram} \). % % The application of SI units is meant to provide a single set of % units which ensure consistency and clarity across all areas. % However, other units are common is many areas, and are not without % merit. The units provided by \pkg{siunitx} by default do not included % any of these; only units which are part of the SI set or are % accepted for use with SI units are defined. However, several other % sets of units can be loaded as optional modules. The binary % prefixes and units (\cref{tab:unit:binary}) are the most obvious % example. These are \emph{not} part of the SI specifications, but the % prefix names are derived from those in \cref{tab:unit:prefix}. % % Other units are normally to be avoided where possible. SI units % should, in the main, be preferred due to the advantages of clear % definition and self-consistency this brings. However, there will % probably always be a place for specialist or non-standard units. % This is particularly true of units derived from basic physical % constants. % % There are also many areas where non-standard units are used so % commonly that to do otherwise is difficult or impossible. For % example, most synthetic chemists measure the pressure inside vacuum % apparatus in \si{\mmHg}, partly because the most common gauge for % the task still uses a column of mercury metal. For these reasons, % \pkg{siunitxx} does define non-SI units. % %\subsection{Mathematical meaning} % % As explained earlier, a number--unit combination is a single % mathematical entity. This has implications for how both the number % and the unit should be printed. Firstly, the two parts should not % be separated. With the exception of the symbols for plane angles % (\si{\degree}, \si{\arcminute} and \si{\arcsecond}), it is usual to % have a space between the unit and the value. This should therefore % be a non-breaking space between the two. %\begin{LaTeXdemo} % A space for \SI{10}{\percent}\\ % and also for \SI{100}{\degreeCelsius}\\ % but not for \ang{1.23}. %\end{LaTeXdemo} % % The mathematical meaning of units also means that the shape, weight % and family are important. Units are supposed to be typeset in an % upright, medium weight serif font. Italic, bold and sans serif are % all used mathematically to convey other meanings. The \pkg{siunitx} % package defaults again follow this convention: any local settings are % ignored, and uses the current upright serif maths font. However, % there are occasions where this may not be the most desirable % behaviour. A classic example would be in an all-bold section % heading. As the surrounding text is bold, some people feel that % any units should follow this. %\begin{LaTeXdemo} % Units should \textbf{not be bold: \SI{54}{\farad}}\\ % \textbf{But perhaps in a running block,\\ % it might look better: \SI[detect-weight]{54}{\farad}} %\end{LaTeXdemo} % % Symbols for units formed from other units by multiplication are % indicated by means of either a half-height (that is, centred) dot % or a (thin) space. %\begin{LaTeXdemo} % \( \si{\metre\second} = \text{metre second} \) \\ % \( \si{\milli\second} = \text{millisecond} \) \\ % \sisetup{inter-unit-separator = { } \cdot { } } % \( \si{\metre\second} = \text{metre second} \) \\ % \( \si{\milli\second} = \text{millisecond} \) %\end{LaTeXdemo} % There are some circumstances under which it is permissible to omit % any spaces. The classic example is \si{\kWh}, where % \enquote{\si[inter-unit-separator = \,]{\kWh}} does not add any % useful information. If using such a unit repeatedly, users of % \pkg{siuntx} are advised to create a custom unit to ensure % consistency. % % Symbols for units formed from other units by division are indicated % by means of a virgule (oblique stroke, slash, |/|), a horizontal % line, or negative exponents.\footnote{Notice that a virgule and a % solidus are not the same symbol.} However, to avoid ambiguity, the % virgule must not be repeated on the same line unless parentheses % are used. This is ensured when using named unit macros in % \pkg{siunitx}, which will \enquote{trap} repeated division and format % it correctly. In complicated cases, negative exponents are to be % preferred over other formats. %\begin{LaTeXdemo} % \si{\joule\per\mole\per\kelvin}\\ % \si[per-mode = fraction]{\joule\per\mole\per\kelvin}\\ % \si[per-mode = symbol]{\joule\per\mole\per\kelvin} %\end{LaTeXdemo} % % Products and errors should show what unit applies to each value % given. Thus \SI{2x3}{\metre} is an ordered set of lengths of a % geometric area, whereas \SI[repeat-units=false,use-brackets = false] % {2x3}{\metre} is a length (and equal to \SI{6}{\metre}). Thus, % \(\times\) is not a product but is a mathematical operator; in the % same way, a \(2 \times 3\) matrix is not a \(6\) matrix! In some % areas, areas and volumes are given with separated units but a unit % raised to the appropriate power: % \SI[repeat-units = false,unit-product-to-power,use-brackets = false] % {2 x 3}{\metre}. Although this does display the correct overall % units, it is potentially-confusing and is not encouraged. % % Care must be taken when writing ranges of numbers. For purely % numerical values, it is common to use a en-dash between values, for % example \enquote{see pages 1--5}. On the other hand, values with % units could be misinterpret as negative values if written in this % way. As the unit--value combination is a single mathematical entity, % writing the values with an en-dash followed by a single unit is also % incorrect. As a result, using the word \enquote{to} is strongly % recommended. %\begin{LaTeXdemo} % \SIrange{1}{5}{\metre} long. %\end{LaTeXdemo} % %\subsection{Graphs and tables} % % In graphs and tables, repetition of the units following each entry % or axis mark is confusing and repetitive. It is therefore best to % place the unit in the label part of the information. Placing the % unit in square brackets is common but mathematically % poor.\footnote{For example, for an acceleration \(a\), the expression % \([a]\) is the dimensions of \(a\), \emph{i.e.}~length per time % squared in this case.} Much better is to show division of all % values by the unit, which leaves the entries as unitless ratios. % This is illustrated in \cref{tab:xmpl:unitless} and % \cref{fig:xmpl:unitless}. %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{An example of table labelling.} % \label{tab:xmpl:unitless} % \sisetup{ % table-align-numbers = centre, % table-figures-integer = 1, % table-figures-decimal = 4 % } % \begin{tabular}{cS} % \toprule % Entry & {Length/\si{\metre}} \\ % \midrule % 1 & 1.1234 \\ % 2 & 1.1425 \\ % 3 & 1.7578 \\ % 4 & 1.9560 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} %\begin{LaTeXdemo}[code and float] % \begin{figure} % \centering % \begin{tikzpicture} % \begin{axis}[ % xlabel = \( t/\si{\second} \), % xmax = 6, % xmin = 0, % ylabel = \( d/\si{\metre} \), % ymin = 0 % ] % \addplot[smooth,mark=*] % plot coordinates { % (0,0) % (1,5) % (2,8) % (3,9) % (4,8) % (5,5) % (6,0) % }; % \end{axis} % \end{tikzpicture} % \caption{An example of graph labelling.} % \label{fig:xmpl:unitless} % \end{figure} %\end{LaTeXdemo} % % In most cases, adding exponent values in the body of a table is % less desirable than adding a fixed exponent to column headers. An % example is shown in \cref{tab:good}. The use of \cs{multicolumn} is % needed here due to the ``|<|''; without \cs{multicolumn}, the % titles are followed by ``\si{\kilo\gram}''! %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{Good and bad columns.} % \label{tab:good} % \sisetup{table-align-numbers = centre} % \begin{tabular}{ % c % S[ % table-figures-integer = 1, % table-figures-decimal = 3, % table-figures-exponent = 1 % ] % @{\,\si{\kilogram}} % S[ % table-figures-integer = 2, % table-figures-decimal = 2 % ] % } % \toprule % Entry & \multicolumn{1}{c}{Mass} & % {Mass/\SI{e3}{\kilogram}} \\ % \midrule % 1 & 4.56e3 & 4.56 \\ % 2 & 2.40e3 & 2.40 \\ % 3 & 1.345e4 & 13.45 \\ % 4 & 4.5e2 & 0.45 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\section{Thanks} % % Many users have provided feedback, bug reports and ideas for new % features for \pkg{siunitx}: thanks to all of them. Particular thanks % to Stefan Pinnow, who has taken the lead role as beta tester for % \pkg{siunitx}, finding incorrect output, bad documentation and the % odd spelling mistake in the documentation. Thanks also to % Danie Els and Marcel Heldoorn for the \pkg{SIstyle} and \pkg{SIunits} % packages, respectively, which provided the starting point for the % development of \pkg{siunitx}. % %\end{documentation} % %\begin{implementation} % %\section{Implementation} % % \begin{macrocode} %<*package> % \end{macrocode} % %\subsection{Preliminaries} % % The usual preliminaries. % \begin{macrocode} \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 , etex , l3keys2e } % \end{macrocode} % %\begin{macro}{\siunitx_tmp:w} %\begin{macro}{\l_siunitx_tmp_bool} %\begin{macro}{\l_siunitx_tmp_box} %\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 \box_new:N \l_siunitx_tmp_box \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} %\end{macro} % %\begin{macro}{\l_siunitx_error_bool} %\begin{macro}{\siunitx_error:nxx} %\begin{macro}{\siunitx_error:nx} %\begin{macro}{\siunitx_error:n} %\begin{macro}{\siunitx_error:nV} % 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} { } { } } \cs_generate_variant:Nn \siunitx_error:nx { nV } % \end{macrocode} %\end{macro} %\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_replace_all_in:NnV} % Variants needed which are not in \pkg{expl3}. % \begin{macrocode} \cs_generate_variant:Nn \tl_replace_all_in:Nnn { NnV } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_cs_if_tl:NT} %\begin{macro}{\siunitx_cs_if_tl:NTF} %\begin{macro}[aux]{\siunitx_cs_if_tl_aux:w} %\begin{macro}{\siunitx_cs_if_macro:NT} % This is basically a re-hash of stuff from \pkg{expl3}, but to test for % short macros only. The second test (with the \cs{cs_to_str:N} part) % is checking for \LaTeXe\ robust commands. % \begin{macrocode} \group_begin: \tl_map_inline:nn { \M \A \C \R \O } { \char_make_other:n { `#1 } } \tl_map_inline:nn { \F \N \T } { \char_set_lccode:nn { `#1 } { `#1 } } \tl_to_lowercase:n { \group_end: \prg_new_conditional:Nnn \siunitx_cs_if_tl:N { T , TF } { \exp_after:wN \siunitx_cs_if_tl_aux:w \token_to_meaning:N #1 MACRO \q_nil { \cs_if_exist:cTF { \cs_to_str:N #1 ~ } { \prg_return_false: } { \prg_return_true: } } { \prg_return_false: } } \cs_new_nopar:Npn \siunitx_cs_if_tl_aux:w #1 MACRO #2 \q_nil { \tl_if_empty:nTF {#1} } \prg_new_conditional:Nnn \siunitx_cs_if_macro:N { T } { \exp_after:wN \siunitx_cs_if_tl_aux:w \token_to_meaning:N #1 MACRO \q_nil { \prg_return_true: } { \prg_return_false: } } } % \end{macrocode} %\end{macro} %\end{macro} %\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_siunitx_tmp_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_weight_tl} % Used by the keys, but needs to be created here. % \begin{macrocode} \tl_new:N \l_siunitx_detect_inline_weight_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_detect_display_maths_bool} %\begin{macro}{\l_siunitx_detect_family_bool} %\begin{macro}{\l_siunitx_detect_inline_weight_bool} %\begin{macro}{\l_siunitx_detect_italic_bool} %\begin{macro}{\l_siunitx_detect_mode_bool} %\begin{macro}{\l_siunitx_detect_weight_bool} % Font detection is all about creating switches, with just a little % gloss for \texttt{detect-all} and \texttt{detect-none}. % \begin{macrocode} \keys_define:nn { siunitx } { detect-all .choice:, detect-all .default:n = true, detect-all / false .meta:n = { detect-family = false, detect-italic = false, detect-mode = false, detect-weight = false }, detect-all / true .meta:n = { detect-family = true, detect-italic = true, detect-mode = true, detect-weight = false }, 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-weight .choice:, detect-inline-weight .value_required:, detect-inline-weight / combined .code:n = { \tl_set:Nn \l_siunitx_detect_inline_weight_tl { combined } }, detect-inline-weight / math .code:n = { \tl_set:Nn \l_siunitx_detect_inline_weight_tl { maths } }, detect-inline-weight / maths .code:n = { \tl_set:Nn \l_siunitx_detect_inline_weight_tl { maths } }, detect-inline-weight / text .code:n = { \tl_set:Nn \l_siunitx_detect_inline_weight_tl { text } }, 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-family = true, detect-italic = true, detect-mode = true, detect-weight = true }, detect-none / true .meta:n = { detect-family = false, detect-italic = false, detect-mode = false, detect-weight = false }, detect-weight .bool_set:N = \l_siunitx_detect_weight_bool } % \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_italic:} %\begin{macro}{\siunitx_font_weight:} % These could be token lists or functions! % \begin{macrocode} \cs_new_nopar:Npn \siunitx_font_italic: { } \cs_new_nopar:Npn \siunitx_font_weight: { } % \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_weight_bool { \siunitx_detect_font_weight: } \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_weight: { \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_weight:} % The font weight 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_weight: { \mode_if_math:TF { \mode_if_inner:TF { \use:c { siunitx_detect_font_weight_ \l_siunitx_detect_inline_weight_tl : } } { \bool_if:NTF \l_siunitx_detect_display_maths_bool { \siunitx_detect_font_weight_maths: } { \siunitx_detect_font_weight_text: } } } { \siunitx_detect_font_weight_text: } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_detect_font_weight_combined:} %\begin{macro}{\siunitx_detect_font_weight_maths:} %\begin{macro}{\siunitx_detect_font_weight_text:} % The tests for font weight depend on whether the module is testing % text or maths content. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_detect_font_weight_combined: { \siunitx_detect_font_weight_maths: \siunitx_detect_font_weight_text: } \cs_new_nopar:Npn \siunitx_detect_font_weight_maths: { \tl_if_eq:nVT { bold } \math@version { \cs_set:Npn \siunitx_font_weight: { \boldmath \bfseries } } \tl_if_eq:nVT { light } \math@version { \cs_set:Npn \siunitx_font_weight: { \lseries } } } \cs_new_nopar:Npn \siunitx_detect_font_weight_text: { \tl_set:Nx \l_siunitx_tmpa_tl { \exp_args:NV \tl_head_i:n \f@series } \tl_if_eq:nVT { b } \l_siunitx_tmpa_tl { \cs_set:Npn \siunitx_font_weight: { \boldmath \bfseries } } \tl_if_eq:nVT { l } \l_siunitx_tmpa_tl { \cs_set:Npn \siunitx_font_weight: { \lseries } } } % \end{macrocode} %\end{macro} %\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 { \fam = \c_siunitx_mathsf_int } { \tl_set:Nn \l_siunitx_font_family_tl { sf } } \intexpr_compare:nT { \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:n} %\begin{macro}{\siunitx_number_mathsf:n} %\begin{macro}{\siunitx_number_mathtt:n} %\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:Npn \siunitx_number_mathrm:n #1 { } \cs_new:Npn \siunitx_number_mathsf:n #1 { } \cs_new:Npn \siunitx_number_mathtt:n #1 { } \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:n ##1 { #1 {##1} } }, number-maths-rm .code:n = { \cs_set_nopar:Npn \siunitx_number_mathrm:n ##1 { #1 {##1} } }, number-math-sf .code:n = { \cs_set_nopar:Npn \siunitx_number_mathsf:n ##1 { #1 {##1} } }, number-maths-sf .code:n = { \cs_set_nopar:Npn \siunitx_number_mathsf:n ##1 { #1 {##1} } }, number-math-tt .code:n = { \cs_set_nopar:Npn \siunitx_number_mathtt:n ##1 { #1 {##1} } }, number-maths-tt .code:n = { \cs_set_nopar:Npn \siunitx_number_mathtt:n ##1 { #1 {##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} % %\begin{macro}{\siunitx_detect_default_family:} % Some packages (for example \pkg{cmbright}) and classes % (for example \pkg{beamer}) set the default family to be something % other than serif family. A one-off detection will make life easier % all round. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_detect_default_family: { \tl_set:Nx \l_siunitx_tmpa_tl { \familydefault } \tl_if_eq:NNT \l_siunitx_tmpa_tl \c_siunitx_textsf_tl { \keys_set:nn { siunitx } { maths-rm = \mathsf, text-rm = \sffamily } } \tl_if_eq:NNT \l_siunitx_tmpa_tl \c_siunitx_texttt_tl { \keys_set:nn { siunitx } { maths-rm = \mathtt, text-rm = \ttfamily } } } \AtBeginDocument { \siunitx_detect_default_family: } % \end{macrocode} %\end{macro} % %\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_weight: \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 \! \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 :n } { \l_siunitx_print_arg_tl } } } \cs_new_nopar:Npn \siunitx_print_text: { \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 } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_print_text_sub:n} %\begin{macro}[aux]{\siunitx_print_text_sub_super: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. The search and replace % code for superscripts deals with the case where a literal number has % been given with text mode printing. % \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 { \cs_set:Npn \siunitx_print_text_sub_super:n ##1 { \ensuremath { @ { \text {#1} } ^ { \text {##1} } } } \peek_meaning_remove:NTF \siunitx_print_text_super:n { \siunitx_print_text_sub_super:n } { \ensuremath { @ { \text {#1} } } } } } \cs_new:Npn \siunitx_print_text_sub_super:n { } \cs_new:Npn \siunitx_print_text_super:n #1 { \tl_set:Nn \l_siunitx_tmpa_tl {#1} \tl_replace_all_in:Nnn \l_siunitx_tmpa_tl { - } { \c_siunitx_minus_tl } \tl_set:Nx \l_siunitx_tmpa_tl { \exp_not:N \ensuremath { ^ { \exp_not:N \text { \exp_not:V \l_siunitx_tmpa_tl } } } } \l_siunitx_tmpa_tl } % \end{macrocode} %\end{macro} %\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 parser is designed to be relativity fast, which means some code is % more or less duplicated to gain more speed. It is also loaded so % that simple numbers (such as \num{-1.23}) are parsed particularly % quickly. For most documents, this gain more than offsets any slight % losses with more complicated numbers. % %\begin{macro}{\c_siunitx_number_part_complex_tl} % A couple of the comparisons needed for checking complex numbers % are done using stored text. To make them a little quicker, a % pre-stored version of the text is stored here. % \begin{macrocode} \tl_new:Nn \c_siunitx_number_part_complex_tl { complex } % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_number_in_complex_bool} %\begin{macro}{\l_siunitx_number_in_complex_root_bool} %\begin{macro}{\l_siunitx_number_in_decimal_bool} %\begin{macro}{\l_siunitx_number_in_exponent_bool} %\begin{macro}{\l_siunitx_number_in_first_bool} %\begin{macro}{\l_siunitx_number_in_sign_bool} %\begin{macro}{\l_siunitx_number_in_uncert_bool} %\begin{macro}{\l_siunitx_number_in_value_bool} % \begin{macrocode} \bool_new:N \l_siunitx_number_in_complex_bool \bool_new:N \l_siunitx_number_in_complex_root_bool \bool_new:N \l_siunitx_number_in_decimal_bool \bool_new:N \l_siunitx_number_in_exponent_bool \bool_new:N \l_siunitx_number_in_first_bool \bool_new:N \l_siunitx_number_in_sign_bool \bool_new:N \l_siunitx_number_in_uncert_bool \bool_new:N \l_siunitx_number_in_value_bool % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_number_in_prop} % The parsed number is stored in a property list as its constituent % parts. % \begin{macrocode} \prop_new:N \l_siunitx_number_in_prop % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_number_parsed_tl} % Each part of the number parsed has to be built up in a token list. % \begin{macrocode} \tl_new:N \l_siunitx_number_parsed_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_number_part_tl} %\begin{macro}{\l_siunitx_number_part_decimal_tl} %\begin{macro}{\l_siunitx_number_part_decimal_marker_tl} %\begin{macro}{\l_siunitx_number_part_integer_tl} %\begin{macro}{\l_siunitx_number_part_sign_tl} %\begin{macro}{\l_siunitx_number_part_uncert_tl} % The names of various parts of a number are set up as stored values. % This lets some code be used for different parts of a number, while % pre-storing everything brings a performance (and clarity) benefit. % \begin{macrocode} \tl_new:N \l_siunitx_number_part_tl \tl_new:N \l_siunitx_number_part_decimal_tl \tl_new:N \l_siunitx_number_part_decimal_marker_tl \tl_new:N \l_siunitx_number_part_integer_tl \tl_new:N \l_siunitx_number_part_sign_tl \tl_new:N \l_siunitx_number_part_uncert_tl % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\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} %\begin{macro}[aux]{\siunitx_number_in_parse_aux:n} % The parsing routine starts by replacing any formatting in the input % using \cs{tl_set_rescan:Nnx}. Next, there is a quick routine to % ensure that all signs are single tokens. The main loop then takes % place, which will parse the input into the property list and also % set up the flags. There are then some checks and possible corrections. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_parse:n #1 { \siunitx_number_in_init: \tl_if_empty:nF {#1} { \siunitx_number_in_parse_aux:n {#1} } } \cs_generate_variant:Nn \siunitx_number_in_parse:n { V } \cs_new:Npn \siunitx_number_in_parse_aux:n #1 { \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} \siunitx_number_in_sign_replace:N \l_siunitx_number_arg_tl \tl_map_function:NN \l_siunitx_number_arg_tl \siunitx_number_in_parse_loop:N \tl_if_empty:NF \l_siunitx_number_parsed_tl { \bool_if:NTF \l_siunitx_number_in_uncert_bool { \siunitx_error:nx { invalid-number } {#1} } { \prop_put:NVn \l_siunitx_number_in_prop \l_siunitx_number_part_tl { true } \bool_if:NTF \l_siunitx_number_in_decimal_bool { \prop_put:NVV \l_siunitx_number_in_prop \l_siunitx_number_part_decimal_tl \l_siunitx_number_parsed_tl } { \prop_put:NVV \l_siunitx_number_in_prop \l_siunitx_number_part_integer_tl \l_siunitx_number_parsed_tl } } } \siunitx_number_in_check:n {#1} } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_init:} %\begin{macro}{\siunitx_number_in_init_part:n} % The set up code is divided into to parts. First, code only needed % once to start the entire parser. Then a second group, which is % carried out at the start of each part of a number, and so is called % from a few places. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_init: { \cs_set_eq:NN \siunitx_number_in_parse_loop:N \siunitx_number_in_parse_mantissa:N \cs_set_eq:NN \siunitx_number_in_parse_more:N \siunitx_number_in_parse_mantissa_aux:N \cs_set_eq:NN \siunitx_number_in_check:n \siunitx_number_in_check_short:n \tl_clear:N \l_siunitx_number_parsed_tl \prop_clear:N \l_siunitx_number_in_prop \bool_set_false:N \l_siunitx_error_bool \bool_set_false:N \l_siunitx_number_in_complex_bool \bool_set_false:N \l_siunitx_number_in_complex_root_bool \bool_set_false:N \l_siunitx_number_in_exponent_bool \bool_set_false:N \l_siunitx_number_in_uncert_bool \siunitx_number_in_init_part:n { mantissa } } \cs_new_nopar:Npn \siunitx_number_in_init_part:n #1 { \bool_set_false:N \l_siunitx_number_in_decimal_bool \bool_set_true:N \l_siunitx_number_in_first_bool \bool_set_false:N \l_siunitx_number_in_sign_bool \bool_set_false:N \l_siunitx_number_in_value_bool \tl_set:Nn \l_siunitx_number_part_tl {#1} \tl_set:Nn \l_siunitx_number_part_decimal_tl { #1 -decimal } \tl_set:Nn \l_siunitx_number_part_decimal_marker_tl { #1 -decimal-marker } \tl_set:Nn \l_siunitx_number_part_integer_tl { #1 -integer } \tl_set:Nn \l_siunitx_number_part_sign_tl { #1 -sign } \tl_set:Nn \l_siunitx_number_part_uncert_tl { #1 -uncertainty } } % \end{macrocode} %\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_sign_replace:N} % A short spin-out to keep the replacement of tokens clear. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_sign_replace:N #1 { \tl_replace_all_in:Nnn #1 { -+ } { \mp } \tl_replace_all_in:Nnn #1 { +- } { \pm } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_in_parse_error:nx} %\begin{macro}{\siunitx_number_in_parse_error:nV} % There are lots of rather similar errors in the parser, all of which % require a \cs{tl_map_break:}. To keep life simple, this is set up % here. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_parse_error:nx #1#2 { \siunitx_error:nx {#1} {#2} \tl_map_break: } \cs_generate_variant:Nn \siunitx_number_in_parse_error:nx { nV } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_parse_loop:N} %\begin{macro}{\siunitx_number_in_parse_more:N} % The main loop is set up as a place holder, as the definition is % varied to keep things fast. There is also a place holder for the % extended routing for normal mantissas. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_parse_loop:N #1 { } \cs_new:Npn \siunitx_number_in_parse_more:N #1 { } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_parse_angle:N} % When parsing numbers for the \cs{ang} function, no extended input % is permitted at all. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_parse_angle:N #1 { \tl_if_in:NnTF \l_siunitx_input_exponent_tl {#1} { \siunitx_number_in_parse_error:nx { invalid-token-in-angle } {#1} } { \tl_if_in:NnTF \l_siunitx_input_uncert_open_tl {#1} { \siunitx_number_in_parse_error:nV { invalid-token-in-angle } \l_siunitx_number_arg_tl } { \tl_if_in:NnTF \l_siunitx_input_uncert_close_tl {#1} { \siunitx_number_in_parse_error:nV { invalid-token-in-angle } \l_siunitx_number_arg_tl } { \tl_if_in:NnTF \l_siunitx_input_complex_tl {#1} { \siunitx_number_in_parse_error:nV { invalid-token-in-angle } \l_siunitx_number_arg_tl } { \siunitx_number_in_parse_error:nx { invalid-token-in-number } {#1} } } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_in_parse_complex:N} % After a complex root when the root is \emph{after} the number, there % are a very limited range of legitimate tokens. Thus most cases can be % trapped with a modified parser. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_parse_complex:N #1 { \tl_if_in:NnTF \l_siunitx_input_exponent_tl {#1} { \cs_set_eq:NN \siunitx_number_in_parse_loop:N \siunitx_number_in_parse_mantissa:N \siunitx_number_in_exponent:N #1 } { \tl_if_in:NnF \l_siunitx_input_ignore_tl {#1} { \siunitx_number_in_parse_error:nV { misplaced-complex-root-token } \l_siunitx_number_arg_tl } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_in_parse_exponent:N} % When processing an exponent, the \enquote{extended} part of the % number which is valid in a mantissa is no longer needed. So the % auxiliary function is pointed to a series of errors instead. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_parse_exponent:N #1 { \tl_if_in:NnTF \l_siunitx_input_exponent_tl {#1} { \siunitx_number_in_parse_error:nx { duplicate-exponent-token } {#1} } { \tl_if_in:NnTF \l_siunitx_input_uncert_open_tl {#1} { \siunitx_number_in_parse_error:nV { invalid-token-in-exponent } \l_siunitx_number_arg_tl } { \tl_if_in:NnTF \l_siunitx_input_uncert_close_tl {#1} { \siunitx_number_in_parse_error:nV { invalid-token-in-exponent } \l_siunitx_number_arg_tl } { \tl_if_in:NnTF \l_siunitx_input_complex_tl {#1} { \siunitx_number_in_parse_error:nV { invalid-token-in-exponent } \l_siunitx_number_arg_tl } { \siunitx_number_in_parse_error:nx { invalid-token-in-number } {#1} } } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_in_parse_mantissa:N} %\begin{macro}{\siunitx_number_in_parse_mantissa_aux:N} % For the mantissa, most things are valid. The procedure is split % into two parts, with the simple symbols handled here and the more % complex ones in a second part(which needs to be varied). Essentially % everything here is a comparison, done so that the code is a fast as % possible. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_parse_mantissa:N #1 { \tl_if_in:NnTF \l_siunitx_input_digit_tl {#1} { \siunitx_number_in_digit:N #1 } { \tl_if_in:NnTF \l_siunitx_input_decimal_tl {#1} { \siunitx_number_in_decimal:N #1 } { \tl_if_in:NnTF \l_siunitx_input_sign_tl {#1} { \siunitx_number_in_sign:N #1 } { \tl_if_in:NnTF \l_siunitx_input_symbol_tl {#1} { \prop_put:Nnn \l_siunitx_number_in_prop { symbolic } { true } \siunitx_number_in_digit:N #1 } { \tl_if_in:NnF \l_siunitx_input_ignore_tl {#1} { \siunitx_number_in_parse_more:N #1 } } } } } } \cs_new:Npn \siunitx_number_in_parse_mantissa_aux:N #1 { \tl_if_in:NnTF \l_siunitx_input_exponent_tl {#1} { \siunitx_number_in_exponent:N #1 } { \tl_if_in:NnTF \l_siunitx_input_uncert_open_tl {#1} { \siunitx_number_in_uncert_open:N #1 } { \tl_if_in:NnTF \l_siunitx_input_uncert_close_tl {#1} { \siunitx_number_in_parse_error:nx { misplaced-uncertainty-token } {#1} } { \tl_if_in:NnTF \l_siunitx_input_complex_tl {#1} { \siunitx_number_in_complex:N #1 } { \siunitx_number_in_parse_error:nx { invalid-token-in-number } {#1} } } } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_parse_uncert:N} % Within uncertainties, the range of tokens is limited. An alternative % parsing system can therefore be used. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_parse_uncert:N #1 { \tl_if_in:NnTF \l_siunitx_input_digit_tl {#1} { \siunitx_number_in_digit:N #1 } { \tl_if_in:NnTF \l_siunitx_input_decimal_tl {#1} { \siunitx_number_in_parse_error:nV { invalid-token-in-uncertainty } \l_siunitx_number_arg_tl } { \tl_if_in:NnTF \l_siunitx_input_sign_tl {#1} { \siunitx_number_in_parse_error:nV { invalid-token-in-uncertainty } \l_siunitx_number_arg_tl } { \tl_if_in:NnTF \l_siunitx_input_symbol_tl {#1} { \prop_put:Nnn \l_siunitx_number_in_prop { symbolic } { true } \siunitx_number_in_digit:N #1 } { \tl_if_in:NnF \l_siunitx_input_ignore_tl {#1} { \tl_if_in:NnTF \l_siunitx_input_uncert_close_tl {#1} { \siunitx_number_in_uncert_close:N #1 } { \siunitx_number_in_parse_error:nV { invalid-token-in-uncertainty } \l_siunitx_number_arg_tl } } } } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_in_parse_uncert_after:N} % After an uncertainty, there is once again a very limited range of % tokens that can be present in a valid number. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_parse_uncert_after:N #1 { \tl_if_in:NnTF \l_siunitx_input_exponent_tl {#1} { \cs_set_eq:NN \siunitx_number_in_parse_loop:N \siunitx_number_in_parse_mantissa:N \siunitx_number_in_exponent:N #1 } { \tl_if_in:NnTF \l_siunitx_input_sign_tl {#1} { \cs_set_eq:NN \siunitx_number_in_parse_loop:N \siunitx_number_in_parse_mantissa:N \siunitx_number_in_sign:N #1 } { \tl_if_in:NnF \l_siunitx_input_ignore_tl {#1} { \tl_if_in:NnTF \l_siunitx_input_complex_tl {#1} { \cs_set_eq:NN \siunitx_number_in_parse_loop:N \siunitx_number_in_parse_mantissa:N \siunitx_number_in_complex:N #1 } { \siunitx_number_in_parse_error:nV { invalid-number } \l_siunitx_number_arg_tl } } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_in_complex:N} %\begin{macro}[aux]{\siunitx_number_in_complex_aux:nn} % Only one complex root token can be give, hence the initial test. % More tests are needed for complex numbers than other systems, so % the additional ones are turned on, followed by some flag setting. % The complex root is stored, then there is a check to see if the % root is at the end of the number: if it is, prevent any more tokens % being added. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_complex:N #1 { \bool_set_false:N \l_siunitx_number_in_first_bool \bool_if:NTF \l_siunitx_number_in_complex_root_bool { \siunitx_number_in_parse_error:nx { duplicate-complex-root-token } {#1} } { \cs_set_eq:NN \siunitx_number_in_check:n \siunitx_number_in_check_full:n \bool_set_true:N \l_siunitx_number_in_complex_root_bool \prop_put:Nnn \l_siunitx_number_in_prop { complex-root } {#1} \tl_if_empty:NF \l_siunitx_number_parsed_tl { \cs_set_eq:NN \siunitx_number_in_parse_loop:N \siunitx_number_in_parse_complex:N } \bool_if:NT \l_siunitx_number_in_decimal_bool { \bool_if:NF \l_siunitx_number_in_complex_bool { \siunitx_number_in_complex_aux:nn { mantissa-integer } { complex-integer } \siunitx_number_in_complex_aux:nn { mantissa-decimal-marker } { complex-decimal-marker } \prop_del:Nn \l_siunitx_number_in_prop { mantissa } \prop_put:Nnn \l_siunitx_number_in_prop { complex } { true } } } \prop_if_in:NnF \l_siunitx_number_in_prop { mantissa } { \prop_if_in:NnT \l_siunitx_number_in_prop { mantissa-sign } { \siunitx_number_in_complex_aux:nn { mantissa-sign } { complex-sign } } } \bool_set_true:N \l_siunitx_number_in_complex_bool \bool_set_false:N \l_siunitx_number_in_first_bool \siunitx_number_in_init_part:n { complex } \prop_if_in:NnT \l_siunitx_number_in_prop { complex-decimal-marker } { \bool_set_true:N \l_siunitx_number_in_decimal_bool } \prop_if_in:NnT \l_siunitx_number_in_prop { complex-sign } { \bool_set_true:N \l_siunitx_number_in_sign_bool } } } \cs_new_nopar:Npn \siunitx_number_in_complex_aux:nn #1#2 { \prop_if_in:NnT \l_siunitx_number_in_prop {#1} { \prop_get:NnN \l_siunitx_number_in_prop {#1} \l_siunitx_tmpa_tl \prop_del:Nn \l_siunitx_number_in_prop {#1} \prop_put:NnV \l_siunitx_number_in_prop {#2} \l_siunitx_tmpa_tl } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_decimal:N} % Only one decimal marker allowed, so a test for this. If an integer % part has been found, it is saved. The flag for the number being % found is not set unless there is an integer, to watch for the case % of invalid numbers. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_decimal:N #1 { \bool_set_false:N \l_siunitx_number_in_first_bool \bool_if:NTF \l_siunitx_number_in_decimal_bool { \siunitx_number_in_parse_error:nx { duplicate-decimal-token } {#1} } { \bool_set_true:N \l_siunitx_number_in_decimal_bool \tl_if_empty:NF \l_siunitx_number_parsed_tl { \prop_put:NVn \l_siunitx_number_in_prop \l_siunitx_number_part_tl { true } \prop_put:NVV \l_siunitx_number_in_prop \l_siunitx_number_part_integer_tl \l_siunitx_number_parsed_tl \tl_clear:N \l_siunitx_number_parsed_tl } \prop_put:NVn \l_siunitx_number_in_prop \l_siunitx_number_part_decimal_marker_tl {#1} } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_in_digit:N} % For digits, only in an uncertainty can the value be stored % directly. Otherwise, there is a need to see if the value is non-zero. % This is used to drop leading zeros and to validate any sign (as zero % is unsigned). % \begin{macrocode} \cs_new:Npn \siunitx_number_in_digit:N #1 { \bool_set_false:N \l_siunitx_number_in_first_bool \bool_if:NTF \l_siunitx_number_in_uncert_bool { \tl_put_right:Nn \l_siunitx_number_parsed_tl {#1} } { \bool_if:NTF \l_siunitx_number_in_decimal_bool { \tl_put_right:Nn \l_siunitx_number_parsed_tl {#1} \tl_if_eq:nnF {#1} { 0 } { \bool_set_true:N \l_siunitx_number_in_value_bool } } { \tl_if_eq:nnTF {#1} { 0 } { \prop_put:NVn \l_siunitx_number_in_prop \l_siunitx_number_part_tl { true } \prop_put:NVn \l_siunitx_number_in_prop \l_siunitx_number_part_integer_tl { 0 } } { \bool_set_true:N \l_siunitx_number_in_value_bool } \bool_if:NT \l_siunitx_number_in_value_bool { \tl_put_right:Nn \l_siunitx_number_parsed_tl {#1} } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_in_exponent:N} % A duplicate token test starts off the code, which if passed % leads to some simple storage manipulation. As exponents are % more simple than the mantissa, the extra processing is swapped for % some that only raises errors. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_exponent:N #1 { \bool_if:NTF \l_siunitx_number_in_exponent_bool { \siunitx_number_in_parse_error:nx { duplicate-exponent-token } {#1} } { \cs_set_eq:NN \siunitx_number_in_parse_more:N \siunitx_number_in_parse_exponent:N \tl_if_empty:NF \l_siunitx_number_parsed_tl { \siunitx_number_in_store: } \bool_set_true:N \l_siunitx_number_in_exponent_bool \siunitx_number_in_init_part:n { exponent } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_in_sign:N} % The code for signs is complicated by complex numbers. A sign token % must be the fist thing in a number, but after the real part of the % mantissa a second sign token can appear to start a complex number. % So most of the code here is to detect that case. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_sign:N #1 { \bool_if:NTF \l_siunitx_number_in_first_bool { \bool_set_false:N \l_siunitx_number_in_first_bool \bool_set_true:N \l_siunitx_number_in_sign_bool \prop_put:NVn \l_siunitx_number_in_prop \l_siunitx_number_part_sign_tl {#1} } { \bool_if:NTF \l_siunitx_number_in_exponent_bool { \siunitx_number_in_parse_error:nx { misplaced-sign-token } {#1} } { \bool_if:NTF \l_siunitx_number_in_complex_bool { \siunitx_number_in_parse_error:nx { misplaced-sign-token } {#1} } { \tl_if_empty:NF \l_siunitx_number_parsed_tl { \siunitx_number_in_store: } \cs_set_eq:NN \siunitx_number_in_check:n \siunitx_number_in_check_full:n \siunitx_number_in_init_part:n { complex } \prop_put:Nnn \l_siunitx_number_in_prop { complex-sign } {#1} \bool_set_true:N \l_siunitx_number_in_complex_bool } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_in_uncert_open:N} %\begin{macro}{\siunitx_number_in_uncert_close:N} % Opening and closing uncertainty tokens are handled separately. For % opening tokens, a check is made that there is something else to the % number before collecting material up. For the closing token, the % uncertainty must contain some numbers. A special loop function is then % set up to prevent any additional digits after the closing token. % \begin{macrocode} \cs_new:Npn \siunitx_number_in_uncert_open:N #1 { \bool_set_false:N \l_siunitx_number_in_first_bool \cs_set_eq:NN \siunitx_number_in_parse_loop:N \siunitx_number_in_parse_uncert:N \bool_set_true:N \l_siunitx_number_in_uncert_bool \tl_if_empty:NTF \l_siunitx_number_parsed_tl { \prop_if_in:NVF \l_siunitx_number_in_prop \l_siunitx_number_part_integer_tl { \siunitx_number_in_parse_error:nV { invalid-number } \l_siunitx_number_arg_tl } } { \siunitx_number_in_store: } } \cs_new:Npn \siunitx_number_in_uncert_close:N #1 { \bool_set_false:N \l_siunitx_number_in_uncert_bool \tl_if_empty:NTF \l_siunitx_number_parsed_tl { \siunitx_number_in_parse_error:nV { empty-uncertainty } \l_siunitx_number_arg_tl } { \prop_put:NVV \l_siunitx_number_in_prop \l_siunitx_number_part_uncert_tl \l_siunitx_number_parsed_tl \prop_put:Nnn \l_siunitx_number_in_prop { uncertainty } { true } \tl_clear:N \l_siunitx_number_parsed_tl \cs_set_eq:NN \siunitx_number_in_parse_loop:N \siunitx_number_in_parse_uncert_after:N } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_in_store:} % A short auxiliary function needed in various places for storing % either the integer or decimal part of a number, as appropriate. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_store: { \prop_put:NVn \l_siunitx_number_in_prop \l_siunitx_number_part_tl { true } \bool_if:NTF \l_siunitx_number_in_decimal_bool { \prop_put:NVV \l_siunitx_number_in_prop \l_siunitx_number_part_decimal_tl \l_siunitx_number_parsed_tl } { \prop_put:NVV \l_siunitx_number_in_prop \l_siunitx_number_part_integer_tl \l_siunitx_number_parsed_tl } \tl_clear:N \l_siunitx_number_parsed_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_in_check:n} %\begin{macro}{\siunitx_number_in_check_short:n} %\begin{macro}{\siunitx_number_in_check_full:n} % The checks needed for a number depend on whether there is a complex % part. In all cases, there must be some digits, as well as a sign or % decimal marker. There is also a check for a zero-valued input, which % has any sign deleted. For complex numbers, the check is needed in % case there was no real part. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_in_check:n #1 { } \cs_new_nopar:Npn \siunitx_number_in_check_short:n #1 { \prop_if_in:NVF \l_siunitx_number_in_prop \l_siunitx_number_part_integer_tl { \prop_if_in:NVF \l_siunitx_number_in_prop \l_siunitx_number_part_decimal_tl { \siunitx_error:nx { invalid-number } {#1} } } \bool_if:NF \l_siunitx_number_in_value_bool { \tl_if_eq:NNF \l_siunitx_number_part_tl \c_siunitx_number_part_complex_tl { \prop_del:NV \l_siunitx_number_in_prop \l_siunitx_number_part_sign_tl } } } \cs_new_nopar:Npn \siunitx_number_in_check_full:n #1 { \tl_if_eq:NNF \l_siunitx_number_part_tl \c_siunitx_number_part_complex_tl { \siunitx_number_in_check_short:n {#1} } \bool_if:NF \l_siunitx_number_in_complex_root_bool { \prop_get:NnN \l_siunitx_number_in_prop { complex-sign } \l_siunitx_tmpa_tl \siunitx_error:nV { misplaced-sign-token } \l_siunitx_tmpa_tl } \prop_if_in:NnT \l_siunitx_number_in_prop { mantissa-sign } { \prop_if_in:NnF \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 { complex-sign } \l_siunitx_tmpa_tl } } } % \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-decimal-zero .bool_set:N = \l_siunitx_process_decimal_zero_bool, add-integer-zero .bool_set:N = \l_siunitx_process_integer_zero_bool, explicit-sign .tl_set:N = \l_siunitx_process_sign_tl, 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 .int_set:N = \l_siunitx_process_figures_int, round-places .int_set:N = \l_siunitx_process_places_int, } \keys_set:nn { siunitx } { add-decimal-zero = true, add-integer-zero = 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: \prop_if_in:NnF \l_siunitx_number_in_prop { symbolic } { \siunitx_number_process_exponent: \siunitx_number_process_uncertainty: \prop_if_in:NnF \l_siunitx_number_in_prop { uncertainty } { \siunitx_number_process_round: } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_process_exponent:} %\begin{macro}[aux]{\siunitx_number_process_exponent_aux:n} % To check for a totally zero exponent, the possibility that one or more % of the exponent storage areas is zero needs to be considered. % \begin{macrocode} \cs_new_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 } { \bool_set_false:N \l_siunitx_tmp_bool \siunitx_number_process_exponent_aux:n { integer } \bool_if:NF \l_siunitx_tmp_bool { \siunitx_number_process_exponent_aux:n { decimal } } \bool_if:NF \l_siunitx_tmp_bool { \prop_del:Nn \l_siunitx_number_in_prop { exponent } \prop_del:Nn \l_siunitx_number_in_prop { exponent-integer } \prop_del:Nn \l_siunitx_number_in_prop { exponent-decimal } } } } } \cs_new_nopar:Npn \siunitx_number_process_exponent_aux: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 } } } % \end{macrocode} %\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}{\c_siunitx_unity_tl} %\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} \tl_new:Nn \c_siunitx_unity_tl { 1 } \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-integer } { \prop_get:NnN \l_siunitx_number_in_prop { mantissa-integer } \l_siunitx_tmpa_tl \tl_if_eq:NNT \c_siunitx_unity_tl \l_siunitx_tmpa_tl { \prop_if_in:NnF \l_siunitx_number_in_prop { mantissa-decimal-marker } { \prop_del:Nn \l_siunitx_number_in_prop { mantissa } \prop_del:Nn \l_siunitx_number_in_prop { mantissa-integer } } } } } } } % \end{macrocode} %\end{macro} %\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: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 { \cs_set_nopar:Npx \siunitx_tmp:w { \exp_not:N \clist_map_function:nN { mantissa , complex } \exp_not:c { siunitx_number_process_ \l_siunitx_round_tl :n } } \siunitx_tmp:w } } % \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 { \prop_if_in:NnTF \l_siunitx_number_in_prop { mantissa-sign } { \siunitx_number_process_sign_plus:n { mantissa } } { \prop_if_in:NnT \l_siunitx_number_in_prop { complex-sign } { \prop_if_in:NnF \l_siunitx_number_in_prop { mantissa } { \siunitx_number_process_sign_plus:n { complex } } } } \prop_if_in:NnT \l_siunitx_number_in_prop { exponent-sign } { \siunitx_number_process_sign_plus:n { exponent } } } \tl_if_empty:NF \l_siunitx_process_sign_tl { \prop_if_in:NnTF \l_siunitx_number_in_prop { mantissa } { \siunitx_number_process_sign_add:n { mantissa } } { \prop_if_in:NnT \l_siunitx_number_in_prop { complex } { \siunitx_number_process_sign_add:n { complex } } } \prop_if_in:NnT \l_siunitx_number_in_prop { exponent } { \siunitx_number_process_sign_add:n { exponent } } } } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{\siunitx_number_process_sign_add:n} % Adding a sign to an existing number needs a couple of to make sure % there is a number to add to, and to see if there is a sign already. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_process_sign_add:n #1 { \prop_if_in:NnF \l_siunitx_number_in_prop { #1 -sign } { \prop_get:NnN \l_siunitx_number_in_prop {#1} \l_siunitx_tmpa_tl \tl_if_empty:NTF \l_siunitx_tmpa_tl { \prop_put:NnV \l_siunitx_number_in_prop { sign } \l_siunitx_process_sign_tl } { \prop_put:NnV \l_siunitx_number_in_prop { #1 -sign } \l_siunitx_process_sign_tl } } } % \end{macrocode} %\end{macro} %\begin{macro}{\c_siunitx_plus_tl} %\begin{macro}[aux]{\siunitx_number_process_sign_plus:n} % Holding onto a plus works very much in the same way as adding a sign: % some quick tests and an assignment. Using a pre-defined token list is % a speed-related choice: very slightly faster comparison. % \begin{macrocode} \tl_new:Nn \c_siunitx_plus_tl { + } \cs_new_nopar:Npn \siunitx_number_process_sign_plus:n #1 { \prop_get:NnN \l_siunitx_number_in_prop { #1 -sign } \l_siunitx_tmpa_tl \tl_if_eq:NNT \c_siunitx_plus_tl \l_siunitx_tmpa_tl { \prop_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 { mantissa , complex } \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-marker } { \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 \prop_get:NnN \l_siunitx_number_in_prop { #1 -decimal-marker } \l_siunitx_tmpa_tl \prop_put:NnV \l_siunitx_number_in_prop { #1 -uncertainty-decimal-marker } \l_siunitx_tmpa_tl } \cs_new_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. The nesting % here makes checking the appropriate flag a little more efficient. % \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 { complex } {#1} \siunitx_number_process_zero_fill_aux:nn { exponent } {#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-marker } { \prop_if_in:NnF \l_siunitx_number_in_prop { #1 - #2 } { \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_group_sep_tl} %\begin{macro}{\l_siunitx_output_decimal_tl} % A couple of variables are declared here, as they need a little more % work than just storage. % \begin{macrocode} \tl_new:N \l_siunitx_group_sep_tl \tl_new:N \l_siunitx_output_decimal_tl % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_bracket_close_tl} %\begin{macro}{\l_siunitx_complex_after_bool} %\begin{macro}{\l_siunitx_output_decimal_copy_bool} %\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_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_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, complex-root-after-number .bool_set:N = \l_siunitx_complex_after_bool, copy-decimal-marker .bool_set:N = \l_siunitx_output_decimal_copy_bool, exponent-base .tl_set:N = \l_siunitx_exponent_base_tl, exponent-product .tl_set:N = \l_siunitx_exponent_product_tl, group-decimal-digits .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 .code:n = { \tl_set:Nn \l_siunitx_group_sep_tl { {#1} } }, 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 .code:n = { \tl_set:Nn \l_siunitx_output_decimal_tl { {#1} } }, 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 = ), complex-root-after-number = true, copy-decimal-marker = false, exponent-base = 10, exponent-product = \times, group-decimal-digits = true, group-integer-digits = true, group-separator = \,, open-bracket = (, % ) ( output-close-uncertainty = ), output-complex-root = \mathrm { 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:} % The master control function for formatting output: the usual set up. % The number is put back together in stages. % \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_complex: \siunitx_number_format_sign:n { mantissa } \siunitx_number_format_sign:n { exponent } \siunitx_number_format_colour: \siunitx_number_format_final: } } % \end{macrocode} %\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 \tl_if_eq:nnTF {#1} { result } { \prop_put:NnV \l_siunitx_number_out_prop {#1} \l_siunitx_tmpa_tl } { \prop_put:NnV \l_siunitx_number_out_prop { #1 -result } \l_siunitx_tmpa_tl } } % \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:} %\begin{macro}[aux]{\siunitx_number_format_complex_aux:n} % The real and complex parts of each number are reassembled, with % brackets if needed. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_complex: { \prop_if_in:NnT \l_siunitx_number_out_prop { complex } { \siunitx_number_format_brackets:n { complex } \siunitx_number_format_complex_aux:n { complex } \prop_if_in:NnT \l_siunitx_number_out_prop { complex-uncertainty } { \siunitx_number_format_complex_aux:n { complex-uncertainty } } \siunitx_number_format_join_complex: } } \cs_new_nopar:Npn \siunitx_number_format_complex_aux:n #1 { \prop_get:NnN \l_siunitx_number_out_prop {#1} \l_siunitx_tmpa_tl \bool_if:NTF \l_siunitx_complex_after_bool { \siunitx_tl_put_right_maths:NV \l_siunitx_tmpa_tl \l_siunitx_output_complex_tl } { \siunitx_tl_put_left_maths:NV \l_siunitx_tmpa_tl \l_siunitx_output_complex_tl } \prop_put:NnV \l_siunitx_number_out_prop {#1} \l_siunitx_tmpa_tl } % \end{macrocode} %\end{macro} %\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:} % For numbers which do not contain an exponent, the mantissa result is % simply copied to the final output position. On the other hand, for % exponents there are further checks, which are handed off to dedicated % functions. There is also a check for complex numbers with no real % part, which needs to be \enquote{copied} to the standard result % slot. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_final: { \prop_if_in:NnT \l_siunitx_number_out_prop { complex } { \prop_if_in:NnF \l_siunitx_number_out_prop { mantissa-result } { \siunitx_number_format_copy:nn { complex } { mantissa-result } } } \prop_if_in:NnTF \l_siunitx_number_out_prop { exponent } { \siunitx_number_format_final_exponent: \prop_if_in:NnTF \l_siunitx_number_out_prop { mantissa-result } { \siunitx_number_format_final_combined: } { \siunitx_number_format_final_exponent_only: } } { \siunitx_number_format_copy:nn { mantissa-result } { result } } \prop_if_in:NnT \l_siunitx_number_out_prop { mantissa-bracket } { \prop_put:Nnn \l_siunitx_number_out_prop { result-bracket } { true } \prop_del:Nn \l_siunitx_number_out_prop { mantissa-bracket } } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_format_final_combined:} % When there is both a mantissa and an exponent, the mantissa is % combined with the product sign before adding the exponent part on. % The combined result is then stored. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_final_combined: { \siunitx_number_format_brackets:n { mantissa } \prop_get:NnN \l_siunitx_number_out_prop { mantissa-result } \l_siunitx_tmpa_tl \tl_set_eq:NN \l_siunitx_tmpb_tl \l_siunitx_exponent_product_tl \bool_if:NT \l_siunitx_tight_bool { \tl_set:Nx \l_siunitx_tmpb_tl { { \exp_not:V \l_siunitx_tmpb_tl } } } \siunitx_tl_put_right_maths:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl \prop_get:NnN \l_siunitx_number_out_prop { exponent-result } \l_siunitx_tmpb_tl \tl_put_right:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl \prop_put:NnV \l_siunitx_number_out_prop { result } \l_siunitx_tmpa_tl \prop_put:Nnn \l_siunitx_number_out_prop { result-bracket } { true } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_format_final_exponent:} % When there is an exponent, the base always needs to be added to the % front of the number itself. The number must be superscripted, of % course. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_final_exponent: { \prop_get:NnN \l_siunitx_number_out_prop { exponent } \l_siunitx_tmpa_tl \tl_set:Nx \l_siunitx_tmpa_tl { ^ { \exp_not:V \l_siunitx_tmpa_tl } } \tl_put_left:NV \l_siunitx_tmpa_tl \l_siunitx_exponent_base_tl \prop_put:NnV \l_siunitx_number_out_prop { exponent-result } \l_siunitx_tmpa_tl } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_number_format_final_exponent_only:} % When there is only an exponent, a check must be made for a % sign in the mantissa part. If there is one, it is copied across. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_final_exponent_only: { \prop_if_in:NnT \l_siunitx_number_in_prop { mantissa-sign } { \prop_get:NnN \l_siunitx_number_in_prop { mantissa-sign } \l_siunitx_tmpa_tl \bool_if:NT \l_siunitx_tight_bool { \tl_set:Nx \l_siunitx_tmpa_tl { { \exp_not:V \l_siunitx_tmpa_tl } } } \prop_get:NnN \l_siunitx_number_out_prop { exponent-result } \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 { exponent-result } \l_siunitx_tmpb_tl } \siunitx_number_format_copy:nn { exponent-result } { result } } % \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_in_prop { #1 -decimal-marker } { \bool_if:NTF \l_siunitx_output_decimal_copy_bool { \prop_get:NnN \l_siunitx_number_in_prop { #1 -decimal-marker } \l_siunitx_tmpb_tl \tl_set:Nx \l_siunitx_tmpb_tl { { \l_siunitx_tmpb_tl } } } { \tl_set_eq:NN \l_siunitx_tmpb_tl \l_siunitx_output_decimal_tl } \tl_set:Nx \l_siunitx_tmpb_tl { \exp_not:N \ensuremath { \exp_not:V \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 -decimal-marker } \l_siunitx_tmpb_tl \prop_if_in:NnTF \l_siunitx_number_out_prop { #1 -decimal } { \prop_get:NnN \l_siunitx_number_out_prop { #1 -decimal } \l_siunitx_tmpb_tl } { \tl_clear:N \l_siunitx_tmpb_tl } \tl_put_right:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl \prop_put:NnV \l_siunitx_number_out_prop {#1} \l_siunitx_tmpa_tl } } \cs_new_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:NNNNNNw} %\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 \bool_if:NTF \l_siunitx_group_four_bool { \siunitx_number_format_group_four_aux:nn {#1} {#2} } { \exp_after:wN \siunitx_number_format_group_four_aux:NNNNNNw \l_siunitx_tmpa_tl \q_no_value \q_no_value \q_no_value \q_no_value \q_no_value \q_nil { \siunitx_number_format_copy:n {#1 - #2} } { \siunitx_number_format_group_four_aux:nn {#1} {#2} } } } \cs_new:Npn \siunitx_number_format_group_four_aux:NNNNNNw #1#2#3#4#5#6 \q_nil { \quark_if_no_value:NTF #5 } \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} %\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:} % For adding the complex part to the main part of a number. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_join_complex: { \siunitx_number_format_sign_complex: \prop_if_in:NnT \l_siunitx_number_out_prop { mantissa } { \siunitx_number_format_brackets:n { mantissa } \prop_get:NnN \l_siunitx_number_out_prop { mantissa-result } \l_siunitx_tmpa_tl \prop_get:NnN \l_siunitx_number_out_prop { complex } \l_siunitx_tmpb_tl \tl_put_right:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl \prop_put:NnV \l_siunitx_number_out_prop { mantissa-result } \l_siunitx_tmpa_tl \prop_put:Nnn \l_siunitx_number_out_prop { mantissa-bracket } { true } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_format_join_uncert:} %\begin{macro}{\siunitx_number_format_join_uncert:n} %\begin{macro}[aux]{\siunitx_number_format_join_uncert_pm:} % 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 { mantissa , complex } \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:NnTF \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 \bool_if:NT \l_siunitx_uncert_sep_bool { \siunitx_number_format_join_uncert_pm: } \tl_put_right:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl \prop_put:NnV \l_siunitx_number_out_prop { #1 -result } \l_siunitx_tmpa_tl \prop_put:Nnn \l_siunitx_number_out_prop { #1 -bracket } { true } } { \siunitx_number_format_copy:nn {#1} { #1 -result } } } } \cs_new_nopar:Npn \siunitx_number_format_join_uncert_pm: { \bool_if:NTF \l_siunitx_tight_bool { \tl_put_left:Nn \l_siunitx_tmpb_tl { \ensuremath { { \pm } } } } { \tl_put_left:Nn \l_siunitx_tmpb_tl { \ensuremath { { } \pm { } } } } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_format_reassemble:} % The integer, decimal and any non-separated uncertainty parts are % put back together. This gives a \enquote{minimal} unit which cannot % need any brackets or repeated units (if applicable). If the % uncertainty is separate, it is stored at this stage pending later % re-attachment. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_format_reassemble: { \prop_if_in:NnT \l_siunitx_number_in_prop { mantissa } { \siunitx_number_format_group:n { mantissa } \siunitx_number_format_uncertainty:n { mantissa } } \prop_if_in:NnT \l_siunitx_number_in_prop { complex } { \siunitx_number_format_group:n { complex } \siunitx_number_format_uncertainty:n { complex } } \prop_if_in:NnT \l_siunitx_number_in_prop { exponent } { \siunitx_number_format_group:n { exponent } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_number_format_sign:n} %\begin{macro}{\siunitx_number_format_sign_complex:} % Some simple sign manipulation: for tight signs, a little shuffling. % In the complex number case, there is a need for a correction to get % the right formatting in text mode. For speed reasons, this is done in % a separate function. % \begin{macrocode} \cs_new_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:Nx \l_siunitx_tmpa_tl { { \exp_not:V \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_left:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl \prop_put:NnV \l_siunitx_number_out_prop {#1} \l_siunitx_tmpa_tl \prop_if_in:NnT \l_siunitx_number_out_prop { #1 -result } { \prop_get:NnN \l_siunitx_number_out_prop { #1 -result } \l_siunitx_tmpa_tl \tl_put_left:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl \prop_put:NnV \l_siunitx_number_out_prop { #1 -result } \l_siunitx_tmpa_tl } } } } \cs_new_nopar:Npn \siunitx_number_format_sign_complex: { \prop_if_in:NnT \l_siunitx_number_out_prop { complex } { \prop_if_in:NnT \l_siunitx_number_in_prop { complex-sign } { \prop_get:NnN \l_siunitx_number_in_prop { complex-sign } \l_siunitx_tmpa_tl \bool_if:NTF \l_siunitx_tight_bool { \tl_set:Nx \l_siunitx_tmpa_tl { { \exp_not:V \l_siunitx_tmpa_tl } } } { \prop_if_in:NnT \l_siunitx_number_out_prop { mantissa } { \tl_set:Nx \l_siunitx_tmpa_tl { { } \exp_not:V \l_siunitx_tmpa_tl { } } } } \tl_clear:N \l_siunitx_tmpb_tl \siunitx_tl_put_left_maths:NV \l_siunitx_tmpb_tl \l_siunitx_tmpa_tl \prop_put:NnV \l_siunitx_number_out_prop { complex-sign } \l_siunitx_tmpb_tl \prop_get:NnN \l_siunitx_number_out_prop { complex } \l_siunitx_tmpa_tl \tl_put_left:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl \prop_put:NnV \l_siunitx_number_out_prop { complex } \l_siunitx_tmpa_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} % 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:NnTF \l_siunitx_number_in_prop { #1 -uncertainty } { \bool_if:NTF \l_siunitx_uncert_sep_bool { \siunitx_number_format_uncertainty_sep:n {#1} } { \siunitx_number_format_uncertainty_joined:n {#1} } \siunitx_number_format_join_uncert: } { \siunitx_number_format_copy:nn {#1} { #1 -result } } } \cs_new_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 } \prop_put:NnV \l_siunitx_number_out_prop { #1 -uncertainty } \l_siunitx_tmpa_tl } % \end{macrocode} %\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}{\siunitx_fraction:nn} % The function used for fractions should be stored here. % \begin{macrocode} \cs_new:Npn \siunitx_fraction:nn { } % \end{macrocode} %\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 } { fraction-function .code:n = { \cs_set_eq:NN \siunitx_fraction:nn #1 }, output-product .tl_set:N = \l_siunitx_output_product_tl, output-quotient .tl_set:N = \l_siunitx_output_quotient_tl, parse-numbers .bool_set:N = \l_siunitx_number_parse_bool, 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 } { fraction-function = \frac, 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} %\begin{macro}{\siunitx_number_output:V} % The number output system simply sets up for the combined number and % unit system. % \begin{macrocode} \cs_new:Npn \siunitx_number_output:n #1 { \tl_clear:N \l_siunitx_unit_tl \tl_clear:N \l_siunitx_preunit_tl \siunitx_combined_output:n {#1} } \cs_generate_variant:Nn \siunitx_number_output:n { V } % \end{macrocode} %\end{macro} %\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_parse:n} %\begin{macro}{\siunitx_number_output_parse:V} %\begin{macro}[aux]{\siunitx_number_output_parse_aux:} %\begin{macro}[aux]{\siunitx_number_output_parse_multi:} % 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_parse_aux: } { \siunitx_number_output_parse_multi: } } } \cs_generate_variant:Nn \siunitx_number_output_parse:n { V } \cs_new_nopar:Npn \siunitx_number_output_parse_aux: { \siunitx_number_in_parse:V \l_siunitx_number_arg_tl \bool_if:NF \l_siunitx_error_bool { \siunitx_number_process: \siunitx_number_format: \siunitx_number_output_colour: \bool_if:NTF \l_siunitx_brackets_bool { \siunitx_number_output_single: } { \prop_if_in:NnTF \l_siunitx_number_out_prop { result-bracket } { \siunitx_number_output_parts: } { \siunitx_number_output_single: } } } } \cs_new_nopar:Npn \siunitx_number_output_parse_multi: { \bool_if:cTF { l_siunitx_calculate_ \l_siunitx_number_multi_tl _bool } { \siunitx_number_output_calculate: } { \use:c { siunitx_number_output_ \l_siunitx_number_multi_tl : } } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_output_parts:} %\begin{macro}[aux]{\siunitx_number_output_parts_aux:} %\begin{macro}[aux]{\siunitx_number_output_parts_aux:n} %\begin{macro}[aux]{\siunitx_number_output_parts_print:n} % Printing numbers by parts is necessary when there are units to % repeat. That means doing things that have already been done by the % number formatter again. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_output_parts: { \bool_if:nTF { \tl_if_empty_p:N \l_siunitx_pre_unit_tl && \tl_if_empty_p:N \l_siunitx_unit_tl } { \siunitx_number_output_single: } { \siunitx_number_output_parts_aux: } } \cs_new_nopar:Npn \siunitx_number_output_parts_aux: { \bool_if:NTF \l_siunitx_number_unit_repeat_bool { \prop_if_in:NnT \l_siunitx_number_out_prop { mantissa-result } { \siunitx_number_output_parts_aux:n { mantissa } \siunitx_number_output_parts_aux:n { mantissa-complex } } \prop_if_in:NnT \l_siunitx_number_out_prop { exponent } { \prop_if_in:NnT \l_siunitx_number_out_prop { mantissa-result } { \prop_get:NnN \l_siunitx_number_out_prop { exponent } \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:Nx \l_siunitx_tmpb_tl { { \exp_not:V \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 } \siunitx_number_output_parts_print:n { exponent } } } { \siunitx_number_output_single: } } \cs_new_nopar:Npn \siunitx_number_output_parts_aux:n #1 { \prop_if_in:NnT \l_siunitx_number_out_prop {#1} { \siunitx_number_output_parts_print:n {#1} } \prop_if_in:NnT \l_siunitx_number_out_prop { #1 -uncertainty } { \siunitx_number_output_parts_print:n { #1 -uncertainty } } } \cs_new_nopar:Npn \siunitx_number_output_parts_print:n #1 { \siunitx_unit_output_pre_print: \prop_get:NnN \l_siunitx_number_out_prop {#1} \l_siunitx_tmpa_tl \siunitx_print:nV { number } \l_siunitx_tmpa_tl \siunitx_unit_output_print: } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_output_product:} % For products, there may need to be the addition of brackets if there % are units about. When not repeating units, some work has to be done to % print everything correctly. The extra group here is necessary % otherwise looping will delete the units entirely! % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_output_product: { \bool_if:NTF \l_siunitx_brackets_bool { \bool_if:nTF { \tl_if_empty_p:N \l_siunitx_pre_unit_tl && \tl_if_empty_p:N \l_siunitx_unit_tl } { \siunitx_number_output_product_aux: } { \siunitx_number_output_product_brackets: } } { \bool_if:NTF \l_siunitx_number_unit_repeat_bool { \siunitx_number_output_product_aux: } { \siunitx_unit_output_pre_print: \tl_set_eq:NN \l_siunitx_unit_saved_tl \l_siunitx_unit_tl \tl_clear:N \l_siunitx_pre_unit_tl \tl_clear:N \l_siunitx_unit_tl \group_begin: \siunitx_number_output_product_aux: \group_end: \tl_set_eq:NN \l_siunitx_unit_tl \l_siunitx_unit_saved_tl \siunitx_unit_output_print: } } } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{\siunitx_number_output_product_brackets:} % When printing products that have to be bracketed, there is a need to % shuffle the units about a bit. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_output_product_brackets: { \siunitx_unit_output_pre_print: \siunitx_print:nn { number } { \ensuremath { \l_siunitx_bracket_open_tl } } \nobreak \tl_set_eq:NN \l_siunitx_unit_saved_tl \l_siunitx_unit_tl \tl_clear:N \l_siunitx_pre_unit_tl \tl_clear:N \l_siunitx_unit_tl \siunitx_number_output_product_aux: \nobreak \tl_set_eq:NN \l_siunitx_unit_tl \l_siunitx_unit_saved_tl \siunitx_print:nn { number } { \ensuremath { \l_siunitx_bracket_close_tl } } \siunitx_unit_output_print: } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{\siunitx_number_output_product_aux:} % Printing the products needs a looping function. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_output_product_aux: { \bool_set_true:N \l_siunitx_number_compound_bool \siunitx_number_preprocess:V \l_siunitx_number_arg_tl \bool_if:NF \l_siunitx_error_bool { \tl_if_empty:NTF \l_siunitx_number_multi_tl { \siunitx_number_output_parse_aux: } { \siunitx_number_output_quotient: } \tl_if_empty:NF \l_siunitx_number_next_tl { \bool_if:NTF \l_siunitx_tight_bool { \siunitx_print:nn { number } { \ensuremath { \l_siunitx_output_product_tl } } } { \siunitx_print:nn { number } { \ensuremath { { } \l_siunitx_output_product_tl { } } } } \siunitx_number_output_parse:V \l_siunitx_number_next_tl } } } % \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:Nx \l_siunitx_number_out_tl { { \exp_not:V \l_siunitx_number_numerator_tl } } \tl_set:Nx \l_siunitx_tmpa_tl { { \exp_not:V \l_siunitx_number_denominator_tl } } \tl_put_right:NV \l_siunitx_number_out_tl \l_siunitx_tmpa_tl \tl_put_left:Nn \l_siunitx_number_out_tl { \siunitx_fraction:nn } \tl_set:Nx \l_siunitx_number_out_tl { \exp_not:N \ensuremath { \exp_not:V \l_siunitx_number_out_tl } } \siunitx_number_output_single_aux: } % \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_set_eq:NN \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 \siunitx_number_output_single_aux: } % \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: \siunitx_number_output_bracket: \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: } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_number_output_single:} %\begin{macro}[aux]{\siunitx_number_output_single_aux:} % Printing a number with no multiple parts is easy. There is a check for % any units, which if present may force the number to have brackets % added. there is then simply a short run to print the units and number. % The test for bracketing numbers does not happen if there is an % exponent: if there is, any other parts will already be bracketed and % mathematically there is no need for brackets at this point. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_number_output_single: { \bool_if:nF { \tl_if_empty_p:N \l_siunitx_pre_unit_tl && \tl_if_empty_p:N \l_siunitx_unit_tl } { \prop_if_in:NnF \l_siunitx_number_out_prop { exponent } { \siunitx_number_format_brackets:n { result } } } \prop_get:NnN \l_siunitx_number_out_prop { result } \l_siunitx_number_out_tl \siunitx_number_output_single_aux: } \cs_new_nopar:Npn \siunitx_number_output_single_aux: { \siunitx_unit_output_pre_print: \siunitx_print:nV { number } \l_siunitx_number_out_tl \siunitx_unit_output_print: } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Angles} % % Angles are a special case of numbers for two reasons. First, there % is always a unit, which is known in advance. Second, there are two % possible input syntaxes, |\ang{1.23}| and |\ang{1;2;3}|. Both need % to be handled correctly. % %\begin{macro}{\l_siunitx_angle_degree_space_bool} %\begin{macro}{\l_siunitx_angle_minute_space_bool} % The need for spaces between parts of an arc needs to be accommodated: % this is achieved by flagging up the need for such spaces using two % switches. % \begin{macrocode} \bool_new:N \l_siunitx_angle_degree_space_bool \bool_new:N \l_siunitx_angle_minute_space_bool % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_angle_to_arc_bool} %\begin{macro}{\l_siunitx_angle_to_decimal_bool} % Switches are required for the \opt{angle-output-format} option, which % has to set two of them at the same time. % \begin{macrocode} \bool_new:N \l_siunitx_angle_to_arc_bool \bool_new:N \l_siunitx_angle_to_decimal_bool % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_angle_marker_box} %\begin{macro}{\l_siunitx_angle_unit_box} %\begin{macro}{\l_siunitx_angle_marker_dim} %\begin{macro}{\l_siunitx_angle_unit_dim} % When creating astronomy-style angles, the decimal marker and angle % symbol have to be boxed up and measured. % \begin{macrocode} \box_new:N \l_siunitx_angle_marker_box \box_new:N \l_siunitx_angle_unit_box \dim_new:N \l_siunitx_angle_marker_dim \dim_new:N \l_siunitx_angle_unit_dim % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_angle_degree_prop} %\begin{macro}{\l_siunitx_angle_minute_prop} %\begin{macro}{\l_siunitx_angle_second_prop} % As there are potentially three numbers to parse, three properly lists % are made available to hold the results. This allows the code to be % generalised, with only the name of the storage area varying. % \begin{macrocode} \prop_new:N \l_siunitx_angle_degree_prop \prop_new:N \l_siunitx_angle_minute_prop \prop_new:N \l_siunitx_angle_second_prop % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_angle_arg_tl} % Used to store the complete angle argument. % \begin{macrocode} \tl_new:N \l_siunitx_angle_arg_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_angle_arc_sign_tl} % Needed when checking for a sign with angles in arc format. % \begin{macrocode} \tl_new:N \l_siunitx_angle_arc_sign_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_angle_degree_zero_bool} %\begin{macro}{\l_siunitx_angle_minute_zero_bool} %\begin{macro}{\l_siunitx_angle_second_zero_bool} %\begin{macro}{\l_siunitx_angle_arc_separator_tl} %\begin{macro}{\l_siunitx_angle_astronomy_bool} %\begin{macro}{\l_siunitx_angle_unit_separator_tl} % The angle-specific options are created here. % \begin{macrocode} \keys_define:nn { siunitx } { add-arc-degree-zero .bool_set:N = \l_siunitx_angle_degree_zero_bool , add-arc-minute-zero .bool_set:N = \l_siunitx_angle_minute_zero_bool , add-arc-second-zero .bool_set:N = \l_siunitx_angle_second_zero_bool , angle-symbol-over-decimal .bool_set:N = \l_siunitx_angle_astronomy_bool , arc-separator .tl_set:N = \l_siunitx_angle_arc_separator_tl , angle-output-format .choice: , angle-output-format / arc .code:n = { \bool_set_true:N \l_siunitx_angle_to_arc_bool \bool_set_false:N \l_siunitx_angle_to_decimal_bool }, angle-output-format / decimal .code:n = { \bool_set_false:N \l_siunitx_angle_to_arc_bool \bool_set_true:N \l_siunitx_angle_to_decimal_bool }, angle-output-format / input .code:n = { \bool_set_false:N \l_siunitx_angle_to_arc_bool \bool_set_false:N \l_siunitx_angle_to_decimal_bool }, number-angle-separator .tl_set:N = \l_siunitx_angle_unit_separator_tl } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_angle_output:n} % The main output routine for angles does very little. The rescanning % function is called to make sure that any \texttt{;} tokens in the % input are not active. After than, the input is passed to the system % to search for semi-colons. % \begin{macrocode} \cs_new:Npn \siunitx_angle_output:n #1 { \siunitx_angle_init: \siunitx_angle_rescan:n {#1} \siunitx_angle_find_semi_colons:V \l_siunitx_angle_arg_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_angle_init:} % The usual separation of initial storage resets. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_angle_init: { \bool_set_false:N \l_siunitx_angle_degree_space_bool \bool_set_false:N \l_siunitx_angle_minute_space_bool \prop_clear:N \l_siunitx_angle_minute_prop \prop_clear:N \l_siunitx_angle_second_prop \tl_clear:N \l_siunitx_preunit_tl \tl_clear:N \l_siunitx_angle_arc_sign_tl \tl_set_eq:NN \l_siunitx_number_unit_separator_tl \l_siunitx_angle_unit_separator_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_angle_rescan:n} % To avoid any issues with active \texttt{;} tokens in the input, a % simple search and replace is employed. % \begin{macrocode} \group_begin: \char_set_lccode:nn { `\@ } { `\; } \char_make_active:N \@ \tl_to_lowercase:n { \group_end: \cs_new:Npn \siunitx_angle_rescan:n #1 { \tl_set:Nn \l_siunitx_angle_arg_tl {#1} \tl_replace_all_in:Nnn \l_siunitx_angle_arg_tl { @ } { ; } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_angle_find_semi_colons:n} %\begin{macro}{\siunitx_angle_find_semi_colons:V} %\begin{macro}[aux]{\siunitx_angle_find_semi_colons:w} % The trailing \texttt{;} and \cs{q_no_value} tokens here mean that % there are four possible input cases, and all of them can be detected % using fast tests. First, if |#4| is \cs{q_no_value} then there were % no \texttt{;} in the input. Exactly one \texttt{;} will mean that % |#5| is \cs{q_no_value}, while exactly two \texttt{;} in the input % makes |#6| \cs{q_no_value}. Any more than two semi-colons means that % all of the tests are negative. % \begin{macrocode} \cs_new:Npn \siunitx_angle_find_semi_colons:n #1 { \siunitx_angle_find_semi_colons:w #1 ; ; ; \q_no_value \q_no_value \q_no_value \q_nil } \cs_generate_variant:Nn \siunitx_angle_find_semi_colons:n { V } \cs_new:Npn \siunitx_angle_find_semi_colons:w #1 ; #2 ; #3 ; #4#5#6#7 \q_nil { \quark_if_no_value:NTF #4 { \siunitx_angle_parse_decimal:n {#1} } { \quark_if_no_value:NTF #5 { \siunitx_angle_parse_arc:nnn {#1} {#2} { } } { \quark_if_no_value:NTF #6 { \siunitx_angle_parse_arc:nnn {#1} {#2} {#3} } { \siunitx_error:nV { invalid-arc-format } \l_siunitx_angle_arg_tl } } } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_angle_parse_arc:nnn} %\begin{macro}[aux]{\siunitx_angle_parse_arc_aux_i:nnn} %\begin{macro}[aux]{\siunitx_angle_parse_arc_aux_ii:nnn} % For angles given as arcs, there may be a need to zero-fill one or % more parts. Doing this here makes life slightly easier later. % \begin{macrocode} \cs_new:Npn \siunitx_angle_parse_arc:nnn #1#2#3 { \tl_if_empty:nTF { #1#2#3 } { \siunitx_error:n { empty-arc } } { \bool_if:NTF \l_siunitx_angle_degree_zero_bool { \tl_if_empty:nTF {#1} { \siunitx_angle_parse_arc_aux_i:nnn { 0 } {#2} {#3} } { \siunitx_angle_parse_arc_aux_i:nnn {#1} {#2} {#3} } } { \siunitx_angle_parse_arc_aux_i:nnn {#1} {#2} {#3} } } } \cs_new:Npn \siunitx_angle_parse_arc_aux_i:nnn #1#2#3 { \bool_if:NTF \l_siunitx_angle_minute_zero_bool { \tl_if_empty:nTF {#2} { \siunitx_angle_parse_arc_aux_ii:nnn {#1} { 0 } {#3} } { \siunitx_angle_parse_arc_aux_ii:nnn {#1} {#2} {#3} } } { \siunitx_angle_parse_arc_aux_ii:nnn {#1} {#2} {#3} } } \cs_new:Npn \siunitx_angle_parse_arc_aux_ii:nnn #1#2#3 { \bool_if:NTF \l_siunitx_angle_second_zero_bool { \tl_if_empty:nTF {#3} { \siunitx_angle_parse_arc_aux_iii:nnn {#1} {#2} { 0 } } { \siunitx_angle_parse_arc_aux_iii:nnn {#1} {#2} {#3} } } { \siunitx_angle_parse_arc_aux_iii:nnn {#1} {#2} {#3} } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}[aux]{\siunitx_angle_parse_arc_aux_iii:nnn} % With the entries now set up correctly, the spacing flags can now be % set. The choice can then be made on whether to parse the three parts % of the arc or simply to print them as given. % \begin{macrocode} \cs_new:Npn \siunitx_angle_parse_arc_aux_iii:nnn #1#2#3 { \tl_if_empty:nTF {#2} { \tl_if_empty:nF {#3} { \bool_set_true:N \l_siunitx_angle_degree_space_bool } } { \bool_set_true:N \l_siunitx_angle_degree_space_bool \tl_if_empty:nF {#3} { \bool_set_true:N \l_siunitx_angle_minute_space_bool } } \bool_if:NTF \l_siunitx_number_parse_bool { \siunitx_angle_parse_arc_aux_iv:nnn {#1} {#2} {#3} } { \siunitx_angle_print_direct:nnn {#1} {#2} {#3} } } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{\siunitx_angle_parse_arc_aux_iv:nnn} % The final part of the parsing chain for arcs actually runs on each % of the three components in turn. There is then a sanity check for the % sign, before handing off either to the conversion code or the output % system. % \begin{macrocode} \cs_new:Npn \siunitx_angle_parse_arc_aux_iv:nnn #1#2#3 { \siunitx_angle_parse_aux:nn {#1} { degree } \siunitx_angle_parse_aux:nn {#2} { minute } \siunitx_angle_parse_aux:nn {#3} { second } \siunitx_angle_parse_arc_sign_check: \bool_if:NF \l_siunitx_error_bool { \bool_if:NTF \l_siunitx_angle_to_decimal_bool { \siunitx_angle_convert_to_decimal: } { \siunitx_angle_print: } } } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{\siunitx_angle_parse_arc_sign_check:} %\begin{macro}[aux]{\siunitx_angle_parse_arc_sign_check_aux:n} % There are two issues with signs for angles given as arcs. First, if % more than one sign has been given, they have to agree. So there is a % need to find any signs and check. Second, the sign needs to be given % only for the \enquote{highest order} entry. That is most easily % achieved by shuffling the sign to the appropriate place. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_angle_parse_arc_sign_check: { \prop_if_in:NnTF \l_siunitx_angle_second_prop { mantissa-sign } { \prop_get:NnN \l_siunitx_angle_second_prop { mantissa-sign } \l_siunitx_angle_arc_sign_tl \siunitx_angle_parse_arc_sign_check_aux:n { minute } \siunitx_angle_parse_arc_sign_check_aux:n { degree } } { \prop_if_in:NnT \l_siunitx_angle_minute_prop { mantissa-sign } { \prop_get:NnN \l_siunitx_angle_minute_prop { mantissa-sign } \l_siunitx_angle_arc_sign_tl \siunitx_angle_parse_arc_sign_check_aux:n { degree } } } \bool_if:NF \l_siunitx_error_bool { \tl_if_empty:NF \l_siunitx_angle_arc_sign_tl { \prop_if_empty:NTF \l_siunitx_angle_degree_prop { \prop_if_empty:NF \l_siunitx_angle_minute_prop { \prop_put:NnV \l_siunitx_angle_minute_prop { mantissa-sign } \l_siunitx_angle_arc_sign_tl \prop_del:Nn \l_siunitx_angle_second_prop { mantissa-sign } } } { \prop_put:NnV \l_siunitx_angle_degree_prop { mantissa-sign } \l_siunitx_angle_arc_sign_tl \prop_del:Nn \l_siunitx_angle_minute_prop { mantissa-sign } \prop_del:Nn \l_siunitx_angle_second_prop { mantissa-sign } } } } } \cs_new_nopar:Npn \siunitx_angle_parse_arc_sign_check_aux:n #1 { \prop_if_in:cnT { l_siunitx_angle_ #1 _prop } { mantissa-sign } { \prop_get:cnN { l_siunitx_angle_ #1 _prop } { mantissa-sign } \l_siunitx_tmpa_tl \tl_if_eq:NNF \l_siunitx_angle_arc_sign_tl \l_siunitx_tmpa_tl { \siunitx_error:n { arc-sign-mismatch } } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_angle_parse_decimal:n} % For decimal input, there is a single piece of parsing to be done. % Following that, either the conversion code or the printing routine can % be called. On the other hand, if parsing is turned off then there is a % direct call to the printing system. % \begin{macrocode} \cs_new:Npn \siunitx_angle_parse_decimal:n #1 { \bool_if:NTF \l_siunitx_number_parse_bool { \siunitx_angle_parse_aux:nn {#1} { degree } \bool_if:NF \l_siunitx_error_bool { \bool_if:NTF \l_siunitx_angle_to_arc_bool { \siunitx_angle_convert_to_arc: } { \siunitx_angle_print: } } } { \siunitx_angle_print_direct:nnn {#1} { } { } } } % \end{macrocode} %\end{macro} % %\begin{macro}[aux]{\siunitx_angle_parse_aux:nn} % A short auxiliary function does the number parsing and also stores the % result appropriately. % \begin{macrocode} \cs_new:Npn \siunitx_angle_parse_aux:nn #1#2 { \siunitx_number_in_parse:n {#1} \siunitx_number_process: \prop_set_eq:cN { l_siunitx_angle_ #2 _prop } \l_siunitx_number_in_prop } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_angle_print:} %\begin{macro}[aux]{\siunitx_angle_print:nn} % The standard printing routine examines each part of the arc in turn % and either does a standard format or calls the special astronomy-style % routine. There may also be some spaces to add. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_angle_print: { \siunitx_angle_print_aux:nn { degree } { \SIUnitSymbolDegree } \bool_if:NT \l_siunitx_angle_degree_space_bool { \nobreak \ensuremath { \l_siunitx_angle_arc_separator_tl } } \siunitx_angle_print_aux:nn { minute } { \SIUnitSymbolArcminute } \bool_if:NT \l_siunitx_angle_minute_space_bool { \nobreak \ensuremath { \l_siunitx_angle_arc_separator_tl } } \siunitx_angle_print_aux:nn { second } { \SIUnitSymbolArcsecond } } \cs_new_nopar:Npn \siunitx_angle_print_aux:nn #1#2 { \prop_if_empty:cF { l_siunitx_angle_ #1 _prop } { \prop_set_eq:Nc \l_siunitx_number_in_prop { l_siunitx_angle_ #1 _prop } \tl_set:Nn \l_siunitx_unit_tl {#2} \tl_clear:N \l_siunitx_number_out_tl \siunitx_number_format: \siunitx_number_output_colour: \bool_if:NTF \l_siunitx_angle_astronomy_bool { \siunitx_angle_print_astronomy: } { \siunitx_number_output_single: } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_angle_print_astronomy:} %\begin{macro}[aux]{\siunitx_angle_print_astronomy_aux:} %\begin{macro}[aux]{\siunitx_angle_print_astronomy_aux:n} %\begin{macro}[aux]{\siunitx_angle_print_astronomy_marker:} %\begin{macro}[aux]{\siunitx_angle_print_astronomy_unit:} % The first check for astronomy-style angles is that there is a decimal % marker in the current input: if not, the standard method can be used. % The method for the astronomy-style angle is not straight-forward, so % needs a little explanation. The integer and decimal parts of the % number are printed at each end of the function. In the middle is a % method to centre the unit symbol on the decimal marker. This is done % by typesetting the two symbols and measuring their respective widths. % The two are then put into zero-width boxes, which allows them to be % aligned horizontally centred with no vertical change. The larger % dimension is then used to reconstruct the appropriate width for the % final output. There is also a need to allow for the \cs{scriptspace} % added in after superscripts, which otherwise messes up the % calculation. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_angle_print_astronomy: { \prop_if_in:NnTF \l_siunitx_number_in_prop { mantissa-decimal-marker } { \siunitx_angle_print_astronomy_aux: } { \siunitx_number_output_single: } } \cs_new_nopar:Npn \siunitx_angle_print_astronomy_aux: { \prop_if_in:NnT \l_siunitx_number_out_prop { mantissa-integer } { \prop_get:NnN \l_siunitx_number_out_prop { mantissa-integer } \l_siunitx_tmpa_tl \siunitx_print:nV { number } \l_siunitx_tmpa_tl } \hbox_set:Nn \l_siunitx_angle_marker_box { \siunitx_print:nn { number } { \ensuremath { { \l_siunitx_output_decimal_tl } } } } \hbox_set:Nn \l_siunitx_angle_unit_box { \siunitx_print:nV { unit } \l_siunitx_unit_tl \tex_hskip:D -\scriptspace } \siunitx_angle_print_astronomy_aux:n { marker } \siunitx_angle_print_astronomy_aux:n { unit } \hbox_set:Nn \l_siunitx_angle_marker_box { \box_use:N \l_siunitx_angle_marker_box \box_use:N \l_siunitx_angle_unit_box } \dim_compare:nNnTF { \l_siunitx_angle_marker_dim } > { \l_siunitx_angle_unit_dim } { \siunitx_angle_print_astronomy_marker: } { \siunitx_angle_print_astronomy_unit: } \prop_if_in:NnT \l_siunitx_number_out_prop { mantissa-decimal } { \prop_get:NnN \l_siunitx_number_out_prop { mantissa-decimal } \l_siunitx_tmpa_tl \siunitx_print:nV { number } \l_siunitx_tmpa_tl } } \cs_new_nopar:Npn \siunitx_angle_print_astronomy_aux:n #1 { \dim_set:cn { l_siunitx_angle_ #1 _dim } { \box_wd:c { l_siunitx_angle_ #1 _box } } \hbox_set_to_wd:cnn { l_siunitx_angle_ #1 _box } { \c_zero_skip } { \tex_hss:D \hbox_unpack:c { l_siunitx_angle_ #1_box } \tex_hss:D } } \cs_new_nopar:Npn \siunitx_angle_print_astronomy_marker: { \hbox_set_to_wd:Nnn \l_siunitx_angle_marker_box { \l_siunitx_angle_marker_dim } { \tex_hss:D \hbox_unpack_clear:N \l_siunitx_angle_marker_box \tex_hss:D } \box_use:N \l_siunitx_angle_marker_box } \cs_new_nopar:Npn \siunitx_angle_print_astronomy_unit: { \hbox_set_to_wd:Nnn \l_siunitx_angle_marker_box { \l_siunitx_angle_unit_dim } { \tex_hss:D \hbox_unpack_clear:N \l_siunitx_angle_marker_box \tex_hss:D } \box_use:N \l_siunitx_angle_marker_box \tex_hskip:D \scriptspace } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_angle_print_direct:nnn} %\begin{macro}[aux]{\siunitx_angle_print_direct_aux:nn} % The direct printing routine is rather similar to the standard % one, with just a modified final step. % \begin{macrocode} \cs_new:Npn \siunitx_angle_print_direct:nnn #1#2#3 { \siunitx_angle_print_direct_aux:nn {#1} { \SIUnitSymbolDegree } \bool_if:NT \l_siunitx_angle_degree_space_bool { \nobreak \ensuremath { \l_siunitx_angle_arc_separator_tl } } \siunitx_angle_print_direct_aux:nn {#2} { \SIUnitSymbolArcminute } \bool_if:NT \l_siunitx_angle_minute_space_bool { \nobreak \ensuremath { \l_siunitx_angle_arc_separator_tl } } \siunitx_angle_print_direct_aux:nn {#3} { \SIUnitSymbolArcsecond } } \cs_new_nopar:Npn \siunitx_angle_print_direct_aux:nn #1#2 { \tl_if_empty:nF {#1} { \tl_set:Nn \l_siunitx_unit_tl {#2} \siunitx_print:nn { number } { \ensuremath {#1} } \siunitx_unit_output_print: } } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Creating unit macros} % % Unit macros and related support are created here. To avoid cluttering % up the user name-space with a lot of short macro names, the standard % method only makes these available inside the unit-processing functions % (\cs{SI}, \cs{si} and the \texttt{S} column). % %\begin{macro}{\l_siunitx_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} } } \tl_if_empty:nTF {#3} { \cs_if_free:cF { l_siunitx_ \token_to_str:N #1 _options_tl } { \cs_gundefine:c { l_siunitx_ \token_to_str:N #1 _options_tl } } } { \cs_if_free:cT { l_siunitx_ \token_to_str:N #1 _options_tl } { \tl_new:c { l_siunitx_ \token_to_str:N #1 _options_tl } } \tl_set:cn { l_siunitx_ \token_to_str:N #1 _options_tl } {#3} } } \cs_new: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:NTF \l_siunitx_create_free_bool { \siunitx_unit_create_functions: } { \siunitx_unit_create_empty_functions: } } \AtBeginDocument { \siunitx_unit_create_check: } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_unit_create_empty_functions:} %\begin{macro}[aux]{\siunitx_unit_create_empty_functions_aux:N} % Without this, horrible things happen with \pkg{memoir} and % \pkg{hyperref}. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_create_empty_functions: { \tl_map_function:NN \l_siunitx_declare_list_tl \siunitx_unit_create_empty_functions_aux:N } \cs_new_nopar:Npn \siunitx_unit_create_empty_functions_aux:N #1 { \cs_if_free:NT #1 { \cs_set_protected_nopar:Npn #1 { \ERROR } } } % \end{macrocode} %\end{macro} %\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 { \ProvideDocumentCommand \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 { \ProvideDocumentCommand \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} % %\begin{macro}{\siunitx_protect_symbols:} %\begin{macro}[aux]{\siunitx_protect_symbols_aux:N} % There are a few unit names which may be defined by other parts of % \LaTeX. They need to be unexpandable, as in an \texttt{s} column % \TeX\ will look for \cs{omit} \emph{before} starting the internal % version of \cs{si} and doing a redefinition. The same is true % for the \cs{color} function, which may well be the first thing in % a table cell. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_protect_symbols: { \tl_map_function:nN { \bar \color \ng \pm } \siunitx_protect_symbols_aux:N } \cs_new_nopar:Npn \siunitx_protect_symbols_aux:N #1 { \cs_if_exist:NT #1 { \siunitx_cs_if_macro:NT #1 { \cs_set_protected_nopar:Npx #1 { \exp_not:V #1 } } } } \AtBeginDocument { \siunitx_protect_symbols: } % \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_forbid_literal_bool} %\begin{macro}{\l_siunitx_unit_parse_bool} % One option is related to how units are pre-processed. % \begin{macrocode} \keys_define:nn { siunitx } { forbid-literal-units .bool_set:N = \l_siunitx_unit_forbid_literal_bool, parse-units .bool_set:N = \l_siunitx_unit_parse_bool } \keys_set:nn { siunitx } { forbid-literal-units = false, parse-units = true } % \end{macrocode} %\end{macro} %\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 { \bool_if:NTF \l_siunitx_unit_parse_bool { \tl_if_empty:nF {#1} { \siunitx_unit_if_literal:nTF {#1} { \bool_if:NTF \l_siunitx_unit_forbid_literal_bool { \msg_error:nnx { siunitx } { literal-unit } {#1} } { \siunitx_unit_format_literal:n {#1} } } { \bool_if:NT \l_siunitx_per_auto_bool { \tl_set:Nn \l_siunitx_per_mode_tl { symbol } \mode_if_inner:F { \mode_if_math:T { \tl_set:Nn \l_siunitx_per_mode_tl { fraction } } } } \siunitx_unit_parse:nn {#1} {#2} \siunitx_unit_format: } } } { \siunitx_unit_format_literal:n {#1} } } \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 \cs_set_eq:NN \pm \siunitx_pm: } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_unit_parse_init:} %\begin{macro}[aux]{\siunitx_unit_parse_init_aux:N} %\begin{macro}{\siunitx_pm:} % As always, the initialisation is a separate routine to make life a % little clearer. The definition of \cs{pm} is saved here as it % is used by units and numbers. % \begin{macrocode} \cs_new_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 \cs_set_eq:NN \siunitx_pm: \pm \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 } } \cs_new_nopar:Npn \siunitx_pm: { } % \end{macrocode} %\end{macro} %\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 } \bool_if:NT \l_siunitx_sticky_per_bool { \cs_set_eq:NN \per \siunitx_unit_parse_per_error: } } \cs_new_nopar:Npn \siunitx_unit_parse_per_error: { \msg_error:nn { siunitx } { duplicate-sticky-per } } % \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} %\begin{macro}{\l_siunitx_unit_saved_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 \tl_new:N \l_siunitx_unit_saved_tl % \end{macrocode} %\end{macro} %\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_auto_bool} %\begin{macro}{\l_siunitx_per_fraction_bool} %\begin{macro}{\l_siunitx_per_mode_tl} %\begin{macro}{\l_siunitx_qualifier_mode_tl} %\begin{macro}{\l_siunitx_per_two_parts_bool} % For saving settings. % \begin{macrocode} \bool_new:N \l_siunitx_per_auto_bool \bool_new:N \l_siunitx_per_fraction_bool \tl_new:N \l_siunitx_per_mode_tl \bool_new:N \l_siunitx_two_parts_bool \tl_new:N \l_siunitx_qualifier_mode_tl % \end{macrocode} %\end{macro} %\end{macro} %\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_false:N \l_siunitx_per_auto_bool \bool_set_true:N \l_siunitx_per_fraction_bool \bool_set_true:N \l_siunitx_per_two_parts_bool \tl_set:Nn \l_siunitx_per_mode_tl { fraction } }, per-mode / power .meta:n = { per-mode = reciprocal } , per-mode / power-positive-first .meta:n = { per-mode = reciprocal-positive-first } , per-mode / reciprocal .code:n = { \bool_set_false:N \l_siunitx_per_auto_bool \bool_set_false:N \l_siunitx_per_fraction_bool \bool_set_false:N \l_siunitx_per_two_parts_bool \tl_clear:N \l_siunitx_per_mode_tl }, per-mode / reciprocal-positive-first .code:n = { \bool_set_false:N \l_siunitx_per_auto_bool \bool_set_false:N \l_siunitx_per_fraction_bool \bool_set_true:N \l_siunitx_per_two_parts_bool \tl_clear:N \l_siunitx_per_mode_tl }, per-mode / repeated-symbol .code:n = { \bool_set_false:N \l_siunitx_per_auto_bool \bool_set_false:N \l_siunitx_per_fraction_bool \bool_set_false:N \l_siunitx_per_two_parts_bool \tl_set:Nn \l_siunitx_per_mode_tl { repeat } }, per-mode / symbol .code:n = { \bool_set_false:N \l_siunitx_per_auto_bool \bool_set_true:N \l_siunitx_per_fraction_bool \bool_set_true:N \l_siunitx_per_two_parts_bool \tl_set:Nn \l_siunitx_per_mode_tl { symbol } }, per-mode / symbol-or-fraction .code:n = { \bool_set_true:N \l_siunitx_per_auto_bool \bool_set_true:N \l_siunitx_per_fraction_bool \bool_set_true:N \l_siunitx_per_two_parts_bool }, 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 = reciprocal, 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. Before starting the loop, there is a check for % the case of a single reciprocal unit when per is set up to create a % symbol. In that special case, the space between a number and a unit % has to be removed. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_format: { \siunitx_unit_format_init: \intexpr_compare:nT { \l_siunitx_unit_int = \c_one } { \tl_if_eq:VnT \l_siunitx_per_mode_tl { symbol } { \prop_if_in:NnT \l_siunitx_unit_prop { per-1 } { \tl_clear:N \l_siunitx_number_unit_separator_tl } } } \intexpr_compare:nT { \l_siunitx_unit_int > \c_zero } { \siunitx_unit_format_loop: } \bool_if:NT \l_siunitx_per_two_parts_bool { \bool_if:NTF \l_siunitx_per_fraction_bool { \siunitx_unit_format_fraction: } { \siunitx_unit_format_sorted: } } } % \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_two_parts_bool { \tl_set:Nx \l_siunitx_tmpb_tl { per- \int_use:N \l_siunitx_unit_int } \prop_if_in:NVTF \l_siunitx_unit_prop \l_siunitx_tmpb_tl { \siunitx_unit_format_add_aux:n { _denominator } \int_incr:N \l_siunitx_unit_denominator_int } { \siunitx_unit_format_add_aux:n { _numerator } \int_incr:N \l_siunitx_unit_numerator_int } } { \siunitx_unit_format_add_aux:n { } } \tl_clear:N \l_siunitx_unit_current_tl } \cs_new_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:Nx \l_siunitx_unit_numerator_tl { { \exp_not:V \l_siunitx_unit_numerator_tl } } \tl_put_left:Nn \l_siunitx_unit_numerator_tl { \siunitx_print:nn { unit } } \tl_set:Nx \l_siunitx_unit_numerator_tl { { \exp_not:V \l_siunitx_unit_numerator_tl } } \tl_set:Nx \l_siunitx_unit_denominator_tl { { \exp_not:V \l_siunitx_unit_denominator_tl } } \tl_put_left:Nn \l_siunitx_unit_denominator_tl { \siunitx_print:nn { unit } } \tl_set:Nx \l_siunitx_unit_denominator_tl { { \exp_not:V \l_siunitx_unit_denominator_tl } } \tl_set:Nn \l_siunitx_unit_tl { \siunitx_fraction:nn } \tl_put_right:NV \l_siunitx_unit_tl \l_siunitx_unit_numerator_tl \tl_put_right:NV \l_siunitx_unit_tl \l_siunitx_unit_denominator_tl \tl_set:Nx \l_siunitx_unit_tl { \exp_not:N \ensuremath { \exp_not:V \l_siunitx_unit_tl } } } \cs_new_nopar:Npn \siunitx_unit_format_fraction_symbol: { \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 \texttt{.} 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:Nx \l_sunitx_tmpa_tl { \exp_not:N \ensuremath { \exp_not:V \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 \siunitx_unit_format_literal_extras: } \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_space:N \~ % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_format_literal_extras:} %\begin{macro}[aux]{\siunitx_unit_format_literal_extras_aux:nN} %\begin{macro}{\siunitx_check_inputenc:} % The code here deals with characters outside the normal range that % can appear in units in UTF-8 and related encodings. The idea is to % do a search and replace, thus avoiding any active characters. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_format_literal_extras: { \siunitx_unit_format_literal_extras_aux:nN { 176 } \SIUnitSymbolDegree \siunitx_unit_format_literal_extras_aux:nN { 181 } \SIUnitSymbolMicro \siunitx_unit_format_literal_extras_aux:nN { 197 } \SIUnitSymbolAngstrom } \cs_new_nopar:Npn \siunitx_unit_format_literal_extras_aux:nN #1#2 { \char_set_lccode:nn { `\@ } {#1} \tl_to_lowercase:n { \tl_replace_all_in:NnV \l_siunitx_unit_tl { @ } \l_siunitx_unit_tl } } \cs_new_nopar:Npn \siunitx_check_inputenc: { \@ifpackageloaded { inputenc } { \tl_set:Nn \l_siunitx_tmpa_tl { latin1 , latin5 , latin9 } \clist_if_in:NVF \l_siunitx_tmpa_tl \inputencodingname { \cs_set_eq:NN \siunitx_unit_format_literal_extras: \scan_stop: } } { \cs_set_eq:NN \siunitx_unit_format_literal_extras: \scan_stop: } } \xetex_if_engine:F { \AtBeginDocument { \siunitx_check_inputenc: } } % \end{macrocode} %\end{macro} %\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:} % 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} %\end{macro} %\begin{macro}[aux]{\siunitx_unit_format_power_aux:} %\begin{macro}[aux]{\siunitx_unit_format_power_aux:n} % The auxiliary function needs to make sure that the printing routine % prints the power as a number, not as text: the two modes may be % different. A search and replace function is needed for superscripts % in text mode so that negative signs get printed correctly. % \begin{macrocode} \cs_new_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 { ^ { \siunitx_unit_format_power_aux:n { \exp_not:V \l_siunitx_tmpa_tl } } } } } \cs_new_protected:Npn \siunitx_unit_format_power_aux:n #1 { \bool_if:NTF \l_siunitx_number_maths_mode_bool { \siunitx_print:nn { number } {#1} } { \tl_set:Nn \l_siunitx_tmpa_tl {#1} \tl_replace_all_in:Nnn \l_siunitx_tmpa_tl { - } { \text { \c_siunitx_minus_tl } } \siunitx_print:nV { number } \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_sorted:} % For when the powers are sorted with the positive ones first. The only % slight issue is making sure that the additional space is included % between the two units, if needed. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_format_sorted: { \tl_set_eq:NN \l_siunitx_unit_tl \l_siunitx_unit_numerator_tl \tl_if_empty:NF \l_siunitx_unit_tl { \tl_if_empty:NF \l_siunitx_unit_denominator_tl { \siunitx_tl_put_right_maths:NV \l_siunitx_unit_tl \l_siunitx_unit_separator_tl } } \tl_put_right:NV \l_siunitx_unit_tl \l_siunitx_unit_denominator_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_unit_format_symbol:} %\begin{macro}[aux]{\siunitx_unit_format_symbol_aux:} %\begin{macro}[aux]{\siunitx_unit_format_symbol_aux_alt:} % If there is no symbol, something is wrong! The only exception is % when the code is inside the \cs{si} function (or similar) and there % is only a prefix with nothing else present at all. % \begin{macrocode} \cs_new_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 } { \siunitx_unit_format_symbol_aux: } } \cs_new_nopar:Npn \siunitx_unit_format_symbol_aux: { \msg_error:nn { siunitx } { prefix-only } } \cs_new_nopar:Npn \siunitx_unit_format_symbol_aux_alt: { \intexpr_compare:nTF { \l_siunitx_unit_int = \c_one } { \prop_del:Nn \l_siunitx_unit_prop { prefix-1 } \prop_if_empty:NF \l_siunitx_unit_prop { \msg_error:nn { siunitx } { prefix-only } } } { \msg_error:nn { siunitx } { prefix-only } } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\subsection{Unit output} % % A collection of the internal parts of various user functions. % %\begin{macro}{\l_siunitx_number_unit_breaks_bool} %\begin{macro}{\l_siunitx_number_unit_power_bool} %\begin{macro}{\l_siunitx_number_unit_repeat_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, repeat-units .bool_set:N = \l_siunitx_number_unit_repeat_bool, unit-product-to-power .bool_set:N = \l_siunitx_number_unit_power_bool } \keys_set:nn { siunitx } { number-unit-separator = \,, repeat-units = true } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_unit_output:nn} %\begin{macro}{\siunitx_unit_output:Vn} % For typesetting a unit directly: used by \cs{si} and the \texttt{s} % column. The second argument is any options to set locally. % \begin{macrocode} \cs_new:Npn \siunitx_unit_output:nn #1#2 { \cs_set_eq:NN \siunitx_unit_format_symbol_aux: \siunitx_unit_format_symbol_aux_alt: \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 } \cs_generate_variant:Nn \siunitx_unit_output:nn { Vn } % \end{macrocode} %\end{macro} %\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} % %\begin{macro}{\siunitx_unit_output_pre_print:} %\begin{macro}{\siunitx_unit_output_print:} % The printing functions for units do some simple tests then % actually print there output. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_unit_output_pre_print: { \tl_if_empty:NF \l_siunitx_pre_unit_tl { \nobreak \siunitx_print:nV { unit } \l_siunitx_pre_unit_tl } } \cs_new_nopar:Npn \siunitx_unit_output_print: { \intexpr_compare:nF { \l_siunitx_unit_prefix_int = \c_zero } { \tl_set:Nx \l_siunitx_tmpa_tl { \bool_if:NTF \l_siunitx_tight_bool { { \exp_not:V \l_siunitx_exponent_product_tl } } { { } \exp_not:V \l_siunitx_exponent_product_tl { } } \int_use:N \l_siunitx_unit_prefix_base_int ^ { \int_use:N \l_siunitx_unit_prefix_int } } \siunitx_print:nV { number } \l_siunitx_tmpa_tl } \tl_if_empty:NF \l_siunitx_unit_tl { \siunitx_unit_output_number_sep: \siunitx_print:nV { unit } \l_siunitx_unit_tl } } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Numbers with units} % % Numbers with units have to be formatted in a more complex way than % simply sticking the two together. % %\begin{macro}{\l_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} % Printing numbers and units means first processing the units, then % handing off this information to the combined number and unit % processor. % \begin{macrocode} \cs_new: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_output:n {#2} } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_combined_output:n} % Printing the combination of a number and a unit means checking for % parsing then parsing the number part. % \begin{macrocode} \cs_new:Npn \siunitx_combined_output:n #1 { \bool_if:NTF \l_siunitx_number_parse_bool { \tl_clear:N \l_siunitx_number_out_tl \bool_set_false:N \l_siunitx_number_compound_bool \siunitx_number_output_parse:n {#1} } { \siunitx_unit_output_pre_print: \siunitx_print:nn { number } { \ensuremath {#1} } \siunitx_unit_output_print: } } % \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 && ( \l_siunitx_brackets_bool || ( !\l_siunitx_number_unit_repeat_bool && !\l_siunitx_brackets_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:Nx \l_siunitx_tmpb_tl { \tothe { \exp_not:V \l_siunitx_number_product_int } } \tl_put_right:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl \siunitx_unit_in:Vn \l_siunitx_tmpa_tl {#3} } { \siunitx_unit_in:nn {#2} {#3} } } { \siunitx_unit_in:nn {#2} {#3} } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_combined_product_count:n} %\begin{macro}[aux]{\siunitx_combined_product_count_aux:n} % For counting how many products are in a number, so that the unit % can be adjusted if needed. % \begin{macrocode} \cs_new: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:NT \l_siunitx_number_compound_bool { \msg_error:nnx { siunitx } { multi-part-range } {#1} } } { \siunitx_unit_output_pre_print: \siunitx_print:nn { number } {#1} \siunitx_unit_output_print: } } % \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} \text { \l_siunitx_range_phrase_tl } \siunitx_range_numbers_aux:n {#4} } % \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:Nn \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: } } \NC@find } } \AtBeginDocument { \siunitx_table_rewrite_create:N s } \AtBeginDocument { \siunitx_table_rewrite_create:N S } % \end{macrocode} %\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_toks} %\begin{macro}{\l_siunitx_table_collect_pre_toks} %\begin{macro}{\l_siunitx_table_collect_post_toks} % Three storage areas. % \begin{macrocode} \toks_new:N \l_siunitx_table_collect_toks \toks_new:N \l_siunitx_table_collect_pre_toks \toks_new:N \l_siunitx_table_collect_post_toks % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_number_valid_tl} % As the \texttt{S} column has to make a judgement about tokens which % can be part of a number, there is a need to have a list of valid % tokens. % \begin{macrocode} \tl_new:N \l_siunitx_number_valid_tl % \end{macrocode} %\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} %\begin{macro}[aux]{\siunitx_table_collect_begin_s:} %\begin{macro}[aux]{\siunitx_table_collect_begin_S:} % 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 { \keys_set:nn { siunitx } {#2} \use:c { siunitx_table_collect_begin_ #1 : } } \cs_new_nopar:Npn \siunitx_table_collect_begin_s: { \cs_set_eq:NN \siunitx_table_collect_token:N \siunitx_table_collect_token_s:N \cs_set_eq:NN \siunitx_table_print: \siunitx_table_print_s: \siunitx_table_collect_init_s: \siunitx_table_collect_get: } \cs_new_nopar:Npn \siunitx_table_collect_begin_S: { \cs_set_eq:NN \siunitx_table_collect_token:N \siunitx_table_collect_token_S:N \cs_set_eq:NN \siunitx_table_print: \siunitx_table_print_S: \siunitx_table_collect_init_S: \bool_if:NTF \l_siunitx_number_parse_bool { \siunitx_table_collect_get: } { \siunitx_table_direct: } } % \end{macrocode} %\end{macro} %\end{macro} %\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 % \cref{tab:xmpl:calc} in the user part of the documentation. % \begin{macrocode} \cs_new:Npn \siunitx_table_collect_expand:N #1 { \siunitx_cs_if_tl:NTF #1 { \toks_use:N \l_siunitx_table_collect_pre_toks \toks_clear:N \l_siunitx_table_collect_pre_toks \cs_set_nopar:Npx \siunitx_table_collect_next: { \exp_not:N \siunitx_table_collect_get: \exp_not:V #1 } } { \bool_if:NTF \l_siunitx_table_collect_pre_bool { \toks_put_right:Nn \l_siunitx_table_collect_pre_toks {#1} } { \bool_set_true:N \l_siunitx_table_collect_post_bool \toks_put_right:Nn \l_siunitx_table_collect_post_toks {#1} } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_table_collect_get:} %\begin{macro}{\siunitx_table_collect_get_aux:} % The token collection system first has to check that the next argument % does not start with an opening-brace character. If it does, the % testing is skipped and the braced token is stored. Otherwise, a check % is made against various ignored tokens. At present, things seem to be % broken with \pkg{expl3}'s \cs{peek_catcode_ignore_spaces:NTF}, so % everything is done by hand. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_collect_get: { \cs_set_eq:NN \siunitx_table_collect_next: \siunitx_table_collect_get: \cs_set_nopar:Npn \peek_execute_branches: { \if_catcode:w \exp_not:N \l_peek_token \c_group_begin_token \exp_after:wN \siunitx_table_collect_braced:n \else: \exp_after:wN \siunitx_table_collect_not_braced:N \fi: } \peek_after:NN \peek_ignore_spaces_execute_branches: } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_table_collect_init:} % The usual spin-out of basics. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_collect_init: { \toks_clear:N \l_siunitx_table_collect_toks \toks_clear:N \l_siunitx_table_collect_pre_toks \toks_clear:N \l_siunitx_table_collect_post_toks \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: { \siunitx_table_collect_init: \bool_set_false:N \l_siunitx_table_collect_pre_bool \cs_set:Npn \siunitx_table_collect_braced:n ##1 { \toks_put_right:Nn \l_siunitx_table_collect_toks { {##1} } \siunitx_table_collect_next: } } \cs_new_nopar:Npn \siunitx_table_collect_init_S: { \siunitx_number_in_init: \tl_set:Nx \l_siunitx_number_valid_tl { \exp_not:V \l_siunitx_input_complex_tl \exp_not:V \l_siunitx_input_decimal_tl \exp_not:V \l_siunitx_input_digit_tl \exp_not:V \l_siunitx_input_exponent_tl \exp_not:V \l_siunitx_input_ignore_tl \exp_not:V \l_siunitx_input_uncert_close_tl \exp_not:V \l_siunitx_input_uncert_open_tl \exp_not:V \l_siunitx_input_sign_tl \exp_not:V \l_siunitx_input_symbol_tl } \bool_set_true:N \l_siunitx_table_collect_pre_bool \cs_set:Npn \siunitx_table_collect_braced:n ##1 { \bool_if:NTF \l_siunitx_table_collect_pre_bool { \toks_put_right:Nn \l_siunitx_table_collect_pre_toks { {##1} } } { \bool_set_true:N \l_siunitx_table_collect_post_bool \toks_put_right:Nn \l_siunitx_table_collect_post_toks { {##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. The % print function is redefined so that it only actually does stuff once. % As each cell is a group anyway, there is no need to save the % definition of \cs{siunitx_table_print:}, as it will re-appear on its % own. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_collect_newline: { \siunitx_table_print: \cs_set_eq:NN \siunitx_table_print: \prg_do_nothing: \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 \tex_ignorespaces:D { \token_if_eq_meaning:NNF #1 \tex_unskip:D { \siunitx_table_collect_not_braced_aux_i:N #1 } } \siunitx_table_collect_next: } \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 { \cs:w \end \endtabular \scan_stop: \siunitx_table_print: } \siunitx_table_collect_not_braced_aux_ii:N \token_if_eq_meaning:NNT \siunitx_table_collect_next: \siunitx_table_collect_get: { \token_if_eq_meaning:NNTF #1 \tabularnewline { \cs_set_eq:NN \siunitx_table_collect_next: \siunitx_table_collect_newline: } { \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 { \toks_put_right:Nn \l_siunitx_table_collect_toks {#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 { \toks_put_right:Nn \l_siunitx_table_collect_post_toks {#1} } { \tl_if_in:NnTF \l_siunitx_number_valid_tl {#1} { \bool_set_false:N \l_siunitx_table_collect_pre_bool \toks_put_right:Nn \l_siunitx_table_collect_toks {#1} } { \siunitx_table_collect_expand:N #1 } } } % \end{macrocode} %\end{macro} % %\subsection{Table printing: general code} % %\begin{macro}{\c_siunitx_one_fill_skip} % A fixed skip of one \texttt{fill}. % \begin{macrocode} \skip_new:N \c_siunitx_one_fill_skip \skip_set:Nn \c_siunitx_one_fill_skip { \c_zero_skip plus 1 fill } % \end{macrocode} %\end{macro} % %\begin{macro}{\c_siunitx_table_correction_skip} %\begin{macro}{\siunitx_colortbl_check:} %\begin{macro}{\siunitx_table_colortbl_correction:} % If the package \pkg{colortbl} is loaded, there is a need to allow % that it changes how centring is carried out. % \begin{macrocode} \skip_new:N \c_siunitx_table_correction_skip \cs_new_nopar:Npn \siunitx_colortbl_check: { \@ifpackageloaded { colortbl } { \skip_set:Nn \c_siunitx_table_correction_skip { \c_zero_skip plus -0.5 fill } } { \skip_set:Nn \c_siunitx_table_correction_skip { \c_zero_skip } } } \AtBeginDocument { \siunitx_colortbl_check: } \cs_new_nopar:Npn \siunitx_table_colortbl_correction: { \skip_horizontal:n { \c_siunitx_table_correction_skip } \tex_kern:D \c_zero_skip } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_table_align_left:n} %\begin{macro}{\siunitx_table_align_right:n} % These are simple shortcuts to keep life clearer in the rest of the % code. The idea is that the kern acts as a \enquote{stop} for the % horizontal skip. The correction for \pkg{colortbl} is separate as the % spacing needs to be explicitly deleted. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_align_left:n #1 { \siunitx_table_colortbl_correction: \skip_horizontal:n {#1} \tex_kern:D \c_zero_skip } \cs_new_nopar:Npn \siunitx_table_align_right:n #1 { \skip_horizontal:n { \c_siunitx_one_fill_skip - #1 } \tex_kern:D \c_zero_skip \siunitx_table_colortbl_correction: } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Printing units in \texttt{s} columns} % % The easiest type of printing is the \texttt{s} column. Here, there is % no real problem with alignment. All that has to happen is to print the % collected input as the argument to the internal part of an \cs{si} % function. % %\begin{macro}{\l_siunitx_table_unit_align_skip} % The spacing used is stored as a skip, which needs to be set up first. % \begin{macrocode} \skip_new:N \l_siunitx_table_unit_align_skip % \end{macrocode} %\end{macro} % % \begin{macrocode} \keys_define:nn { siunitx } { table-align-units .choice:, table-align-units / center .code:n = { \skip_set:Nn \l_siunitx_table_unit_align_skip { \c_zero_skip plus 0.5 fill } }, table-align-units / centre .code:n = { \skip_set:Nn \l_siunitx_table_unit_align_skip { \c_zero_skip plus 0.5 fill } }, table-align-units / left .code:n = { \skip_set:Nn \l_siunitx_table_unit_align_skip { \c_zero_skip } }, table-align-units / right .code:n = { \skip_set:Nn \l_siunitx_table_unit_align_skip { \c_zero_skip plus 1 fill } }, } \keys_set:nn { siunitx } { table-align-units = centre } % \end{macrocode} % %\begin{macro}{\siunitx_table_print_s:} % Actually printing an \texttt{s} column is not very complex. There is % some spacing to do at each side, with the main part of the job being % to print the material using the internal version of \cs{si}. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_s: { \siunitx_table_align_left:n { \l_siunitx_table_unit_align_skip } \siunitx_unit_output:Vn \l_siunitx_table_collect_toks { } \siunitx_table_align_right:n { \l_siunitx_table_unit_align_skip } } % \end{macrocode} %\end{macro} % %\subsection{Formatting and printing in tables} % % With the content grabbed, the next stage is to turn it into formatted % output then print it. Most of the formatting is done elsewhere, so % most of the work here is in printing. % %\begin{macro}{\l_siunitx_table_centre_decimal_bool} % A switch for the basic \enquote{decimal marker in the middle} % mode. % \begin{macrocode} \bool_new:N \l_siunitx_table_centre_decimal_bool % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_table_fill_box} % A box which is only ever filled with \texttt{fil} glue, for padding % out numbers. % \begin{macrocode} \box_new:N \l_siunitx_table_fill_box % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_table_fill_dim} % Calculating the fill needed can be a bit complicated, so is best % done using a dedicated dimension. % \begin{macrocode} \dim_new:N \l_siunitx_table_fill_dim % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_table_pre_box} %\begin{macro}{\l_siunitx_table_post_box} % Boxes for the content before and after the numerical part. % \begin{macrocode} \box_new:N \l_siunitx_table_pre_box \box_new:N \l_siunitx_table_post_box % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_table_result_box} % The box which is actually needed for printing. % \begin{macrocode} \box_new:N \l_siunitx_table_result_box % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_table_exponent_dim} %\begin{macro}{\l_siunitx_table_integer_dim} %\begin{macro}{\l_siunitx_table_mantissa_dim} %\begin{macro}{\l_siunitx_table_marker_dim} %\begin{macro}{\l_siunitx_table_result_dim} %\begin{macro}{\l_siunitx_table_uncert_dim} % Dimensions for the various model measurements. % \begin{macrocode} \dim_new:N \l_siunitx_table_exponent_dim \dim_new:N \l_siunitx_table_integer_dim \dim_new:N \l_siunitx_table_mantissa_dim \dim_new:N \l_siunitx_table_marker_dim \dim_new:N \l_siunitx_table_result_dim \dim_new:N \l_siunitx_table_uncert_dim % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_table_model_prop} % To store the model version of a number, used when reserving space. % \begin{macrocode} \prop_new:N \l_siunitx_table_model_prop % \end{macrocode} %\end{macro} % %\begin{macro}{\l_siunitx_table_text_align_skip} %\begin{macro}{\l_siunitx_table_number_align_skip} % Skips for aligning text and numbers. % \begin{macrocode} \skip_new:N \l_siunitx_table_number_align_skip \skip_new:N \l_siunitx_table_text_align_skip % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_siunitx_table_auto_bool} %\begin{macro}{\l_siunitx_table_complex_decimal_int} %\begin{macro}{\l_siunitx_table_complex_integer_int} %\begin{macro}{\l_siunitx_table_decimal_int} %\begin{macro}{\l_siunitx_table_exponent_int} %\begin{macro}{\l_siunitx_table_integer_int} %\begin{macro}{\l_siunitx_table_uncert_int} %\begin{macro}{\l_siunitx_table_parse_only_bool} %\begin{macro}{\l_siunitx_table_pre_tl} %\begin{macro}{\l_siunitx_table_post_tl} %\begin{macro}{\l_siunitx_table_sign_exponent_bool} %\begin{macro}{\l_siunitx_table_sign_manitssa_bool} % As usual, set up the options. % \begin{macrocode} \keys_define:nn { siunitx } { table-align-numbers .choice:, table-align-numbers / centre .code:n = { \skip_set:Nn \l_siunitx_table_number_align_skip { \c_zero_skip plus 0.5 fill } \bool_set_false:N \l_siunitx_table_centre_decimal_bool }, table-align-numbers / center .code:n = { \skip_set:Nn \l_siunitx_table_number_align_skip { \c_zero_skip plus 0.5 fill } \bool_set_false:N \l_siunitx_table_centre_decimal_bool }, table-align-numbers / centre-decimal-marker .code:n = { \skip_set:Nn \l_siunitx_table_number_align_skip { \c_zero_skip plus 0.5 fill } \bool_set_true:N \l_siunitx_table_centre_decimal_bool }, table-align-numbers / center-decimal-marker .code:n = { \skip_set:Nn \l_siunitx_table_number_align_skip { \c_zero_skip plus 0.5 fill } \bool_set_true:N \l_siunitx_table_centre_decimal_bool }, table-align-numbers / left .code:n = { \skip_set:Nn \l_siunitx_table_number_align_skip { \c_zero_skip } \bool_set_false:N \l_siunitx_table_centre_decimal_bool }, table-align-numbers / right .code:n = { \skip_set:Nn \l_siunitx_table_number_align_skip { \c_zero_skip plus 1 fill } \bool_set_false:N \l_siunitx_table_centre_decimal_bool }, table-align-text .choice:, table-align-text / center .code:n = { \skip_set:Nn \l_siunitx_table_text_align_skip { \c_zero_skip plus 0.5 fill } }, table-align-text / centre .code:n = { \skip_set:Nn \l_siunitx_table_text_align_skip { \c_zero_skip plus 0.5 fill } }, table-align-text / left .code:n = { \skip_set:Nn \l_siunitx_table_text_align_skip { \c_zero_skip } }, table-align-text / right .code:n = { \skip_set:Nn \l_siunitx_table_text_align_skip { \c_zero_skip plus 1 fill } }, table-auto-round .bool_set:N = \l_siunitx_table_auto_bool, table-figures-complex-decimal .int_set:N = \l_siunitx_table_complex_decimal_int , table-figures-complex-integer .int_set:N = \l_siunitx_table_complex_integer_int , table-figures-decimal .int_set:N = \l_siunitx_table_decimal_int , table-figures-exponent .int_set:N = \l_siunitx_table_exponent_int, table-figures-integer .int_set:N = \l_siunitx_table_integer_int , table-figures-uncertainty .int_set:N = \l_siunitx_table_uncert_int , table-parse-only .bool_set:N = \l_siunitx_table_parse_only_bool, table-space-text-pre .tl_set:N = \l_siunitx_table_pre_tl, table-space-text-post .tl_set:N = \l_siunitx_table_post_tl, table-sign-exponent .bool_set:N = \l_siunitx_table_sign_exponent_bool, table-sign-mantissa .bool_set:N = \l_siunitx_table_sign_mantissa_bool } \keys_set:nn { siunitx } { table-align-numbers = centre-decimal-marker, table-align-text = centre, table-figures-decimal = 2, table-figures-integer = 3 } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_table_print_S:} % The main printing function does a simple test: was there anything % found that counts as a number. If there was, most of the detail % is handled elsewhere. If there is only test (such as a heading) % then it can be printed. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S: { \bool_if:NTF \l_siunitx_table_collect_pre_bool { \siunitx_table_align_left:n { \l_siunitx_table_text_align_skip } \toks_use:N \l_siunitx_table_collect_pre_toks \siunitx_table_align_right:n { \l_siunitx_table_text_align_skip } } { \siunitx_table_align_left:n { \l_siunitx_table_number_align_skip } \siunitx_table_print_S_aux: \siunitx_table_align_right:n { \l_siunitx_table_number_align_skip } } } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{\siunitx_table_print_S_aux:} % The auxiliary function now splits the path. If the number is only % being parsed, then it is printed with no more fuss. Otherwise, there % is a second choice based on the alignment approach. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_aux: { \bool_if:NTF \l_siunitx_table_parse_only_bool { \siunitx_number_output:V \l_siunitx_table_collect_toks } { \bool_if:NTF \l_siunitx_table_centre_decimal_bool { \siunitx_table_print_S_centred: } { \siunitx_table_print_S_reserved: } } } % \end{macrocode} %\end{macro} % %\begin{macro}[aux]{\siunitx_table_print_S_parse:} % A modified version of the number parser for tables. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_parse: { \bool_set_false:N \l_siunitx_error_bool \siunitx_number_in_parse:V \l_siunitx_table_collect_toks \bool_if:NF \l_siunitx_error_bool { \siunitx_number_process: \siunitx_number_format: \siunitx_number_output_colour: } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_table_print_S_centred:} % When centring the decimal marker, the logic is relatively simple. % First, box up the integer part of the number, the entire number and % the decimal marker itself. There is then a measurement to see % which part of the number is bigger: before or after the decimal % marker. Based on that, a path is chosen. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_centred: { \siunitx_table_print_S_centred_ends: \dim_compare:nNnTF { \box_wd:N \l_siunitx_table_pre_box } = { \c_zero_skip } { \toks_use:N \l_siunitx_table_collect_pre_toks } { \box_use:N \l_siunitx_table_pre_box } \siunitx_table_print_S_parse: \siunitx_table_print_S_measure:Nnn \l_siunitx_number_out_prop { integer } { mantissa } \siunitx_table_print_S_measure:Nnn \l_siunitx_number_out_prop { marker } { mantissa } \siunitx_table_print_S_measure:Nnn \l_siunitx_number_out_prop { result } { } \box_set_eq:NN \l_siunitx_table_result_box \l_siunitx_tmp_box \dim_set:Nn \l_siunitx_table_fill_dim { \l_siunitx_table_result_dim - \l_siunitx_table_integer_dim } \prop_if_in:NnT \l_siunitx_number_out_prop { mantissa-decimal-marker } { \dim_set:Nn \l_siunitx_table_fill_dim { \l_siunitx_table_fill_dim - \l_siunitx_table_marker_dim } } \dim_compare:nNnTF { \l_siunitx_table_integer_dim } > { \l_siunitx_table_fill_dim } { \siunitx_table_print_S_centred_integer: } { \siunitx_table_print_S_centred_decimal: } \box_use:N \l_siunitx_table_post_box } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{\siunitx_table_print_S_centred_ends:} % Here, the material before and after the numerical content is boxed up. % The shorter one is then re-boxed so that both sides are the same % length: this stops the alignment going out. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_centred_ends: { \hbox_set:Nn \l_siunitx_table_pre_box { { \toks_use:N \l_siunitx_table_collect_pre_toks } } \hbox_set:Nn \l_siunitx_table_post_box { \toks_use:N \l_siunitx_table_collect_post_toks } \dim_compare:nNnTF { \box_wd:N \l_siunitx_table_pre_box } > { \box_wd:N \l_siunitx_table_post_box } { \hbox_set_to_wd:Nnn \l_siunitx_table_post_box { \box_wd:N \l_siunitx_table_pre_box } { \hbox_unpack_clear:N \l_siunitx_table_post_box \tex_hfil:D } } { \hbox_set_to_wd:Nnn \l_siunitx_table_pre_box { \box_wd:N \l_siunitx_table_post_box } { \tex_hfil:D \hbox_unpack_clear:N \l_siunitx_table_pre_box } } } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{\siunitx_table_print_S_centred_integer:} %\begin{macro}[aux]{\siunitx_table_print_S_centred_decimal:} % Actually printing the content is a case of calculating a suitable % filler box, then printing it and the content. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_centred_integer: { \dim_set:Nn \l_siunitx_table_fill_dim { \l_siunitx_table_integer_dim - \l_siunitx_table_fill_dim } \hbox_set_to_wd:Nnn \l_siunitx_table_fill_box { \l_siunitx_table_fill_dim } { \tex_hfil:D } \box_use:N \l_siunitx_table_result_box \box_use:N \l_siunitx_table_fill_box } \cs_new_nopar:Npn \siunitx_table_print_S_centred_decimal: { \dim_set:Nn \l_siunitx_table_fill_dim { \l_siunitx_table_fill_dim - \l_siunitx_table_integer_dim } \hbox_set_to_wd:Nnn \l_siunitx_table_fill_box { \l_siunitx_table_fill_dim } { \tex_hfil:D } \box_use:N \l_siunitx_table_fill_box \box_use:N \l_siunitx_table_result_box } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_table_print_S_reserved:} % Sorting out a number with reserved space means checking each part % in turn. After sorting out the ends, a model number is constructed, % and this is then used by the various sub-routines to get the spacing % correct. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_reserved: { \siunitx_table_print_S_reserved_ends: \box_use:N \l_siunitx_table_pre_box \siunitx_table_print_S_model_create: \bool_if:NT \l_siunitx_table_auto_bool { \int_set:Nn \l_siunitx_process_places_int { \l_siunitx_table_decimal_int } \tl_set:Nn \l_siunitx_round_tl { places } } \siunitx_table_print_S_parse: \intexpr_compare:nNnTF { \l_siunitx_table_integer_int + \l_siunitx_table_decimal_int } > { \c_zero } { \siunitx_table_print_S_reserved_mantissa: } { \prop_if_in:NnT \l_siunitx_number_out_prop { mantissa-result } { \msg_warning:nn { siunitx } { table-partial-number } } } \intexpr_compare:nNnTF { \l_siunitx_table_complex_integer_int + \l_siunitx_table_complex_decimal_int } > { \c_zero } { \siunitx_table_print_S_reserved_complex: } { \prop_if_in:NnT \l_siunitx_number_out_prop { complex-result } { \msg_warning:nn { siunitx } { table-partial-number } } } \intexpr_compare:nTF { \l_siunitx_table_exponent_int > \c_zero } { \siunitx_table_print_S_reserved_exponent: } { \prop_if_in:NnT \l_siunitx_number_out_prop { exponent-result } { \msg_warning:nn { siunitx } { table-partial-number } } } \box_use:N \l_siunitx_table_post_box } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_table_print_S_reserved_ends:} % First, the reserved space needs to be worked out by setting the % model material. The the ends are typeset. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_reserved_ends: { \hbox_set:Nn \l_siunitx_tmp_box { \l_siunitx_table_pre_tl } \hbox_set_to_wd:Nnn \l_siunitx_table_pre_box { \box_wd:N \l_siunitx_tmp_box } { \tex_hfil:D { \toks_use:N \l_siunitx_table_collect_pre_toks } } \hbox_set:Nn \l_siunitx_tmp_box { \l_siunitx_table_post_tl } \hbox_set_to_wd:Nnn \l_siunitx_table_post_box { \box_wd:N \l_siunitx_tmp_box } { \toks_use:N \l_siunitx_table_collect_post_toks \tex_hfil:D } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_table_print_S_model_create:} %\begin{macro}[aux]{\siunitx_table_print_S_model_aux:nn} % A model value is created from the various numbers set up as % options. The main formatting routine is used to get everything sorted % out, so that there is no code copying here. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_model_create: { \prop_clear:N \l_siunitx_number_in_prop \siunitx_table_print_S_model_aux:nn { integer } { mantissa-integer } \siunitx_table_print_S_model_aux:nn { decimal } { mantissa-decimal } \siunitx_table_print_S_model_aux:nn { uncert } { mantissa-uncertainty } \siunitx_table_print_S_model_aux:nn { exponent } { exponent-integer } \intexpr_compare:nNnF { \l_siunitx_table_integer_int + \l_siunitx_table_decimal_int } = { \c_zero } { \prop_put:Nnn \l_siunitx_number_in_prop { mantissa } { true } } \intexpr_compare:nT { \l_siunitx_table_decimal_int > \c_zero } { \prop_put:NnV \l_siunitx_number_in_prop { mantissa-decimal-marker } \l_siunitx_output_decimal_tl } \bool_if:NT \l_siunitx_table_sign_mantissa_bool { \prop_put:Nnn \l_siunitx_number_in_prop { mantissa-sign } { - } } \intexpr_compare:nT { \l_siunitx_table_exponent_int > \c_zero } { \bool_if:NT \l_siunitx_table_sign_exponent_bool { \prop_put:Nnn \l_siunitx_number_in_prop { exponent-sign } { - } } } \siunitx_number_process: \siunitx_number_format: \prop_set_eq:NN \l_siunitx_table_model_prop \l_siunitx_number_out_prop } \cs_new_nopar:Npn \siunitx_table_print_S_model_aux:nn #1#2 { \tl_set:Nx \l_siunitx_tmpa_tl { \prg_replicate:nn { \int_use:c { l_siunitx_table_ #1 _int } } { 8 } } \tl_if_empty:NF \l_siunitx_tmpa_tl { \prop_put:NnV \l_siunitx_number_in_prop {#2} \l_siunitx_tmpa_tl \prop_put:Nnn \l_siunitx_number_in_prop {#1} { true } } } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_table_print_S_reserved_mantissa:} %\begin{macro}[aux]{\siunitx_table_print_S_reserved_mantissa_aux:n} % Printing the mantissa is done by measuring the integer part of the % model and the real number, and padding out if necessary. Everything % else is straight forward. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_reserved_mantissa: { \siunitx_table_print_S_reserved_mantissa_aux:n { mantissa } \siunitx_table_print_S_measure:Nnn \l_siunitx_table_model_prop { mantissa } { } \siunitx_table_print_S_get_mantissa:Nn \l_siunitx_number_out_prop { } \hbox_set_to_wd:Nnn \l_siunitx_table_result_box { \l_siunitx_table_mantissa_dim } { \box_use:N \l_siunitx_table_fill_box \siunitx_print:nV { number } \l_siunitx_tmpa_tl \tex_hfil:D } \box_use_clear:N \l_siunitx_table_result_box \siunitx_table_print_S_reserved_uncert:n { mantissa } } \cs_new_nopar:Npn \siunitx_table_print_S_reserved_mantissa_aux:n #1 { \siunitx_table_print_S_measure:Nnn \l_siunitx_table_model_prop { integer } {#1} \siunitx_table_print_S_get_integer:Nn \l_siunitx_number_out_prop {#1} \box_clear:N \l_siunitx_tmp_box \tl_if_empty:NF \l_siunitx_tmpa_tl { \hbox_set:Nn \l_siunitx_tmp_box { \siunitx_print:nV { number } \l_siunitx_tmpa_tl } } \hbox_set_to_wd:Nnn \l_siunitx_table_fill_box { \l_siunitx_table_integer_dim - \box_wd:N \l_siunitx_tmp_box } { \tex_hfil:D } } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_table_print_S_reserved_complex:} % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_reserved_complex: { } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_table_print_S_reserved_uncert:n} %\begin{macro}[aux]{\siunitx_table_print_S_reserved_uncert_aux:n} % The uncertainty code is generalised for both real and complex parts. % A lot of the logic is similar to the exponent part (the \cs{pm} % symbol) or the mantissa (the number measuring). So some of the % code is shared. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_reserved_uncert:n #1 { \bool_if:NT \l_siunitx_uncert_sep_bool { \intexpr_compare:nTF { \l_siunitx_table_uncert_int > \c_zero } { \siunitx_table_print_S_reserved_uncert_aux:n {#1} } { \prop_if_in:NnT \l_siunitx_number_out_prop { #1 -uncertainty } { \msg_warning:nn { siunitx } { table-partial-number } } } } } \cs_new_nopar:Npn \siunitx_table_print_S_reserved_uncert_aux:n #1 { \siunitx_table_print_S_reserved_uncert_pm:n {#1} \siunitx_table_print_S_reserved_mantissa_aux:n { #1 -uncertainty } \siunitx_table_print_S_measure:Nnn \l_siunitx_table_model_prop { uncert } {#1} \siunitx_table_print_S_get_uncert:Nn \l_siunitx_number_out_prop {#1} \hbox_set_to_wd:Nnn \l_siunitx_table_result_box { \l_siunitx_table_uncert_dim } { \box_use:N \l_siunitx_table_fill_box \siunitx_print:nV { number } \l_siunitx_tmpa_tl \tex_hfil:D } \box_use_clear:N \l_siunitx_table_result_box } \cs_new_nopar:Npn \siunitx_table_print_S_reserved_uncert_pm:n #1 { \tl_clear:N \l_siunitx_tmpb_tl \siunitx_number_format_join_uncert_pm: \tl_set:Nx \l_siunitx_tmpb_tl { { } \exp_not:V \l_siunitx_tmpb_tl { } } \hbox_set:Nn \l_siunitx_table_result_box { \siunitx_print:nV { number } \l_siunitx_tmpb_tl } \prop_if_in:NnF \l_siunitx_number_out_prop { #1 -uncertainty } { \hbox_set_to_wd:Nnn \l_siunitx_table_result_box { \box_wd:N \l_siunitx_table_result_box } { \tex_hfil:D } } \box_use_clear:N \l_siunitx_table_result_box } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\siunitx_table_print_S_reserved_exponent:} %\begin{macro}[aux]{\siunitx_table_print_S_reserved_exponent_product:} %\begin{macro}[aux] % {\siunitx_table_print_S_reserved_exponent_product_aux_i:} %\begin{macro}[aux] % {\siunitx_table_print_S_reserved_exponent_product_aux_ii:} % Most of the code for the exponent is concerned with getting the % product sign correct.Other than that, the exponent result is quite % easy to handle: just print it with some filling. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_reserved_exponent: { \siunitx_table_print_S_reserved_exponent_product: \siunitx_table_print_S_measure:Nnn \l_siunitx_table_model_prop { exponent } { } \siunitx_table_print_S_get_exponent:Nn \l_siunitx_number_out_prop { } \hbox_set_to_wd:Nnn \l_siunitx_table_result_box { \l_siunitx_table_exponent_dim } { \siunitx_print:nV { number } \l_siunitx_tmpa_tl \tex_hfil:D } \box_use_clear:N \l_siunitx_table_result_box } \cs_new_nopar:Npn \siunitx_table_print_S_reserved_exponent_product: { \tl_clear:N \l_siunitx_tmpa_tl \box_clear:N \l_siunitx_table_result_box \prop_if_in:NnTF \l_siunitx_table_model_prop { mantissa-result } { \siunitx_table_print_S_reserved_exponent_product_aux_i: } { \prop_if_in:NnT \l_siunitx_table_model_prop { complex-result } { \siunitx_table_print_S_reserved_exponent_product_aux_i: } } \box_use_clear:N \l_siunitx_table_result_box } \cs_new_nopar:Npn \siunitx_table_print_S_reserved_exponent_product_aux_i: { \tl_set_eq:NN \l_siunitx_tmpa_tl \l_siunitx_exponent_product_tl \bool_if:NT \l_siunitx_tight_bool { \tl_set:Nx \l_siunitx_tmpa_tl { { \exp_not:V \l_siunitx_tmpa_tl } } } \tl_set:Nx \l_siunitx_tmpa_tl { \exp_not:N \ensuremath { { } \exp_not:V \l_siunitx_tmpa_tl { } } } \hbox_set:Nn \l_siunitx_table_result_box { \siunitx_print:nV { number } \l_siunitx_tmpa_tl } \prop_if_in:NnTF \l_siunitx_number_out_prop { exponent-result } { \prop_if_in:NnF \l_siunitx_number_out_prop { mantissa-result } { \prop_if_in:NnF \l_siunitx_number_out_prop { complex-result } { \siunitx_table_print_S_reserved_exponent_product_aux_ii: } } } { \siunitx_table_print_S_reserved_exponent_product_aux_ii: } } \cs_new_nopar:Npn \siunitx_table_print_S_reserved_exponent_product_aux_ii: { \hbox_set_to_wd:Nnn \l_siunitx_table_result_box { \box_wd:N \l_siunitx_table_result_box } { \tex_hfil:D } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_table_print_S_measure:Nnn} % The measuring code recovers whatever is needed into % \cs{l_siunitx_tmpa_tl} (as this is internal code, that is okay). % The content is then boxed up and measured: if there is nothing to do, % a bit of time can be saved by not boxing up at all. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_measure:Nnn #1#2#3 { \use:c { siunitx_table_print_S_get_ #2 :Nn } #1 {#3} \tl_if_empty:NTF \l_siunitx_tmpa_tl { \dim_set:cn { l_siunitx_table_ #2 _dim } { \c_zero_skip } } { \hbox_set:Nn \l_siunitx_tmp_box { \siunitx_print:nV { number } \l_siunitx_tmpa_tl } \dim_set:cn { l_siunitx_table_ #2 _dim } { \box_wd:N \l_siunitx_tmp_box } } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_table_print_S_get_exponent:Nn} % Getting the exponent part is quite easy. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_get_exponent:Nn #1#2 { \tl_clear:N \l_siunitx_tmpa_tl \prop_if_in:NnT #1 { exponent-result } { \prop_get:NnN #1 { exponent-result } \l_siunitx_tmpa_tl } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_table_print_S_get_integer:Nn} % Getting the integer part of a number means that the sign also has be % considered, even if there is no actual integer. This leas to a % slightly odd approach here. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_get_integer:Nn #1#2 { \tl_clear:N \l_siunitx_tmpa_tl \tl_clear:N \l_siunitx_tmpb_tl \prop_if_in:NnT #1 { #2 -sign } { \prop_get:NnN #1 { #2 -sign } \l_siunitx_tmpa_tl } \prop_if_in:NnT #1 { #2 -integer } { \prop_get:NnN #1 { #2 -integer } \l_siunitx_tmpb_tl } \tl_put_right:NV \l_siunitx_tmpa_tl \l_siunitx_tmpb_tl } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_table_print_S_get_mantissa:Nn} % The mantissa without any uncertainty is needed by the reserved % space routine. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_get_mantissa:Nn #1#2 { \tl_clear:N \l_siunitx_tmpa_tl \prop_if_in:NnT #1 { mantissa } { \prop_get:NnN #1 { mantissa } \l_siunitx_tmpa_tl } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_table_print_S_get_marker:Nn} % The decimal marker is always going to be boxed up using the % standard version, not any possible copied value. So the code can be % kept quite clear. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_get_marker:Nn #1#2 { \tl_set:Nx \l_siunitx_tmpa_tl { \exp_not:N \ensuremath { \exp_not:V \l_siunitx_output_decimal_tl } } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_table_print_S_get_result:Nn} % Getting the result values is easy. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_get_result:Nn #1#2 { \tl_clear:N \l_siunitx_tmpa_tl \prop_if_in:NnT #1 { result } { \prop_get:NnN #1 { result } \l_siunitx_tmpa_tl } } % \end{macrocode} %\end{macro} %\begin{macro}{\siunitx_table_print_S_get_uncert:Nn} % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_print_S_get_uncert:Nn #1#2 { \tl_clear:N \l_siunitx_tmpa_tl \prop_if_in:NnT #1{ #2 -uncertainty } { \prop_get:NnN #1 { #2 -uncertainty } \l_siunitx_tmpa_tl } } % \end{macrocode} %\end{macro} % %\subsection{Direct printing in \texttt{S} columns} % % When number parsing is turned off the usual approach to printing % tabular material is not suitable. Instead, the strategy used by % \pkg{dcolumn} can be applied, which requires the decimal marker to % be made active in maths mode. % %\begin{macro}{\siunitx_table_direct:} % The main part of the system simply makes a choice about the % methods to use. % \begin{macrocode} \cs_new_nopar:Npn \siunitx_table_direct: { \m@th \bool_if:NTF \l_siunitx_table_centre_decimal_bool { \siunitx_table_direct_centred: } { \siunitx_table_direct_reserved: } } % \end{macrocode} %\end{macro} % %\begin{macro}{\siunitx_table_direct_centred:} %\begin{macro}[aux]{\siunitx_table_direct_centred_aux:N} %\begin{macro}{\siunitx_table_direct_centred_end:} % When centring the content about a decimal marker, the trick is % to collect everything into two boxes and then compare the sizes. % In that sense this is very similar to the normal method, except that % it will work with non-numerical input. % \begin{macrocode} \char_make_active:N \@ \cs_new_nopar:Npn \siunitx_table_direct_centred: { \cs_set_eq:NN \siunitx_table_print: \siunitx_table_direct_centred_end: \hbox_set:Nn \l_siunitx_tmp_box { \ensuremath { \l_siunitx_output_decimal_tl } } \hbox_set_to_wd:Nnn \l_siunitx_table_post_box { \box_wd:N \l_siunitx_tmp_box } { \tex_hfil:D } \hbox_set:Nn \l_siunitx_table_pre_box \c_group_begin_token \c_math_shift_token \tl_map_function:NN \l_siunitx_input_decimal_tl \siunit_table_direct_centred_aux:N } \cs_new_nopar:Npn \siunit_table_direct_centred_aux:N #1 { \char_set_lccode:nn { `\@ } { `#1 } \char_set_mathcode:nn { `#1 } { 32768 } \tl_to_lowercase:n { \cs_set_nopar:Npn @ } { \c_math_shift_token \c_group_end_token \hbox_set:Nn \l_siunitx_table_post_box \c_group_begin_token \c_math_shift_token \l_siunitx_output_decimal_tl } } \char_make_letter:N \@ \cs_new_nopar:Npn \siunitx_table_direct_centred_end: { \c_math_shift_token \c_group_end_token \dim_compare:nNnTF { \box_wd:N \l_siunitx_table_pre_box } > { \box_wd:N \l_siunitx_table_post_box } { \hbox_set_to_wd:Nnn \l_siunitx_table_post_box { \box_wd:N \l_siunitx_table_pre_box } { \hbox_unpack:N \l_siunitx_table_post_box \tex_hfil:D } } { \hbox_set_to_wd:Nnn \l_siunitx_table_pre_box { \box_wd:N \l_siunitx_table_post_box } { \tex_hfil:D \hbox_unpack:N \l_siunitx_table_pre_box } } \box_use:N \l_siunitx_table_pre_box \box_use:N \l_siunitx_table_post_box } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\siunitx_table_direct_reserved:} %\begin{macro}[aux]{\siunitx_table_direct_reserved_aux:N} %\begin{macro}{\siunitx_table_direct_reserved_end:} % The plan here is to box up the entire number using the information % available about the size of the two parts. Relatively easy, % but needs a bit of measuring. The first box here does need to use % \cs{tex_hill:D} as \texttt{fil} glue will not work. % \begin{macrocode} \char_make_active:N \@ \cs_new_nopar:Npn \siunitx_table_direct_reserved: { \cs_set_eq:NN \siunitx_table_print: \siunitx_table_direct_reserved_end: \tl_set:Nx \l_siunitx_tmpa_tl { \prg_replicate:nn { \l_siunitx_table_integer_int } { 8 } } \hbox_set:Nn \l_siunitx_tmp_box { \ensuremath { \bool_if:NT \l_siunitx_table_sign_mantissa_bool { - } \l_siunitx_tmpa_tl } } \dim_set:Nn \l_siunitx_table_integer_dim { \box_wd:N \l_siunitx_tmp_box } \tl_set:Nx \l_siunitx_tmpa_tl { \prg_replicate:nn { \l_siunitx_table_decimal_int } { 8 } } \hbox_set:Nn \l_siunitx_tmp_box { \ensuremath { \l_siunitx_output_decimal_tl \l_siunitx_tmpa_tl } } \hbox_set_to_wd:Nnn \l_siunitx_table_post_box { \box_wd:N \l_siunitx_tmp_box } { \tex_hfil:D } \hbox_set_to_wd:Nnn \l_siunitx_table_pre_box { \l_siunitx_table_integer_dim } \c_group_begin_token \c_math_shift_token \tl_map_function:NN \l_siunitx_input_decimal_tl \siunit_table_direct_reserved_aux:N \tex_hfill:D } \cs_new_nopar:Npn \siunit_table_direct_reserved_aux:N #1 { \char_set_lccode:nn { `\@ } { `#1 } \char_set_mathcode:nn { `#1 } { 32768 } \tl_to_lowercase:n { \cs_set_nopar:Npn @ } { \c_math_shift_token \c_group_end_token \hbox_set_to_wd:Nnn \l_siunitx_table_post_box { \box_wd:N \l_siunitx_tmp_box } \c_group_begin_token \c_math_shift_token \l_siunitx_output_decimal_tl } } \char_make_letter:N \@ \cs_new_nopar:Npn \siunitx_table_direct_reserved_end: { \c_math_shift_token \tex_hfil:D \c_group_end_token \siunitx_table_align_left:n { \l_siunitx_table_number_align_skip } \box_use:N \l_siunitx_table_pre_box \box_use:N \l_siunitx_table_post_box \siunitx_table_align_right:n { \l_siunitx_table_number_align_skip } } % \end{macrocode} %\end{macro} %\end{macro} %\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 \mathrm { 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 \text { 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 { \cs_new_protected_nopar:cpn { 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-complex-root-token } {Duplicate complex root token '\exp_not:n{#1}' in input.} {Only one complex root token can appear in a single number.} \msg_new:nnnn { siunitx } { duplicate-decimal-token } {Duplicate decimal marker token '\exp_not:n{#1}' in input.} {Only one decimal marker token can appear in a single number.} \msg_new:nnnn { siunitx } { duplicate-exponent-token } {Duplicate exponent marker token '\exp_not:n{#1}' in input.} {Only one exponent marker token can appear in a single number.} \msg_new:nnnn { siunitx } { duplicate-quotient-token } {Duplicate quotient token.} {Only one quotient token can appear in a single number.} \msg_new:nnnn { siunitx } { duplicate-sticky-per } {Duplicate \token_to_str:N \per.} {% When the sticky-per option is on, only one \token_to_str:N \per \msg_space: \\% may appear in a unit. } \msg_new:nnnn { siunitx } { empty-arc } {Empty degree-minute-second angle.} { The angle given does not contain any numbers.} \msg_new:nnnn { siunitx } { empty-uncertainty } {Empty uncertainty given in '\exp_not:n{#1}'.} {The number given contains an empty uncertainty, which is invalid.} \msg_new:nnnn { siunitx } { ending-product-token } {Misplaced product token.} {A number cannot end with a product token.} \msg_new:nnnn { siunitx } { ending-quotient-token } {Misplaced quotient token.} {A number cannot end with a quotient token.} \msg_new:nnnn { siunitx } { invalid-arc-format } {Invalid degree-minute-second angle '\exp_not:n{#1}'.} {% Angles given in degree-minute-second format should contain one or two ';'\\% symbols to divide up the parts of the input.\\% The given input contains more than two ';' symbols.% } \msg_new:nnnn { siunitx } { invalid-number } {Invalid numerical input '\exp_not:n{#1}'.} {% The input given as a number does not make logical sense.\\% This happens, for example, if a number only contains a sign.% } \msg_new:nnnn { siunitx } { invalid-token-in-exponent } {Invalid exponent in numerical input '\exp_not:n{#1}'.} {% The exponent part of a number cannot contain an uncertainty or complex part.\\The input given appears to contain one of these in the exponent.% } \msg_new:nnnn { siunitx } { invalid-token-in-number } {Invalid token '#1' in numerical input.} {% Numbers can only contain tokens defined using the various 'input-...'\\options: the token '#1' is not set up as a valid part of a number.% } \msg_new:nnnn { siunitx } { invalid-token-in-uncertainty } {Invalid uncertainty in numerical input '\exp_not:n{#1}'.} {% The uncertainty part of a number may only contain digits or symbols.% } \msg_new:nnnn { siunitx } { literal-unit } {Literal units disabled.} {% You gave the literal input '\exp_not:n {#1}'\\% but literal unit output is disabled.% } \msg_new:nnnn { siunitx } { misplaced-sign-token } {Misplaced sign token '\exp_not:n {#1}'.} {Sign tokens can only come at the beginning of a number.} \msg_new:nnnn { siunitx } { misplaced-complex-root-token } {Misplaced complex token in numerical input '\exp_not:n {#1}'.} {% The root token must come either before or after the real digits of the\\% complex part.% } \msg_new:nnnn { siunitx } { misplaced-uncertainty-token } {Misplaced uncertainty token '\exp_not:n {#1}'.} {% The uncertainty in a number must be given between a set of delimiters.\\% These are '\exp_not:V \l_siunitx_input_uncert_open_tl' and '\exp_not:V \l_siunitx_input_uncert_close_tl' for opening and closing, respectively.% } \msg_new:nnnn { siunitx } { multi-part-range } {Numerical range with multiple parts.} {% The input '\exp_note:n {#1}' is a number which has more than one part.\\% Ranges can only contain one number in each part.% } \msg_new:nnn { siunitx } { option-not-available } {Option '#1' not available in strict mode.} \msg_new:nnn { siunitx } { option-preamble-only } {Option '#1' only available in the preamble.} \msg_new:nnnn { siunitx } { prefix-base-mismatch } {Prefix bases do not match.} {% You have asked for prefixes to be converted into a power,\\% but the bases do not match.% } \msg_new:nnn { siunitx } { prefix-only } {Prefix with no unit.} \msg_new:nnnn { siunitx } { qualifier-before-unit } {Qualifier before unit.} {Unit qualifiers have to follow after units, not before them.} \msg_new:nnnn { siunitx } { 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:nnn { siunitx } { table-partial-number } {S column does not print entire number \msg_line_context:.} \msg_new:nnnn { siunitx } { unknown-configuration-file } {Unknown configuration '#1'.} {The configuration file 'siunitx-#1.cfg' was not found.} % \end{macrocode} % %\subsection{Design-level macros} % %\begin{macro}{\DeclareBinaryPrefix} %\begin{macro}{\DeclareSIPostPower} %\begin{macro}{\DeclareSIPrefix} %\begin{macro}{\DeclareSIPrePower} %\begin{macro}{\DeclareSIQualifier} %\begin{macro}{\DeclareSIUnit} %\begin{macro}{\DeclareSIUnitWithOptions} % The macros for creating units and so on are in design name space. % Basically, a set of shuffles for arguments. % \begin{macrocode} \cs_new_protected_nopar:Npn \DeclareBinaryPrefix #1#2#3 { \siunitx_declare_prefix:Nnnn #1 {#2} { 2 } {#3} } \cs_new_protected_nopar:Npn \DeclareSIPostPower #1#2 { \siunitx_declare_power_after:Nn #1 {#2} } \cs_new_protected_nopar:Npn \DeclareSIPrefix #1#2#3 { \siunitx_declare_prefix:Nnnn #1 {#2} { 10 } {#3} } \cs_new_protected_nopar:Npn \DeclareSIPrePower #1#2 { \siunitx_declare_power_before:Nn #1 {#2} } \cs_new_protected_nopar:Npn \DeclareSIQualifier #1#2 { \siunitx_declare_qualifier:Nn #1 {#2} } \cs_new_protected_nopar:Npn \DeclareSIUnit #1#2 { \siunitx_declare_unit:Nnn #1 {#2} { } } \cs_new_protected_nopar:Npn \DeclareSIUnitWithOptions #1#2#3 { \siunitx_declare_unit:Nnn #1 {#2} {#3} } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % % None of this should be done after the preamble. % \begin{macrocode} \@onlypreamble \DeclareBinaryPrefix \@onlypreamble \DeclareSIPostPower \@onlypreamble \DeclareSIPrefix \@onlypreamble \DeclareSIPrePower \@onlypreamble \DeclareSIQualifier \@onlypreamble \DeclareSIUnit \@onlypreamble \DeclareSIUnitWithOptions % \end{macrocode} % %\subsection{Document macros} % % The user document macros are all collected together here for ease. % %\begin{macro}{\ang} % The \cs{ang} function does very little beyond setting the local % keys and passing on the input. % \begin{macrocode} \NewDocumentCommand \ang { o m } { \group_begin: \IfNoValueF {#1} { \keys_set:nn { siunitx } {#1} } \siunitx_angle_output:n {#2} \group_end: } % \end{macrocode} %\end{macro} % %\begin{macro}{\num} % The \cs{num} macro is quite simple: read the number, check it is % correct then print it. % \begin{macrocode} \NewDocumentCommand \num { o m } { \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} \NewDocumentCommand \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}{\si} % The \cs{si} macro needs to pass options through to the internal % function as well as setting them here. This is used so that options % set for a unit can be overridden on a one-off basis. % \begin{macrocode} \NewDocumentCommand \si { o m } { \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} \NewDocumentCommand \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} % The main \cs{SI} function follows the same pattern as the previous % ones. % \begin{macrocode} \NewDocumentCommand \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} \NewDocumentCommand \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. % \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 } \cs_set_eq:NN \num \siunitx_bookmark_num:w \cs_set_eq:NN \numrange \siunitx_bookmark_numrange:w \cs_set_eq:NN \si \siunitx_bookmark_si:w \cs_set_eq:NN \SI \siunitx_bookmark_SI:w \cs_set_eq:NN \SIrange \siunitx_bookmark_SIrange:w \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_bookmark_num:w} %\begin{macro}{\siunitx_bookmark_numrange:w} %\begin{macro}{\siunitx_bookmark_si:w} %\begin{macro}{\siunitx_bookmark_SI:w} %\begin{macro}{\siunitx_bookmark_SIrange:w} % To keep things fast, expandable versions of the document commmands % are created only once. These are then used if necessary to remove % and re-order arguments in an expandable fashion. % \begin{macrocode} \DeclareExpandableDocumentCommand \siunitx_bookmark_num:w { o m } {#2} \DeclareExpandableDocumentCommand \siunitx_bookmark_numrange:w { o m m } { #2 \l_siunitx_range_phrase_tl #3 } \DeclareExpandableDocumentCommand \siunitx_bookmark_si:w { o m } {#2} \DeclareExpandableDocumentCommand \siunitx_bookmark_SI:w { o m o m } { \IfNoValueF {#3} {#3} #2 ~ #4 } \DeclareExpandableDocumentCommand \siunitx_bookmark_SIrange:w { o m m m } { #2 ~ #4 \l_siunitx_range_phrase_tl #3 ~ #4 } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\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}{\celsius} %\begin{macro}{\degreeCelsius} %\begin{macro}{\coulomb} %\begin{macro}{\farad} %\begin{macro}{\gray} %\begin{macro}{\hertz} %\begin{macro}{\henry} %\begin{macro}{\joule} %\begin{macro}{\katal} %\begin{macro}{\lumen} %\begin{macro}{\lux} % A number of derived units with defined names and symbols. % \begin{macrocode} \DeclareSIUnit \becquerel { Bq } \DeclareSIUnit \celsius { \SIUnitSymbolCelsius } \DeclareSIUnit \degreeCelsius { \SIUnitSymbolCelsius } \DeclareSIUnit \coulomb { C } \DeclareSIUnit \farad { F } \DeclareSIUnit \gray { Gy } \DeclareSIUnit \hertz { Hz } \DeclareSIUnit \henry { H } \DeclareSIUnit \joule { J } \DeclareSIUnit \katal { kat } \DeclareSIUnit \lumen { lm } \DeclareSIUnit \lux { lx } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\newton} %\begin{macro}{\ohm} %\begin{macro}{\pascal} %\begin{macro}{\radian} %\begin{macro}{\siemens} %\begin{macro}{\sievert} %\begin{macro}{\steradian} %\begin{macro}{\tesla} %\begin{macro}{\volt} %\begin{macro}{\watt} %\begin{macro}{\weber} % More units. % \begin{macrocode} \DeclareSIUnit \newton { N } \DeclareSIUnit \ohm { \SIUnitSymbolOhm } \DeclareSIUnit \pascal { Pa } \DeclareSIUnit \radian { rad } \DeclareSIUnit \siemens { S } \DeclareSIUnit \sievert { Sv } \DeclareSIUnit \steradian { sr } \DeclareSIUnit \tesla { T } \DeclareSIUnit \volt { V } \DeclareSIUnit \watt { W } \DeclareSIUnit \weber { Wb } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\arcminute} %\begin{macro}{\arcsecond} %\begin{macro}{\day} %\begin{macro}{\degree} %\begin{macro}{\hectare} %\begin{macro}{\hour} %\begin{macro}{\litre} %\begin{macro}{\liter} %\begin{macro}{\minute} %\begin{macro}{\percent} %\begin{macro}{\tonne} % Non-SI, but accepted for general use. % \begin{macrocode} \DeclareSIUnitWithOptions \arcmin { \arcminute } { number-unit-separator = } \DeclareSIUnitWithOptions \arcminute { \SIUnitSymbolArcminute } { number-unit-separator = } \DeclareSIUnitWithOptions \arcsecond { \SIUnitSymbolArcsecond } { number-unit-separator = } \DeclareSIUnit \day { d } \DeclareSIUnitWithOptions \degree { \SIUnitSymbolDegree } { number-unit-separator = } \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}{\decibel} %\begin{macro}{\knot} %\begin{macro}{\mmHg} %\begin{macro}{\nauticalmile} %\begin{macro}{\neper} % There are then some day-to-day units which are accepted for use % with SI, but are not part of the official specification. % \begin{macrocode} \DeclareSIUnit \angstrom { \SIUnitSymbolAngstrom } \DeclareSIUnit \bar { bar } \DeclareSIUnit \barn { b } \DeclareSIUnit \bel { B } \DeclareSIUnit \decibel { \deci \bel } \DeclareSIUnit \knot { kn } \DeclareSIUnit \mmHg { mmHg } \DeclareSIUnit \nauticalmile { M } \DeclareSIUnit \neper { Np } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\square} %\begin{macro}{\squared} %\begin{macro}{\cubic} %\begin{macro}{\cubed} % The basic powers are also defined. % \begin{macrocode} \DeclareSIPrePower \square { 2 } \DeclareSIPostPower \squared { 2 } \DeclareSIPrePower \cubic { 3 } \DeclareSIPostPower \cubed { 3 } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\subsection{Strict application of the rules} % %\begin{macro}{\siunitx_strict_option:n} %\begin{macro}[aux]{\siunitx_strict_option_aux:n} % When sticking to the rules closely, a few options are not available. % \begin{macrocode} \keys_define:nn { siunitx } { strict .code:n = { \keys_set:nn { siunitx } { detect-italic = false, detect-mode = false, detect-weight = false, parse-numbers = true, parse-units = true, repeat-units = true, unit-product-to-power = true, use-brackets = true } \siunitx_strict_option:n { detect-italic , detect-mode , detect-weight , parse-numbers , parse-units , repeat-units , unit-product-to-power , use-brackets } \keys_define:nn { siunitx } { per-mode / repeated-symbol .code:n = { \msg_warning:nnx { siunitx } { option-not-available } { per-mode~=~repeated-symbol } } } } } \siunitx_option_deactivate:n { strict } \cs_new_nopar:Npn \siunitx_strict_option:n #1 { \clist_map_function:nN {#1} \siunitx_strict_option_aux:n } \cs_new_nopar:Npn \siunitx_strict_option_aux:n #1 { \keys_define:nn { siunitx } { #1 .code:n = { \msg_warning:nnx { siunitx} { option-not-available } {#1} } } } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Loading additional configurations} % % There is only only option for loading files: keeps things simple. % \begin{macrocode} \keys_define:nn { siunitx } { load-configurations .code:n = { \siunitx_load_configuration:n {#1} } } % \end{macrocode} % %\begin{macro}{\siunitx_load_configuration:n} %\begin{macro}[aux]{\siunitx_load_configuration_aux:n} %\begin{macro}{\c_siunitx_configuration_ext_tl} % Loading configuration files is made slightly complex by the need % to remove spaces in the file names (none of the files contain any at % all, so this is easy). Secondly, the \LaTeXe\ \cs{@onefilewithoptions} % function is used for file loading, as \LaTeX3 currently needs the % \LaTeXe\ category code stack to keep things sane. % \begin{macrocode} \cs_new:Npn \siunitx_load_configuration:n #1 { \tl_set_rescan:Nnn \l_siunitx_tmpa_tl { \char_make_ignore:N \ } {#1} \clist_map_function:NN \l_siunitx_tmpa_tl \siunitx_load_configuration_aux:n } \cs_new:Npn \siunitx_load_configuration_aux:n #1 { \tl_if_empty:nF {#1} { \file_if_exist:nTF { siunitx- #1 . \c_siunitx_configuration_ext_tl } { \@onefilewithoptions { siunitx- #1 } [ ] [ ] \c_siunitx_configuration_ext_tl } { \msg_error:nnx { siunitx } { unknown-configuration-file } {#1} } } } \tl_new:Nn \c_siunitx_configuration_ext_tl { cfg } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % % \begin{macrocode} \ProcessKeysOptions { siunitx } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % %\subsection{Support for version one} % % \begin{macrocode} %<*version-1> % \end{macrocode} % % \begin{macrocode} \ProvidesExplFile {siunitx-version-1.cfg} {\filedate} {\fileversion} {siunitx: Version 1 settings} % \end{macrocode} % % The re-arrangements made to the code in version two, and in particular % the new option names, mean that support for version one needs to be % included explicitly. % % \begin{macrocode} \keys_define:nn { siunitx } { addsign .choice: , addsign / false .meta:n = { explicit-sign = }, addsign / true .meta:n = { explicit-sign = + }, addsign .default:n = { true }, allowlitunits .meta:n = { free-standing-units = #1 }, allowlitunits .default:n = { true }, allowoptarg .meta:n = { unit-optional-argument = #1 }, allowoptargs .default:n = { true }, allowzeroexp .meta:n = { retain-zero-exponent = #1 }, allowzeroexp .default:n = { true }, % angformat & List & Conversion of angle format \\ angelsep .choice: , angelsep / cdot .code:n = { arc-separator = { } \cdot { } }, angelsep / comma .code:n = { arc-separator = { {,} } }, angelsep / fullstop .code:n = { arc-separator = { { . } } }, angelsep / med .code:n = { arc-separator = \: }, angelsep / medium .code:n = { arc-separator = \: }, angelsep / none .code:n = { arc-separator = }, angelsep / period .code:n = { arc-separator = { { . } } }, angelsep / space .code:n = { arc-separator = \text { ~ } }, angelsep / stop .code:n = { arc-separator = { { . } } }, angelsep / thick .code:n = { arc-separator = \; }, angelsep / thin .code:n = { arc-separator = \, }, angelsep / tightcdot .code:n = { arc-separator = \bgroup \cdot \egroup }, angelsep / tighttimes .code:n = { arc-separator = \bgroup \times \egroup }, angelsep / times .code:n = { arc-separator = \times }, angelsep / unknown .code:n = { arc-separator = #1 }, astroang .meta:n = { angle-symbol-over-decimal = #1 }, astroang .default:n = { true }, 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 }, detectdisplay .default:n = { true }, 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 }, fixdp .default:n = { true }, fixsf .choice: , fixsf / false .meta:n = { round-mode = none }, fixsf / true .meta:n = { round-mode = figures }, fixsf .default:n = { true }, fraction .choice: , fraction / frac .meta:n = { fraction-function = \frac }, fraction / nice .meta:n = { fraction-function = \frac }, fraction / sfrac .meta:n = { fraction-function = \sfrac }, fraction / ugly .meta:n = { fraction-function = \frac , per-mode = symbol-or-fraction }, inlinebold .meta:n = { detect-inline-weight = #1 }, log .code:n = , load .code:n = , 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 }, mathsrm .meta:x = { math-rm = \exp_not:c {#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 .code:n = , numaddn .meta:n = { input-symbols = #1 }, numcloseerr .meta:n = { input-close-uncertainty = #1 }, numdecimal .meta:n = { input-decimal-markers = #1 }, numdigits .meta:n = { input-digits = #1 }, numdiv .meta:n = { input-quotient = #1 }, numexp .meta:n = { input-exponent-markers = #1 }, numgobble .meta:n = { input-ignore = #1 }, numopenerr .meta:n = { input-open-uncertainty = #1 }, numprod .meta:n = { input-product = #1 }, numsign .meta:n = { input-signs = #1 }, obeyall .meta:n = { detect-all = #1 }, obeyall .default:n = { true }, obeybold .meta:n = { detect-weight = #1 }, obeybold .default:n = { true }, obeyitalic .meta:n = { detect-italic = #1 }, opbeyitalic .default:n = { true }, obeymode .meta:n = { detect-mode = #1 }, obeymode .default:n = { true }, openerr .meta:n = { open-bracket = #1 }, openfrac .meta:n = { open-bracket = #1 }, openrange .meta:n = { open-bracket = #1 }, padangle .choice: , padangle / all .meta:n = { add-arc-degree-zero = true, add-arc-minute-zero = true, add-arc-second-zero = true }, both .meta:n = { add-arc-degree-zero = true, add-arc-minute-zero = true, add-arc-second-zero = true }, padangle / false .meta:n = { add-arc-degree-zero = false, add-arc-minute-zero = false, add-arc-second-zero = false }, padangle / large .meta:n = { add-arc-degree-zero = true, add-arc-minute-zero = true, add-arc-second-zero = false }, padangle / none .meta:n = { add-arc-degree-zero = false, add-arc-minute-zero = false, add-arc-second-zero = false }, padangle / small .meta:n = { add-arc-degree-zero = false, add-arc-minute-zero = true, add-arc-second-zero = true }, true .meta:n = { add-arc-degree-zero = true, add-arc-minute-zero = true, add-arc-second-zero = true }, padnumber .choice: , padnumber / all .meta:n = { add-decimal-zero = true, add-integer-zero = true }, padnumber / both .meta:n = { add-decimal-zero = true, add-integer-zero = true }, padnumber / false .meta:n = { add-decimal-zero = false, add-integer-zero = false }, padnumber / leading .meta:n = { add-decimal-zero = true, add-integer-zero = false }, padnumber / none .meta:n = { add-decimal-zero = false, add-integer-zero = false }, padnumber / trailing .meta:n = { add-decimal-zero = false, add-integer-zero = true }, padnumber / true .meta:n = { add-decimal-zero = true, add-integer-zero = true }, per .choice: , per / fraction .code:n = { per-mode = fraction }, per / reciprocal .code:n = { per-mode = reciprocal }, per / slash .code:n = { per-mode = symbol }, prefixbase .code:n = , prefixproduct .code:n = , prefixsymbolic .meta:n = { prefixes-as-symbols = #1 }, prefixsymbolic .default:n = { true }, prespace .meta:n = { space-before-unit = #1 }, prespace .default:n = { true }, redefsymbols .meta:n = { redefine-symbols = #1 }, redefsymbols .default:n = { true }, repeatunits .choice: , repeatunits / false .meta:n = { repeat-units = false, unit-product-to-power = false }, repeatunits / power .meta:n = { repeat-units = false, unit-product-to-power = true }, repeatunits / true .meta:n = { repeat-units = true }, repeatunits .default:n = { true }, retainplus .meta:n = { retain-explicit-plus = #1 }, retainplus .default:n = { true }, seperr .meta:n = { separate-uncertainty = #1 }, seperr .default:n = { true }, sepfour .meta:n = { group-four-digits = true }, sepfour .default:n = { true }, sf .meta:n = { round-mode = figures, round-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 }, stickyper .default:n = { true }, strictarc .code:n = , tabalign .meta:n = { table-align-numbers = #1, table-align-text = #1, table-align-units = #1 }, tabalignexp .code:n = , tabautofit .meta:n = { table-auto-round = #1 }, tabformat .code:n = { \number_in_parse:n {#1} \prop_if_in:NnTF \l_siunitx_number_in_prop { mantissa-integer } { \prop_get:NnN \l_siunitx_number_in_prop { mantissa-integer } \l_siunitx_tmpa_tl \int_set:Nn \l_siunitx_table_integer_int { \l_siunitx_tmpa_tl } } { \int_set:Nn \l_siunitx_table_integer_int { 0 } } \prop_if_in:NnTF \l_siunitx_number_in_prop { mantissa-decimal } { \prop_get:NnN \l_siunitx_number_in_prop { mantissa-decimal } \l_siunitx_tmpa_tl \int_set:Nn \l_siunitx_table_decimal_int { \l_siunitx_tmpa_tl } } { \int_set:Nn \l_siunitx_table_decimal_int { 0 } } \prop_if_in:NnTF \l_siunitx_number_in_prop { exponent-decimal } { \prop_get:NnN \l_siunitx_number_in_prop { exponent-decimal } \l_siunitx_tmpa_tl \int_set:Nn \l_siunitx_table_exponent_int { \l_siunitx_tmpa_tl } } { \int_set:Nn \l_siunitx_table_exponent_int { 0 } } \prop_if_in:NnTF \l_siunitx_number_in_prop { mantissa-sign } { \bool_set_true:N \l_siunitx_table_sign_mantissa_bool } { \bool_set_false:N \l_siunitx_table_sign_mantissa_bool } \prop_if_in:NnTF \l_siunitx_number_in_prop { exponent-sign } { \bool_set_true:N \l_siunitx_table_sign_mantissa_bool } { \bool_set_false:N \l_siunitx_table_sign_mantissa_bool } \keys_set:nn { siunitx } { table-align-numbers = centre } }, tabnumalign .meta:n = { table-align-numbers = #1 }, tabparseonly .meta:n = { table-parse-only = #1 }, tabparseonly .default:n = { true }, tabtextalign .meta:n = { table-text-numbers = #1 }, tabunitalign .meta:n = { table-align-units = #1 }, textOmega .meta:n = { text-ohm = #1 }, textcelsius .meta:n = { text-celsius = #1 }, textdegree .meta:n = { text-degree = #1 }, textminute .meta:n = { text-arcminute = #1 }, textmode .choice: , textmode / true .meta:n = { mode = text }, textmode / false .meta:n = { mode = 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 }, tightpm .default:n = { true }, tophrase .meta:n = { range-phrase = #1 }, trapambigerr .meta:n = { use-brackets = #1 }, trapambigerr .default:n = { true }, trapambigfrac .meta:n = { use-brackets = #1 }, trapambigfrac .default:n = { true }, trapambigrange .meta:n = { use-brackets = #1 }, trapambigrange .default:n = { true }, unitcolor .meta:n = { unit-colour = #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 }, xpace .default:n = { true } } % \end{macrocode} % %\begin{macro}{\newunit} %\begin{macro}{\renewunit} %\begin{macro}{\provideunit} % The functions for creating units from version one are easy to create. % \begin{macrocode} \cs_new_eq:NN \newunit \DeclareSIUnit \cs_new_eq:NN \renewunit \DeclareSIUnit \cs_new_eq:NN \provideunit \DeclareSIUnit % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\newpower} %\begin{macro}{\renewpower} %\begin{macro}{\providepower} % Slightly more complex: an optional argument to check. A simple % assumption is made that it will be \texttt{post}: anything else % would not make sense anyway. % \begin{macrocode} \NewDocumentCommand \newpower { o m m } { \IfNoValueTF {#1} { \DeclareSIPrePower #2 {#3} } { \DeclareSIPostPower #2 {#3} } } \NewDocumentCommand \renewpower { o m m } { \IfNoValueTF {#1} { \DeclareSIPrePower #2 {#3} } { \DeclareSIPostPower #2 {#3} } } \NewDocumentCommand \providepower { o m m } { \IfNoValueTF {#1} { \DeclareSIPrePower #2 {#3} } { \DeclareSIPostPower #2 {#3} } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\newprefix} %\begin{macro}{\renewprefix} %\begin{macro}{\provideprefix} % Slightly more complex: an optional argument to check. A simple % assumption is made that it will be \texttt{post}: anything else % would not make sense anyway. % \begin{macrocode} \NewDocumentCommand \newprefix { o m m m } { \IfNoValueTF {#1} { \DeclareSIPrefix #2 {#3} {#4} } { \DeclareBinaryPrefix #2 {#3} {#4} } } \NewDocumentCommand \renewprefix { o m m m } { \IfNoValueTF {#1} { \DeclareSIPrefix #2 {#3} {#4} } { \DeclareBinaryPrefix #2 {#3} {#4} } } \NewDocumentCommand \provideprefix { o m m m } { \IfNoValueTF {#1} { \DeclareSIPrefix #2 {#3} {#4} } { \DeclareBinaryPrefix #2 {#3} {#4} } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\newqualifier} %\begin{macro}{\renewqualifier} %\begin{macro}{\providequalifier} % The functions for creating qualifiers are easy to create again. % \begin{macrocode} \cs_new_eq:NN \newqualifier \DeclareSIQualifier \cs_new_eq:NN \renewqualifier \DeclareSIQualifier \cs_new_eq:NN \providequalifier \DeclareSIQualifier % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\Square} %\begin{macro}{\ssquare} % In version 1, \cs{square} is not used with these two alternatives % preferred. % \begin{macrocode} \DeclareSIPrePower \Square { 2 } \DeclareSIPrePower \ssquare { 2 } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\BAR} %\begin{macro}{\bbar} %\begin{macro}{\Day} %\begin{macro}{\dday} %\begin{macro}{\Gray} %\begin{macro}{\ggray} % Units which are given awkward names in version one. % \begin{macrocode} \DeclareSIUnit \BAR { \bar } \DeclareSIUnit \bbar { \bar } \DeclareSIUnit \Day { \day } \DeclareSIUnit \dday { \day } \DeclareSIUnit \Gray { \gray } \DeclareSIUnit \ggray { \gray } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\atomicmass} % Slightly different: given more complete names in version two. % \begin{macrocode} \DeclareSIUnit \atomicmass { \atomicmassunit } \DeclareSIUnit \arcmin { \arcminute } \DeclareSIUnit \arcsec { \arcsecond } % \end{macrocode} %\end{macro} % %\begin{macro}{\are} %\begin{macro}{\curie} %\begin{macro}{\gal} %\begin{macro}{\millibar} %\begin{macro}{\rad} %\begin{macro}{\rem} %\begin{macro}{\roentgen} % Units which were defined in version one but are no longer listed % by the \textsc{bipm} as acceptable. % \begin{macrocode} \DeclareSIUnit \are { a } \DeclareSIUnit \curie { Ci } \DeclareSIUnit \gal { Gal } \DeclareSIUnit \millibar { \milli \bar } \DeclareSIUnit \rad { rad } \DeclareSIUnit \rem { rem } \DeclareSIUnit \roentgen { R } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\micA} %\begin{macro}{\micmol} %\begin{macro}{\micl} %\begin{macro}{\micL} %\begin{macro}{\nanog} %\begin{macro}{\micg} %\begin{macro}{\picm} %\begin{macro}{\micm} %\begin{macro}{\Sec} %\begin{macro}{\mics} %\begin{macro}{\cmc} %\begin{macro}{\dmc} %\begin{macro}{\cms} % A few abbreviations which have been renamed. % \begin{macrocode} \DeclareSIUnit \micA { \micro \ampere } \DeclareSIUnit \micmol { \micro \mole } \DeclareSIUnit \micl { \micro \litre } \DeclareSIUnit \micL { \micro \liter } \DeclareSIUnit \nanog { \nano \gram } \DeclareSIUnit \micg { \micro \gram } \DeclareSIUnit \picm { \pico \metre } \DeclareSIUnit \micm { \micro \metre } \DeclareSIUnit \Sec { \second } \DeclareSIUnit \mics { \micro \second } \DeclareSIUnit \cmc { \centi \metre \cubed } \DeclareSIUnit \dmc { \deci \metre \cubed } \DeclareSIUnit \cms { \centi \metre \squared } % \end{macrocode} %\end{macro} %\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{macrocode} % % \end{macrocode} % %\subsection{Abbreviated units} % % \begin{macrocode} %<*abbreviations> % \end{macrocode} % % \begin{macrocode} \ProvidesExplFile {siunitx-abbreviations.cfg} {\filedate} {\fileversion} {siunitx: Abbreviated units} % \end{macrocode} % % The abbreviation file contains a number of short (mainly two or % three letter) versions of the usual long names. They are divided up % into related groups, mainly to avoid an overly long list in one % place. % %\begin{macro}{\pA} %\begin{macro}{\nA} %\begin{macro}{\uA} %\begin{macro}{\mA} %\begin{macro}{\kA} % Currents. % \begin{macrocode} \DeclareSIUnit \pA { \pico \ampere } \DeclareSIUnit \nA { \nano \ampere } \DeclareSIUnit \uA { \micro \ampere } \DeclareSIUnit \mA { \milli \ampere } \DeclareSIUnit \kA { \kilo \ampere } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\Hz} %\begin{macro}{\mHz} %\begin{macro}{\kHz} %\begin{macro}{\MHz} %\begin{macro}{\GHz} %\begin{macro}{\THz} % Then frequencies. % \begin{macrocode} \DeclareSIUnit \Hz { \hertz } \DeclareSIUnit \mHz { \milli \hertz } \DeclareSIUnit \kHz { \kilo \hertz } \DeclareSIUnit \MHz { \mega \hertz } \DeclareSIUnit \GHz { \giga \hertz } \DeclareSIUnit \THz { \tera \hertz } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\fmol} %\begin{macro}{\pmol} %\begin{macro}{\nmol} %\begin{macro}{\umol} %\begin{macro}{\mmol} %\begin{macro}{\kmol} % Amounts of substance (moles). % \begin{macrocode} \DeclareSIUnit \fmol { \femto \mole } \DeclareSIUnit \pmol { \pico \mole } \DeclareSIUnit \nmol { \nano \mole } \DeclareSIUnit \umol { \micro \mole } \DeclareSIUnit \mmol { \milli \mole } \DeclareSIUnit \kmol { \kilo \mole } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\mV} %\begin{macro}{\kV} % Potentials. % \begin{macrocode} \DeclareSIUnit \mV { \milli \volt } \DeclareSIUnit \kV { \kilo \volt } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\ml} %\begin{macro}{\ul} %\begin{macro}{\mL} %\begin{macro}{\uL} % Volumes. % \begin{macrocode} \DeclareSIUnit \ml { \milli \litre } \DeclareSIUnit \ul { \micro \litre } \DeclareSIUnit \mL { \milli \liter } \DeclareSIUnit \uL { \micro \liter } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\fg} %\begin{macro}{\pg} %\begin{macro}{\ng} %\begin{macro}{\ug} %\begin{macro}{\mg} %\begin{macro}{\g} %\begin{macro}{\kg} %\begin{macro}{\amu} % Masses. % \begin{macrocode} \DeclareSIUnit \fg { \femto \gram } \DeclareSIUnit \pg { \pico \gram } \DeclareSIUnit \ng { \nano \gram } \DeclareSIUnit \ug { \micro \gram } \DeclareSIUnit \mg { \milli \gram } \DeclareSIUnit \g { \gram } \DeclareSIUnit \kg { \kilo \gram } \DeclareSIUnit \amu { \atomicmassunit } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\kJ} %\begin{macro}{\eV} %\begin{macro}{\meV} %\begin{macro}{\keV} %\begin{macro}{\MeV} %\begin{macro}{\GeV} %\begin{macro}{\TeV} %\begin{macro}{\kWh} % Energies. % \begin{macrocode} \DeclareSIUnit \kJ { \kilo\joule } \DeclareSIUnit \eV { \electronvolt } \DeclareSIUnit \meV { \milli \electronvolt } \DeclareSIUnit \keV { \kilo \electronvolt } \DeclareSIUnit \MeV { \mega \electronvolt } \DeclareSIUnit \GeV { \giga \electronvolt } \DeclareSIUnit \TeV { \tera \electronvolt } \DeclareSIUnitWithOptions \kWh { \kilo \watt \hour } { inter-unit-separator = } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\pm} %\begin{macro}{\nm} %\begin{macro}{\um} %\begin{macro}{\mm} %\begin{macro}{\cm} %\begin{macro}{\dm} %\begin{macro}{\km} % Lengths. % \begin{macrocode} \DeclareSIUnit \nm { \nano \metre } \DeclareSIUnit \pm { \pico \metre } \DeclareSIUnit \um { \micro \metre } \DeclareSIUnit \mm { \milli \metre } \DeclareSIUnit \cm { \centi \metre } \DeclareSIUnit \dm { \deci \metre } \DeclareSIUnit \km { \kilo \metre } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\s} %\begin{macro}{\as} %\begin{macro}{\fs} %\begin{macro}{\ps} %\begin{macro}{\ns} %\begin{macro}{\us} %\begin{macro}{\ms} % Finally, times. % \begin{macrocode} \DeclareSIUnit \s { \second } \DeclareSIUnit \as { \atto \second } \DeclareSIUnit \fs { \femto \second } \DeclareSIUnit \ps { \pico \second } \DeclareSIUnit \ns { \nano \second } \DeclareSIUnit \us { \micro \second } \DeclareSIUnit \ms { \milli \second } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % % \begin{macrocode} % % \end{macrocode} % %\subsection{Additional units for astronomy} % % \begin{macrocode} %<*astronomy> % \end{macrocode} % % \begin{macrocode} \ProvidesExplFile {siunitx-astronomy.cfg} {\filedate} {\fileversion} {siunitx: Units for astronomy} % \end{macrocode} % %\begin{macro}{\parsec} %\begin{macro}{\lightyear} % A few units for astronomy. % \begin{macrocode} \DeclareSIUnit \parsec { pc } \DeclareSIUnit \lightyear { ly } % \end{macrocode} %\end{macro} %\end{macro} % % \begin{macrocode} % % \end{macrocode} % %\subsection{Additional units for chemical engineering} % % \begin{macrocode} %<*chemical-engineering> % \end{macrocode} % % \begin{macrocode} \ProvidesExplFile {siunitx-chemical-engineering.cfg} {\filedate} {\fileversion} {siunitx: Units for chemical engineering} % \end{macrocode} % %\begin{macro}{\gmol} %\begin{macro}{\kgmol} %\begin{macro}{\lbmol} % Slightly odd chemical engineering units. % \begin{macrocode} \DeclareSIUnit \gmol { g \text { - } mol } \DeclareSIUnit \kgmol { kg \text { - } mol } \DeclareSIUnit \lbmol { lb \text { - } mol } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % % \begin{macrocode} % % \end{macrocode} % %\subsection{Additional units for chemistry} % % \begin{macrocode} %<*chemistry> % \end{macrocode} % % \begin{macrocode} \ProvidesExplFile {siunitx-chemistry.cfg} {\filedate} {\fileversion} {siunitx: Units for chemistry} % \end{macrocode} % %\begin{macro}{\molar} %\begin{macro}{\Molar} %\begin{macro}{\torr} % A few common units for chemistry. \cs{molar} is simply a handy % abbreviation: \cs{Molar} is common but rather questionable. % \begin{macrocode} \DeclareSIUnit \molar { \mole \per \cubic \deci \metre } \DeclareSIUnit \Molar { \textsc { m } } \DeclareSIUnit \torr { Torr } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % % \begin{macrocode} % % \end{macrocode} % %\subsection{Additional units for geophysics} % % \begin{macrocode} %<*geophysics> % \end{macrocode} % % \begin{macrocode} \ProvidesExplFile {siunitx-geophysics.cfg} {\filedate} {\fileversion} {siunitx: Units for geophysics} % \end{macrocode} % %\begin{macro}{\gon} % A single unit for geophysics. % \begin{macrocode} \DeclareSIUnit \gon { gon } % \end{macrocode} %\end{macro} % % \begin{macrocode} % % \end{macrocode} % %\subsection{Binary units} % % \begin{macrocode} %<*binary> % \end{macrocode} % % \begin{macrocode} \ProvidesExplFile {siunitx-binary.cfg} {\filedate} {\fileversion} {siunitx: Binary units} % \end{macrocode} % %\begin{macro}{\kibi} %\begin{macro}{\mebi} %\begin{macro}{\gibi} %\begin{macro}{\tebi} %\begin{macro}{\pebi} %\begin{macro}{\exbi} %\begin{macro}{\zebi} %\begin{macro}{\yobi} % The binary units as specified by the IEC. % \begin{macrocode} \DeclareBinaryPrefix \kibi { Ki } { 10 } \DeclareBinaryPrefix \mebi { Mi } { 20 } \DeclareBinaryPrefix \gibi { Gi } { 30 } \DeclareBinaryPrefix \tebi { Ti } { 40 } \DeclareBinaryPrefix \pebi { Pi } { 50 } \DeclareBinaryPrefix \exbi { Ei } { 60 } \DeclareBinaryPrefix \zebi { Zi } { 70 } \DeclareBinaryPrefix \yobi { Yi } { 80 } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\bit} %\begin{macro}{\byte} % Now the units. % \begin{macrocode} \DeclareSIUnit \bit { bit } \DeclareSIUnit \byte { B } % \end{macrocode} %\end{macro} %\end{macro} % % \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{NIST} % \emph{International System of Units from NIST}, % \url{http://physics.nist.gov/cuu/Units/index.html}. % % \bibitem{SI:2.1} % \emph{SI base units}, % \url{http://www.bipm.org/en/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