% \iffalse meta-comment %<*internal> \iffalse % %<*readme> siunitx - A comprehensive (SI) units package ============================================== Physical quantities have both numbers and units, and each physical quantity should be expressed as the product of a number and a unit. Typesetting physical quantities requires care to ensure that the combined mathematical meaning of the number-unit combination is clear. In particular, the SI units system lays down a consistent set of units with rules on how these are to be used. However, different countries and publishers have differing conventions on the exact appearance of numbers (and units). The `siunitx` package provides a set of tools for authors to typeset quantities in a consistent way. The package has an extended set of configuration options which make it possible to follow varying typographic conventions with the same input syntax. The package includes automated processing of numbers and units, and the ability to control tabular alignment of numbers. Installation ------------ The package is supplied in `dtx` format and as a pre-extracted zip file, `siunitx.tds.zip`. The later is most convenient for most users: simply unzip this in your local texmf directory . If you want to unpack the `.dtx` yourself, running `tex siunitx.dtx` will extract the package whereas `latex siunitx.dtx` will extract it and also typeset the documentation. The package requires LaTeX3 support as provided in the `l3kernel` and `l3packages` bundles. Both of these are available on [CTAN](http://www.ctan.org/) as ready-to-install zip files. Suitable versions are available in MiKTeX 2.9 and TeX Live 2012 (updating the relevant packages online may be necessary). LaTeX3, and so `siunitx`, requires the e-TeX extensions: these are available on all modern TeX systems. Typesetting the documentation requires a number of packages in addition to those needed to use the package. This is mainly because of the number of demonstration items included in the text. To compile the documentation without error, you will need the packages: - `amsmath` - `booktabs` - `cancel` - `caption` - `cleveref` - `colortbl` - `csquotes` - `datatool` - `helvet` - `mathpazo` - `multirow` - `listings` - `pgfplots` - `xcolor` % %<*internal> \fi \def\nameofplainTeX{plain} \ifx\fmtname\nameofplainTeX\else \expandafter\begingroup \fi % %<*install> \input l3docstrip.tex \keepsilent \askforoverwritefalse \preamble --------------------------------------------------------------- The siunitx package --- A comprehensive (SI) units package Maintained by Joseph Wright E-mail: joseph.wright@morningstar2.co.uk Released under the LaTeX Project Public License v1.3c or later See http://www.latex-project.org/lppl.txt --------------------------------------------------------------- \endpreamble \postamble Copyright (C) 2008-2014 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}} \file{siunitx-abbreviations.cfg} {\from{\jobname.dtx}{config,abbreviations}} \file{siunitx-binary.cfg}{\from{\jobname.dtx}{config,binary}} \file{siunitx-version-1.cfg}{\from{\jobname.dtx}{config,version-1}} } % %\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,xparse} % %<*driver> \documentclass[german,french,english,UKenglish]{l3doc} \usepackage[table]{xcolor} \usepackage{amsmath,babel,booktabs,cancel,caption,colortbl,csquotes} \usepackage{datatool,helvet,multirow,pgfplots,siunitx,xfrac,xtab} \usepackage[capitalise]{cleveref} \usepackage[final]{listings} \usepackage[osf]{mathpazo} \crefformat{section}{#2Section~#1#3} \Crefformat{section}{#2Section~#1#3} \crefformat{subsection}{#2Section~#1#3} \Crefformat{subsection}{#2Section~#1#3} \crefformat{figure}{#2Figure~#1#3} \Crefformat{figure}{#2Figure~#1#3} \crefformat{table}{#2Table~#1#3} \Crefformat{table}{#2Table~#1#3} \crefrangeformat{table}{#3Tables~#1#4 to~#5#2#6} \Crefrangeformat{table}{#3Tables~#1#4 to~#5#2#6} \crefmultiformat{table}{#2Tables~#1#3}{ and~#2#1#3}{, #2#1#3}{, and~#2#1#3} \Crefmultiformat{table}{#2Tables~#1#3}{ and~#2#1#3}{, #2#1#3}{, and~#2#1#3} % Silence annoying fp package messages \FPmessagesfalse \pgfplotsset{compat = newest} \sisetup{binary-units} \DeclareSIUnit{\KWH}{kWh} \DeclareSIPrePower\quartic{4} \DeclareSIPostPower\tothefourth{4} \DeclareSIQualifier\catalyst{cat} \DeclareSIQualifier\isotropic{i} \DeclareSIQualifier\polymer{pol} \newlength\mylength %\DisableImplementation \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % %\makeatletter % %^^A Some short cuts for the tables %\NewDocumentCommand\DescribePrefix{m}{^^A % \expandafter\SpecialUsageIndex\expandafter{\csname #1\endcsname}^^A % #1 & \cs{#1} & \expandafter\si\expandafter{\csname #1\endcsname} %} %\NewDocumentCommand\DescribeUnit{m}{^^A % \expandafter\SpecialUsageIndex\expandafter{\csname #1\endcsname}^^A % #1 & % \cs{#1} & % \expandafter\si\expandafter{\csname #1\endcsname} %} %\NewDocumentCommand\DescribeNamedUnit{mm}{^^A % \expandafter\SpecialUsageIndex\expandafter{\csname #2\endcsname}^^A % #1 & % \cs{#2} & % \expandafter\si\expandafter{\csname #2\endcsname} %} % %^^A For creating examples with nice highlighting of code, and so %^^A on; based on the system used in the listings source (lstsample). %\lst@RequireAspects{writefile} %\newsavebox{\LaTeXdemo@box} %\lstnewenvironment{LaTeXdemo}[1][code and example] % {^^A % \global\let\lst@intname\@empty % \expandafter\let\expandafter\LaTeXdemo@end % \csname LaTeXdemo@#1@end\endcsname % \@nameuse{LaTeXdemo@#1}^^A % } % {\LaTeXdemo@end} %\newcommand*\LaTeXdemo@new[3]{^^A % \expandafter\newcommand\expandafter*\expandafter % {\csname LaTeXdemo@#1\endcsname}{#2}^^A % \expandafter\newcommand\expandafter*\expandafter % {\csname LaTeXdemo@#1@end\endcsname}{#3}^^A %} %\newcommand*\LaTeXdemo@common{^^A % \setkeys{lst} % { % basicstyle = \small\ttfamily, % basewidth = 0.51em, % gobble = 3, % keywordstyle = \color{blue}, % language = [LaTeX]{TeX}, % moretexcs = % { % addto, % ampere, % ang, % angstrom, % becquerel, % bel, % bit, % bottomrule, % byte, % cancel, % candela, % centi, % color, % coulomb, % cubed, % cubic, % deci, % decibel, % degree, % degreeCelsius, % DeclareBinaryPrefix, % DeclareRobustCommand, % DeclareSIPostPower, % DeclareSIPrefix, % DeclareSIPrePower, % DeclareSIQualifier, % DeclareSIUnit, % DTLdisplaydb, % DTLforeach, % DTLiffirstrow, % DTLmul, % DTLnewdb, % DTLnewdbentry, % DTLnewrow, % farad, % fontspec, % gram, % gray, % henry, % highlight, % hour, % Hz, % joule, % kelvin, % kibi, % kilo, % kilogram, % kWh, % litre, % lumen, % lux, % mathnormal, % metre, % mebi, % micro, % midrule, % milli, % mm, % mole, % multirow, % num, % numlist, % numrange, % of, % pascal, % per, % percent, % protected, % radian, % raiseto, % robustify, % rowcolor, % second, % selectlanguage, % SendSettingsToPgf, % si, % SI, % SIlist, % SIrange, % sievert, % sisetup, % SIUnitSymbolDegree, % square, % squared, % tablenum, % tesla, % texorpdfstring, % text, % textmu, % toprule, % tothe, % translate, % unit, % volt, % watt % } % }^^A %} %\newcommand*\LaTeXdemo@input{^^A % \MakePercentComment % \catcode`\^^M=10\relax % \small % \begingroup % \setkeys{lst} % { % SelectCharTable=\lst@ReplaceInput{\^\^I}{\lst@ProcessTabulator} % }^^A % \leavevmode % \input{\jobname.tmp}^^A % \endgroup % \MakePercentIgnore %} %\LaTeXdemo@new{code and example} % {^^A % \setbox\LaTeXdemo@box=\hbox\bgroup % \lst@BeginAlsoWriteFile{\jobname.tmp}^^A % \LaTeXdemo@common % } % {^^A % \lst@EndWriteFile % \egroup % \begin{center} % \ifdim\wd\LaTeXdemo@box>0.48\linewidth\relax % \hbox to\linewidth{\box\LaTeXdemo@box\hss}^^A % \begin{minipage}{\linewidth} % \LaTeXdemo@input % \end{minipage} % \else % \begin{minipage}{0.48\linewidth} % \LaTeXdemo@input % \end{minipage} % \hfill % \begin{minipage}{0.48\linewidth} % \hbox to\linewidth{\box\LaTeXdemo@box\hss}^^A % \end{minipage} % \fi % \end{center} % } %\LaTeXdemo@new{code and float}{^^A % \lst@BeginAlsoWriteFile{siunitx.tmp}^^A % \LaTeXdemo@common %}{^^A % \lst@EndWriteFile % \LaTeXdemo@input %} %\LaTeXdemo@new{code only} % {\LaTeXdemo@common}{} % %^^A Turning of the marginpar warnings is a bit awkward. %^^A It is achieved by temporarily disabling \@latex@warning@no@line %\let\latex@addmarginpar\@addmarginpar %\let\latex@warning@no@line\@latex@warning@no@line %\def\@addmarginpar{^^A % \let\@latex@warning@no@line\@gobble % \latex@addmarginpar % \let\@latex@warning@no@line\latex@warning@no@line %} % %\ProvideDocumentCommand\opt{m}{\texttt{#1}} % %\makeatother % %\GetFileInfo{\jobname.sty} % %\title{^^A % \textsf{siunitx} --- A comprehensive (SI) units package\thanks{^^A % This file describes \fileversion, last revised \filedate.^^A % }^^A %} %\author{^^A % Joseph Wright\thanks % {^^A % E-mail: \href{mailto:joseph.wright@morningstar2.co.uk} % {\texttt{joseph.wright@morningstar2.co.uk}}^^A % }^^A %} %\date{Released \filedate} % %\maketitle % %\changes{v0.6}{2008/02/18}{First public testing release (as \pkg{si})} %\changes{v1.0}{2008/06/15}{First official release} %\changes{v1.1}{2008/09/28}{Package extended to a greater range of unit % types} %\changes{v1.2}{2009/01/22}{Correct handling for ranges of numbers % added} %\changes{v1.3}{2009/09/20}{Better definition for micro symbol} %\changes{v1.4}{2010/01/16}{Detect entire document in non-serif font} %\changes{v2.0}{2010/05/23}{Complete re-write of package to add many new % features} %\changes{v2.0c}{2010/06/07}{Mixed literal and macro units now print % more reliably} %\changes{v2.0d}{2010/06/10}{Fix error in \opt{table-format} option % concerning exponent signs} %\changes{v2.0e}{2010/06/20}{Correct behaviour of \cs{pm} in numbers % when \texttt{abbreviations} configuration is loaded: problem % introduced in v2.0c} %\changes{v2.0f}{2010/06/27}{Fix issue with spacing of multiplication % sign in text mode} %\changes{v2.0g}{2010/06/28}{Fix issue with complex numbers in % quotients} %\changes{v2.0g}{2010/06/28}{Repair broken \opt{bracket-numbers} % option} %\changes{v2.0g}{2010/06/28}{Improve handling of complex root token} %\changes{v2.0g}{2010/06/28}{Introduce localisation for text values} %\changes{v2.0h}{2010/06/29}{Actually get localisation into the % code} %\changes{v2.0j}{2010/06/30}{Ensure symbols specified in % \opt{input-symbols} are always printed in math mode} %\changes{v2.0k}{2010/07/04}{Fix for \pkg{babel} French settings with % \cs{fg} in tabular material} %\changes{v2.0l}{2010/07/07}{Further adjustments to \pkg{babel} support} %\changes{v2.0p}{2010/07/28}{Actually get change from v2.0o working} %\changes{v2.0q}{2010/07/29}{Errors with free-standing unit code fixed} %\changes{v2.0q}{2010/07/29}{Deal with bad definition of \cs{color} % by \pkg{textpos} package} %\changes{v2.0s}{2010/08/08}{Correct errors in rounding code when % precision requested is zero decimal places} %\changes{v2.0t}{2010/08/24}{Replace \cs{exp_afer:wN} in code for % \cs{per} with \cs{exp_after:wN}} %\changes{v2.0u}{2010/09/14}{Fix second possible issue with % \pkg{textpos} package and \cs{color}} %\changes{v2.0u}{2010/09/14}{Prevent infinite loop if \cs{SI} function % is used with an empty number} %\changes{v2.0v}{2010/09/26}{Internal changes reflecting \pkg{expl3} % updates} %\changes{v2.0w}{2010/09/29}{Deal with internal function used by % REV\TeX{} in tables} %\changes{v2.0x}{2010/10/05}{Fix bug when detecting single prefixes % and converting prefixes to numbers} %\changes{v2.1a}{2010/11/05}{Ensure that output of list separators is % in text mode} %\changes{v2.1a}{2010/11/05}{Print prefixes correctly in text mode % when converting to numerical value} %\changes{v2.1b}{2010/11/05}{Bug in printing code for complex part with % no number fixed} %\changes{v2.1b}{2010/11/05}{Bug in hyphen printing when detecting mode % sorted} %\changes{v2.1c}{2010/11/11}{Discourage line break between number and % unit even when it is permitted} %\changes{v2.1c}{2010/11/14}{After reviewing internals, \cs{numlist}, % \cs{numrange}, \cs{SIlist} and \cs{SIrange} are documented as % requiring text mode due to issues with spacing and line breaks} %\changes{v2.1c}{2010/11/14}{Auto-detect math mode in tables and % correct output accordingly} %\changes{v2.1e}{2010/11/22}{Fix issues with text mode symbols and % \pkg{fontspec} package} %\changes{v2.1g}{2010/12/21}{Checks on the versions of \pkg{expl3} and % \pkg{xparse} installed} %\changes{v2.1h}{2011/01/18}{Detect AMS display-like environments} %\changes{v2.1j}{2011/02/01}{Allow for loading of \pkg{inputenc} package % with no options} %\changes{v2.1k}{2011/02/09}{Bug fix when printing superscript minus % signs and using \pkg{fontspec} package} %\changes{v2.1m}{2011/03/18}{Avoid expansion of erroneous literal % units when these are forbidden} %\changes{v2.1m}{2011/03/20}{Ensure some output occurs in all cases % when \opt{round-precision} is set to \opt{0} and \opt{round-mode} % is set to \opt{places}} %\changes{v2.1n}{2011/03/31}{Consistent behaviour for % \opt{round-integer-to-decimal} when \opt{round-precision} is 0} %\changes{v2.1o}{2011/04/03}{Fix incorrect font choice when % \pkg{arev} package is loaded} %\changes{v2.1o}{2011/04/03}{Account for negative exponents % when using \opt{fixed-exponent} system} %\changes{v2.1p}{2011/04/04}{Bad table alignment when some rows % contain comparators fixed} %\changes{v2.1p}{2011/04/04}{Poor position of comparators in % numbers fixed} %\changes{v2.2a}{2011/04/15}{Fix issue with \texttt{*} tokens in % tabular preambles} %\changes{v2.2a}{2011/04/15}{Expand macros with arguments correctly % in tables} %\changes{v2.2a}{2011/04/16}{Group digits for input containing symbolic % entries} %\changes{v2.2a}{2011/04/16}{Insert tokens correctly when last tabular cell % does not end \cs{\\}} %\changes{v2.2a}{2011/04/16}{Fix bug with literal units and auto-insertion % of \num{1} when \opt{per-mode} is \opt{symbol}} %\changes{v2.2b}{2011/04/17}{Make \cs{of} work in hyper-linked sections} %\changes{v2.2b}{2011/04/17}{Fix bug with \cs{highlight} macro when % no colour support is loaded} %\changes{v2.2b}{2011/04/19}{Fix bad formatting of negative exponents when % using the \opt{output-exponent-marker} option} %\changes{v2.2c}{2011/04/20}{Fix bad interaction with \pkg{cellspace} package} %\changes{v2.2d}{2011/04/28}{Fix the \opt{strict} option} %\changes{v2.2e}{2011/05/23}{Fix incorrect interpretation of complex numbers % with no real part} %\changes{v2.2g}{2011/06/02}{Correctly space \cs{degree} and similar units % in lists and ranges when only a single unit is given} %\changes{v2.2h}{2011/06/03}{Fix bug in significant figures rounding code % for some integer part values} %\changes{v2.2i}{2011/06/15}{Fix \opt{detect-mode} option inside % table cells} %\changes{v2.2j}{2011/06/26}{Fix incorrect line breaking in \cs{SIrange}} %\changes{v2.2k}{2011/06/27}{Fix behaviour of subscripts inside alignments % when printing in text mode} %\changes{v2.2l}{2011/06/30}{Fix loss of main unit when \opt{per-mode} is set % to \opt{symbol} and a pre-unit is used} %\changes{v2.3}{2011/06/19}{New implementation for alignment in \texttt{S} % column} %\changes{v2.3a}{2011/07/09}{Restore fix in v2.2l missing in v2.3} %\changes{v2.3b}{2011/08/08}{Adjust internal load order so that % \opt{free-standing-units} works correctly for abbreviations} %\changes{v2.3c}{2011/07/12}{Fix display of \( \pm \) in numbers when % \opt{separate-uncertainty} is \opt{true} and literal units are used} %\changes{v2.3d}{2011/08/18}{Fix broken superscript display in literal unit % mode} %\changes{v2.3e}{2011/09/09}{Internal changes to work with \LaTeX3 % updates} %\changes{v2.3f}{2011/09/03}{Fix processing of numbers in tables when entire % number is invalid} %\changes{v2.3g}{2011/10/06}{Deal with erroneous leading zero in some % fixed exponent cases} %\changes{v2.3h}{2011/10/14}{Ensure math mode for exponent products in all % circumstances} %\changes{v2.3h}{2011/10/14}{Improvements to output when using \pkg{tex4ht}} %\changes{v2.4}{2011/11/03}{Reduce number of math mode options, improving % consistency of output} %\changes{v2.4a}{2011/11/28}{Extend search-and-replace code for UTF-8 % characters} %\changes{v2.4a}{2011/12/04}{Use a more cautious approach to changing % settings at the start of the document} %\changes{v2.4b}{2011/12/06}{Erroneous doubled \texttt{\#} corrected} %\changes{v2.4c}{2011/12/09}{Erroneous check for text mode sanserif font fixed} %\changes{v2.4d}{2011/12/09}{Fix for edge-case user commands in captions % where the command clashes with a unit name} %\changes{v2.4e}{2011/12/11}{Fix issue with \pkg{inputenc} package and % some of the recent special symbol changes} %\changes{v2.4f}{2011/12/21}{Allow easier use of headings when not parsing % numbers in tables} %\changes{v2.4f}{2011/12/23}{Fix bug with detection of bold font in table % cells} %\changes{v2.4g}{2012/01/06}{Update internals to match changes in \pkg{expl3} % which caused issues with some tokens in numerical arguments} %\changes{v2.4h}{2012/01/15}{Bug fix for implementation of % \opt{reciprocal-positive-first}} %\changes{v2.4i}{2012/01/19}{Bug fix for rounding with large numbers of % decimal places} %\changes{v2.4j}{2012/01/26}{Leave vertical mode before any document-level % commands} %\changes{v2.4k}{2012/03/22}{Internal changes to allow for \pkg{breqn} % package tricks} %\changes{v2.4l}{2012/03/23}{Fix a load-order issue with \pkg{soulpos} % package} %\changes{v2.4m}{2012/04/03}{Correct bug in \cs{SIlist} when only a single % number is given} %\changes{v2.4n}{2012/04/04}{Allow conversion of numbers with more than % nine digits to scientific notation} %\changes{v2.5}{2012/04/07}{Minor change to table code to give fewer underfull % boxes when comparators are used} %\changes{v2.5}{2012/04/08}{Reduced number of intrinsically-mathematical % options} %\changes{v2.5a}{2012/04/19}{When creating free-standing unit, allow % for \enquote{dynamic} nature of spacing (bug introduced in v2.5)} %\changes{v2.5b}{2012/04/20}{Deal correctly with \texttt{\^} and \texttt{\_} % in literal units when \pkg{breqn} package is loaded} %\changes{v2.5b}{2012/04/20}{Detect \pkg{eulervm} package and alter % math mode font setting accordingly} %\changes{v2.5c}{2012/04/03}{Allow conversion of numbers with more than % nine digits when using fixed exponents} %\changes{v2.5c}{2012/05/03}{Detect entirely empty cells in \texttt{s} columns} %\changes{v2.5d}{2012/06/11}{Extend range of settings automatically altered % to use UTF-8 values is appropriate} %\changes{v2.5e}{2012/06/13}{Fix an internal error in unit expansion, % introduced in v2.4f} %\changes{v2.5f}{2012/07/16}{Track changes in \pkg{expl3}} %\changes{v2.5h}{2012/08/28}{Alter literal unit test to allow spaces in % units to be ignored} %\changes{v2.5i}{2012/09/11}{Fix alignment of values without uncertainties in % columns where space is reserved for uncertainties} %\changes{v2.5j}{2012/09/18}{Fix rounding when uncertainties are present} %\changes{v2.5k}{2012/09/20}{Store fraction function as a macro rather than % using \cs{let}: fixes a warning with \pkg{amsmath}} %\changes{v2.5k}{2012/11/13}{Skip spaces correctly after start of document} %\changes{v2.5l}{2012/11/21}{Track changes in \pkg{expl3}} %\changes{v2.5m}{2012/11/27}{Fix bug with UTF8 engines and literal units} %\changes{v2.5m}{2012/11/27}{Handle \cs{highlight} correctly in bookmarks} %\changes{v2.5m}{2012/11/27}{Load \opt{binary-units} only if requested} %\changes{v2.5m}{2012/11/27}{Allow for right-to-left mode with \pkg{bidi} % package} %\changes{v2.5n}{2012/12/29}{Fix transmission of grouping information by % \cs{SendSettingsToPgf}} %\changes{v2.5o}{2013/01/09}{Update internals to track \pkg{expl3} changes} %\changes{v2.5p}{2013/02/01}{Fix printing of \cs{pm} and \cs{mp} when used % as signs in text mode} %\changes{v2.5q}{2013/03/10}{Replace active \texttt{-} in numbers with % standard hyphen} %\changes{v2.5q}{2013/03/10}{Reorder internals to allow for binary units % in tables} %\changes{v2.5r}{2013/07/11}{Update internals to track \pkg{expl3} changes} %\changes{v2.5s}{2013/07/31}{Update internals to track \pkg{expl3} changes} % \changes{v2.6}{2013/11/19}{Allow for loading of \pkg{mdwtab}} % \changes{v2.6}{2014/09/03}{Produce proper minus sign when \pkg{tex4ht} % is in use} % \changes{v2.6}{2014/09/03}{Fix spacing when printing comparators} % \changes{v2.6}{2014/09/04}{Fix printing of uncertainties when the % input is an integer and the uncertainty is given as a separate part} % \changes{v2.6}{2014/09/04}{Preserve standard meaning of \cs{fg} in % bookmarks when \pkg{babel} is loaded with the \opt{french} option} % \changes{v2.6a}{2014/09/15}{Better glyph selection when \pkg{fontspec} % is detected} % \changes{v2.6b}{2014/09/27}{Extend range of font shapes which can be % detected} % %\begin{abstract} % Physical quantities have both numbers and units, and each physical % quantity should be expressed as the product of a number and a unit. % Typesetting physical quantities requires care to ensure that the % combined mathematical meaning of the number--unit combination is % clear. In particular, the SI units system lays down a consistent % set of units with rules on how these are to be used. However, % different countries and publishers have differing conventions on % the exact appearance of numbers (and units). % % The \pkg{siunitx} package provides a set of tools for authors % to typeset quantities in a consistent way. The package has an % extended set of configuration options which make it possible to % follow varying typographic conventions with the same input syntax. % The package includes automated processing of numbers and units, and % the ability to control tabular alignment of numbers. %\end{abstract} % %\tableofcontents % %\begin{documentation} % %\section{Introduction} % % The correct application of units of measurement is very important % in technical applications. For this reason, carefully-crafted % definitions of a coherent units system have been laid down by the % \emph{Conf\'erence G\'en\'erale des Poids et % Mesures} (CGPM): this has resulted in the \emph{Syst\`eme % International d'Unit\'es} (SI). At the same time, typographic % conventions for correctly displaying both numbers and units exist to % ensure that no loss of meaning occurs in printed matter. % % \pkg{siunitx} aims to provide a unified method for \LaTeX{} users to % typeset numbers and units correctly and easily. The design % philosophy of \pkg{siunitx} is to follow the agreed rules by % default, but to allow variation through option settings. In this way, % users can use \pkg{siunitx} to follow the requirements of % publishers, co-authors, universities, \emph{etc}.~without needing to % alter the input at all. % %\section{Installation} % % The package is supplied in \file{dtx} format and as a pre-extracted % zip file, \file{\jobname.tds.zip}. The later is most convenient for % most users: simply unzip this in your local texmf directory and % run \texttt{texhash} to update the database of file locations. If % you want to unpack the \file{dtx} yourself, running % \texttt{tex \jobname.dtx} will extract the package whereas % \texttt{latex \jobname.dtx} will extract it and also typeset the % documentation. % % The package requires \LaTeX3 support as provided in the % \pkg{l3kernel} and \pkg{l3packages} bundles. Both of these are available % on \href{http://www.ctan.org}{\textsc{ctan}} as ready-to-install % zip files. Suitable versions are available in MiK\TeX{}~2.9 and % \TeX{}~Live 2012 (updating the relevant packages online may be % necessary). \LaTeX3, and so \pkg{siunitx}, requires the \eTeX{} % extensions: these are available on all modern \TeX{} systems. % % Typesetting the documentation requires a number of packages in % addition to those needed to use the package. This is mainly % because of the number of demonstration items included in the text. To % compile the documentation without error, you will need the packages: %\begin{itemize} % \item \pkg{amsmath} % \item \pkg{booktabs} % \item \pkg{cancel} % \item \pkg{caption} % \item \pkg{cleveref} % \item \pkg{colortbl} % \item \pkg{csquotes} % \item \pkg{helvet} % \item \pkg{mathpazo} % \item \pkg{multirow} % \item \pkg{listings} % \item \pkg{pgfplots} % \item \pkg{xcolor} %\end{itemize} % %\section{\pkg{siunitx} for the impatient} % % The package provides the user macros: %\begin{itemize} % \item \cs{ang}\oarg{options}\marg{angle} % \item \cs{num}\oarg{options}\marg{number} % \item \cs{si}\oarg{options}\marg{unit} % \item \cs{SI}\oarg{options}\marg{number}\oarg{pre-unit}\marg{unit} % \item \cs{numlist}\oarg{options}\marg{numbers} % \item \cs{numrange}\oarg{options}\marg{numbers}\marg{number2} % \item \cs{SIlist}\oarg{options}\marg{numbers}\marg{unit} % \item \cs{SIrange}\oarg{options}\marg{number1}\marg{number2}^^A % \marg{unit} % \item \cs{sisetup}\marg{options} % \item \cs{tablenum}\oarg{options}\marg{number} %\end{itemize} % plus the \texttt{S} and \texttt{s} column types for decimal % alignments and units in tabular environments. These user macros and % column types are designed for % typesetting numbers and units with control of appearance and with % intelligent processing. % % Numbers are processed with understanding of exponents, complex numbers % and multiplication. %\begin{LaTeXdemo} % \num{12345,67890} \\ % \num{1+-2i} \\ % \num{.3e45} \\ % \num{1.654 x 2.34 x 3.430} %\end{LaTeXdemo} % % The unit system can interpret units given as text to be used directly % or as macro-based units. In the latter case, different formatting is % possible. %\begin{LaTeXdemo} % \si{kg.m.s^{-1}} \\ % \si{\kilogram\metre\per\second} \\ % \si[per-mode=symbol] % {\kilogram\metre\per\second} \\ % \si[per-mode=symbol] % {\kilogram\metre\per\ampere\per\second} %\end{LaTeXdemo} % % Simple lists and ranges of numbers can be handled. %\begin{LaTeXdemo} % \numlist{10;20;30} \\ % \SIlist{0.13;0.67;0.80}{\milli\metre} \\ % \numrange{10}{20} \\ % \SIrange{0.13}{0.67}{\milli\metre} %\end{LaTeXdemo} % % By default, all text is typeset in the current upright, serif math % font. This can be changed by setting the appropriate options: % "\sisetup{detect-all}" will use the current font for typesetting. % %\section{Using the \pkg{siunitx} package} % %\subsection{Loading the package} % % The package should be loaded in the usual \LaTeXe{} way. %\begin{LaTeXdemo}[code only] % \usepackage{siunitx} %\end{LaTeXdemo} % The key--value options described later in this document can be used % when loading the package, for example %\begin{LaTeXdemo}[code only] % \usepackage[version-1-compatibility]{siunitx} %\end{LaTeXdemo} % to use options from version 1 of the package. % %\subsection{Numbers} % %\DescribeMacro{\num} % \changes{v2.6}{2014/09/03}{Ignore hard spaces (\texttt{\~}) in % argument of \cs{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 both \enquote{soft} (\verb*" ") and % \enquote{hard} spaces (\cs{,} and "~"), automatically identifies % exponents (by default % marked using \texttt{e}, \texttt{E}, \texttt{d} or \texttt{D}) and % adds the appropriate spacing of large numbers. With the standard % settings a leading zero is added before a decimal marker, if needed: % both \enquote{\texttt{.}} and \enquote{\texttt{,}} are recognised as % decimal markers. %\begin{LaTeXdemo} % \num{123} \\ % \num{1234} \\ % \num{12345} \\ % \num{0.123} \\ % \num{0,1234} \\ % \num{.12345} \\ % \num{3.45d-4} \\ % \num{-e10} %\end{LaTeXdemo} % Note that numbers are parsed before typesetting, which does % have a performance overhead (only obvious with very large amounts % of numerical input). The parser understands a range of input syntaxes, % as demonstrated above. % %\DescribeMacro{\numlist} %\begin{syntax} % \cs{numlist}\oarg{options}\marg{numbers} %\end{syntax} %\changes{v2.0}{2010/05/23}{Introduced \cs{numlist} and \cs{SIlist} % functions} % Lists of numbers may be processed using the \cs{numlist} function. % Each \meta{number} is given within the list of \meta{numbers} within % a brace pair, as the list can have a flexible length. This function % should be used in text mode, a common feature of all of the list and % range functions provided by \pkg{siunitx}.\footnote{The reason for % this restriction is that the separators between items may involve % text-mode spaces which must be able to vanish at line breaks. It is % not possible to achieve this effect from inside math mode.} %\begin{LaTeXdemo} % \numlist{10;30;50;70} %\end{LaTeXdemo} % %\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 should % be used in text mode. %\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 the \meta{si} contains literal items (for example letters or % numbers) then \pkg{siunitx} converts \texttt{.} and "~" into % inter-unit product and correctly positions sub- and superscripts % specified using "_" and "^". The formatting methods will work with % both math and text mode. %\begin{LaTeXdemo} % \si{kg.m/s^2} \\ % \si{g_{polymer}~mol_{cat}.s^{-1}} %\end{LaTeXdemo} % The second operation mode for the \cs{si} macro is an % \enquote{interpreted} system, Here, each unit, SI multiple prefix and % power is given a macro name. These are entered in a method very % similar to the reading of the unit name in English. %\begin{LaTeXdemo} % \si{\kilo\gram\metre\per\square\second} \\ % \si{\gram\per\cubic\centi\metre} \\ % \si{\square\volt\cubic\lumen\per\farad} \\ % \si{\metre\squared\per\gray\cubic\lux} \\ % \si{\henry\second} %\end{LaTeXdemo} % On its own, this is less convenient than the direct method, although % it does use meaning rather than appearance for input. However, the % package allows you to define new unit macros; a large number of % pre-defined abbreviations are also supplied. More importantly, by % defining macros for units, instead of literal input, new % functionality is made available. By altering the settings used by the % package, the same input can yield a variety of different output % formats. For example, the \cs{per} macro can give reciprocal powers, % slashes or be used to construct units as fractions. % %\DescribeMacro{\SI} %\begin{syntax} % \cs{SI}\oarg{options}\marg{number}\oarg{preunit}\marg{unit} %\end{syntax} % Very often, numbers and units are given together. Formally, the % value of a quantity is the product of the number and the unit, the % space being regarded as a multiplication sign \cite{SI:5.3.3}. The % \cs{SI} macro combines the functionality of \cs{num} and % \cs{si}, and makes this both possible and easy. The \meta{number} % and \meta{si} arguments work exactly like those for the \cs{num} and % \cs{si} macros, respectively. \meta{preunit} is a unit to be typeset % \emph{before} the numerical value (most likely to be a currency). %\begin{LaTeXdemo} % \SI[mode=text]{1.23}{J.mol^{-1}.K^{-1}} \\ % \SI{.23e7}{\candela} \\ % \SI[per-mode=symbol]{1.99}[\$]{\per\kilogram} \\ % \SI[per-mode=fraction]{1,345}{\coulomb\per\mole} %\end{LaTeXdemo} % % It is possible to set up the unit macros to be available outside of % the \cs{SI} and \cs{si} functions. This is not the standard % behaviour as there is the risk of name clashes (for example, \cs{bar} % is used by other packages, and several packages define \cs{degree}). % Full details of using \enquote{stand alone} units are found in % \cref{sec:units:creating}. % %\DescribeMacro{\SIlist} %\begin{syntax} % \cs{SIlist}\oarg{options}\marg{numbers}\marg{unit} %\end{syntax} % Lists of numbers with units can be handled using the \cs{SIlist} % function. The behaviour of this function is similar to \cs{numlist}, % but with the addition of a unit to each number. This function should % be used in text mode. %\begin{LaTeXdemo} % \SIlist{10;30;45}{\metre} %\end{LaTeXdemo} % %\DescribeMacro{\SIrange} %\begin{syntax} % \cs{SIrange}\oarg{options}\marg{number1}\marg{number2}\marg{unit} %\end{syntax} % Ranges of numbers with units can be handled using the \cs{SIrange} % function. The behaviour of this function is similar to \cs{numrange}, % but with the addition of a unit to each number. This function should % be used in text mode. %\begin{LaTeXdemo} % \SIrange{10}{30}{\metre} %\end{LaTeXdemo} % %\subsection{The unit macros} % % The package always defines the basic set of SI units with macro names. % This includes the base SI units, the derived units with special names % and the prefixes. A small number of powers are also given pre-defined % names. Full details of units in the SI are available % on-line~\cite{BIPM}. % %\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 % Unit & Macro & 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{celsius} is defined equivalent to \cs{degreeCelsius} . %\begin{table} % \caption{Coherent derived units in the SI with special names and % symbols.} % \label{tab:unit:derived} % \centering % \begin{tabular}{lll>{\qquad}lll} % \toprule % Unit & Macro & Symbol & Unit & Macro & Symbol \\ % \midrule % \DescribeUnit{becquerel} & % \DescribeUnit{newton} \\ % \DescribeNamedUnit{degree Celsius}{degreeCelsius} & % \DescribeUnit{ohm} \\ % \DescribeUnit{coulomb} & % \DescribeUnit{pascal} \\ % \DescribeUnit{farad} & % \DescribeUnit{radian} \\ % \DescribeUnit{gray} & % \DescribeUnit{siemens} \\ % \DescribeUnit{hertz} & % \DescribeUnit{sievert} \\ % \DescribeUnit{henry} & % \DescribeUnit{steradian} \\ % \DescribeUnit{joule} & % \DescribeUnit{tesla} \\ % \DescribeUnit{katal} & % \DescribeUnit{volt} \\ % \DescribeUnit{lumen} & % \DescribeUnit{watt} \\ % \DescribeUnit{lux} & % \DescribeUnit{weber} \\ % \bottomrule % \end{tabular} %\end{table} % % In addition to the official SI units, \pkg{siunitx} also provides % macros for a number of units which are accepted for use in the SI % although they are not SI units. \cref{tab:unit:accepted} lists % the \enquote{accepted} units \cite{SI:4.1.T6}. Some units are % fundamental physical quantities, and these are non-SI but can be used % within the SI (\cref{tab:unit:physical}, \cite{SI:4.1.T7}). % There are also a set of non-SI units which are used in certain % defined circumstances (\cref{tab:unit:other}), although they are % not necessarily officially sanctioned \cite{SI:4.1.T8}. % \DescribeMacro{\percent} % The package also predefines the \cs{percent} macro. While this is not a % unit, it is used in the same way in many cases and is therefore provided % on the grounds of realism. %\begin{table} % \caption{Non-SI units accepted for use with the % International System of Units.} % \label{tab:unit:accepted} % \centering % \begin{tabular}{lll} % \toprule % Unit & Macro & Symbol \\ % \midrule % \DescribeUnit{day} \\ % \DescribeUnit{degree} \\ % \DescribeUnit{hectare} \\ % \DescribeUnit{hour} \\ % \DescribeUnit{litre} \\ % \SpecialUsageIndex{\liter}^^A % & \cs{liter} & \si{\liter} \\ % \DescribeNamedUnit{minute (plane angle)}{arcminute} \\ % \DescribeNamedUnit{minute (time)}{minute} \\ % \DescribeNamedUnit{second (plane angle)}{arcsecond} \\ % \DescribeUnit{tonne} \\ % \bottomrule % \end{tabular} %\end{table} %\begin{table} % \changes{v2.0j}{2010/06/30}{Correct \cs{hartree} unit appearance} % \caption{Non-SI units whose values in SI units must be obtained % experimentally.} % \label{tab:unit:physical} % \centering % \begin{tabular}{lll} % \toprule % Unit & Macro & Symbol \\ % \midrule % \DescribeNamedUnit{astronomical unit}{astronomicalunit} \\ % \DescribeNamedUnit{atomic mass unit}{atomicmassunit} \\ % \DescribeUnit{bohr} \\ % \DescribeNamedUnit{speed of light}{clight} \\ % \DescribeUnit{dalton} \\ % \DescribeNamedUnit{electron mass}{electronmass} \\ % \DescribeUnit{electronvolt} \\ % \DescribeNamedUnit{elementary charge}{elementarycharge} \\ % \DescribeUnit{hartree} \\ % \DescribeNamedUnit{reduced Planck constant}{planckbar} \\ % \bottomrule % \end{tabular} %\end{table} %\begin{table} % \caption{Other non-SI units.} % \label{tab:unit:other} % \centering % \begin{tabular}{lll} % \toprule % Unit & Macro & Symbol \\ % \midrule % \DescribeNamedUnit{{\aa}ngstr{\"o}m}{angstrom} \\ % \DescribeUnit{bar} \\ % \DescribeUnit{barn} \\ % \DescribeUnit{bel} \\ % \DescribeUnit{decibel} \\ % \DescribeUnit{knot} \\ % \DescribeNamedUnit{millimetre of mercury}{mmHg} \\ % \DescribeNamedUnit{nautical mile}{nauticalmile} \\ % \DescribeUnit{neper} \\ % \bottomrule % \end{tabular} %\end{table} % %\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<{$}>{\qquad}llc>{$}l<{$}} % \toprule % Prefix & Macro & Symbol & \multicolumn{1}{l}{Power} & % Prefix & Macro & Symbol & \multicolumn{1}{l}{Power} \\ % \midrule % \DescribePrefix{yocto} & -24 & % \DescribePrefix{deca} & 1 \\ % \DescribePrefix{zepto} & -21 & % \DescribePrefix{hecto} & 2 \\ % \DescribePrefix{atto} & -18 & % \DescribePrefix{kilo} & 3 \\ % \DescribePrefix{femto} & -15 & % \DescribePrefix{mega} & 6 \\ % \DescribePrefix{pico} & -12 & % \DescribePrefix{giga} & 9 \\ % \DescribePrefix{nano} & -9 & % \DescribePrefix{tera} & 12 \\ % \DescribePrefix{micro} & -6 & % \DescribePrefix{peta} & 15 \\ % \DescribePrefix{milli} & -3 & % \DescribePrefix{exa} & 18 \\ % \DescribePrefix{centi} & -2 & % \DescribePrefix{zetta} & 21 \\ % \DescribePrefix{deci} & -1 & % \DescribePrefix{yotta} & 24 \\ % \bottomrule % \end{tabular} %\end{table} % %\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} %\DescribeMacro{\of} %\changes{v2.0i}{2010/06/29}{Correct behaviour of \cs{of} function % so it actually works (bug introduced in v2.0d)} % As for generic powers, generic qualifiers are also available using % the \cs{of} function: %\begin{LaTeXdemo} % \si{\kilogram\of{metal}} \\ % \SI[qualifier-mode = brackets] % {0.1}{\milli\mole\of{cat}\per\kilogram\of{prod}} %\end{LaTeXdemo} % %\DescribeMacro{\cancel} %\DescribeMacro{\highlight} %\changes{v2.2}{2011/04/05}{Support use of \cs{cancel} macro in units} %\changes{v2.2}{2011/04/06}{New \cs{highlight} macro for selective % colour in units} % If the \pkg{cancel} package is loaded, it is possible to % \enquote{cancel out} units using the \cs{cancel} macro. This applies % to the next unit, in a similar manner to a prefix. The \cs{highlight} % macro is also available to selectively colour units. Both \cs{cancel} % and \cs{highlight} are of course outside of the normal semantic % meaning of units, but are provided as they may be useful in some % cases. %\begin{LaTeXdemo} % \si[per-mode = fraction] % {\cancel\kilogram\metre\per\cancel\kilogram\per\second} \\ % \si{\highlight{red}\kilogram\metre\per\second} \\ % \si[unit-color = purple] % {\highlight{red}\kilogram\metre\per\second} %\end{LaTeXdemo} % % When using the unit macros, the package is able to validate the % input given. As part of this, stand-alone unit prefixes can be used % with the \cs{si} macro %\begin{LaTeXdemo} % \si{\kilo} \\ % \si{\micro} \\ % \si[prefixes-as-symbols = false]{\kilo} %\end{LaTeXdemo} % However, the package only allows a single prefix to be used in this % way: multiple prefixes will give an error, as will trying to give % a number without a unit. So the following will raise errors: %\begin{LaTeXdemo}[code only] % \si{\kilo\gram\micro} \\ % \SI{10}{\micro} %\end{LaTeXdemo} % %\subsection{Creating new macros} % % The various macro components of a unit have to be defined before % they can be used. The package supplies a number of common definitions, % but new definitions are also possible. As the definition of a logical % unit should remain the same in a single document, these creation % functions are all preamble-only. % %\DescribeMacro{\DeclareSIUnit} %\changes{v2.2}{2011/04/01}{Extend \cs{DeclareSIUnit} to take % optional argument} %\begin{syntax} % \cs{DeclareSIUnit}\oarg{options}\marg{unit}\marg{symbol} %\end{syntax} % New units are produced using the \cs{DeclareSIUnit} macro. % \meta{symbol} can contain literal input, other units, multiple % prefixes, powers and \cs{per}, although literal text should not be % intermixed with unit macros. Units can be created with \meta{options} % from the usual list understood by \pkg{siunitx}, and apply the % specific unit macro only. The (first) optional argument to \cs{SI} % and \cs{si} can be used to override the settings for the unit. A % typical example is the \cs{degree} unit. %\begin{LaTeXdemo} % \SI{3.1415}{\degree} %\end{LaTeXdemo} % This is declared in the package as: %\begin{LaTeXdemo}[code only] % \DeclareSIUnit[number-unit-product = {}] % \degree{\SIUnitSymbolDegree} %\end{LaTeXdemo} % The spacing can still be altered at point of use: %\begin{LaTeXdemo} % \SI{67890}{\degree} \\ % \SI[number-unit-product = \,]{67890}{\degree} %\end{LaTeXdemo} % The meaning of a pre-defined unit can be altered by using % \cs{DeclareSIUnit} after loading \pkg{siunitx}. This will overwrite % the original definition with the newer version. % %\DescribeMacro{\DeclareSIPrefix} %\DescribeMacro{\DeclareBinaryPrefix} %\begin{syntax} % \cs{DeclareSIPrefix}\marg{prefix}\marg{symbol}\marg{powers-ten} % \cs{DeclareBinaryPrefix}\marg{prefix}\marg{symbol}\marg{powers-two} %\end{syntax} % The standard SI powers of ten are defined by the package, and are % described above. However, the user can define new prefixes with % \cs{DeclareSIPrefix}. The \cs{DeclareBinaryPrefix} function is also % available for creating binary prefixes, with the same syntax % (\meta{powers-ten} being replaced by \meta{powers-two}). For % example, \cs{kilo} and \cs{kibi} are defined: %\begin{LaTeXdemo}[code only] % \DeclareSIPrefix\kilo{k}{3} % \DeclareBinaryPrefix\kibi{Ki}{10} %\end{LaTeXdemo} % %\DescribeMacro{\DeclareSIPostPower} %\DescribeMacro{\DeclareSIPrePower} %\begin{syntax} % \cs{DeclareSIPostPower}\marg{power}\marg{num} % \cs{DeclareSIPrePower}\marg{power}\marg{num} %\end{syntax} % These create power macros to appear before or after the unit they % apply to. For example, the preamble to a document might contain: %\begin{LaTeXdemo}[code only] % \DeclareSIPrePower\quartic{4} % \DeclareSIPostPower\tothefourth{4} %\end{LaTeXdemo} % with the functions then used in the document as: %\begin{LaTeXdemo} % \si{\kilogram\tothefourth}\\ % \si{\quartic\metre} %\end{LaTeXdemo} % %\DescribeMacro{\DeclareSIQualifier} % Following the syntax of the other macros, qualifiers are created % with the syntax \cs{DeclareSIQualifier}\marg{qualifier}\marg{symbol}. % In contrast to the other parts of a unit, there are no pre-defined % qualifiers. It is therefore entirely up to the user to create these. % For example, to identify the mass of a product created when using % a particular catalyst, the preamble could contain: %\begin{LaTeXdemo}[code only] % \DeclareSIQualifier\polymer{pol} % \DeclareSIQualifier\catalyst{cat} %\end{LaTeXdemo} % and then in the body the document could read: %\begin{LaTeXdemo} % \SI{1.234}{\gram\polymer\per\mole\catalyst\per\hour} %\end{LaTeXdemo} % %\subsection{Tabular material} % % Aligning numbers in tabular content is handled by a new column % type, the \texttt{S} column. This new column type can align material % using a number of different strategies, with the aim of flexibility % of output without needing to alter the input. The method used % as standard is to place the decimal marker in the number at the % centre of the cell and to align the material appropriately % (\cref{tab:S:standard}). % %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Standard behaviour of the \texttt{S} column type.} % \label{tab:S:standard} % \centering % \begin{tabular}{S} % \toprule % {Some Values} \\ % \midrule % 2.3456 \\ % 34.2345 \\ % -6.7835 \\ % 90.473 \\ % 5642.5 \\ % 1.2e3 \\ % e4 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % % The \texttt{S} column will attempt to automatically detect % material which should be placed before or after a number, and will % maintain the alignment of the numerical data % (\cref{tab:S:extras}). If the material could be mistaken for % part of a number, it should be protected by braces. The use of % \cs{color} in a table cell will also be detected and will override any % general colour applied by \pkg{siunitx}. %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Detection of surrounding material in an \texttt{S} % column.} % \label{tab:S:extras} % \centering % \begin{tabular}{S[color=orange]} % \toprule % {Some Values} \\ % \midrule % 12.34 \\ % \color{purple} 975,31 \\ % 44.268 \textsuperscript{\emph{a}} \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeMacro{\tablenum} %\begin{syntax} % \cs{tablenum}\oarg{options}\marg{number} %\end{syntax} %\changes{v2.2}{2011/03/20}{Add new \cs{tablenum} macro to allow % complex table alignments} %\changes{v2.2g}{2011/06/02}{Ensure \cs{tablenum} works correctly when % \opt{parse-numbers} is set \opt{false}} % Within more complex tables, aligned numbers may be desirable within % the argument of \cs{multicolumn} or % \cs{multirow}.\footnote{Provided by the \pkg{multirow} package} The % \cs{tablenum} function is available to achieve alignment in these % situations: this is, in effect, a macro version of the \texttt{S} macro % (\cref{tab:tablenum}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Controlling complex alignment with the \cs{tablenum} % macro.} % \label{tab:tablenum} % \centering % \begin{tabular}{lr} % \toprule % Heading & Heading \\ % \midrule % Info & More info \\ % Info & More info \\ % \multicolumn{2}{c}{\tablenum[table-format = 4.4]{12,34}} \\ % \multicolumn{2}{c}{\tablenum[table-format = 4.4]{333.5567}} \\ % \multicolumn{2}{c}{\tablenum[table-format = 4.4]{4563.21}} \\ % \bottomrule % \end{tabular} % \hfil % \begin{tabular}{lr} % \toprule % Heading & Heading \\ % \midrule % \multirow{2}*{\tablenum{88,999}} & aaa \\ % & bbb \\ % \multirow{2}*{\tablenum{33,435}} & ccc \\ % & ddd \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % % As a complement to the \texttt{S} column type, \pkg{siunitx} also provides % a second column type, \texttt{s}. This is intended for producing % columns of units. This allows both macro-based and explicit units to % be printed easily (\cref{tab:s:demo}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{Units in tables.} % \label{tab:s:demo} % \begin{tabular}{s} % \toprule % \multicolumn{1}{c}{Unit} \\ % \midrule % \metre\squared\per\second \\ % \pascal \\ % m.s^{-1} \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % % As the \cs{si} macro can take literal or macro input, the \texttt{s} % column cannot validate the input. \emph{Everything} in an \texttt{s} % column is therefore passed to the \cs{si} macro for processing. To % prevent this, you have to use \cs{multicolumn}, as is shown in % \cref{tab:s:processing}. Notice that braces alone do not prevent % processing and colouring of the cell contents. %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{The \texttt{s} column processes everything.} % \label{tab:s:processing} % \sisetup{color = orange} % \begin{tabular}{ss} % \toprule % {Unit} & \multicolumn{1}{c}{Unit}\\ % \midrule % {\si{m^3}} & \multicolumn{1}{c}{\si{m^3}} \\ % \kilogram & \kilogram \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\section{Comprehensive details of package control options} % %\subsection{The key--value control system} % %\DescribeMacro{\sisetup} % The behaviour of the \pkg{siunitx} package is controlled by a % number of key--value options. These can be given globally using % the \cs{sisetup} function or locally as the optional argument to the % user macros. % % The package uses a range of different key types: %\begin{description} % \item[\texttt{Choice}] Takes a limited number of choices, which % are described separately for each key. % \item[\texttt{Integer}] Requires a number as the argument. % \item[\texttt{Length}] Requires a length, either as a literal % value such as "2.0 cm", or stored as a \LaTeX{} length, or % \TeX{} dimension. % \item[\texttt{Literal}] A key which uses the value(s) given directly, % either to check input (for example the \texttt{input-digits} key) % or in output. % \item[\texttt{Macro}] Requires a macro, which may need a single % argument. % \item[\texttt{Math}] Similar to a \texttt{literal} option, but the % input is always used in math mode, irrespective of other % \pkg{siunitx} settings. Thus to text-mode only input must be % placed inside the argument of a \cs{text} macro. % \item[\texttt{Meta}] These are options which actually apply % a number of other options. As such, they do not take any % value at all. % \item[\texttt{Switch}] These are on--off switches, and recognise % \opt{true} and \opt{false}. Giving just the key name also % turns the key on. %\end{description} % The tables of option names use these descriptions to indicate how the % keys should be used. % %\subsection{Detecting fonts} % % The \pkg{siunitx} package controls the font used to print output % independently of the surrounding material. The standard method is to % ignore the surroundings entirely, and to use the current body fonts. % However, the package can detect and follow surrounding bold, italic % and font family changes. The font detection options are summarised in % \cref{tab:opt:font:det}. %\begin{table} % \centering % \caption{Font detection options.} % \label{tab:opt:font:det} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{l}{Option name} & % Type & % \multicolumn{1}{l}{Default} \\ % \midrule % detect-all & Meta & \meta{none} \\ % detect-display-math & Switch & false \\ % detect-family & Switch & false \\ % detect-inline-family & Choice & text \\ % detect-inline-weight & Choice & text \\ % detect-mode & Switch & false \\ % detect-none & Meta & \meta{none} \\ % detect-shape & Switch & false \\ % detect-weight & Switch & false \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{detect-weight} %\DescribeOption{detect-family} %\DescribeOption{detect-shape} %\DescribeOption{detect-mode} %\changes{v2.0o}{2010/07/21}{Extend \opt{detect-italic} option % to other shapes, renaming as \opt{detect-shape} as a result} % The options \opt{detect-weight} and \opt{detect-shape} set detection % of the prevailing font weight and font shape states, respectively. The % font shape state is only checked if the surrounding material is not in % math mode (as math text is always italic). The \opt{detect-shape} % option is an extension of the older \opt{detect-italic} option, which % is retained for backward compatibility. Detecting the current % family (roman, sans serif or monospaced) is controlled by the % \opt{detect-family} setting, while the current mode (text or math) % is detected using the \opt{detect-mode} switch. %\DescribeOption{detect-all} %\DescribeOption{detect-none} % For convenience, all of the preceding options can be turned on or % off in one go using the \opt{detect-all} and \opt{detect-none} % options. As the names indicate, \opt{detect-all} sets all % of \opt{detect-weight}, \opt{detect-family}, \opt{detect-shape} % and \opt{detect-mode} to \texttt{true}, while \opt{detect-none} % sets all of them to \texttt{false}. % %\DescribeOption{detect-inline-family} %\DescribeOption{detect-inline-weight} %\changes{v2.1k}{2011/02/09}{Remove \opt{combined} choice for option % \opt{detect-inline-weight}} %\changes{v2.1k}{2011/02/09}{New option \opt{detect-inline-family}} %\changes{v2.1l}{2011/02/10}{Error in font family detection introduced % in v2.1k corrected} % When \pkg{siunitx} macros are used in in-line math, the detection % of font weight and font family can be tuned using the % \opt{detect-inline-family} and \opt{detect-inline-weight} options. % Both of these take the choices \opt{text} and \opt{math}. %\begin{LaTeXdemo} % \sisetup{ % detect-family = true, % detect-inline-family = math % }% % $\num{1234}$ \\ % { \sffamily $\num{1234}$ } \\ % $ \mathsf { \num{1234}} $ \\ % \sisetup{detect-inline-family = text} % { \sffamily $\num{1234}$ } \\ % $ \mathsf { \num{1234} } $ \\ % \sisetup{ % detect-weight = true, % detect-inline-weight = math % }% % $\num{5678}$ \\ % { \boldmath $\num{5678}$ } \\ % { \bfseries $\num{5678}$ } \\ % \sisetup{detect-inline-weight = text} % { \boldmath $\num{5678}$ } \\ % { \bfseries $\num{5678}$ } %\end{LaTeXdemo} % %\DescribeOption{detect-display-math} % The font detection system can treat displayed mathematical content % in two ways. This is controlled by the \opt{detect-display-math} % option. When set \opt{true}, display mathematics is treated % independently from the body of the document. Thus the local % \emph{math} font is checked for matching. In contrast, when set % \opt{false}, display material is treated with the current running % text font.\footnote{Here, \enquote{display} math means either typeset % in \TeX's display math mode or using the AMS display-like % environments. Simply using \cs{displaystyle} will not make otherwise % in line math be detected as display math.} %\begin{LaTeXdemo} % \sffamily % Some text % \sisetup{ % detect-family, % detect-display-math = true % } % \[ x = \SI{1.2e3}{\kilogram\kelvin\candela} \] % More text % \sisetup{detect-display-math = false} % \[ y = \SI{3}{\metre\second\mole} \] %\end{LaTeXdemo} % %\subsection{Font settings} % % The relationship between font family detected and font family used % for output is not fixed. The font detected by the package in the % surrounding material does not have to match that used for % output (\cref{tab:opt:font:set}). % %\begin{table} % \centering % \caption{^^A % Font options (also available as \opt{number-\ldots} and % \opt{unit-\ldots} versions). % } % \label{tab:opt:font:set} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{l}{Option name} & % Type & % \multicolumn{1}{l}{Default} \\ % \midrule % color & Literal & \meta{none} \\ % math-rm & Macro & \cs{mathrm} \\ % math-sf & Macro & \cs{mathsf} \\ % math-tt & Macro & \cs{mathtt} \\ % mode & Choice & math \\ % text-rm & Macro & \cs{rmfamily} \\ % text-sf & Macro & \cs{sffamily} \\ % text-tt & Macro & \cs{ttfamily} \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{mode} % \changes{v2.6}{2014/09/03}{Switch standard setting for \opt{mode} option % to \opt{math}} % The \opt{mode} option determines whether \pkg{siunitx} uses % math or text mode when printing output. The choices are \opt{math} and % \opt{text}. When using math mode, text is printed using a math font % whereas in text mode a text font is used. The extent to which this is % visually obvious depends on the fonts in use in the document. This % manual uses old style (lower-case) figures in text mode to highlight % the differences. This option has no effect if the \opt{detect-mode} % switch is \opt{true}. % %\DescribeOption{math-rm} %\DescribeOption{math-sf} %\DescribeOption{math-tt} %\DescribeOption{text-rm} %\DescribeOption{text-sf} %\DescribeOption{text-tt} % If font family detection is inactive, \pkg{siunitx} uses the font % family stored in either \opt{math-rm} or \opt{text-rm} for % output. The choice of \opt{math} or \opt{text} depends on the % \opt{mode} setting. If font family detection is active, % \pkg{siunitx} may be using a sans serif or monospaced font for % output. In math mode, these are stored in \opt{math-sf} and % \opt{math-tt}, and for text mode in \opt{text-sf} and \opt{text-tt}. % Notice that the detected and output font families can differ. %\begin{LaTeXdemo} % \sisetup{detect-family}% % \num{1234} \\ % { \sffamily \num{1234} } \\ % \SI{99}{\metre} \\ % \sisetup{math-rm = \mathtt}% % \SI{99}{\metre} %\end{LaTeXdemo} % %\DescribeOption{color} % The colour of printed output can be set using the \opt{color} % option. When no colour is given, printing follows the surrounding % text. In contrast, when a specific colour is given, it is used % irrespective of the surroundings. As there are a number of different % colour models available, it is left to user to load \pkg{color} or % a more powerful colour package such as \pkg{xcolor}. %\begin{LaTeXdemo} % \color{red} % Some text \\ % \SI{4}{\metre\per\sievert} \\ % More text \\ % \SI[color = blue]{4}{\metre\per\sievert} \\ % Still red here! %\end{LaTeXdemo} % % Every one of the font options can be given independently for units % and number, with the prefixes \opt{unit-} and \opt{number-}, % respectively. This allows fine control of output. %\begin{LaTeXdemo} % \SI{4}{\angstrom} \\ % \SI[number-color = green]{4}{\angstrom} \\ % \SI[unit-color = green]{4}{\angstrom} %\end{LaTeXdemo} % %\subsection{Parsing numbers} % % The package uses a sophisticated parsing system to understand % numbers. This allows \pkg{siunitx} to carry out a range of % formatting, as described later. All of the input options take lists of % literal tokens, and are summarised in \cref{tab:opt:num:in}. % %\begin{table} % \centering % \caption{Options for number parsing.} % \label{tab:opt:num:in} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{l}{Option name} & % Type & % \multicolumn{1}{l}{Default} \\ % \midrule ^^A ( % input-close-uncertainty & Literal & ) \\ % input-comparators & Literal & % <=>\cs{approx}\cs{ge}\cs{geq} \\ % & & \cs{gg}\cs{le}\cs{leq}\cs{ll} \cs{sim} \\ % input-complex-roots & Literal & ij \\ % input-decimal-markers & Literal & ., \\ % input-digits & Literal & 0123456789 \\ % input-exponent-markers & Literal & dDeE \\ % input-ignore & Literal & \meta{none} \\ % input-open-uncertainty & Literal & ( \\ ^^A ) % input-protect-tokens & Literal & % \cs{approx}\cs{dots}\cs{ge}\cs{geq}\cs{gg}\cs{le} \\ % & & \cs{leq}\cs{ll}\cs{mp}\cs{pi}\cs{pm}\cs{sim} \\ % input-signs & Literal & +-\cs{pm}\cs{mp} \\ % input-uncertainty-signs & Literal & \cs{pm} \\ % input-symbols & Literal & \cs{pi}\cs{dots} \\ % parse-numbers & Switch & true \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{input-digits} %\DescribeOption{input-decimal-markers} %\DescribeOption{input-signs} %\DescribeOption{input-exponent-markers} % The basic parts of a number are the digits, any sign and a separator % between the integer and decimal parts. These are stored in the input % options \opt{input-digits}, \opt{input-decimal-markers} and % \opt{input-signs}, respectively. More than one input decimal marker % can be used: it will be converted by the package to the appropriate % output marker. Numbers which include an exponent part also require % a marker for the exponent: this again is taken from the range of % tokens in the \opt{input-exponent-markers} option. % %\DescribeOption{input-symbols} %\DescribeOption{input-ignore} % As well as \enquote{normal} digits, the package will interpret % symbolic \enquote{numbers} (such as \cs{pi}) correctly if they are % included in the \opt{input-symbols} list. Symbols are always % printed in math mode. Tokens given in the \opt{input-ignore} list % are totally passed over by \pkg{siunitx}: they will be removed from % the input with no further processing. % %\DescribeOption{input-comparators} %\changes{v2.1}{2010/10/26}{New \opt{input-comparators} option % for numbers greater than, less than and so on} % In addition to signs, \pkg{siunitx} can recognise comparators, such % as \texttt{<}. The package will automatically carry out conversions % for "<<", ">>", "<=" and ">=" to \cs{ll}, \cs{gg}, \cs{le} and % \cs{ge}, respectively: %\begin{LaTeXdemo} % \num{< 10} \\ % \SI{>> 5}{\metre} \\ % \num{\le 0.12} %\end{LaTeXdemo} % %\DescribeOption{input-open-uncertainty} %\DescribeOption{input-close-uncertainty} % In some fields, it is common to give the uncertainty in a number % in brackets after the main part of the number, for example % \enquote{\num{1.234(5)}}. The opening and closing symbols used for % this type of input are set as \opt{input-open-uncertainty} and % \opt{input-close-uncertainty}. %\DescribeOption{input-uncertainty-signs} %\changes{v2.2}{2011/04/03}{New \opt{input-uncertainty-signs} % option} % Alternatively, the uncertainty may be given as a separate part % following a sign. Which signs are valid for this operation is % determined by the \opt{input-uncertainty-signs} option. As with % other signs, the combination \texttt{+-} will automatically be % converted to \cs{pm} internally. %\begin{LaTeXdemo} % \num{9.99(9)} \\ % \num{9.99 +- 0.09} \\ % \num{9.99 \pm 0.09} \\ % \num{123 +- 4.5} \\ % \num{12.3 +- 6} %\end{LaTeXdemo} % %\DescribeOption{input-complex-roots} % When using complex numbers in input, the complex root % \( ( \mathrm{i} = \sqrt{-1} \, ) \) is indicated by one of the tokens stored % in \opt{input-complex-roots}. The parser understands complex root % symbols given either before or after the associated number (but will % detect any invalid arrangement): %\begin{LaTeXdemo} % \num{9.99 + 88.8i} \\ % \num{9.99 + i88.8} %\end{LaTeXdemo} % %\DescribeOption{input-protect-tokens} % Some symbols can be problematic under expansion in \LaTeXe. To allow % these to be used in input without issue, the package can protect these % tokens while expanding input. Symbols to be protected in this way % should be listed in \opt{input-protect-tokens}. % %\DescribeOption{parse-numbers} % The \opt{parse-numbers} option turns the entire parsing system on % and off. The option is made available for two reasons. First, if % all of the numbers in a document are to be reproduced \enquote{as % given}, turning off the parser will represent a significant saving in % processing required. Second, it allows the use of arbitrary \TeX{} % code in numbers. If the parser is turned off, the input will be % printed in math mode (requiring \cs{text} to protect any text % in the number). %\begin{LaTeXdemo} % \num[parse-numbers = false]{\sqrt{2}} \\ % \SI[parse-numbers = false]{\sqrt{3}}{\metre} %\end{LaTeXdemo} % %\subsection{Post-processing numbers} % % Before typesetting numbers, various post-processing steps can be % carried out. These involve adding or removing information from the % number in a systematic way; the options are summarised in % \cref{tab:opt:num:post}. % %\begin{table} % \centering % \caption{Number post-processing options.} % \label{tab:opt:num:post} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{l}{Option name} & % Type & % \multicolumn{1}{l}{Default} \\ % \midrule % add-decimal-zero & Switch & true \\ % add-integer-zero & Switch & true \\ % explicit-sign & Literal & \meta{none} \\ % fixed-exponent & Integer & 0 \\ % minimum-integer-digits & Integer & 0 \\ % omit-uncertainty & Switch & false \\ % retain-explicit-plus & Switch & false \\ % retain-unity-mantissa & Switch & true \\ % retain-zero-exponent & Switch & false \\ % round-half & Choice & up \\ % round-integer-to-decimal & Switch & false \\ % round-minimum & Literal & 0 \\ % round-mode & Choice & off \\ % round-precision & Integer & 2 \\ % scientific-notation & Switch & false \\ % zero-decimal-to-integer & Switch & false \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{round-mode} %\DescribeOption{round-precision} %\changes{v2.1n}{2011/03/31}{Set output to 0 when \opt{round-mode} % is \opt{figures} and \opt{round-precision} is 0} % The \pkg{siunitx} package can round numerical input to a fixed % number of significant figures or decimal places. This is controlled by % the \opt{round-mode} option, which takes the choices \opt{off}, % \opt{figures} and \opt{places}. When rounding is turned on, the % number of digits used (either decimal places or significant figures in % the mantissa) is set using the \opt{round-precision} option. No rounding will % take place if the number contains an uncertainty component. %\begin{LaTeXdemo} % \num{1.23456} \\ % \num{14.23} \\ % \num{0.12345(9)} \\ % \sisetup{ % round-mode = places, % round-precision = 3 % }% % \num{1.23456} \\ % \num{14.23} \\ % \num{0.12345(9)} \\ % \sisetup{ % round-mode = figures, % round-precision = 3 % }% % \num{1.23456} \\ % \num{14.23} \\ % \num{0.12345(9)} %\end{LaTeXdemo} %\DescribeOption{round-integer-to-decimal} %\changes{v2.1}{2010/10/25}{New \opt{zero-integer-to-decimal} option % to convert integers to decimals on rounding} % The standard settings for \pkg{siunitx} do not add a decimal part % if none was given in the input. The \opt{round-integer-to-decimal} % option can be used to allow this conversion as part of the rounding % process. %\begin{LaTeXdemo} % \num[round-mode = figures]{1} \\ % \num[round-mode = places]{1} \\ % \sisetup{round-integer-to-decimal} % \num[round-mode = figures]{1} \\ % \num[round-mode = places]{1} %\end{LaTeXdemo} % \DescribeOption{zero-decimal-to-integer} % \changes{v2.5}{2011/04/07}{New \opt{zero-decimal-to-integer} option} % It may be desirable to convert decimals to integers if the decimal part is % zero. This is set up using the \opt{zero-decimal-to-integer} option. %\begin{LaTeXdemo} % \num{2.0} \\ % \num{2.1} \\ % \sisetup{zero-decimal-to-integer} % \num{2.0} \\ % \num{2.1} %\end{LaTeXdemo} %\DescribeOption{round-minimum} %\changes{v2.1}{2010/10/27}{New \opt{round-minimum} option % to set a floor for rounding numbers downward} % There are cases in which rounding will result in the number reaching % zero. It may be desirable to show such results as below a threshold % value. This can be achieved by setting \opt{round-minimum} to the % threshold value. There will be no effect when rounding to a number of % significant figures as it is not possible to obtain the value zero in % these cases. %\begin{LaTeXdemo} % \sisetup{round-mode = places}% % \num{0.0055} \\ % \num{0.0045} \\ % \sisetup{round-minimum = 0.01}% % \num{0.0055} \\ % \num{0.0045} %\end{LaTeXdemo} % \DescribeOption{round-half} % \changes{v2.4}{2011/1/04}{New \opt{round-half} option} % In cases where the rounded part of a number is exactly half, there are % two common methods for \enquote{breaking the tie}. The choice of method % is determined by the option \opt{round-half}, which recognises the % choices \opt{up} and \opt{even}. %\begin{LaTeXdemo} % \sisetup{round-mode = places, round-half = up}% % \num{0.055} \\ % \num{0.045} \\ % \sisetup{round-half = even}% % \num{0.055} \\ % \num{0.045} %\end{LaTeXdemo} % %\DescribeOption{add-decimal-zero} %\DescribeOption{add-integer-zero} % It is possible to give real (floating point) numbers as input omitting % the decimal or the integer parts of the number (for example \num{.123} % or \num{123.}). The options \opt{add-decimal-zero} and % \opt{add-integer-zero} allow the package to \enquote{fill in} the % missing zero. %\begin{LaTeXdemo} % \num{123.} \\ % \num{456} \\ % \num{.789} \\ % \sisetup{ % add-decimal-zero = false, % add-integer-zero = false, % }% % \num{123.} \\ % \num{456} \\ % \num{.789} %\end{LaTeXdemo} %\DescribeOption{minimum-integer-digits} %\changes{v2.2}{2011/04/04}{New \opt{minimum-integer-digits} option} % Related is the \opt{minimum-integer-digits} option. This applies % only to the integer part of the mantissa, and ensures that it will % contain at least the specified number of digits. This is achieved % by padding with zeros if needed. %\begin{LaTeXdemo} % \num{123} \\ % \num[minimum-integer-digits = 1]{123} \\ % \num[minimum-integer-digits = 2]{123} \\ % \num[minimum-integer-digits = 3]{123} \\ % \num[minimum-integer-digits = 4]{123} %\end{LaTeXdemo} % %\DescribeOption{explicit-sign} %\DescribeOption{retain-explicit-plus} % The inclusion of a leading plus sign is usually unnecessary for % positive numbers, and so the \opt{retain-explicit-plus} option is % available to control whether these are printed. At the same time, it % may be useful to force all numbers to have a sign. This behaviour % is controlled by the \opt{explicit-sign} option: this is used if % given and if no sign was present in the input. %\begin{LaTeXdemo} % \num{+345} \\ % \num[retain-explicit-plus]{+345} \\ % \num[explicit-sign = -]{345} \\ % \num[explicit-sign = -]{+345} %\end{LaTeXdemo} % %\DescribeOption{retain-unity-mantissa} %\DescribeOption{retain-zero-exponent} % The retention of a zero exponent is controlled by the % \opt{retain-zero-exponent} option. The retention of a mantissa of one % is likewise controlled by the \opt{retain-unity-mantissa} option. %\begin{LaTeXdemo} % \num{1e4} \\ % \num[retain-unity-mantissa = false]{1e4} \\ % \num{444e0} \\ % \num[retain-zero-exponent = true]{444e0} %\end{LaTeXdemo} % %\DescribeOption{scientific-notation} %\changes{v2.1}{2010/10/13}{New \opt{scientific-notation} option % for to use exponent form for numbers in all cases} %\changes{v2.2}{2011/04/04}{Extend \opt{scientific-notation} option % to include \opt{engineering} mode} %\DescribeOption{fixed-exponent} % Numbers can be converted to scientific notation by the package. This % is controlled by the \opt{scientific-notation} option, which takes % choices \opt{false}, \opt{true}, \opt{fixed} and % \opt{engineering}. The \opt{fixed} setting will use the exponent value % by the \opt{fixed-exponent} option. When \opt{engineering} is set, % the exponent is always a power of three. %\begin{LaTeXdemo} % \num{0.001} \\ % \num{0.0100} \\ % \num{1200} \\ % \sisetup{scientific-notation = true}% % \num{0.001} \\ % \num{0.0100} \\ % \num{1200} \\ % \sisetup{scientific-notation = engineering}% % \num{0.001} \\ % \num{0.0100} \\ % \num{1200} \\ % \sisetup{ % fixed-exponent = 2, % scientific-notation = fixed, % }% % \num{0.001} \\ % \num{0.0100} \\ % \num{1200} %\end{LaTeXdemo} % \changes{v2.5}{2012/04/08}{Slight alteration of code order so that % \opt{fixed-exponent} can be used to remove an exponent part from % numerical input} % When used with a \opt{fixed-exponent} of zero, this may be used to remove % scientific notation from the input %\begin{LaTeXdemo} % \num{1.23e4} \\ % \num[scientific-notation = fixed, fixed-exponent = 0]{1.23e4} %\end{LaTeXdemo} % % \DescribeOption{omit-uncertainty} % \changes{v2.5}{2012/04/07}{New \opt{omit-uncertainty} option} % The printing of an uncertainty can be suppressed entirely using the % \opt{omit-uncertainty} option. %\begin{LaTeXdemo} % \num{0.01(2)} \\ % \num[omit-uncertainty]{0.01(2)} %\end{LaTeXdemo} % %\subsection{Printing numbers} % % Actually printing numbers is controlled by a number of settings, % which apply ideas such as differing decimal markers, digit % grouping and so on. All of these options are concerned with the % appearance of output, rather than the data it conveys. The options are % summarised in \cref{tab:opt:num:out}. % %\begin{table} % \centering % \caption{Output options for numbers.} % \label{tab:opt:num:out} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{l}{Option name} & % Type & % \multicolumn{1}{l}{Default} \\ % \midrule % bracket-negative-numbers & Switch & false \\ % bracket-numbers & Switch & true \\ ^^A ( % close-bracket & Literal & ) \\ % complex-root-position & Choice & after-number \\ % copy-complex-root & Choice & false \\ % copy-decimal-marker & Choice & false \\ % exponent-base & Literal & 10 \\ % exponent-product & Math & \verb=\times= \\ % group-digits & Choice & true \\ % group-minimum-digits & integer & 5 \\ % group-separator & Literal & \cs{,} \\ % negative-color & Literal & \meta{none} \\ % open-bracket & Literal & ( % \\ ^^A ) ( % output-close-uncertainty & Literal & ) \\ % output-complex-root & Literal & \verb=\ensuremath{\mathrm{i}}= \\ % output-decimal-marker & Literal & . \\ % output-exponent-marker & Literal & \meta{none} \\ % output-open-uncertainty & Literal & ( \\ ^^A ) % separate-uncertainty & Switch & false \\ % tight-spacing & Switch & false \\ % uncertainty-separator & Literal & \meta{none} \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{group-digits} %\changes{v2.2a}{2011/04/15}{Add missing default for \opt{group-digits} option} % \changes{v2.3}{2011/06/06}{Extend \opt{group-digits} option, deprecating % \opt{group-decimal-digits} and \opt{group-integer-digits}} %\DescribeOption{group-four-digits} %\DescribeOption{group-separator} % Grouping digits into blocks of three is a common method to increase % the ease of reading of numbers. The \opt{group-digits} choice controls % whether this behaviour applies, and takes the values \opt{true}, \opt{false}, % \opt{decimal} and \opt{integer}. Grouping can be activated separately for % the integer and decimal parts of a number using the appropriately-named % values. %\begin{LaTeXdemo} % \num{12345.67890} \\ % \num[group-digits = false]{12345.67890} \\ % \num[group-digits = decimal]{12345.67890} \\ % \num[group-digits = integer]{12345.67890} %\end{LaTeXdemo} % The separator used between groups of digits is stored by the % \opt{group-separator} option. This takes literal input and may be % used in math mode: for a text-mode full space use |\text{~}|. %\begin{LaTeXdemo} % \num{12345} \\ % \num[group-separator = {,}]{12345} \\ % \num[group-separator = \text{~}]{12345} %\end{LaTeXdemo} % \DescribeOption{group-minimum-digits} % \changes{v2.3}{2011/06/06}{New \opt{group-minimum-digits} option to % replace \opt{group-four-digits}} % Grouping is not always applied to smaller numbers, and the option % \opt{group-minimum-digits} is available to specify how many digits must % be present before grouping is applied. The number of digits is considered % separately for the integer and decimal parts of the number: grouping % does not \enquote{cross the boundary}. %\begin{LaTeXdemo} % \num{1234} \\ % \num[group-minimum-digits = 4]{1234} \\ % \num{1234.5678} \\ % \num[group-minimum-digits = 4]{1234.5678} %\end{LaTeXdemo} % %\DescribeOption{output-complex-root} %\DescribeOption{output-decimal-marker} %\DescribeOption{copy-complex-root} %\changes{v2.1}{2010/10/02}{New \opt{copy-complex-root} option for % moving input complex root to output} %\DescribeOption{copy-decimal-marker} % The decimal marker used in output is set using the % \opt{output-decimal-marker} option. This can differ from the input % marker, as can the root of $\sqrt{-1}$, which is stored in the % \opt{output-complex-root} option. The standard setting uses \cs{mathrm} % in math mode to give an upright % \enquote{i}: this can easily be altered. The complex root or decimal % marker from the input can be used in the output by setting the % \opt{copy-complex-root} and \opt{copy-decimal-marker} options, % respectively. %\begin{LaTeXdemo} % \num{1.23} \\ % \num[output-decimal-marker = {,}]{1.23} \\ % \num{1+2i} \\ % \num[output-complex-root = \text{\ensuremath{i}}]{1+2i} \\ % \num[output-complex-root = j]{1+2i} \\ % \num[copy-complex-root]{1+2j} \\ % \num[copy-decimal-marker]{555,555} %\end{LaTeXdemo} % %\DescribeOption{complex-root-position} % The position of the complex root can be adjusted to place it % either before or after the associated numeral in a complex number % using the \opt{complex-root-position} option. %\begin{LaTeXdemo} % \num{67-0.9i} \\ % \num[complex-root-position = before-number]{67-0.9i} \\ % \num[complex-root-position = after-number]{67-0.9i} %\end{LaTeXdemo} % %\DescribeOption{exponent-base} %\DescribeOption{exponent-product} % When exponents are present in the input, the % \opt{exponent-base} and \opt{exponent-product} options set the obvious % parts of the output. Notice that the base is in the current mode, but % the product sign is always in math mode. %\begin{LaTeXdemo} % \num[exponent-product = \times]{1e2} \\ % \num[exponent-product = \cdot]{1e2} \\ % \num[exponent-base = 2]{1e2} %\end{LaTeXdemo} %\DescribeOption{output-exponent-marker} %\changes{v2.2}{2011/04/03}{New \opt{output-exponent-marker} option} % \changes{v2.6}{2014/09/05}{Fix printing exponent in tables when % \opt{output-exponent-marker} is active} % Alternatively, if the \opt{output-exponent-marker} option is % set then the value stored will be used in place of the normal % product and base combination. This will normally be set up to % ensure math or text mode. %\begin{LaTeXdemo} % \num[output-exponent-marker = \text{e}]{1e2} \\ % \num[output-exponent-marker = \ensuremath{\mathrm{E}}]{1e2} %\end{LaTeXdemo} % %\DescribeOption{separate-uncertainty} %\DescribeOption{uncertainty-separator} %\DescribeOption{output-open-uncertainty} %\DescribeOption{output-close-uncertainty} % When input is given including an uncertainty in a number, it can be % printed either with the uncertainty in brackets or as a separate % number. This behaviour is controlled by the % \opt{separate-uncertainty} choice. If the uncertainty is given in % brackets, a space may be added between the main number and the % uncertainty: this is stored using the \opt{uncertainty-separator} % option. The opening and closing brackets used are stored in % \opt{output-open-uncertainty} and % \opt{output-close-uncertainty}, respectively. %\begin{LaTeXdemo} % \num{1.234(5)} \\ % \num[separate-uncertainty = true]{1.234(5)} \\ % \sisetup{ % output-open-uncertainty = [, % output-close-uncertainty = ], % uncertainty-separator = {\,} % } % \num{1.234(5)} %\end{LaTeXdemo} % Notice that \pkg{siunitx} correctly interprets uncertainties which % cross the decimal marker position whether these are separated out % or not. %\begin{LaTeXdemo} % \num{8.2(13)} \\ % \num[separate-uncertainty]{8.2(13)} %\end{LaTeXdemo} % %\DescribeOption{bracket-numbers} %\DescribeOption{open-bracket} %\DescribeOption{close-bracket} % There are certain combinations of numerical input which can be % ambiguous. This can be corrected by adding brackets in the appropriate % place, and is controlled by the \opt{bracket-numbers} switch. The % opening and closing brackets used are stored in \opt{open-bracket} and % \opt{close-bracket}, respectively. Note that \opt{bracket-numbers} % only applies to numbers without units: for numbers with units % see the \opt{multi-part-units} option. %\begin{LaTeXdemo} % \num{1+2i e10} \\ % \num[bracket-numbers = false]{1+2i e10} \\ % \sisetup{ % open-bracket = \{, % close-bracket = \}, % } % \num{1+2i e10} %\end{LaTeXdemo} % %\DescribeOption{negative-color} % \pkg{siunitx} can detect negative mantissa values and alter print % colour accordingly. This is disabled by setting the option to an empty % value. %\begin{LaTeXdemo} % \num{-15673} \\ % \num[negative-color = red]{-15673} %\end{LaTeXdemo} % %\DescribeOption{bracket-negative-numbers} %\changes{v2.2}{2011/04/02}{New \opt{bracket-negative-numbers} option} % A common means to display negative numbers in financial situations % is to place them in brackets. This can be carried out automatically % using the \opt{bracket-negative-numbers} option. %\begin{LaTeXdemo} % \num{-15673} \\ % \num[bracket-negative-numbers]{-15673} \\ % \SI{-10}{\metre} \\ % \SI[bracket-negative-numbers]{-10}{\metre} %\end{LaTeXdemo} % %\DescribeOption{tight-spacing} %\changes{v2.0y}{2010/10/09}{Error with \opt{tight-spacing} option % and exponents corrected} % Under some circumstances is may be desirable to \enquote{squeeze} % the output spacing. This is turned on using the \opt{tight-spacing} % switch, which compresses spacing where possible. %\begin{LaTeXdemo} % \num{1 \pm 2i e3} \\ % \num[tight-spacing = true]{1 \pm 2i e3} %\end{LaTeXdemo} % %\subsection{Multi-part numbers} % % \pkg{siunitx} recognises the idea of products and quotients in % numbers, both with and without units. These multi-part numbers have % a number of options affecting how they are processed. The options are % summarised in \cref{tab:opt:num:multi}. % %\begin{table} % \centering % \caption{Multi-part number options.} % \label{tab:opt:num:multi} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{l}{Option name} & % Type & % \multicolumn{1}{l}{Default} \\ % \midrule ^^A ( % fraction-function & Macro & \cs{frac} \\ % input-product & Literal & x \\ % input-quotient & Literal & / \\ % output-product & Math & \verb=\times= \\ % output-quotient & Literal & / \\ % quotient-mode & Choice & symbol \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{input-product} %\DescribeOption{input-quotient} % The options \opt{input-product} and \opt{input-quotient} contain the % tokens used to determine if a number contains multiple parts. %\begin{LaTeXdemo} % \num{1 x 2 x 3} \\ % \num{1e4 x 2(3) x 3/4} \\ % \num[input-product=*]{4 * 5 * 6} \\ % \num{ 1 / 2e4 } \\ % \num{ 1e2 / 3e4 } %\end{LaTeXdemo} %\DescribeOption{output-product} %\DescribeOption{output-quotient} % The symbols used for printing products and quotients are stored using % the options \opt{output-product} and \opt{output-quotient}. %\begin{LaTeXdemo} % \num[output-product = \cdot]{4.87 x 5.321 x 6.90545} \\ % \num[output-quotient = \text{ div }]{1 / 2} %\end{LaTeXdemo} % %\DescribeOption{quotient-mode} % For quotients, there is the possibility to print output either using % a slash, or using the \cs{frac} macro. This is controlled by the % \opt{quotient} choice option, which takes values \opt{symbol} and % \opt{fraction}. %\begin{LaTeXdemo} % \num{1 / 2e4} \\ % \num[quotient-mode = fraction]{1 / 2e4} %\end{LaTeXdemo} % %\DescribeOption{fraction-function} % The function used when \opt{quotient-mode = fraction} is set is % determined by the \opt{fraction-function} option. This should % be set to a function which takes two arguments, and presumably % creates some type of fraction. Most alternatives to the standard % \cs{frac} function will involve loading additional packages: the % demonstrations here need \pkg{amsmath} and % \pkg{xfrac}. %\begin{LaTeXdemo} % \sisetup{quotient-mode = fraction} % \num{1 / 1} % \num[fraction-function = \dfrac]{1 / 2} % \num[fraction-function = \sfrac]{1 / 3} % \num[fraction-function = \tfrac]{1 / 4} %\end{LaTeXdemo} % %\subsection{Lists and ranges of numbers} % % Lists and ranges of numbers have a small number of specialised % options, which apply to these more unusual input forms % (\cref{tab:opt:num:list}). % %\begin{table} % \centering % \caption{Output options for lists and ranges of numbers.} % \label{tab:opt:num:list} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{l}{Option name} & % Type & % \multicolumn{1}{l}{Default} \\ % \midrule % list-final-separator & Literal & \verb*= and = \\ % list-pair-separator & Literal & \verb*= and = \\ % list-separator & Literal & \verb*=, = \\ % range-phrase & Literal & \verb*= to = \\ % \bottomrule % \end{tabular} %\end{table} % % \DescribeOption{list-final-separator} % \DescribeOption{list-pair-separator} % \changes{v2.4}{2011/11/02}{New \opt{list-pair-separator} option} % \DescribeOption{list-separator} % Lists of numbers are printed with a separator between each item, % which is stored using the \opt{list-separator} option. The % separator before the last item of a list may be different, and % is therefore set using the \opt{list-final-separator} option. % The separator used for exactly two items is set using the % \opt{list-pair-separator} option. Any % spaces needed should be included in the option settings: none are % added within the code. These items are printed in text mode. %\begin{LaTeXdemo} % \numlist{0.1;0.2;0.3} \\ % \numlist[list-separator = {; }]{0.1;0.2;0.3} \\ % \numlist[list-final-separator = {, }]{0.1;0.2;0.3} \\ % \numlist[ % list-separator = { and }, % list-final-separator = { and finally } % ]{0.1;0.2;0.3} \\ % \numlist{0.1;0.2} \\ % \numlist[list-pair-separator = {, and }]{0.1;0.2} %\end{LaTeXdemo} % %\DescribeOption{range-phrase} % Ranges of numbers can be given as input. These will have an % appropriate word or symbol inserted between the two entries: this % is stored using the \opt{range-phrase} option. The phrase should % include any necessary spaces: no extra space is added. %\begin{LaTeXdemo} % \numrange{5}{100} \\ % \numrange[range-phrase = --]{5}{100} %\end{LaTeXdemo} % % \changes{v2.4}{2011/11/04}{Automatically compress exponents for lists and % ranges when fixed exponents are active} % For lists and ranges when a single unit is given, \pkg{siunitx} will % automatically \enquote{compress} exponents when a fixed exponent is in % use. %\begin{LaTeXdemo} % \sisetup{ % fixed-exponent = 3 , % list-units = brackets , % range-units = brackets , % scientific-notation = fixed % }% % \SIrange{1e3}{7e3}{\metre} \\ % \SIlist{1e3;2e3;3e3}{\kg} %\end{LaTeXdemo} % %\subsection{Angles} % % Angle processing provided by the \cs{ang} function has a set of % options which apply in addition to the general ones set up for number % processing (\cref{tab:opt:ang}). % %\begin{table} % \centering % \caption{Angle options.} % \label{tab:opt:ang} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{l}{Option name} & % Type & % \multicolumn{1}{l}{Default} \\ % \midrule % add-arc-degree-zero & Switch & false \\ % add-arc-minute-zero & Switch & false \\ % add-arc-second-zero & Switch & false \\ % angle-symbol-over-decimal & Switch & false \\ % arc-separator & Literal & false \\ % number-angle-product & Literal & \meta{empty} \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{number-angle-product} % The separator between the number and angle symbol (degrees, minutes % or seconds) can be set using the \opt{number-angle-product} % option, independent of the related \opt{number-unit-product} % option used by the \cs{SI} function. %\begin{LaTeXdemo} % \ang{2.67} \\ % \ang[number-angle-product = \,]{2.67} %\end{LaTeXdemo} % %\DescribeOption{arc-separator} % When angles are printed in arc format, the separation of the different % parts is set up using the \opt{arc-separator} option. %\begin{LaTeXdemo} % \ang{6;7;6.5} \\ % \ang[arc-separator = \,]{6;7;6.5} %\end{LaTeXdemo} % %\DescribeOption{add-arc-degree-zero} %\DescribeOption{add-arc-minute-zero} %\DescribeOption{add-arc-second-zero} % Zero-filling for the degree, minute or second parts of an arc is % controlled using the \opt{add-arc-degree-zero}, % \opt{add-arc-minute-zero} and \opt{add-arc-second-zero} options. % All are off as standard. %\begin{LaTeXdemo} % \ang{-1;;} \\ % \ang{;-2;} \\ % \ang{;;-3} \\ % \sisetup{add-arc-degree-zero} % \ang{-1;;} \\ % \ang{;-2;} \\ % \ang{;;-3} \\ % \sisetup{add-arc-minute-zero} % \ang{-1;;} \\ % \ang{;-2;} \\ % \ang{;;-3} \\ % \sisetup{add-arc-second-zero} % \ang{-1;;} \\ % \ang{;-2;} \\ % \ang{;;-3} %\end{LaTeXdemo} % %\DescribeOption{angle-symbol-over-decimal} % In some subject areas, most notably astronomy, the angle symbols % are given over the decimal marker, rather than at the end of the % number. This behaviour is available using the % \opt{angle-symbol-over-decimal} option. %\begin{LaTeXdemo} % \ang{45.697} \\ % \ang{6;7;6.5} \\ % \ang[angle-symbol-over-decimal]{45.697} \\ % \ang[angle-symbol-over-decimal]{6;7;6.5} %\end{LaTeXdemo} % %\subsection{Creating units} %\label{sec:units:creating} % % The various macro units are created at the start of the document. % \pkg{siunitx} can define these such that they are only available for % use within the \cs{si} and \cs{SI} functions, or can make the unit % macros available throughout the document body. There are a number of % settings which control this creation process % (\cref{tab:opt:units:def}). As a result, these options all apply % in the preamble only. % %\begin{table} % \centering % \caption{Unit creation options.} % \label{tab:opt:units:def} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{l}{Option name} & % Type & % \multicolumn{1}{l}{Default} \\ % \midrule ^^A ( % free-standing-units & Switch & false \\ % overwrite-functions & Switch & false \\ % space-before-unit & Switch & false \\ % unit-optional-argument & Switch & false \\ % use-xspace & Switch & false \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{free-standing-units} %\changes{v2.1d}{2010/11/14}{Apply unit options when % \opt{free-standing-units} is active} %\changes{v2.1e}{2010/11/22}{Further corrections when applying unit % options when \opt{free-standing-units} is active} %\DescribeOption{overwrite-functions} % The \opt{free-standing-units} option controls whether the unit macros % exist outside of the \cs{si} and \cs{SI} arguments. When this option % is \opt{true}, \pkg{siunitx} creates the macros for general use. % The standard method to achieve this does not overwrite any existing % macros: this behaviour can be altered using the % \opt{overwrite-functions} switch. % %\DescribeOption{space-before-unit} %\DescribeOption{unit-optional-argument} %\changes{v2.1f}{2010/11/24}{Typo in definition for % \opt{unit-optional-argument} implementation corrected} %\DescribeOption{use-xspace} % When \enquote{free standing} unit macros are created, their behaviour % can be adjusted by a number of options. These are mainly intended for % emulating the input syntax of older packages. The option % \opt{unit-optional-argument} gives the same behaviour for the % inputs %\begin{LaTeXdemo}[code only] % \SI{10}{\metre} %\end{LaTeXdemo} % and %\begin{LaTeXdemo}[code only] % \metre[10]. %\end{LaTeXdemo} % The \opt{space-before-unit} and \opt{use-xspace} options control % the behaviour at the \enquote{ends} of the unit macros. Activating % \opt{space-before-unit} inserts the number--unit space before the % unit is printed. This is suitable for the input syntax %\begin{LaTeXdemo}[code only] % 30\metre %\end{LaTeXdemo} % but does mean that the unit macros are incorrectly spaced in running % text. On the other hand, the \opt{use-xspace} option attempts to % correctly space input such as %\begin{LaTeXdemo}[code only] % \metre is the symbol for metres. %\end{LaTeXdemo} % %\subsection{Loading additional units} % % \DescribeOption{abbreviations} % As standard, \pkg{siunitx} loads a set of abbreviated versions of the % SI units (\cref{tab:unit:abbr}). The standard \pkg{siunitx} settings only % create these abbreviations within the scope of the \cs{si} and \cs{SI} % functions, meaning that no clashes should occur (for example with the % standard \cs{pm} symbol). Loading of these abbreviations can be prevented % by setting the option \opt{abbreviations = false} in the preamble. % %\begin{center} % \changes{v2.0n}{2010/07/15}{More abbreviated units} % \changes{v2.3b}{2011/07/27}{More abbreviated units} % \tablecaption{Abbreviated units.} % \label{tab:unit:abbr} % \tablefirsthead{^^A % \toprule % \multicolumn{1}{l}{Unit} & % \multicolumn{1}{l}{Abbreviation} & % \multicolumn{1}{l}{Symbol} \\ % \midrule % } % \tablehead{^^A % \multicolumn{3}{l}{\emph{Continued from previous page}} \\ % \toprule % \multicolumn{1}{l}{Unit} & % \multicolumn{1}{l}{Abbreviation} & % \multicolumn{1}{l}{Symbol} \\ % \midrule % } % \tabletail{^^A % \bottomrule % \multicolumn{3}{r}{\emph{Continued on next page}} \\ % } % \tablelasttail{\bottomrule} % \begin{xtabular}{lcc} % \DescribeNamedUnit{femtogram}{fg} \\ % \DescribeNamedUnit{picogram}{pg} \\ % \DescribeNamedUnit{nanogram}{ng} \\ % \DescribeNamedUnit{microgram}{ug} \\ % \DescribeNamedUnit{milligram}{mg} \\ % \DescribeNamedUnit{gram}{g} \\ % \DescribeNamedUnit{kilogram}{kg} \\ % \DescribeNamedUnit{atomic mass unit}{amu} \\ % % \midrule % % \DescribeNamedUnit{picometre}{pm} \\ % \DescribeNamedUnit{nanometre}{nm} \\ % \DescribeNamedUnit{micrometre}{um} \\ % \DescribeNamedUnit{millimetre}{mm} \\ % \DescribeNamedUnit{centimetre}{cm} \\ % \DescribeNamedUnit{decimetre}{dm} \\ % \DescribeNamedUnit{metre}{m} \\ % \DescribeNamedUnit{kilometre}{km} \\ % % \midrule % % \DescribeNamedUnit{attosecond}{as} \\ % \DescribeNamedUnit{femtosecond}{fs} \\ % \DescribeNamedUnit{picosecond}{ps} \\ % \DescribeNamedUnit{nanosecond}{ns} \\ % \DescribeNamedUnit{microsecond}{us} \\ % \DescribeNamedUnit{millisecond}{ms} \\ % \DescribeNamedUnit{second}{s} \\ % % \midrule % % \DescribeNamedUnit{femtomole}{fmol} \\ % \DescribeNamedUnit{picomole}{pmol} \\ % \DescribeNamedUnit{nanomole}{nmol} \\ % \DescribeNamedUnit{micromole}{umol} \\ % \DescribeNamedUnit{millimole}{mmol} \\ % \DescribeNamedUnit{mole}{mol} \\ % \DescribeNamedUnit{kilomole}{kmol} \\ % % \midrule % % \DescribeNamedUnit{picoampere}{pA} \\ % \DescribeNamedUnit{nanoampere}{nA} \\ % \DescribeNamedUnit{microampere}{uA} \\ % \DescribeNamedUnit{milliampere}{mA} \\ % \DescribeNamedUnit{ampere}{A} \\ % \DescribeNamedUnit{kiloampere}{kA} \\ % % \midrule % % \DescribeNamedUnit{microlitre}{ul} \\ % \DescribeNamedUnit{millilitre}{ml} \\ % \DescribeNamedUnit{litre}{l} \\ % \DescribeNamedUnit{hectolitre}{hl} \\ % \DescribeNamedUnit{microliter}{uL} \\ % \DescribeNamedUnit{milliliter}{mL} \\ % \DescribeNamedUnit{liter}{L} \\ % \DescribeNamedUnit{hectoliter}{hL} \\ % % \midrule % % \DescribeNamedUnit{millihertz}{mHz} \\ % \DescribeNamedUnit{hertz}{Hz} \\ % \DescribeNamedUnit{kilohertz}{kHz} \\ % \DescribeNamedUnit{megahertz}{MHz} \\ % \DescribeNamedUnit{gigahertz}{GHz} \\ % \DescribeNamedUnit{terahertz}{THz} \\ % % \midrule % % \DescribeNamedUnit{millinewton}{mN} \\ % \DescribeNamedUnit{newton}{N} \\ % \DescribeNamedUnit{kilonewton}{kN} \\ % \DescribeNamedUnit{meganewton}{MN} \\ % % \midrule % % \DescribeNamedUnit{pascal}{Pa} \\ % \DescribeNamedUnit{kilopascal}{kPa} \\ % \DescribeNamedUnit{megapacal}{MPa} \\ % \DescribeNamedUnit{gigapascal}{GPa} \\ % % \midrule % % \DescribeNamedUnit{milliohm}{mohm} \\ % \DescribeNamedUnit{kilohm}{kohm} \\ % \DescribeNamedUnit{megohm}{Mohm} \\ % % \midrule % % \DescribeNamedUnit{picovolt}{pV} \\ % \DescribeNamedUnit{nanovolt}{nV} \\ % \DescribeNamedUnit{microvolt}{uV} \\ % \DescribeNamedUnit{millivolt}{mV} \\ % \DescribeNamedUnit{volt}{V} \\ % \DescribeNamedUnit{kilovolt}{kV} \\ % % \midrule % % \DescribeNamedUnit{watt}{W} \\ % \DescribeNamedUnit{microwatt}{uW} \\ % \DescribeNamedUnit{milliwatt}{mW} \\ % \DescribeNamedUnit{kilowatt}{kW} \\ % \DescribeNamedUnit{megawatt}{MW} \\ % \DescribeNamedUnit{gigawatt}{GW} \\ % \DescribeNamedUnit{joule}{J} \\ % \DescribeNamedUnit{kilojoule}{kJ} \\ % \DescribeNamedUnit{electronvolt}{eV} \\ % \DescribeNamedUnit{millielectronvolt}{meV} \\ % \DescribeNamedUnit{kiloelectronvolt}{keV} \\ % \DescribeNamedUnit{megaelectronvolt}{MeV} \\ % \DescribeNamedUnit{gigaelectronvolt}{GeV} \\ % \DescribeNamedUnit{teraelectronvolt}{TeV} \\ % \DescribeNamedUnit{kilowatt hour}{kWh} \\ % % \midrule % % \DescribeNamedUnit{farad}{F} \\ % \DescribeNamedUnit{femtofarad}{fF} \\ % \DescribeNamedUnit{picofarad}{pF} \\ % % \midrule % % \DescribeNamedUnit{kelvin}{K} \\ % % \midrule % % \DescribeNamedUnit{decibel}{dB} \\ % % \end{xtabular} %\end{center} % % \DescribeOption{binary-units} % \changes{v2.5g}{2012/07/22}{Fix \opt{binary-units} option} % \DescribeMacro{\bit} % \DescribeMacro{\byte} % Binary data is expressed in units of bits and bytes. These are % normally given prefixes which use powers of two, rather than the % powers of ten used by the SI prefixes. As these binary prefixes are % closely related to the SI prefixes, they are defined by \pkg{siunitx} % but do have to be loaded using \opt{binary-units = true} (or % simply \opt{binary-units}) % (\cref{tab:unit:binary}). The units \cs{bit} and \cs{byte} are % then also available. %\begin{LaTeXdemo} % \SI{100}{\mebi\byte} \\ % \SI[prefixes-as-symbols=false]{30}{\kibi\bit} %\end{LaTeXdemo} % %\begin{table} % \caption{Binary prefixes.} % \label{tab:unit:binary} % \centering % \begin{tabular}{llc>{$}l<{$}} % \toprule % Prefix & Macro & Symbol & \multicolumn{1}{l}{Power} \\ % \midrule % \DescribePrefix{kibi} & 10 \\ % \DescribePrefix{mebi} & 20 \\ % \DescribePrefix{gibi} & 30 \\ % \DescribePrefix{tebi} & 40 \\ % \DescribePrefix{pebi} & 50 \\ % \DescribePrefix{exbi} & 60 \\ % \DescribePrefix{zebi} & 70 \\ % \DescribePrefix{yobi} & 80 \\ % \bottomrule % \end{tabular} %\end{table} % % \DescribeOption{version-1-compatibility} % A configuration file is also included which will use settings % and define macros as defined by version 1 of \pkg{siunitx}: this % can be accessed with the option \opt{version-1-compatibility}. % This is intended to allow easy transition to version 2: users % should update their source to use the new interfaces and functions. % % Users upgrading from version 1 of \pkg{siunitx} will notice that % the various \enquote{specialist} units available in version 1 are % no longer provided as loadable options.\footnote{They are included % in the loaded configuration file \opt{version-1}, but this is intended % purely to ease transition to version 2.} These are not included in % version 2 as the criteria for inclusion of such units are far from % clear, and it is difficult to justify providing clearly non-SI % units in the package. For reference, appropriate definitions for % the units which where provided in version 1 are as follows. %\begin{LaTeXdemo}[code only] % % Astronomy % \DeclareSIUnit\parsec{pc} % \DeclareSIUnit\lightyear{ly} % % % Chemical engineering % \DeclareSIUnit\gmol{g\text{-}mol} % \DeclareSIUnit\kgmol{kg\text{-}mol} % \DeclareSIUnit\lbmol{lb\text{-}mol} % % % Chemistry % \DeclareSIUnit\molar{\mole\per\cubic\deci\metre} % \DeclareSIUnit\Molar{\textsc{m}} % \DeclareSIUnit\torr{torr} % % % Geophysics % \DeclareSIUnit\gon{gon} % % % High energy physics % \DeclareSIUnit\micron{\micro\metre} % \DeclareSIUnit\mrad{\milli\rad} % \DeclareSIUnit\gauss{G} % \DeclareSIUnit\eVperc{\eV\per\clight} % \DeclareSIUnit\nanobarn{\nano\barn} % \DeclareSIUnit\picobarn{\pico\barn} % \DeclareSIUnit\femtobarn{\femto\barn} % \DeclareSIUnit\attobarn{\atto\barn} % \DeclareSIUnit\zeptobarn{\zepto\barn} % \DeclareSIUnit\yoctobarn{\yocto\barn} % \DeclareSIUnit\nb{\nano\barn} % \DeclareSIUnit\pb{\pico\barn} % \DeclareSIUnit\fb{\femto\barn} % \DeclareSIUnit\ab{\atto\barn} % \DeclareSIUnit\zb{\zepto\barn} % \DeclareSIUnit\yb{\yocto\barn} %\end{LaTeXdemo} % Users can use a local configuration file to make additional units % available on a local basis, as described in \cref{sec:config:local}. % %\subsection{Using units} % % Part of the power of \pkg{siunitx} is the ability to alter the output % format for units without changing the input. The behaviour of units % is therefore controlled by a number of options which alter either the % processing of units or the output directly % (\cref{tab:opt:units:out}). % %\begin{table} % \centering % \caption{Unit output options.} % \label{tab:opt:units:out} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{l}{Option name} & % Type & % \multicolumn{1}{l}{Default} \\ % \midrule % bracket-unit-denominator & Switch & true \\ % forbid-literal-units & Switch & false \\ % literal-superscript-as-power & Switch & true \\ % inter-unit-product & Literal & \cs{,} \\ % parse-units & Switch & true \\ % per-mode & Choice & reciprocal \\ % per-symbol & Literal & / \\ % power-font & Choice & number \\ % prefixes-as-symbols & Switch & true \\ % qualifier-mode & Choice & subscript \\ % sticky-per & Switch & false \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{forbid-literal-units} % Some users may prefer to completely disable the use of literal input % in units, for example to enforce consistency. This can be % accomplished by setting the \opt{forbid-literal-units} switch. With % this option enabled, only macro-based units can be used in a document. % %\DescribeOption{inter-unit-product} % The separator between each unit is stored using the % \opt{inter-unit-product} option. The standard setting is a thin % space: another common choice is a centred dot. To get the correct % spacing it is necessary to use |\ensuremath{{}\cdot{}}| in the latter case. %\begin{LaTeXdemo} % \si{\farad\squared\lumen\candela} \\ % \si[inter-unit-product = \ensuremath{{}\cdot{}}] % {\farad\squared\lumen\candela} %\end{LaTeXdemo} % %\DescribeOption{per-mode} %\changes{v2.1i}{2011/01/27}{Improved logic for \opt{per-mode} setting % \opt{symbol-or-fraction}} %\changes{v2.2}{2011/04/05}{Include leading \( 1 \) when \opt{per-mode} % is set to \opt{symbol} and there are no numerator units in \cs{si} % arguments} %\DescribeOption{per-symbol} %\DescribeOption{bracket-unit-denominator} % The handling of \cs{per} is altered using the \opt{per-mode} choice % option. The standard setting is \opt{reciprocal}, meaning that % \cs{per} generates reciprocal powers for units. Setting the option % to \opt{fraction} uses the \cs{frac} function to typeset the positive % and negative powers of a unit separately. %\begin{LaTeXdemo} % \si{\joule\per\mole\per\kelvin} \\ % \si{\metre\per\second\squared} \\ % \si[per-mode=fraction]{\joule\per\mole\per\kelvin} \\ % \si[per-mode=fraction]{\metre\per\second\squared} %\end{LaTeXdemo} % The closely-related \opt{reciprocal-positive-first} setting acts in % the same way but places all of the positive powers before any negative % ones. %\begin{LaTeXdemo} % \si{\ampere\per\mole\second} \\ % \si[per-mode = reciprocal-positive-first] % {\ampere\per\mole\second} %\end{LaTeXdemo} % It is possible to use a symbol (usually \texttt{/}) to separate the % two parts of a unit by setting \opt{per-mode} to \opt{symbol}; the % symbol used is stored using the setting \opt{per-symbol}. This method % for displaying units can be ambiguous, and so brackets are added % unless \opt{bracket-unit-denominator} is set to \opt{false}. % Notice that \opt{bracket-unit-denominator} only applies when % \opt{per-mode} is set to \opt{symbol} or \opt{symbol-or-fraction}. %\begin{LaTeXdemo} % \sisetup{per-mode = symbol}% % \si{\joule\per\mole\per\kelvin} \\ % \si{\metre\per\second\squared} \\ % \si[per-symbol = \text{~div~}]{\joule\per\mole\per\kelvin} \\ % \si[bracket-unit-denominator = false]{\joule\per\mole\per\kelvin} %\end{LaTeXdemo} % The often-requested (but mathematically invalid) % \opt{repeated-symbol} option is also available to repeat the symbol % for each \cs{per}. %\begin{LaTeXdemo} % \si[per-mode=repeated-symbol]{\joule\per\mole\per\kelvin} %\end{LaTeXdemo} % Finally, it is possible for the behaviour of the \cs{per} function % to depend on the prevailing math style. Setting \opt{per-mode} to % \opt{symbol-or-fraction} will use the \opt{symbol} setting for % in line math, and the \opt{fraction} setting when used in % \cs{displaystyle} math. %\begin{LaTeXdemo} % \sisetup{per-mode = symbol-or-fraction}% % \( \si{\joule\per\mole\per\kelvin} \) % \[ \si{\joule\per\mole\per\kelvin} \] % \si{\joule\per\mole\per\kelvin} \\ % \( % \displaystyle % \si{\joule\per\mole\per\kelvin} % \) % \[ % \textstyle % \si{\joule\per\mole\per\kelvin} % \] %\end{LaTeXdemo} % %\DescribeOption{sticky-per} % By default, \cs{per} applies only to the next unit % given.\footnote{This is the standard method of reading units in % English: for example, \si{\joule\per\mole\per\kelvin} is pronounced % \enquote{joules per mole per kelvin}.} By setting the % \opt{sticky-per} flag, this behaviour is changed so that \cs{per} % applies to all subsequent units. %\begin{LaTeXdemo} % \si{\pascal\per\gray\henry} \\ % \si[sticky-per]{\pascal\per\gray\henry} %\end{LaTeXdemo} % %\DescribeOption{power-font} %\changes{v2.1}{2010/10/12}{New \opt{power-font} option for controlling % whether superscript powers are treated as numbers or units} % The font used for the powers in units can be typeset using the % current number or unit font. This may be of use when the font used % for numbers and units are very different, for example when the % \pkg{euler} package is loaded. Note that this setting applies to all % printing options for numbers, including the color used for displaying % the number. %\begin{LaTeXdemo} % \si{\metre\per\second\squared} \\ % \si[power-font = unit]{\metre\per\second\squared} %\end{LaTeXdemo} % \DescribeOption{literal-superscript-as-power} % \changes{v2.3}{2011/06/08}{New \opt{literal-superscript-as-power} option for % controlling how literal units superscripts behave} % When printing units in \enquote{literal} mode, it is possible that simply % printing superscripts \enquote{as is} may lead to poor appearance for the % numbers. This is most likely if the text font of the document uses % old style (lower case) numerals, but the math font uses lining (upper % case) numerals. It is therefore possible to treat superscripts within % literal units as powers, and thus for the \opt{power-font} option to % apply within these literal units. This behaviour is controlled using the % \opt{literal-superscript-as-power} switch. %\begin{LaTeXdemo} % \si{m.s^{2}} \\ % \si[literal-superscript-as-power = false]{m.s^{2}} %\end{LaTeXdemo} % %\DescribeOption{qualifier-mode} %\changes{v2.1c}{2010/11/13}{New \opt{text} choice for % \opt{qualifier-mode} option} % \changes{v2.5d}{2012/06/11}{New \opt{phrase} choice for \opt{qualifier-mode} % option} % \DescribeOption{qualifier-phrase} % \changes{v2.5d}{2012/06/11}{New \opt{qualifier-phrase} option} % Unit qualifiers can be printed in three different formats, set by the % \opt{qualifier-mode} option. The standard setting is \opt{subscript}, % while the options \opt{brackets}, \opt{phrase}, \opt{space} and \opt{text} % are also possible. With the last settings, powers can lead to ambiguity and % are automatically detected and brackets added as appropriate. %\begin{LaTeXdemo} % \si{\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ % \si[qualifier-mode = brackets] % {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ % \si[qualifier-mode = subscript] % {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ % \si[qualifier-mode = space] % {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ % \si[qualifier-mode = text] % {\deci\bel\isotropic} %\end{LaTeXdemo} % The \opt{phrase} setting for \opt{qualifier-mode} uses the text stored using % \opt{qualifier-phrase} to separate the qualifier. %\begin{LaTeXdemo} % \si[qualifier-mode = phrase] % {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ % \si[qualifier-mode = phrase, qualifier-phrase = { by }] % {\kilogram\polymer\squared\per\mole\catalyst\per\hour} \\ %\end{LaTeXdemo} % %\DescribeOption{prefixes-as-symbols} % The unit prefixes (\cs{kilo}, \emph{etc}.) are normally given as % letters. However, the package can convert these into numerical powers. % This is controlled by the \opt{prefixes-as-symbols} switch option. % This correctly deals with the kilogram, which is a base unit even % though it involves a prefix. %\begin{LaTeXdemo} % \si{\milli\litre\per\mole\deci\ampere} \\ % \SI{10}{\kilo\gram\squared\deci\second} \\ % \si[prefixes-as-symbols=false]{\milli\litre\per\mole\deci\ampere}\\ % \SI[prefixes-as-symbols=false]{10}{\kilo\gram\squared\deci\second} %\end{LaTeXdemo} % %\DescribeOption{parse-units} % Normally, \pkg{siunitx} is used with the unit parse enabled, and % only prints units directly if there is literal input. However, if % the input is known to be essentially consistent and high performance % is desired, then the parser can be turned off using the % \opt{parse-units} switch. %\begin{LaTeXdemo} % \SI{300}{\MHz} \\ % \SI[parse-units = false]{300}{\MHz} %\end{LaTeXdemo} % %\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}{l}{Option name} & % Type & % \multicolumn{1}{l}{Default} \\ % \midrule ^^A ( % allow-number-unit-breaks & Switch & false \\ % exponent-to-prefix & Switch & false \\ % list-units & Choice & repeat \\ % multi-part-units & Choice & brackets \\ % number-unit-product & Literal & \cs{,} \\ % product-units & Choice & repeat \\ % range-units & Choice & repeat \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{allow-number-unit-breaks} % Usually, the combination of a number and unit is regarded as a single % mathematical entity which should not be split across lines. However, % there are cases (very long units, narrow columns, \emph{etc}.) where % breaks may be needed. This can be turned on using the % \opt{allow-number-unit-breaks} option. %\begin{LaTeXdemo} % \begin{minipage}{2.55 cm} % % Gives an underfull hbox % Some filler text \SI{10}{\metre} \\ % \sisetup{allow-number-unit-breaks} % Some filler text \SI{10}{\metre} % \end{minipage} %\end{LaTeXdemo} % %\DescribeOption{number-unit-product} % The product symbol between the number and unit is set using the % \opt{number-unit-product} option. %\begin{LaTeXdemo} % \SI{2.67}{\farad} \\ % \SI[number-unit-product = \ ]{2.67}{\farad} \\ % \SI[number-unit-product = ]{2.67}{\farad} %\end{LaTeXdemo} % %\DescribeOption{multi-part-units} % When a number has multiple parts (such as a separate uncertainty) then % the unit must apply to all parts of the number. How this is shown is % controlled using the \opt{multi-part-units} options. The standard % setting is \opt{brackets}, which will place the entire numerical part % in brackets and use a single unit symbol. Alternative options are % \opt{repeat} (print the unit for each part of the number) and % \opt{single} (print only one unit symbol: mathematically incorrect). %\begin{LaTeXdemo} % \sisetup{separate-uncertainty}% % \SI{12.3(4)}{\kilo\gram} \\ % \SI[multi-part-units = brackets]{12.3(4)}{\kilo\gram} \\ % \SI[multi-part-units = repeat]{12.3(4)}{\kilo\gram} \\ % \SI[multi-part-units = single]{12.3(4)}{\kilo\gram} %\end{LaTeXdemo} % It is important to notice that numbers with units are not affected by % the setting of \opt{bracket-numbers}, which applies to \enquote{pure} % numbers only. For example: %\begin{LaTeXdemo} % \sisetup{separate-uncertainty,bracket-numbers = false}% % \num{1.234(5)e-4} \\ % \SI{1.234(5)e-4}{\metre} %\end{LaTeXdemo} % The reason is that the requirements to bracket values with units are % fundamentally different from those for numbers alone. Some % combinations which are mathematically valid in the absence of a unit % become invalid when a unit is present. % %\DescribeOption{product-units} % When a product of quantities is given, the resulting units can be % displayed in a number of ways, set using the \opt{product-units} % option. The standard setting is \opt{repeat}, which prints one % unit symbol for each numbers. Alternatives are \opt{brackets}, % \opt{brackets-power}, \opt{power}, \opt{repeat} and \opt{single}. % This option does not affect the application of brackets for each % number within the product list: it only sets those around the % entire list. %\begin{LaTeXdemo} % \SI{2 x 3 x 4}{\metre} \\ % \SI[product-units = brackets]{2 x 3 x 4}{\metre} \\ % \SI[product-units = brackets-power]{2 x 3 x 4}{\metre} \\ % \SI[product-units = power]{2 x 3 x 4}{\metre} \\ % \SI[product-units = repeat]{2 x 3 x 4}{\metre} \\ % \SI[product-units = single]{2 x 3 x 4}{\metre} %\end{LaTeXdemo} % %\DescribeOption{list-units} %\DescribeOption{range-units} % The \opt{list-units} and \opt{range-units} options determine how % the \cs{SIlist} and \cs{SIrange} functions display units, % respectively. The standard setting for both is \opt{repeat}, where % each number will be printed with a unit. Alternatives are % \opt{brackets} and \opt{single}. Any brackets needed on individual % numbers within a product are controlled by the \opt{brackets-numbers} % option (\emph{i.e}.~they are treated as pure numbers). % These options do not affect the application of brackets for each % number within the list or range: they only set those around the % entire group. %\begin{LaTeXdemo} % \SIlist{2;4;6;8}{\tesla} \\ % \SIlist[list-units = brackets]{2;4;6;8}{\tesla} \\ % \SIlist[list-units = repeat]{2;4;6;8}{\tesla} \\ % \SIlist[list-units = single]{2;4;6;8}{\tesla} \\ % \SIrange{2}{4}{\degreeCelsius} \\ % \SIrange[range-units = brackets]{2}{4}{\degreeCelsius} \\ % \SIrange[range-units = repeat]{2}{4}{\degreeCelsius} \\ % \SIrange[range-units = single]{2}{4}{\degreeCelsius} %\end{LaTeXdemo} % % \DescribeOption{exponent-to-prefix} % \changes{v2.4}{2011/11/06}{New \opt{exponent-to-prefix} option} % When the \opt{exponent-to-prefix} option is set \opt{true}, the package % will attempt to convert any exponents in quantities into unit prefixes, % and will attach these to the first unit given. This process is only % possible if the exponent is one for which a prefix is available, and % retains the number of significant figures in the input. %\begin{LaTeXdemo} % \SI{1700}{\g} \\ % \SI{1.7e3}{\g} \\ % \sisetup{exponent-to-prefix}% % \SI{1700}{\g} \\ % \SI{1.7e3}{\g} \\ % \sisetup{fixed-exponent = 3, scientific-notation = fixed}% % \SI{1700}{\g} \\ % \SI{1.7e3}{\g} %\end{LaTeXdemo} % %\subsection{Tabular material} % % Processing of material in tables obeys the same settings as described % for the functions already described. However, there are some settings % which apply only to the layout of tabular material % (\cref{tab:opt:tables}). % %\begin{table} % \centering % \caption{Options for tabular material.} % \label{tab:opt:tables} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{l}{Option name} & % Type & % \multicolumn{1}{l}{Default} \\ % \midrule ^^A ( % table-align-comparator & Switch & true \\ % table-align-exponent & Switch & true \\ % table-align-text-pre & Switch & true \\ % table-align-text-post & Switch & true \\ % table-align-uncertainty & Switch & true \\ % table-alignment & Choice & \meta{none} \\ % table-auto-round & Switch & false \\ % table-column-width & Length & 0 pt \\ % table-comparator & Switch & false \\ % table-figures-decimal & Integer & 2 \\ % table-figures-exponent & Integer & 0 \\ % table-figures-integer & Integer & 3 \\ % table-figures-uncertainty & Integer & 0 \\ % table-format & Special & \meta{none} \\ % table-number-alignment & Choice & % center-decimal-marker \\ % table-parse-only & Switch & false \\ % table-omit-exponent & Switch & true \\ % table-space-text-pre & Literal & \meta{empty} \\ % table-space-text-post & Literal & \meta{empty} \\ % table-sign-exponent & Switch & false \\ % table-sign-mantissa & Switch & false \\ % table-text-alignment & Choice & center \\ % table-unit-alignment & Choice & center \\ % \bottomrule % \end{tabular} %\end{table} % %\DescribeOption{table-parse-only} % The main use of the \texttt{S} column is to control the alignment of % the resulting output. However, it is possible to turn off alignment % entirely and only use the number parser of \pkg{siunitx}. This is % achieved using the \opt{table-parse-only} switch, as illustrated % in \cref{tab:S:parse}. %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{Parsing without aligning in an \texttt{S} column.} % \label{tab:S:parse} % \begin{tabular} % { % S % S[table-parse-only] % } % \toprule % {Decimal-centred} & % {Simple centring} \\ % \midrule % 12.345 & 12.345 \\ % 6,78 & 6,78 \\ % -88.8(9) & -88.8(9) \\ % 4.5e3 & 4.5e3 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{table-number-alignment} % The alignment of numbers with the boundaries of the \texttt{S} % column is controlled using the \opt{table-number-alignment} option, % which takes the values \opt{center-decimal-marker}, \opt{center}, % \opt{left} and \opt{right}. The \opt{center-decimal-marker} places the % decimal marker for the number at the centre of the column. This does % not need any information in advance, and so is the standard setting. % It works best for approximately symmetrical input (equal numbers of % digits before and after the decimal). On the other hand, the % \opt{center}, \opt{left} and \opt{right} options require space to be % reserved for the numbers, and then use this fixed space to align with % the edges of the column. The different alignment choices are % illustrated in \cref{tab:S:align}, which uses somewhat % exaggerated column headings to show the relative position of the % cell contents. %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Aligning the \texttt{S} column.} % \label{tab:S:align} % \centering % \sisetup{ % table-figures-integer = 2, % table-figures-decimal = 4 % } % \begin{tabular}{ % S % S[table-number-alignment = center] % S[table-number-alignment = left] % S[table-number-alignment = right] % } % \toprule % {Some Values} & {Some Values} & {Some Values} & {Some Values} \\ % \midrule % 2.3456 & 2.3456 & 2.3456 & 2.3456 \\ % 34.2345 & 34.2345 & 34.2345 & 34.2345 \\ % 56.7835 & 56.7835 & 56.7835 & 56.7835 \\ % 90.473 & 90.473 & 90.473 & 90.473 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % Many of the other table options do not apply when % \opt{table-number-alignment = center-decimal-marker} is set, as this % mode always centres the marker at the expense of any other % choices. % %\DescribeOption{table-figures-decimal} %\DescribeOption{table-figures-exponent} %\DescribeOption{table-figures-integer} %\DescribeOption{table-figures-uncertainty} % The space reserved by \pkg{siunitx} for a number is controlled by % two families of options. The first family cover the number of digits % allowed for in different parts of the number, for example % \opt{table-figures-integer} controls the space for integer digits in % the mantissa. If the number of figures is set to \num{0}, then no % space is reserved and some output will either be out of position % or not printed at all (although a warning will result). Reserving % space for a given part of number will automatically include space % for any associated items (for example the \enquote{\( \times \)} % symbol for exponents). %\DescribeOption{table-sign-exponent} %\DescribeOption{table-sign-mantissa} % The second family of options are switches which govern whether % space is reserved for a sign: \opt{table-sign-exponent} and % \opt{table-sign-mantissa}. The effect of altering some of these % settings is shown in \cref{tab:S:space}. %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Reserving space in \texttt{S} columns.} % \label{tab:S:space} % \sisetup{ % table-number-alignment = center, % table-figures-integer = 2 % } % \centering % \begin{tabular}{ % S % S[table-number-alignment = right] % S[table-figures-uncertainty = 1] % S[ % separate-uncertainty, % table-figures-uncertainty = 1 % ] % S[table-sign-mantissa] % S[table-figures-exponent = 1] % } % \toprule % {Values} % & {Values} % & {Values} % & {Values} % & {Values} % & {Values} \\ % \midrule % 2.3 & 2.3 & 2.3(5) & 2.3(5) & 2.3 & 2.3e8 \\ % 34.23 & 34.23 & 34.23(4) & 34.23(4) & 34.23 & 34.23 \\ % 56.78 & 56.78 & 56.78(3) & 56.78(3) & -56.78 & 56.78e3 \\ % 3,76 & 3,76 & 3,76(2) & 3.76(2) & +-3.76 & e6 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} %\DescribeOption{table-comparator} %\changes{v2.1}{2010/10/26}{New \opt{table-comparator} option % for reserving space for comparators in tables} % Space can also be reserved in a table for a comparator (greater than, % less than, and so forth). This is activated using the % \opt{table-comparator} switch (\cref{tab:S:comparators}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Reserving space for comparators in \texttt{S} columns.} % \label{tab:S:comparators} % \sisetup{ % table-number-alignment = center, % table-figures-integer = 2, % table-figures-decimal = 2, % table-figures-exponent = 2, % } % \centering % \begin{tabular}{ % S % S[table-comparator = true] % } % \toprule % {Values} % & {Values} \\ % \midrule % 2.3 & < 2.3e8 \\ % 34.23 & = 34.23 \\ % 56.78 & >= 56.78e3 \\ % 3,76 & \gg e6 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % The table-printing code will omit any part of a number which has no % space reserved, placing a warning in the \LaTeX{} log. This means that % uncertainties and exponents will not be printed if no space is % reserved for them. % %\DescribeOption{table-format} % As a short cut for the preceding options, \pkg{siunitx} also % provides the \opt{table-format} option. This can be used to give the % same information about the space to reserve for a number in a % \enquote{compressed} manner. The input to \opt{table-format} should % consist of a number showing how many figures to reserve in each part % of the input. Thus %\begin{LaTeXdemo}[code only] % \sisetup{ % table-format = 3.2 % } %\end{LaTeXdemo} % is equivalent to %\begin{LaTeXdemo}[code only] % \sisetup{ % table-figures-integer = 3, % table-figures-decimal = 2 % } %\end{LaTeXdemo} % The \opt{table-format} option will also correctly interpret the % presence of a sign, so that %\begin{LaTeXdemo}[code only] % \sisetup{ % table-format = +3.2e+4 % } %\end{LaTeXdemo} % will have the same effect as %\begin{LaTeXdemo}[code only] % \sisetup{ % table-figures-integer = 3, % table-figures-decimal = 2, % table-figures-exponent = 4, % table-sign-mantissa, % table-sign-exponent % } %\end{LaTeXdemo} % It is important to note that any parts of a number \emph{not} % specified in the table format argument are set to be absent (the % number of figures is set to zero). Setting the \opt{table-format} % option also resets \opt{table-number-alignment} to \opt{center} % (\cref{tab:S:format}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Using the \opt{table-format} option.} % \label{tab:S:format} % \centering % \begin{tabular}{ % S % S[table-format = 2.2] % S[table-format = 2.2(1)] % S[table-format = +2.2] % S[table-format = 2.2e1] % } % \toprule % {Values} % & {Values} % & {Values} % & {Values} % & {Values} \\ % \midrule % 2.3 & 2.3 & 2.3(5) & 2.3 & 2.3e8 \\ % 34.23 & 34.23 & 34.23(4) & 34.23 & 34.23 \\ % 56.78 & 56.78 & 56.78(3) & -56.78 & 56.78e3 \\ % 3,76 & 3,76 & 3.76(2) & +-3.76 & e6 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{table-space-text-pre} %\DescribeOption{table-space-text-post} % Space for material before and after the \texttt{S} column can % be reserved by giving model text for the options % \opt{table-space-text-pre} and \opt{\ldots -post}. % This is then used to provide the necessary gap while maintaining % alignment (\cref{tab:S:ends}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Text before and after numbers.} % \label{tab:S:ends} % \centering % \sisetup{ % table-number-alignment = center, % table-figures-integer = 2, % table-figures-decimal = 4, % table-space-text-pre = now~, % table-space-text-post = % \textsuperscript{\emph{a}} % } % \begin{tabular}{S} % \toprule % {Values} \\ % \midrule % 2.3456 \\ % 34.2345 \textsuperscript{\emph{a}}\\ % 56.7835 \\ % now~ 90.473 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{table-align-comparator} %\changes{v2.2}{2010/04/04}{New \opt{table-align-comparator} % option for more control of table formatting} %\DescribeOption{table-align-exponent} %\DescribeOption{table-align-uncertainty} %\changes{v2.1}{2010/10/12}{New \opt{table-align-exponent} and % \opt{table-align-uncertainty} options for additional choices of % table formatting} % When printing exponents in tables, there is a choice of aligning % the exponent parts or having these close up to the mantissa. This % is controlled by the \opt{table-align-exponent} option % (\cref{tab:align:exp}). Similarly, uncertainty parts which are printed % separately from the mantissa can be aligned or closed up. This is % set by the \opt{table-align-uncertainty} option % (\cref{tab:align:uncert}). Finally, the same approach is available % for the comparator with the \opt{table-align-comparator} option % (\cref{tab:align:comp}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{The \opt{table-align-exponent} option} % \label{tab:align:exp} % \sisetup{table-format = 1.3e2, table-number-alignment = center} % \begin{tabular}{SS[table-align-exponent = false]} % \toprule % {Header} & {Header} \\ % \midrule % 1.2e3 & 1.2e3 \\ % 1.234e56 & 1.234e56 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{The \opt{table-align-uncertainty} option} % \label{tab:align:uncert} % \sisetup{ % separate-uncertainty, % table-format = 1.3(1), % } % \begin{tabular}{SS[table-align-uncertainty = false]} % \toprule % {Header} & {Header} \\ % \midrule % 1.2(1) & 1.2(3) \\ % 1.234(5) & 1.234(5) \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{The \opt{table-align-comparator} option} % \label{tab:align:comp} % \sisetup{table-format = >2.2} % \begin{tabular}{SS[table-align-comparator = false]} % \toprule % {Header} & {Header} \\ % \midrule % > 1.2 & > 1.2 \\ % < 12.34 & < 12.34 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{table-omit-exponent} %\changes{v2.1}{2010/10/13}{New \opt{table-omit-exponent} option % for simplifying tables} % In cases where data cover a range of values, printing using a fixed % exponent in a table may make presentation clearer. In these cases, % omitting the exponent value from the table is useful. The package % offers the \opt{table-omit-exponent} option to do this % (\cref{tab:exp:omit}); this automatically sets % \opt{scientific-notation = fixed} for the table column. %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{The \opt{table-omit-exponent} option} % \label{tab:exp:omit} % \begin{tabular}{ % S[table-format = 1.1e1] % S[ % fixed-exponent = 3, % table-format = 2.1, % table-omit-exponent % ] % } % \toprule % {Header} & {Header / \num{e3}} \\ % \midrule % 1.2e3 & 1.2e3 \\ % 3e2 & 3e2 \\ % 1.0e4 & 1.0e4 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{table-align-text-pre} % \changes{v2.3}{2011/06/19}{New \opt{table-align-text-pre} option} %\DescribeOption{table-align-text-post} % Note markers are often given in tables after the numerical content. It % may be desirable for these to close up to the numbers. Whether this % takes place is controlled by the \opt{table-align-text-pre} % and \opt{\ldots-post} % option (\cref{tab:S:notes}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Closing notes up to text.} % \label{tab:S:notes} % \newrobustcmd\NoteMark[1]{% % \textsuperscript{\emph{#1}}% % } % \centering % \sisetup{ % table-number-alignment = center, % table-figures-integer = 2, % table-figures-decimal = 4, % table-space-text-pre = \NoteMark{a} % } % \begin{tabular}{ % S % S[table-align-text-pre = false] % } % \toprule % {Values} & {Values} \\ % \midrule % 2.3456 & 2.3456 \\ % \NoteMark{a} 4.234 & \NoteMark{a} 4.234 \\ % \NoteMark{b} .78 & \NoteMark{b} .78 \\ % \NoteMark{d} 88 & \NoteMark{d} 88 \\ % \bottomrule % \end{tabular} % \hfil % \sisetup{table-space-text-post = \NoteMark{a}} % \begin{tabular}{ % S % S[table-align-text-post = false] % } % \toprule % {Values} & {Values} \\ % \midrule % 2.3456 & 2.3456 \\ % 34.234 \NoteMark{a} & 34.234 \NoteMark{a} \\ % 56.78 \NoteMark{b} & 56.78 \NoteMark{b} \\ % 90.4 \NoteMark{c} & 90.4 \NoteMark{c} \\ % 88 \NoteMark{d} & 88 \NoteMark{d} \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{table-auto-round} % The contents of table cells can automatically be rounded or % zero-filled to the number of decimal digits given for the % \opt{table-figures-decimal} option. This mode is activated using % the \opt{table-auto-round} switch, as illustrated in % \cref{tab:S:auto}. %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{The \opt{table-auto-round} option.} % \label{tab:S:auto} % \sisetup{ % table-number-alignment = center, % table-figures-integer = 1, % table-figures-decimal = 3 % } % % Notice the overfull hbox which results with % % the first column % \begin{tabular}{ % S % S[table-auto-round] % } % \toprule % {Header} & {Header} \\ % \midrule % 1.2 & 1.2 \\ % 1.2345 & 1.2345 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{parse-numbers} % When the \opt{parse-numbers} option is set to \opt{false}, then % the alignment code for tables takes a different approach. The % output is always set in math mode, and alignment takes place % at the first decimal marker. This is achieved by making it % active in math mode. When reserving space for content only % the integer and decimal values for the mantissa are considered % (\cref{tab:S:nonparsed}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Aligning without parsing.} % \label{tab:S:nonparsed} % \sisetup{ % parse-numbers = false, % table-figures-integer = 2, % table-figures-decimal = 3 % } % \centering % \begin{tabular}{ % S % S[table-number-alignment = center] % S[table-number-alignment = right] % S[table-number-alignment = left] % } % \toprule % {Some values} % & {Some values} % & {Some values} % & {Some values} \\ % \midrule % 2.35 & 2.35 & 2.35 & 2.35 \\ % 34.234 & 34.234 & 34.234 & 34.234 \\ % 56.783 & 56.783 & 56.783 & 56.783 \\ % 3,762 & 3,762 & 3,762 & 3.762 \\ % \sqrt{2} & \sqrt{2} & \sqrt{2} & \sqrt{2} \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{table-text-alignment} % Cell contents which are not part of a number can be protected % using braces, as illustrated. Cells which contain no numerical data % at all are aligned using the setting specified by the % \opt{table-text-alignment} option, which recognises the values % \opt{center}, \opt{left} and \opt{right} (\cref{tab:S:text}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Aligning text in \texttt{S} columns.} % \label{tab:S:text} % \sisetup{ % table-number-alignment = center, % table-figures-integer = 4, % table-figures-decimal = 4 % } % \centering % \begin{tabular}{ % S % S[table-text-alignment = left] % S[table-text-alignment = right] % } % \toprule % {Values} % & {Values} % & {Values} \\ % \midrule % 992.435 & 992.435 & 992.435 \\ % 7734.2344 & 7734.2344 & 7734.2344 \\ % 56.7834 & 56.7834 & 56.7834 \\ % 3,7462 & 3,7462 & 3,7462 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{table-unit-alignment} % The contents of \texttt{s} columns can be centred or aligned to the % left or right using the \opt{table-unit-alignment} option. As for the % other alignment options, this recognises the choices \opt{center}, % \opt{left} and \opt{right}. %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{Alignment options in \texttt{s} columns.} % \label{tab:s:align} % \begin{tabular} % { % s[table-unit-alignment = right] % s % s[table-unit-alignment = left] % } % \toprule % {Right-aligned} & % {Centred text} & % {Left-aligned} \\ % \midrule % \metre\per\second & \metre\per\second & \metre\per\second \\ % \kilogram & \kilogram & \kilogram \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\DescribeOption{table-alignment} % The three table alignment options (\opt{table-number-alignment}, % \opt{table-text-alignment} and \opt{table-unit-alignment}) can be set % to the same value using the \opt{table-alignment} option. This will % set all three alignment options to the same value (one of % \opt{center}, \opt{right} or \opt{left}). % %\DescribeOption{table-column-width} %\changes{v2.2}{2011/04/02}{New \opt{table-column-width} option} %\changes{v2.2f}{2011/05/25}{Fix setting \opt{table-column-width} to % \opt{0 pt} to restore auto-sizing} % Usually, the width of the \texttt{S} and \texttt{s} columns is allowed % to vary depending on the content. However, there are cases where a % strictly fixed width is desirable. For these cases, the % \opt{table-column-width} option is available. The standard % setting, "0 pt", indicates that no fixing takes place. If a value % is set for this option then the tabular material is typeset to % the specified width (\cref{tab:width:fixed}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{Fixed-width columns.} % \label{tab:width:fixed} % \begin{tabular} % { % s % s[table-column-width = 2 cm] % S % S[table-column-width = 2 cm] % } % \toprule % {Flexible} & % {Fixed} & % {Flexible} & % {Fixed} \\ % \midrule % \metre\per\second & \metre\per\second & 1.23 & 1.23 \\ % \kilogram\candela & \kilogram\candela & 45.6 & 45.6 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % % The \opt{table-column-width} option can also be used to achieve % special effects. One example is centring a column of numbers under % a wide heading, with the numbers themselves right-aligned % (\cref{tab:width:special}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{Right-aligning under a heading.} % \label{tab:width:special} % \settowidth\mylength{Long header} % \sisetup{ % table-format = 4 , % table-number-alignment = center , % table-column-width = \mylength , % input-decimal-markers = , % input-symbols = . , % } % \begin{tabular}{S} % \toprule % {Long header} \\ % \midrule % 12.33 \\ % 2 \\ % 1234 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\subsection{Symbols} % % Most units use letters as the symbol for the unit, and these are all % very easy to control. However, a small number of units use other % symbols, and matching these to the body text requires more work. % \pkg{siunitx} provides appropriate symbols for commonly-used units, % but the definitions may need adjustment depending on the body font % used in a document. % %\DescribeOption{redefine-symbols} % The package provides one general option for the handling of symbols. % If the packages \pkg{textcomp} or \pkg{upgreek} are loaded, symbols % can be taken from these for units, rather than using the % \pkg{siunitx} default values. The switch \opt{redefine-symbols} % can be used to turn this behaviour on or off: the standard setting % is \opt{true}. % % The individual symbols are set up independently for math and text % output, and are summarised in \cref{tab:opt:symbols}. Many of % the definitions are variations using \cs{text} or \cs{ensuremath} to % produce the correct output, as the symbols available in the document % may vary considerably. In the case of the micro symbol % (\SIUnitSymbolMicro), \pkg{siunitx} provides a suitable low-level % definition for the symbol. Depending on the fonts available, this % may need to be replaced by an alternative by the user. The % ohm symbol (\SIUnitSymbolOhm) is usually set to \cs{Omega}, but % will check that this has not been redefined as a slanted letter. If % \cs{Omega} has been redefined, an alternative definition is used. % %\begin{table} % \centering % \caption{Symbol options.} % \label{tab:opt:symbols} % \begin{tabular}{>{\ttfamily}ll>{\ttfamily}l} % \toprule % \multicolumn{1}{l}{Option name} & % Type & % \multicolumn{1}{l}{Default} \\ % \midrule ^^A ( % math-angstrom & Literal & \verb=\text{\AA}= \\ % math-arcminute & Literal & \verb={}^{\prime}= \\ % math-arcsecond & Literal & \verb={}^{\prime\prime}= \\ % math-celsius & Literal & \verb={}^{\circ}= \\ % & & \verb=\kern -\scriptspace \mathrm{C}= \\ % math-degree & Literal & \verb={}^{\circ}= \\ % math-micro & Literal & \meta{see text} \\ % math-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 math and text symbols defined above are wrapped up into mode % independent functions with user names. These are then used in the % definitions of the appropriate units. For example, the micro % symbol can be accessed using the macro \cs{SIUnitSymbolMicro}. % Notice that these names capitalise the unit name (to make reading % the macro name easier!).\footnote{The function % \cs{SIUnitSymbolAngstrom} uses the name without accents.} % % \changes{v2.4a}{2011/12/04}{Use UTF-8 symbols with \XeTeX{} and \LuaTeX{} % if \pkg{fontspec} is loaded} % When using \XeTeX{} or \LuaTeX{}, if \pkg{fontspec} is loaded these options % are redefined to use UTF-8 characters directly. % %\subsection{Other options} % %\DescribeOption{locale} %\changes{v2.0m}{2010/07/09}{Re-introduce \opt{locale} option} % \pkg{siunitx} allows the user to switch between the typographic % conventions of different (geographical) areas by using locales. % Currently, the package is supplied with configurations for locales % \opt{UK}, \opt{US}, \opt{DE} (Germany), \opt{FR} (French) and \opt{ZA} % (South Africa). The \opt{locale} option is used to switch to a % particular locale. %\begin{LaTeXdemo} % \SI{1.234}{\metre}\\ % \SI[locale = DE]{6.789}{\metre} %\end{LaTeXdemo} % %\DescribeOption{strict} % Some users will want to stick closely to the official rules for % typesetting units. This could be made complicated if the options % for non-standards behaviour could not be turned off. The % preamble-only option \opt{strict} resets package behaviour to % follow the rules closely, and disables options which deviate from % this. If the package is loaded with the \opt{strict} option, all % output is made using the upright serif font. % %\subsection{Local configurations} %\label{sec:config:local} % % The \pkg{siunitx} package will check for a local configuration file % \file{siunitx.cfg} during package loading. This occurs before % applying any setting given in the optional argument to % \cs{usepackage}. A typical configuration file may include % settings (using \cs{sisetup}) and locally-defined units, for % example %\begin{LaTeXdemo}[code only] % \ProvidesFile{siunitx.cfg} % \sisetup{ % output-decimal-marker = {,}, % per-mode = symbol, % } % \DeclareSIUnit\torr{torr} %\end{LaTeXdemo} % As units are always declared, overwriting any existing definition, % units may safely be created in the configuration file even when also % included in individual \LaTeX{} document headers. % % Installing a local configuration file on your system is very much like doing % a local installation of a package. The exact method depends on the \TeX{} % system in use. For advice on this, a good start is the % \href{http://tex.stackexchange.com/questions/1137/} % {TeX.SX question on local installation}. % %\section{Localisation} % % The \pkg{translator} package provides a structured framework for % localisation of words and phrases, and is part of the larger % \pkg{beamer} bundle. The \pkg{translator} package provides the % \cs{translate} macro, which will provide appropriate translations % based on the current \pkg{babel} or \pkg{polyglossia} language % setting. % % If \pkg{translator} is available, \pkg{siunitx} will load it and alter % the standard settings for the \opt{list-final-separator} and % \opt{range-phrase} options to read: %\begin{LaTeXdemo}[code only] % \sisetup{ % list-final-separator = { \translate{and} }, % list-pair-separator = { \translate{and} }, % range-phrase = { \translate{to (numerical range)} }, % } %\end{LaTeXdemo} % If the current language is known to the \pkg{translator} package % then the result will be localised text. The preamble for this manual % loads English, French and German as options, and also loads the % \pkg{babel} package: %\begin{LaTeXdemo} % % In English by default % \SIlist{1;2;3}{\metre} \\ % \SIrange{1}{10}{\degreeCelsius} \\ % \selectlanguage{french}% % \SIlist{1;2;3}{\metre} \\ % \SIrange{1}{10}{\degreeCelsius} \\ % \selectlanguage{german}% % \SIlist{1;2;3}{\metre} \\ % \SIrange{1}{10}{\degreeCelsius} \\ %\end{LaTeXdemo} % % Note that the in order for this to work correctly, languages should % be given as global (class) options rather than as package options % for \pkg{babel}. % %\section{Hints for using \pkg{siunitx}} % %\subsection{Ensuring text or math output} % % The macros \cs{ensuremath} and \cs{text} should be used to ensure that % a particular item is always printed in the desired mode. Some % mathematical output does not work well in \cs{mathrm} (the standard % font used by \pkg{siunitx} for printing). The easiest way to solve % this is to use the construction "\text{\ensuremath{...}}", which will % print the material in the standard mathematics font without affecting % the rest of the output. In some cases, simply forcing \cs{mathnormal} % will suffice, but this is less reliable with non-Latin characters. % %\subsection{Expanding content in tables} %\label{sec:expanding} % % When processing tables, \pkg{siunitx} will expand anything stored % inside a macro, unless it is long or protected. \LaTeXe{} robust % commands are also detected and are not expanded % (\cref{tab:xmpl:macro}). Values which would otherwise be expanded % can be protected by wrapping them in a set of braces. As \TeX{} itself % will expand the first token in a table cell before \pkg{siunitx} % can act on it, using the \eTeX{} protected mechanism is the % recommended course of action to prevent expansion of macros in % table cells. (As is shown in the table, \TeX's expansion of % \LaTeXe{} robust commands can lead to unexpected results.) %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{Values as macros in \texttt{S} columns.} % \label{tab:xmpl:macro} % \newcommand*\myvaluea{1234} % \newcommand\myvalueb{1234} % \DeclareRobustCommand*\myvaluec{1234} % \protected\def\myvalued{1234} % \begin{tabular}{S} % \toprule % {Some Values} \\ % \midrule % \myvaluea 8.8 \myvaluea \\ % Both expanded % \myvalueb 8.8 \myvalueb \\ % First expanded by TeX % % to numbers % \myvaluec 8.8 \myvaluec \\ % First expanded by TeX % % but not to numbers! % \myvalued 8.8 \myvalued \\ % Neither expanded % {\myvaluea\ 8.8 \myvaluea} \\ % Neither expanded % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % % It is possible to use calculated values in tables. For this to % work, the calculation must take place before attempting to parse % the number. An added complication is that \TeX{} itself will % expand the first macro in a table cell until it finds % something unexpandable. The \eTeX{} protected mechanism can be % used to prevent this; using the \pkg{etoolbox} package provides % a convenient way to apply this protection to existing functions. % The general approach is illustrated in \cref{tab:xmpl:calc}. % The macro \cs{DTLmul} is made robust inside the table using % the \cs{robustify} command from \pkg{etoolbox}, before % constructing the table using an extra column to contain the % calculation. %\begin{LaTeXdemo}[code and float] % \DTLnewdb{data} % \DTLnewrow{data}\DTLnewdbentry{data}{value}{66.7012} % \DTLnewrow{data}\DTLnewdbentry{data}{value}{66.0212} % \DTLnewrow{data}\DTLnewdbentry{data}{value}{64.9026} % \begin{table} % \caption{Calculated values.} % \label{tab:xmpl:calc} % \centering % \robustify\DTLmul % \sisetup{ % table-number-alignment = center, % table-figures-integer = 2, % table-figures-decimal = 4 % } % \begin{tabular}{ % S % S[table-figures-integer = 3] % @{}l % } % \toprule % {Value} & {Doubled} & % \DTLforeach{data}{\myvalue=value}{% % \DTLiffirstrow {\\ \midrule}{\\}% % \myvalue & % First column % \DTLmul{\myvalue}{\myvalue}{2} \myvalue % second column % & }\\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\subsection{Using \pkg{siunitx} with \pkg{datatool}} % % As illustrated in \cref{tab:xmpl:calc}, \pkg{siunitx} can be used % to typeset data stored using \pkg{datatool}. For quickly displaying % the contents of tables, \pkg{datatool} offers the \cs{DTLshowtable} % macro. This will only work with \texttt{S} columns if number parsing % is turned off (\cref{tab:xmpl:datatool}). %\begin{LaTeXdemo}[code and float] % \DTLnewdb{moredata} % \DTLnewrow{moredata}\DTLnewdbentry{moredata}{value}{ 6.7012} % \DTLnewrow{moredata}\DTLnewdbentry{moredata}{value}{66.0212} % \DTLnewrow{moredata}\DTLnewdbentry{moredata}{value}{64.902 } % \begin{table} % \caption{Displaying a \textsf{datatool} table.} % \label{tab:xmpl:datatool} % \centering % \sisetup{ % parse-numbers = false, % table-number-alignment = center, % table-figures-integer = 2, % table-figures-decimal = 4 % } % \renewcommand*\dtlrealalign{S} % \DTLdisplaydb{moredata} % \end{table} %\end{LaTeXdemo} % %\subsection{Using units such as \si{\micro\metre\per\second} in % headings} % % The \pkg{siunitx} code is designed to work correctly with functions % in headings. They will print correctly in headings and in the table % of contents. As illustrated here, the standard behaviour is to ignore % font changes. When the \pkg{hyperref} package is loaded, the % functions automatically \enquote{degrade gracefully} to produce % useful information in PDF bookmarks. If you want more control over % the bookmark text, use the \cs{texorpdfstring} function from % \pkg{hyperref}, for example: %\begin{LaTeXdemo}[code only] % \section{Some text % \texorpdfstring % {\si{\joule\per\mole\per\kelvin}} % {J mol-1 K-1}% % } %\end{LaTeXdemo} % % \subsection{A left-aligned column visually centred under a heading} % % When you have a column of non-related numbers, the usual advice is to % make these left-aligned and then centre the resulting column under the % heading. With the \pkg{dcolumn} package, that would be done with % something like |D{x}{}{5.0}|. This is something of an abuse of the % nature of a number, but can also be done using \pkg{siunitx} % (\ref{tbl:xmpl:unrel}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Formatting unrelated numbers} % \label{tbl:xmpl:unrel} % \centering % \begin{tabular} % { % S[ % table-format = 5.0, % parse-numbers = false, % input-symbols=., % input-decimal-markers = x % ] % } % \toprule % \multicolumn{1}{c}{Header} \\ % \midrule % 120 \\ % 12.3 \\ % 12340 \\ % 12.02 \\ % 123 \\ % 1 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\subsection{Symbols and \texorpdfstring{\XeTeX}{XeTeX}} % % A small number of non-Latin symbols are needed by \pkg{siunitx}, % notably \SIUnitSymbolOhm\ and \SIUnitSymbolMicro. The package picks % glyphs for these which are correct in the sense that they are upright % (not italic) symbols, and match the \LaTeX{} standard Computer Modern % font. However, this does not make them the best choice if other % fonts are in use, which is particularly common when \XeTeX{} is % being used. % % \XeTeX{} users will probably need to choose appropriate symbols % themselves. The correct choice depends on the fonts in use, but many % system fonts include Greek letters and other symbols (which is not % the case with most \TeX-specific fonts). An appropriate setting % could then be to use the text \SIUnitSymbolMicro\ symbol in all % cases: %^^A This document cannot be UTF-8, as it has to work correctly with %^^A pdfLaTeX. So there is a bit of work to do here to get the right %^^A output. %\begin{flushleft} % \ttfamily % \textbackslash \textcolor{blue}{sisetup}\{\\ % \ \ math-micro = \textbackslash % \textcolor{blue}{text}\{\SIUnitSymbolMicro\}, \\ % \ \ text-micro \ = \SIUnitSymbolMicro \\ % \} %\end{flushleft} % It may also be desirable in these cases to select a fixed font % using the \pkg{fontspec} package, for example %\begin{LaTeXdemo}[code only] % \sisetup{ % math-micro = \fontspec{Minion Pro} \textmu, % text-micro = \fontspec{Minion Pro} \textmu % } %\end{LaTeXdemo} % %\subsection{Scaled document fonts with \texorpdfstring{\XeTeX}{XeTeX}} % % The \pkg{fontspec} package makes it possible to scale the document % body font. This can lead to unexpected problems with printing % for \pkg{siunitx}, as some symbols will not scale while numbers % and text will. The problem is best avoided by forcing \pkg{siunitx} % to use the default math font for all output: %\begin{LaTeXdemo}[code only] % \sisetup{ % mode = math, % math-rm = \ensuremath % } %\end{LaTeXdemo} % This will cause all \pkg{siunitx} output \emph{not} to scale at all, % consistent with other mathematical content. % % \subsection{Interaction with \pkg{tex4ht}} % % \pkg{siunitx} will detect when \pkg{tex4ht} is in use, and makes % some changes to the way output is printed. Text mode printing is % automatically selected, and certain items (such as spaces) are % printed in text mode rather than as math. This is designed to % reduce the likelihood of spurious formulae appearing in, for % example, output converted to OpenOffice format. % %\subsection{Maximising performance} % % Both the number and unit parsers require significant effort in % terms of \TeX{} programming. For input that does not require % such processing, the maximum performance for \pkg{siunitx} can % therefore be obtained by turning off both systems: %\begin{LaTeXdemo} % \SI{7.3}{\Hz} \\ % \SI[parse-units = false]{7.3}{\Hz} \\ % \SI[ % parse-numbers = false, % parse-units = false % ]{7.3}{\Hz} %\end{LaTeXdemo} % %\subsection{Transferring settings to \pkg{pgf}} % %\DescribeMacro{\SendSettingsToPgf} %\changes{v2.0a}{2010/05/28}{Make \cs{SendSettingsToPgf} available % in document body} % The numerical engine in the \pkg{pgf} package has settings similar % to those in \pkg{siunitx}. To enable working with both packages % easily, the macro \cs{SendSettingsToPgf} is available. It will % set some commonly-used numerical formatting options in \pkg{pgf} % to the current values used by \pkg{siunitx} to make using the % two packages together more convenient for end users. This % function can be used at any point after loading both the % \pkg{pgf} and \pkg{siunitx} packages. %\begin{LaTeXdemo}[code only] % \documentclass{article} % \usepackage{pgf,siunitx} % \sisetup{...} % \SendSettingsToPgf % ... %\end{LaTeXdemo} % %\subsection{Using \pkg{siunitx} with the \pkg{cellspace} package} % % Both \pkg{siunitx} and \pkg{cellspace} use the letter \texttt{S} for a % new column type. This obviously leads to a problem. If both are % loaded, \pkg{siunitx} will retain the \texttt{S} column, and moves the % functionality of \pkg{cellspace} to the letter \texttt{C}. This % allows the normal use of \pkg{cellspace} with standard column types: % it does \emph{not} work with the \pkg{siunitx} \texttt{S} or % \texttt{s} columns. % %\subsection{Special considerations for the \cs{kWh} unit} % % The \file{abbreviations} configuration file provides the unit % \cs{kWh}, which is set up with no spacing between the % \enquote{\si{\kilo\watt}} and the \enquote{\si{\hour}} unit to % give \enquote{\si{\kWh}}. However, this only applies when the unit % is given on its own: combinations will follow the normal rules %\begin{LaTeXdemo} % \si{\kWh} \\ % \si{\kWh\per\metre} %\end{LaTeXdemo} % This is because the unit \cs{kWh} is defined so that it can still be % varied by altering \cs{kilo}, \cs{watt} and \cs{hour}, and so that % the prefix can still be turned into a number. However, some users % may prefer to have a non-flexible macro which never adds a space. % This can be achieved by redefining \cs{kWh} with \cs{DeclareSIUnit}, % by added an alternative definition %\begin{LaTeXdemo}[code only] % \DeclareSIUnit\kWh{kWh} % \DeclareSIUnit\KWH{kWh} %\end{LaTeXdemo} % or of course by using literal unit input. %\begin{LaTeXdemo} % \si{\KWH\per\metre}\\ % \si{kWh.m^{-1}} %\end{LaTeXdemo} % % Another point to notice is that the \cs{per} macro applies to % the next unit, and not an entire unit combination. Thus in %\begin{LaTeXdemo} % \si{\candela\per\kWh} %\end{LaTeXdemo} % \cs{per} applies to the watts but not to the hours. In this case, % the units need to be written out in full or the \opt{sticky-per} % option should be used. %\begin{LaTeXdemo} % \si{\candela\per\kilo\watt\per\hour} \\ % \si[sticky-per]{\candela\per\kWh} %\end{LaTeXdemo} % %\subsection{Adding items after the last column of a tabular} %\changes{v2.0d}{2010/06/10}{Document special case situations for last % cell in table row} % % When using the \pkg{array} package \enquote{\texttt{<}} construct % to insert material after an \texttt{S} or \texttt{s} column, the % alignment of the final column may be wrong if the standard tabular row % terminator |\\| is used. % This is due to the way that \LaTeX{} constructs % tables at a low level. The incorrect spacing can be avoided by using % the \TeX{} \cs{cr} primitive to end the table rows (\cref{tab:cr}). %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Correcting spacing in last \texttt{S} column} % \label{tab:cr} % \hfil % \begin{tabular}{S<{\,\si{\kg}}S<{\,\si{\kg}}} % \toprule % \multicolumn{1}{c}{Long header} & % \multicolumn{1}{c}{Long header} \\ % \midrule % 1.23 & 1.23 \\ % 4.56 & 4.56 \\ % 7.8 & 7.8 \\ % \bottomrule % \end{tabular} % \hfil % \begin{tabular}{S<{\,\si{\kg}}S<{\,\si{\kg}}} % \toprule % \multicolumn{1}{c}{Long header} & % \multicolumn{1}{c}{Long header} \\ % \midrule % 1.23 & 1.23 \cr % 4.56 & 4.56 \cr % 7.8 & 7.8 \cr % \bottomrule % \end{tabular} % \hfil % \end{table} %\end{LaTeXdemo} % %\subsection{Creating a column with numbers and units} % % Usually, numbers in a table should be given with the units in the % column heading. However, there are cases where a series of data are % best presented in a table but have different units. There are two % ways to do this (\cref{tab:xmpl:mixed}). The first is to place the % units in the first column of the table, which makes sense if there % are several related items in the table. The second method is to % generate two columns, one for numbers and a second for units, and then % to format these to give the visual effect of a single column. The % later effect is most appropriate when only one set of numbers are % presented in a table. %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Tables where numbers have different units} % \label{tab:xmpl:mixed} % \hfil % \begin{tabular} % { % >{$}l<{$} % S[table-format = 2.3(1)] % S[table-format = 3.3(1)] % } % \toprule % & {One} & {Two} \\ % \midrule % a / \si{\angstrom} & 1.234(2) & 5.678(4) \\ % \beta / \si{\degree} & 90.34(4) & 104.45(5) \\ % \mu / \si{\per\mm} & 0.532 & 0.894 \\ % \bottomrule % \end{tabular} % \hfil % \begin{tabular} % {S[table-format=1.3]@{\,}s[table-unit-alignment = left]} % \toprule % \multicolumn{2}{c}{Heading} \\ % \midrule % 1.234 & \metre \\ % 0.835 & \candela \\ % 4.23 & \joule\per\mole \\ % \bottomrule % \end{tabular} % \hfil % \end{table} %\end{LaTeXdemo} % %\subsection{Tables with heading rows} %\changes{v2.0s}{2010/08/12}{Document how to do mixed bold and normal % numbers in tables} % % A common format for tables is to make the heading row visually % distinct using a background colour and bold text. If numbers appear % in such a heading row within an \texttt{S} column then getting the % appearance right can be challenging. The best approach is to % make the \cs{bfseries} macro \enquote{robust} (as demonstrated in % \cref{sec:expanding}), then to use this macro to make the heading % cells bold. This approach is illustrated in \cref{tab:xmpl:headers}, % along with the use of \cs{rowcolor} to provide a background colour. %\begin{LaTeXdemo}[code and float] % \begin{table} % \caption{Header row in a table} % \label{tab:xmpl:headers} % \robustify\bfseries % \centering % \begin{tabular} % {S[detect-weight,table-format = 3.3]} % \rowcolor[gray]{0.9} % \bfseries 123.456 \\ % 23.45 \\ % 123.4 \\ % 3.456 \\ % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\subsection{Associating a locale with a \pkg{babel} language} % % It is possible to instruct the \pkg{babel} package to switch % to a particular \pkg{siunitx} locale when changing language. This % can be done using the \pkg{babel} \cs{extras\meta{language}} % system. For example, to associate the \texttt{DE} locale with % the \texttt{german} \pkg{babel} language, the appropriate % code would be %\begin{LaTeXdemo}[code only] % \addto\extrasgerman{\sisetup{locale = DE}} %\end{LaTeXdemo} % %\section{Information for those upgrading} % %\subsection{Upgrading from version 1} %\changes{v2.0a}{2010/05/28}{Fix various errors in \file{version-1} % configuration file} %\changes{v2.0a}{2010/05/28}{Detect use of version 1 options and % automatically load appropriate configuration file} %\changes{v2.0a}{2010/05/28}{Include high energy physics units in % discussion of old configurations and in \file{version-1} % configuration file} %\changes{v2.0b}{2010/06/01}{Further improvements to \file{version-1} % configuration file} %\changes{v2.0r}{2010/08/02}{Error in definition for old % \opt{decimalsymbol} option corrected} %\changes{v2.1d}{2010/11/14}{Error with definition of version 1 option % \opt{xspace} corrected} % % The key--value control system of \pkg{siunitx} has been completely % rewritten for version 2, and at the same time some of the macros % provided by the package have been renamed and reworked. The package % can be loaded with a configuration file to provide most of the % same options and defaults as in version 1: %\begin{LaTeXdemo}[code only] % \usepackage[version-1-compatibility]{siunitx} %\end{LaTeXdemo} % Many of the options from version 1 map to similar ones in version 2 % (\cref{tab:opt:map}). The correspondence often includes a syntax % change: consult details of the new options for the correct syntax for % the new options. In some cases, the new approach is different to the % older one, and in these cases the most appropriate option new has been % listed in the table. %\begin{center} % \tablecaption{Mapping of version 1 options to version 2.} % \label{tab:opt:map} % \tablefirsthead{^^A % \toprule % \multicolumn{1}{l}{Version 1} & % \multicolumn{1}{l}{See in version 2} \\ % \midrule % } % \tablehead{^^A % \multicolumn{2}{l}{\emph{Continued from previous page}} \\ % \toprule % \multicolumn{1}{l}{Version 1} & % \multicolumn{1}{l}{See in version 2} \\ % \midrule % } % \tabletail{^^A % \bottomrule % \multicolumn{2}{r}{\emph{Continued on next page}} \\ % } % \tablelasttail{\bottomrule} % % \begin{xtabular}{>{\ttfamily}l>{\ttfamily}l} % addsign & explicit-sign \\ % allowlitunits & free-standing-units \\ % allowoptarg & unit-optional-argument \\ % allowzeroexp & retain-zero-exponent \\ % anglesep & arc-separator \\ % astroang & angle-symbol-over-decimal \\ % closeerr & close-bracket \\ % closefrac & close-bracket \\ % closerange & close-bracket \\ % colour & color \\ % colorall & color \\ % colourall & color \\ % colorunits & unit-color \\ % colorneg & negative-color \\ % colourneg & negative-color \\ % colourunits & unit-color \\ % colorvalues & number-color \\ % colourvalues & number-color \\ % decimalsymbol & output-decimal-marker \\ % detectdisplay & detect-display-math \\ % digitsep & group-separator \\ % dp & round-mode \\ % & round-precision \\ % errspace & uncertainty-separator \\ % expbase & exponent-base \\ % expproduct & exponent-product \\ % fixdp & round-mode \\ % fixsf & round-mode \\ % fraction & fraction-function \\ % inlinebold & detect-inline-weight \\ % locale & locale \\ % mathOmega & math-ohm \\ % mathcelsius & math-celsius \\ % mathdegree & math-degree \\ % mathminute & math-arcminute \\ % mathmu & math-micro \\ % mathringA & math-angstrom \\ % mathrm & math-rm \\ % mathsOmega & math-ohm \\ % mathscelsius & math-celsius \\ % mathsdegree & math-degree \\ % mathsecond & math-arcsecond \\ % mathsf & math-sf \\ % mathsminute & math-arcminute \\ % mathsmu & math-micro \\ % mathsringA & math-angstrom \\ % mathsrm & math-rm \\ % mathssecond & math-arcsecond \\ % mathssf & math-sf \\ % mathstt & math-tt \\ % mathtt & math-tt \\ % mode & mode \\ % negcolor & negative-color \\ % negcolour & negative-color \\ % numaddn & input-symbols \\ % numcloseerr & input-close-uncertainty \\ % numdecimal & input-decimal-markers \\ % numdigits & input-digits \\ % numdiv & input-quotient \\ % numexp & input-exponent-markers \\ % numgobble & input-ignore \\ % numopenerr & input-open-uncertainty \\ % numprod & input-product \\ % numsign & input-signs \\ % obeyall & detect-all \\ % obeybold & detect-weight \\ % obeyfamily & detect-family \\ % obeyitalic & detect-shape \\ % obeymode & detect-mode \\ % openerr & open-bracket \\ % openfrac & open-bracket \\ % openrange & open-bracket \\ % padangle & add-arc-degree-zero \\ % & add-arc-minute-zero \\ % & add-arc-second-zero \\ % padnumber & add-decimal-zero \\ % & add-integer-zero \\ % per & per-mode \\ % prefixsymbolic & prefixes-as-symbols \\ % prespace & space-before-unit \\ % redefsymbols & redefine-symbols \\ % repeatunits & multi-part-units \\ % & product-units \\ % & range-units \\ % retainplus & retain-explicit-plus \\ % seperr & separate-uncertainty \\ % sepfour & group-four-digits \\ % sf & round-mode \\ % & round-precision \\ % sign & explicit-sign \\ % slash & per-symbol \\ % stickyper & sticky-per \\ % strict & strict \\ % tabalign & table-alignment \\ % tabalignexp & table-align-exponent \\ % tabautofit & table-auto-round \\ % tabformat & table-format \\ % tabnumalign & table-number-alignment \\ % tabparseonly & table-parse-only \\ % tabexpalign & table-align-exponent \\ % tabtextalign & table-text-alignment \\ % tabunitalign & table-unit-alignment \\ % textcelsius & text-celsius \\ % textdegree & text-degree \\ % textminute & text-arcminute \\ % textmode & mode \\ % textmu & text-micro \\ % textOmega & text-ohm \\ % textringA & text-angstrom \\ % textrm & text-rm \\ % textsecond & text-arcsecond \\ % textsf & text-sf \\ % texttt & text-tt \\ % tightpm & tight-spacing \\ % tophrase & range-phrase \\ % trapambigerr & multi-part-units \\ % trapambigfrac & bracket-numbers \\ % trapambigrange & range-units \\ % unitcolor & unit-color \\ % unitcolour & unit-color \\ % unitmathrm & unit-math-rm \\ % unitmathsf & unit-math-sf \\ % unitmathsrm & unit-math-rm \\ % unitmathssf & unit-math-sf \\ % unitmathstt & unit-math-tt \\ % unitmathtt & unit-math-tt \\ % unitmode & unit-mode \\ % unitsep & inter-unit-product \\ % unitspace & inter-unit-product \\ % valuecolor & number-color \\ % valuecolour & number-color \\ % valuemathrm & number-math-rm \\ % valuemathsf & number-math-sf \\ % valuemathsrm & number-math-rm \\ % valuemathssf & number-math-sf \\ % valuemathstt & number-math-tt \\ % valuemathtt & number-math-tt \\ % valuemode & value-mode \\ % valuesep & number-unit-product \\ % xspace & use-xspace \\ % \end{xtabular} %\end{center} % A small number of the options from version 1 are used unchanged in % version 2, for example the \opt{mode} setting. These are listed above % but require no action on the part of the user. There are also a % few options which are no longer used at all, and are therefore ignored % by the current code. % % Loading configuration files has been completely changed, and this % means that the options \opt{alsoload}, \opt{load} and \opt{noload} are % ignored by version 2. In the same way the options \opt{debug} and % \opt{log} are not used by the current release of \pkg{siunitx}, as % this information is usually only needed by the package author. % Emulation of older packages is no longer offered (it was intended % to help with the transition form earlier packages), and so the % \opt{emulate} option no longer applies. % %\subsection{Upgrading from version 2.0 or 2.1} % % User feedback on \pkg{siunitx} means that over time some renaming % takes place. The following functions and options have been deprecated % in version 2.2. They are therefore available in version 2.2, but % should be replaced in new or updated documents with the successor % names. % %\DescribeOption{angle-unit-separator} %\DescribeOption{inter-unit-separator} %\DescribeOption{number-unit-separator} %\changes{v2.2}{2011/03/20}{Renamed \opt{angle-unit-separator} option % to \opt{angle-unit-product}} %\changes{v2.2}{2011/03/20}{Renamed \opt{inter-unit-separator} option % to \opt{inter-unit-product}} %\changes{v2.2}{2011/03/20}{Renamed \opt{number-unit-separator} option % to \opt{number-unit-product}} % These options have been replaced by the options %\begin{itemize} % \item \opt{angle-unit-product} % \item \opt{inter-unit-product} % \item \opt{number-unit-product} %\end{itemize} % as these items are formally products, and the new option names % emphasise this. % %\DescribeMacro{\DeclareSIUnitWithOptions} %\changes{v2.2}{2011/04/01}{Depreciate \cs{DeclareSIUnitWithOptions}} % The \cs{DeclareSIUnit} function has been extended to take a % first optional argument, which removes the need for % \cs{DeclareSIUnitWithOptions}. This function is therefore depreciated % but retained for compatibility. % % \subsection{Upgrading from version 2.2} % % \DescribeOption{load-configurations} % \changes{v2.3}{2011/03/20}{Load abbreviations as standard} % \changes{v2.3}{2011/03/20}{Replace \opt{load-configurations} option % with separate \opt{abbreviations}, \opt{binary-units} and % \opt{version-1-compatibility} options} % The option \opt{load-configurations} has been deprecated in favour of the % three options \opt{abbreviations}, \opt{binary-units} and % \opt{version-1-compatibility}. At the same time, loading of the abbreviations % is now the standard behaviour, and so in most cases no % explicit configuration file loading will be needed. % % \DescribeOption{group-decimal-digits} % \DescribeOption{group-integer-digits} % The digit grouping options have been revised, and the options % \opt{group-decimal-digits} and \opt{group-integer-digits} are now % integrated into \opt{group-digits}. % \DescribeOption{group-four-digits} % At the same time, the \opt{group-four-digits} option has been extended % to the new option \opt{group-minimum-digits}. % % \DescribeOption{literal-superscript-as-power} % The new {literal-superscript-as-power} option means that the standard % behaviour now uses the current math font for superscripts, even when % units are printed literally. This will only be obvious in documents such % as this manual, where the text and math mode numerals are (deliberately) % different. To restore the previous behaviour, set % \opt{literal-superscript-as-power = false}. % % \subsection{Upgrading from version 2.3} % % The number of options which assume that the input is given in math mode % has been significantly reduced. As most material can be typeset in either % math or text mode, the \enquote{intrinsic} math mode options could lead to % inconsistent output. The only options which now force math mode are those % for products, which will almost always require the use of math mode. % % \subsection{Upgrading from version 2.4} % % The process of removing options which assume math mode, begun with % version~2.4, has been taken further, and only \opt{output-product} % and \opt{exponent-product} now do not require \cs{ensuremath} for material % which must be in math mode. The standard settings have been altered to take % account of this, but user-set options for products may need to be updated % accordingly. % % \subsection{Upgrading from version 2.5} % % All printing now takes place in math mode (\emph{i.e.}~\opt{mode = math} % is set). This may alter the appearance of some units, and users may want % to verify the output is correct. % %\section{Correct application of (SI) units} % % Consistent and logical units are a necessity for scientific work, % and have applicability everywhere. Historically, a number of % systems have been used for physical units. SI units were % introduced by the \emph{Conf{\'e}rence G{\'e}n{\'e}rale des Poids et % Mesures} (CGPM) in 1960. SI units are a coherent system based on % seven base units, from which all other units may be derived. % % At the same time, physical quantities with units are mathematical % entities, and as such way that they are typeset is important. In % mathematics, changes of type (such as using bold, italic, sans % serif typeface and so on) convey information. This means that % rules exist not only for the type of units to be used under the SI % system, but also the way they should appear in print. Advice on % best practice has been made available by the \emph{National % Institute of Standards and Technology} (NIST) \cite{NIST}. % % As befits an agreed international standard, the full rules are % detailed. It is not appropriate to reproduce these in totality % here; instead, a useful summary of the key points is provided. The % full details are available from the \emph{Bureau International des % Poids et Mesures} \cite{BIPM}. % % \pkg{siunitx} takes account of the information given here, so far as % is possible. Thus the package defaults follow the recommendations % made for typesetting numbers and units. Spacing and so forth is % handled in such a way as to make implementing the rules % (relatively) easy. % %\subsection{Units} % % There are seven base SI units, listed in \cref{tab:unit:base}. % Apart from the kilogram, these are defined in terms of a measurable % physical quantity needing the definition alone.\footnote{Some base % units need others defined first; there is therefore a required % order of definition.} The base units have been chosen such that % all physical quantities can be expressed using an appropriative % combination of these units, needing no others and with no % redundancy. The kilogram is slightly different from the other base % units as it is still defined in terms of a \enquote{prototype} held in % Paris. % % All other units within the SI system are regarded as \enquote{derived} % from the seven base units. At the most basic, all other SI units % can be expressed as combinations of the base units. However, many % units (listed in \cref{tab:unit:derived,tab:unit:accepted}) have a % special name and symbol. Most of these units are simple combinations % of one or more base units (raised to powers as appropriate). A small % number of units derived from experimental data are allowed as SI % units (\cref{tab:unit:physical}). % % A series of SI prefixes for decimal multiples and sub-multiples are % provided, and can be used as modifiers for any SI unit (either base % or derived units) with the exception of the kilogram. The prefixes % are listed in \cref{tab:unit:prefix}. No space should be used % between a prefix and the unit, and only a single prefix should be % used. Even the degree Celsius can be given a prefix, for example % \SI{1}{\milli\degreeCelsius}. % % It is important to note that the kilogram is the only SI unit with % a prefix as part of its name and symbol. Only single prefix may % be used, and so in the case of the kilogram prefix names are used % with the unit name \enquote{gram} and the prefix symbols are used with % the unit symbol \si{\gram}. For example % \( \SI[prefixes-as-symbols = false]{1}{\milli\gram} = % \SI{1}{\milli\gram} \). % % The application of SI units is meant to provide a single set of % units which ensure consistency and clarity across all areas. % However, other units are common is many areas, and are not without % merit. The units provided by \pkg{siunitx} by default do not include % any of these; only units which are part of the SI set or are % accepted for use with SI units are defined. However, several other % sets of units can be loaded as optional modules. The binary % prefixes and units (\cref{tab:unit:binary}) are the most obvious % example. These are \emph{not} part of the SI specifications, but the % prefix names are derived from those in \cref{tab:unit:prefix}. % % Other units are normally to be avoided where possible. SI units % should, in the main, be preferred due to the advantages of clear % definition and self-consistency this brings. However, there will % probably always be a place for specialist or non-standard units. % This is particularly true of units derived from basic physical % constants. % % There are also many areas where non-standard units are used so % commonly that to do otherwise is difficult or impossible. For % example, most synthetic chemists measure the pressure inside vacuum % apparatus in \si{\mmHg}, partly because the most common gauge for % the task still uses a column of mercury metal. For these reasons, % \pkg{siunitx} does define non-SI units. % %\subsection{Mathematical meaning} % % As explained earlier, a number--unit combination is a single % mathematical entity. This has implications for how both the number % and the unit should be printed. Firstly, the two parts should not % be separated: a quantity is a product of the number and the unit. % With the exception of the symbols for plane angles (\si{\degree}, % \si{\arcminute} and \si{\arcsecond}), the \textsc{bipm} % specifies either a space or half-height (centred) dot should be % used \cite{BIPM}. %\begin{LaTeXdemo} % A space for \SI{10}{\percent}\\ % and also for \SI{100}{\degreeCelsius}\\ % but not for \ang{1.23}. %\end{LaTeXdemo} % % The mathematical meaning of units also means that the shape, weight % and family are important. Units are supposed to be typeset in an % upright, medium weight 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 math font. However, % there are occasions where this may not be the most desirable % behaviour. A classic example would be in an all-bold section % heading. As the surrounding text is bold, some people feel that % any units should follow this. %\begin{LaTeXdemo} % Units should \textbf{not be bold: \SI{54}{\farad}}\\ % \textbf{But perhaps in a running block,\\ % it might look better: \SI[detect-weight]{54}{\farad}} %\end{LaTeXdemo} % % Symbols for units formed from other units by multiplication are % indicated by means of either a half-height (that is, centred) dot % or a (thin) space. %\begin{LaTeXdemo} % \( \si{\metre\second} = \text{metre second} \) \\ % \( \si{\milli\second} = \text{millisecond} \) \\ % \sisetup{inter-unit-product = \ensuremath { { } \cdot { } } } % \( \si{\metre\second} = \text{metre second} \) \\ % \( \si{\milli\second} = \text{millisecond} \) %\end{LaTeXdemo} % There are some circumstances under which it is common practice to omit % any spaces. The classic example is \si{\kWh}, where % \enquote{\si[inter-unit-product = \,]{\kWh}} does not add any % useful information. If using such a unit repeatedly, users of % \pkg{siunitx} are advised to create a custom unit to ensure % consistency. It is important to note that while this is common % practice, it is \emph{not} allowed by the \textsc{bipm} % \cite{BIPM}. % % Symbols for units formed from other units by division are indicated % by means of a virgule (oblique stroke, slash, "/"), a horizontal % line, or negative exponents.\footnote{Notice that a virgule and a % solidus are not the same symbol.} However, to avoid ambiguity, the % virgule must not be repeated on the same line unless parentheses % are used. This is ensured when using named unit macros in % \pkg{siunitx}, which will \enquote{trap} repeated division and format % it correctly. In complicated cases, negative exponents are to be % preferred over other formats. %\begin{LaTeXdemo} % \si{\joule\per\mole\per\kelvin}\\ % \si[per-mode = fraction]{\joule\per\mole\per\kelvin}\\ % \si[per-mode = symbol]{\joule\per\mole\per\kelvin} %\end{LaTeXdemo} % % Products and errors should show what unit applies to each number % given. Thus \SI[product-units = brackets]{2x3}{\metre} is an % ordered set of lengths of a geometric area, whereas % \SI[product-units = single]{2x3}{\metre} is a length (and equal % to \SI{6}{\metre}). Thus, \(\times\) is not a product but is a % mathematical operator; in the same way, a \(2 \times 3\) matrix is not % a \(6\) matrix! In some areas, areas and volumes are given with % separated units but a unit raised to the appropriate power: % \SI[product-units = power]{2 x 3}{\metre}. Although this does % display the correct overall units, it is potentially-confusing and is % not encouraged. % % Care must be taken when writing ranges of numbers. For purely % numerical values, it is common to use a en-dash to show a range, for % example \enquote{see pages 1--5}. On the other hand, physical % quantities could be misinterpret as negative values if written in this % way. As the unit--number combination is a single mathematical entity, % writing the values with an en-dash followed by a single unit is also % incorrect. As a result, using the word \enquote{to} is strongly % recommended. %\begin{LaTeXdemo} % \SIrange{1}{5}{\metre} long. %\end{LaTeXdemo} % %\subsection{Graphs and tables} % % In graphs and tables, repetition of the units following each entry % or axis mark is confusing and repetitive. It is therefore best to % place the unit in the label part of the information. Placing the % unit in square brackets is common but mathematically % poor.\footnote{For example, for an acceleration \(a\), the expression % \([a]\) is the dimensions of \(a\), \emph{i.e.}~length per time % squared in this case.} Much better is to show division of all % quantities by the unit, which leaves the entries as unitless ratios. % This is illustrated in \cref{tab:xmpl:unitless} and % \cref{fig:xmpl:unitless}. %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{An example of table labelling.} % \label{tab:xmpl:unitless} % \sisetup{ % table-number-alignment = center, % table-figures-integer = 1, % table-figures-decimal = 4 % } % \begin{tabular}{cS} % \toprule % Entry & {Length/\si{\metre}} \\ % \midrule % 1 & 1.1234 \\ % 2 & 1.1425 \\ % 3 & 1.7578 \\ % 4 & 1.9560 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} %\begin{LaTeXdemo}[code and float] % \begin{figure} % \centering % \begin{tikzpicture} % \begin{axis}[ % xlabel = \( t/\si{\second} \), % xmax = 6, % xmin = 0, % ylabel = \( d/\si{\metre} \), % ymin = 0 % ] % \addplot[smooth,mark=*] % plot coordinates { % (0,0) % (1,5) % (2,8) % (3,9) % (4,8) % (5,5) % (6,0) % }; % \end{axis} % \end{tikzpicture} % \caption{An example of graph labelling.} % \label{fig:xmpl:unitless} % \end{figure} %\end{LaTeXdemo} % % In most cases, adding exponent values in the body of a table is % less desirable than adding a fixed exponent to column headers. An % example is shown in \cref{tab:good}. The use of \cs{multicolumn} is % needed here due to the \enquote{\texttt{<}}; without \cs{multicolumn}, % the titles are followed by \enquote{\si{\kilo\gram}}! %\begin{LaTeXdemo}[code and float] % \begin{table} % \centering % \caption{Good and bad columns.} % \label{tab:good} % \sisetup{table-number-alignment = center} % \begin{tabular}{ % c % S[ % table-figures-integer = 1, % table-figures-decimal = 3, % table-figures-exponent = 1 % ] % @{\,\si{\kilogram}} % S[ % table-figures-integer = 2, % table-figures-decimal = 2 % ] % } % \toprule % Entry & \multicolumn{1}{c}{Mass} & % {Mass/\SI{e3}{\kilogram}} \\ % \midrule % 1 & 4.56e3 & 4.56 \\ % 2 & 2.40e3 & 2.40 \\ % 3 & 1.345e4 & 13.45 \\ % 4 & 4.5e2 & 0.45 \\ % \bottomrule % \end{tabular} % \end{table} %\end{LaTeXdemo} % %\section{Making suggestions and reporting bugs} % % Feedback on \pkg{siunitx} is always welcome, either to make % suggestions or to report problems. When sending feedback, it is % always useful if a small example file is included, showing the % bug being reported or illustrating the desired output. It is % helpful if a \enquote{reference rendering} is included, showing what % the output should look like. A typical example file might read %\begin{LaTeXdemo}[code only] % \listfiles % % Use the article class unless the problem is class-dependent % \documentclass{article} % \usepackage{siunitx} % % Other packages loaded as required % \begin{document} % Reference output: $ 1.23\,\mathrm{m} $ % % siunitx output: \SI{1.23}{\metre} % \end{document} %\end{LaTeXdemo} % As illustrated, it is usually best to use the \texttt{article} % class and to only load packages which are needed to show the issue. % It is also useful to include a copy of the log file generate by % \TeX{} when reporting a bug (as the versions of packages can be % important to solving the issue). % % Feedback can be sent in a range of ways. The development code % is hosted by % \href{http://bitbucket.org/josephwright/siunitx}{BitBucket}, % and the site includes an issue tracker. Adding feedback directly % to the database means that other users can see it, and also % ensures that it does not get forgotten. E-mailing directly % will also definitely get attention: % \href{mailto:joseph.wright@morningstar2.co.uk} % {\texttt{joseph.wright@morningstar2.co.uk}}. I also keep an eye % on various groups, for example % \href{http://groups.google.com/group/comp.text.tex/topics} % {\texttt{comp.text.tex}} and % \href{http://www.latex-community.org/forum/}{The \LaTeX{} Community}. % Sometimes I miss posts to these places, so it's useful if you also % e-mail me pointing to the appropriate thread. % %\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} % % \begin{macrocode} %<@@=siunitx> % \end{macrocode} % %\subsection{Preliminaries} % % The usual preliminaries. % \begin{macrocode} \ProvidesExplPackage {siunitx} {2014/09/27} {2.6b} {A comprehensive (SI) units package} % \end{macrocode} % % Make sure that the version of \pkg{l3kernel} in use is sufficiently new. % This will also trap any problems with \pkg{l3packages} (as the two are now % tied together, version-wise). % \begin{macrocode} \@ifpackagelater { expl3 } { 2012/11/21 } { } { \PackageError { siunitx } { Support~package~expl3~too~old } { You~need~to~update~your~installation~of~the~bundles~'l3kernel'~and~ 'l3packages'.\MessageBreak Loading~siunitx~will~abort! } \tex_endinput:D } % \end{macrocode} % %\begin{macro}{\@@_load_check:} % There are also a number of packages that are incompatible with % \pkg{siunitx}. These are all checked for next. Some of the % incompatible packages will not raise an error if loaded after % \pkg{siunitx}. So a test is made at the beginning of the % document as well. The message for this may be needed immediately, so % it is created here not with the other messages. % \begin{macrocode} \msg_new:nnnn { siunitx } { incompatible-package } { Package~'#1'~incompatible. } { The~#1~package~and~siunitx~are~incompatible. } \cs_new_protected:Npn \@@_load_check:n #1 { \group_begin: \@ifpackageloaded {#1} { \msg_error:nnx { siunitx } { incompatible-package } {#1} } { } \group_end: } \clist_map_function:nN { SIunits , sistyle , siunits , SIstyle , unitsdef , fancyunits } \@@_load_check:n \AtBeginDocument { \clist_map_function:nN { SIunits , sistyle , siunits , SIstyle } \@@_load_check:n } % \end{macrocode} %\end{macro} % % Now load the support packages. % \begin{macrocode} \RequirePackage{ amstext , array , l3keys2e } % \end{macrocode} % %\begin{macro}{\@@_tmp:w} % A scratch function. % \begin{macrocode} \cs_new:Npn \@@_tmp:w { } % \end{macrocode} %\end{macro} % % \begin{macro}{\clist_map_function:nc} % \begin{macrocode} \cs_generate_variant:Nn \clist_map_function:nN { nc } % \end{macrocode} % \end{macro} % % \begin{macro}{\tl_if_blank:VTF} % Needed for the literal test. % \begin{macrocode} \cs_generate_variant:Nn \tl_if_blank:nTF { V } % \end{macrocode} % \end{macro} % %\begin{macro}{ % \l_@@_tmp_bool , % \l_@@_tmp_box , % \l_@@_tmp_dim , % \l_@@_tmp_int , % \l_@@_tmpa_tl , % \l_@@_tmpb_tl %} % Scratch variables. % \begin{macrocode} \bool_new:N \l_@@_tmp_bool \box_new:N \l_@@_tmp_box \dim_new:N \l_@@_tmp_dim \int_new:N \l_@@_tmp_int \tl_new:N \l_@@_tmpa_tl \tl_new:N \l_@@_tmpb_tl % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_error:nxx , % \@@_error:nx , % \@@_error:n %} %\begin{macro}{\l_@@_error_bool} % General-purpose functions for throwing errors. % \begin{macrocode} \cs_new_protected:Npn \@@_error:nxx #1#2#3 { \bool_set_true:N \l_@@_error_bool \msg_error:nnxx { siunitx } {#1} {#2} {#3} } \cs_new_protected:Npn \@@_error:nx #1#2 { \@@_error:nxx {#1} {#2} { } } \cs_new_protected:Npn \@@_error:n #1 { \@@_error:nxx {#1} { } { } } \bool_new:N \l_@@_error_bool % \end{macrocode} %\end{macro} %\end{macro} % % 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} \AtBeginDocument { \cs_if_free:cT { T@TS1 } { \DeclareFontEncoding { TS1 } { } { } \DeclareFontSubstitution { TS1 } { cmr } { m } { n } } } % \end{macrocode} % %\begin{macro}{ % \c_@@_minus_tl , % \c_@@_minus_int %} % To allow the correct symbol to appear in text mode: this is the same % as \cs{textminus} from \pkg{textcomp}. If \pkg{fontspec} is loaded % then the real character can be used. % \begin{macrocode} \DeclareTextSymbolDefault \c_@@_minus_tl { TS1 } \DeclareTextSymbol \c_@@_minus_tl { TS1 } { 61 } \AtBeginDocument { \@ifpackageloaded { fontspec } { \int_const:Nn \c_@@_minus_int { 8722 } \tl_set:Nn \c_@@_minus_tl { \tex_char:D \c_@@_minus_int } } { } } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \c_@@_mu_tl , % \c_@@_mu_int %} % The lack of an upright mu has to be sorted out. The same consideration % for \pkg{fontspec} as above. % \begin{macrocode} \DeclareTextSymbol \c_@@_mu_tl { TS1 } { 181 } \DeclareTextSymbolDefault \c_@@_mu_tl { TS1 } \AtBeginDocument { \@ifpackageloaded { fontspec } { \int_const:Nn \c_@@_mu_int { 181 } \tl_set:Nn \c_@@_mu_tl { \tex_char:D \c_@@_mu_int } } { } } % \end{macrocode} %\end{macro} % %\begin{macro}{\c_@@_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:N \c_@@_omega_tl \tl_set:Nn \c_@@_omega_tl { \Omega } \AtBeginDocument { \cs_if_exist:NT \upOmega { \tl_set:Nn \c_@@_omega_tl { \upOmega } } } % \end{macrocode} %\end{macro} % % \begin{macro} % { % \@@_tl_put_left_math:Nn , % \@@_tl_put_left_math:NV , % } % To add stuff in math mode. % \begin{macrocode} \cs_new_protected:Npn \@@_tl_put_left_math:Nn #1#2 { \tl_put_left:Nn #1 { \ensuremath {#2} } } \cs_generate_variant:Nn \@@_tl_put_left_math:Nn { NV } % \end{macrocode} % \end{macro} % %\begin{macro}{\c_@@_old_options_seq} % To pick up old options, all of the names need to be known. % \begin{macrocode} \seq_new:N \c_@@_old_options_seq \cs_set_protected:Npn \@@_tmp:w #1 { \seq_put_right:No \c_@@_old_options_seq { \tl_to_str:n {#1} } } \@@_tmp:w { addsign } \@@_tmp:w { allowlitunits } \@@_tmp:w { allowoptarg } \@@_tmp:w { allowzeroexp } \@@_tmp:w { alsoload } \@@_tmp:w { angformat } \@@_tmp:w { anglesep } \@@_tmp:w { astroang } \@@_tmp:w { closeerr } \@@_tmp:w { closrfrac } \@@_tmp:w { closerange } \@@_tmp:w { colour } \@@_tmp:w { colorall } \@@_tmp:w { colourall } \@@_tmp:w { colorneg } \@@_tmp:w { colourneg } \@@_tmp:w { colourunits } \@@_tmp:w { colourunits } \@@_tmp:w { colorvalues } \@@_tmp:w { colourvalues } \@@_tmp:w { decimalsymbol } \@@_tmp:w { debug } \@@_tmp:w { detectdisplay } \@@_tmp:w { digitsep } \@@_tmp:w { dp } \@@_tmp:w { emulate } \@@_tmp:w { errspace } \@@_tmp:w { eVcorra } \@@_tmp:w { eVcorrb } \@@_tmp:w { expbase } \@@_tmp:w { expproduct } \@@_tmp:w { fixdp } \@@_tmp:w { fixsf } \@@_tmp:w { fraction } \@@_tmp:w { inlinebold } \@@_tmp:w { loctolang } \@@_tmp:w { log } \@@_tmp:w { load } \@@_tmp:w { mathOmega } \@@_tmp:w { mathcelsius } \@@_tmp:w { mathdegree } \@@_tmp:w { mathminute } \@@_tmp:w { mathmu } \@@_tmp:w { mathringA } \@@_tmp:w { mathrm } \@@_tmp:w { mathsOmega } \@@_tmp:w { mathscelsius } \@@_tmp:w { mathsdegree } \@@_tmp:w { mathsecond } \@@_tmp:w { mathsf } \@@_tmp:w { mathsminute } \@@_tmp:w { mathsmu } \@@_tmp:w { mathsringA } \@@_tmp:w { mathsrm } \@@_tmp:w { mathssecond } \@@_tmp:w { mathssf } \@@_tmp:w { mathstt } \@@_tmp:w { mathtt } \@@_tmp:w { negcolor } \@@_tmp:w { negcolour } \@@_tmp:w { noload } \@@_tmp:w { numaddn } \@@_tmp:w { numcloseerr } \@@_tmp:w { numdecimal } \@@_tmp:w { numdigits } \@@_tmp:w { numdiv } \@@_tmp:w { numexp } \@@_tmp:w { numgobble } \@@_tmp:w { numopenerr } \@@_tmp:w { numprod } \@@_tmp:w { numsign } \@@_tmp:w { obeyall } \@@_tmp:w { obeybold } \@@_tmp:w { obeyfamily } \@@_tmp:w { obeymode } \@@_tmp:w { obeyitalic } \@@_tmp:w { openerr } \@@_tmp:w { openfrac } \@@_tmp:w { openrange } \@@_tmp:w { padangle } \@@_tmp:w { padnumber } \@@_tmp:w { per } \@@_tmp:w { prefixbase } \@@_tmp:w { prefixproduct } \@@_tmp:w { prefixsymbolic } \@@_tmp:w { prespace } \@@_tmp:w { redefsymbols } \@@_tmp:w { repeatunits } \@@_tmp:w { retainplus } \@@_tmp:w { seperr } \@@_tmp:w { sepfour } \@@_tmp:w { sf } \@@_tmp:w { sign } \@@_tmp:w { slash } \@@_tmp:w { stickyper } \@@_tmp:w { strictarc } \@@_tmp:w { tabalign } \@@_tmp:w { tabalignexp } \@@_tmp:w { tabautofit } \@@_tmp:w { tabexpalign } \@@_tmp:w { tabformat } \@@_tmp:w { tabnumalign } \@@_tmp:w { tabparseonly } \@@_tmp:w { tabtextalign } \@@_tmp:w { textOmega } \@@_tmp:w { textcelsius } \@@_tmp:w { textdegree } \@@_tmp:w { textminute } \@@_tmp:w { textmode } \@@_tmp:w { textmu } \@@_tmp:w { textringA } \@@_tmp:w { textrm } \@@_tmp:w { textsecond } \@@_tmp:w { textsf } \@@_tmp:w { texttt } \@@_tmp:w { tightpm } \@@_tmp:w { tophrase } \@@_tmp:w { trapamigerr } \@@_tmp:w { trapambigfrac } \@@_tmp:w { trapambigrange } \@@_tmp:w { unitcolor } \@@_tmp:w { unitcolour } \@@_tmp:w { unitmathrm } \@@_tmp:w { unitmathsf } \@@_tmp:w { unitmathsrm } \@@_tmp:w { unitmathssf } \@@_tmp:w { unitmathstt } \@@_tmp:w { unitmathtt } \@@_tmp:w { unitmode } \@@_tmp:w { unitsep } \@@_tmp:w { unitspace } \@@_tmp:w { valuecolor } \@@_tmp:w { valuecolour } \@@_tmp:w { valuemathrm } \@@_tmp:w { valuemathsf } \@@_tmp:w { valuemathsrm } \@@_tmp:w { valuemathssf } \@@_tmp:w { valuemathstt } \@@_tmp:w { valuemathtt } \@@_tmp:w { valuemode } \@@_tmp:w { valuesep } \@@_tmp:w { xpace } % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_key_tl} % Unknown options should raise an \pkg{siunitx}-specific error message. % \begin{macrocode} \tl_new:N \l_@@_key_tl \keys_define:nn { siunitx } { unknown .code:n = { \seq_if_in:NVTF \c_@@_old_options_seq \l_keys_key_tl { \msg_warning:nnx { siunitx } { version-1-option } { \exp_not:V \l_keys_key_tl } \tl_set:Nx \l_@@_key_tl { \keys_set:nn { siunitx } { \exp_not:V \l_keys_key_tl \tl_if_blank:nF {#1} { = \exp_not:n {#1} } } } \keys_set:nn { siunitx } { version-1-compatibility } \tl_use:N \l_@@_key_tl } { \msg_error:nnx { siunitx } { unknown-option } { \exp_not:V \l_keys_key_tl } } } } \AtBeginDocument { \keys_define:nn { siunitx } { unknown .code:n = { \seq_if_in:NVTF \c_@@_old_options_seq \l_keys_key_tl { \msg_error:nnx { siunitx } { version-1-option } { \exp_not:V \l_keys_key_tl } } { \msg_error:nnx { siunitx } { unknown-option } { \exp_not:V \l_keys_key_tl } } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_option_deactivate:n} %\begin{macro}[aux]{\@@_option_deactivate_aux:n} %\begin{macro}{\l_@@_option_deactivate_clist} % Some options need to be deactivated at the start of the document. % \begin{macrocode} \cs_new_protected:Npn \@@_option_deactivate:n #1 { \clist_put_right:Nn \l_@@_option_deactivate_clist {#1} } \cs_new_protected:Npn \@@_option_deactivate_aux:n #1 { \keys_define:nn { siunitx } { #1 .code:n = { \msg_warning:nnx { siunitx } { option-preamble-only } {#1} } } } \AtBeginDocument { \clist_map_function:NN \l_@@_option_deactivate_clist \@@_option_deactivate_aux:n } \clist_new:N \l_@@_option_deactivate_clist % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % % \begin{macro}{\@@_option_unchanged:Nnn} % Needed to allow for altering of options at the start of the document % only if they are unchanged. This needs to use the low-level implementation % detail, hence the use of variable name directly. % \begin{macrocode} \cs_new_protected:Npn \@@_option_unchanged:Nnn #1#2#3 { \str_if_eq:VnT #1 {#2} { \tl_set:Nn #1 {#3} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\tl_if_in:NVTF, \tl_replace_all:NnV} % Variants needed which are not in \pkg{expl3}. % \begin{macrocode} \cs_generate_variant:Nn \tl_if_in:NnTF { NV } \cs_generate_variant:Nn \tl_replace_all:Nnn { NnV } % \end{macrocode} % \end{macro} % %\begin{macro}[pTF]{ % \@@_cs_if_tl:N , % \@@_cs_if_macro:N %} %\begin{macro}[aux]{\@@_cs_if_tl_aux:w} % 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_set_catcode_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:Npnn \@@_cs_if_tl:N #1 { T , F, TF , p } { \exp_last_unbraced:No \@@_cs_if_tl_aux:w { \token_to_meaning:N #1 MACRO \q_stop } { \cs_if_exist:cTF { \cs_to_str:N #1 ~ } { \prg_return_false: } { \prg_return_true: } } { \prg_return_false: } } \cs_new:Npn \@@_cs_if_tl_aux:w #1 MACRO #2 \q_stop { \tl_if_empty:nTF {#1} } \prg_new_conditional:Npnn \@@_cs_if_macro:N #1 { T , F , TF , p } { \exp_last_unbraced:No \@@_cs_if_tl_aux:w { \token_to_meaning:N #1 MACRO \q_stop } { \prg_return_true: } { \prg_return_false: } } } % \end{macrocode} %\end{macro} %\end{macro} % % If \pkg{tex4ht} is in use, make a few changes to give nicer looking % conversion to other formats. % \begin{macrocode} \AtBeginDocument { \@ifpackageloaded { tex4ht } { \cs_set_eq:NN \@@_print_text_super:n \textsuperscript \@@_option_unchanged:Nnn \l_@@_qualifier_mode_tl { subscript } { brackets } \keys_set:nn { siunitx } { mode = text } \tl_set:Nn \c_@@_minus_tl { \HCode { &\#x2212; } } } { } } % \end{macrocode} % % \begin{macro}{\@@_ensure_ltr:n} % When the \pkg{bidi} package is loaded with \XeTeX{} we need to make sure % that \cs{text} is doing the correct thing. The \pkg{bidi} package seems to % lead to a slightly broken \cs{text}, so this is something of a hack. % \begin{macrocode} \cs_new_eq:NN \@@_ensure_ltr:n \use:n \AtBeginDocument { \@ifpackageloaded { bidi } { \xetex_if_engine:T { \cs_set_protected:Npn \@@_ensure_ltr:n #1 { \LRE {#1} } } } { } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_textsuperscript:n} % This function is set up here so that it can be redefined % elsewhere as expandable. That is used in the bookmark system so % that \pkg{hyperref} does not raise any unnecessary warnings. % \begin{macrocode} \cs_new_eq:NN \@@_textsuperscript:n \textsuperscript % \end{macrocode} % \end{macro} % %\begin{macro}{\l_@@_display_math_bool} % To test for display math, a flag is added to the start of every % display environment. % \begin{macrocode} \bool_new:N \l_@@_display_math_bool \tex_everydisplay:D \exp_after:wN { \tex_the:D \tex_everydisplay:D \bool_set_true:N \l_@@_display_math_bool } % \end{macrocode} %\end{macro} % % \begin{macro}[TF]{\prop_get:NVN} % Missing from \pkg{expl3} at the moment. % \begin{macrocode} \cs_generate_variant:Nn \prop_get:NnNT { NV } \cs_generate_variant:Nn \prop_get:NnNF { NV } \cs_generate_variant:Nn \prop_get:NnNTF { NV } % \end{macrocode} % \end{macro} % %\subsection{Font detection} % % A number of controls and tests are needed to control the font used % for output. The detection routines set up various functions which can % then be used inside the \cs{text} macro from the \pkg{amstext} % package. By carrying out the changes outside math mode, bold can % reliably be applied to math output. % %\begin{macro}{\@@_set_math_fam:n} %\begin{macro}{ % \c_@@_mathsf_int , % \c_@@_mathtt_int %} % The detection routine needs some basic data about the sans serif and % monospaced fonts in use. This is collected up at the start of the % document. The families used can change between here and the start of % the document. This is run as a hook onto \cs{document}, rather than % using \cs{AtBeginDocument} as it has to come after anything that % \pkg{fontspec} does (nasty errors arise otherwise). % \begin{macrocode} \cs_new_protected:Npn \@@_set_math_fam:n #1 { \int_new:c { c_@@_math #1 _int } \group_begin: \hbox_set:Nn \l_@@_tmp_box { \ensuremath { \use:c { math #1 } { \int_gset:cn { c_@@_math #1 _int } { \fam } } } } \group_end: } \tl_put_right:Nn \document { \@@_set_math_fam:n { sf } \@@_set_math_fam:n { tt } \ignorespaces } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_font_set_text_fam:n} %\begin{macro}{ % \c_@@_textsf_tl , % \c_@@_texttt_tl %} % The text families are done in a somewhat different manner: there are % no issues with \cs{AtBeginDocument}, luckily. The need to define % new macros here arises as \cs{sfdefault} and \cs{ttdefault} are % \cs{long}, whereas \cs{f@family} is not. % \begin{macrocode} \cs_new_protected:Npn \@@_set_text_fam:n #1 { \tl_new:c { c_@@_text #1 _tl } \tl_set:cx { c_@@_text #1 _tl } { \use:c { #1 default } } } \AtBeginDocument { \@@_set_text_fam:n { sf } \@@_set_text_fam:n { tt } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_@@_detect_inline_weight_tl} % Used by the keys, but needs to be created here. % \begin{macrocode} \tl_new:N \l_@@_detect_inline_weight_tl % \end{macrocode} %\end{macro} % % \begin{variable}{\l_@@_detect_inline_family_tl} % This one is not generated by the keys system. % \begin{macrocode} \tl_new:N \l_@@_detect_inline_family_tl % \end{macrocode} % \end{variable} % %\begin{macro}{ % \l_@@_detect_display_math_bool , % \l_@@_detect_family_bool , % \l_@@_detect_inline_family_tl , % \l_@@_detect_shape_bool , % \l_@@_detect_mode_bool , % \l_@@_detect_weight_bool %} % Font detection is all about creating switches, with just a little % gloss for \texttt{detect-all} and \texttt{detect-none}. % \begin{macrocode} \keys_define:nn { siunitx } { detect-all .choice:, detect-all .default:n = true, detect-all / false .meta:n = { detect-family = false , detect-mode = false , detect-shape = false , detect-weight = false , }, detect-all / true .meta:n = { detect-family = true , detect-mode = true , detect-shape = true , detect-weight = true , }, detect-display-math .bool_set:N = \l_@@_detect_display_math_bool, detect-family .bool_set:N = \l_@@_detect_family_bool, detect-inline-family .choice:, detect-inline-family .value_required:, detect-inline-family / math .code:n = { \tl_set:Nn \l_@@_detect_inline_family_tl { math } }, detect-inline-family / text .code:n = { \tl_set:Nn \l_@@_detect_inline_family_tl { text } }, detect-inline-weight .choice:, detect-inline-weight .value_required:, detect-inline-weight / math .code:n = { \tl_set:Nn \l_@@_detect_inline_weight_tl { math } }, detect-inline-weight / text .code:n = { \tl_set:Nn \l_@@_detect_inline_weight_tl { text } }, detect-italic .bool_set:N = \l_@@_detect_shape_bool, detect-mode .bool_set:N = \l_@@_detect_mode_bool, detect-none .choice:, detect-none .default:n = true, detect-none / false .meta:n = { detect-family = true, detect-mode = true, detect-shape = true, detect-weight = true }, detect-none / true .meta:n = { detect-family = false, detect-mode = false, detect-shape = false, detect-weight = false }, detect-shape .bool_set:N = \l_@@_detect_shape_bool, detect-weight .bool_set:N = \l_@@_detect_weight_bool } \keys_set:nn { siunitx } { detect-inline-family = text , detect-inline-weight = text , } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_font_set_bool , % \l_@@_font_math_mode_bool %} % The internals of the package need a number of switches to track what % is happening. % \begin{macrocode} \bool_new:N \l_@@_font_set_bool \bool_new:N \l_@@_font_math_mode_bool % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_font_family_tl} % Also some token storage. % \begin{macrocode} \tl_new:N \l_@@_font_family_tl % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_font_shape: , % \@@_font_weight: %} % These could be token lists or functions! % \begin{macrocode} \cs_new:Npn \@@_font_shape: { } \cs_new:Npn \@@_font_weight: { } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_detect_font:} % The main font-setting macro is a control point for the other % functions. Nesting font-control should not happen, so the first % test is to ensure this is not happening. % \begin{macrocode} \cs_new_protected:Npn \@@_detect_font: { \bool_if:NF \l_@@_font_set_bool { \@@_detect_font_init: \bool_if:NT \l_@@_detect_weight_bool { \@@_detect_font_weight: } \bool_if:NT \l_@@_detect_family_bool { \@@_detect_font_family: } \bool_if:NT \l_@@_detect_shape_bool { \@@_detect_font_shape: } \bool_if:NT \l_@@_detect_mode_bool { \@@_detect_font_mode: } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_detect_font_init:} % Set up the basic macros on the assumption nothing happens. % \begin{macrocode} \cs_new_protected:Npn \@@_detect_font_init: { \bool_set_true:N \l_@@_font_set_bool \cs_set:Npn \@@_font_weight: { \unboldmath \mdseries } \cs_set:Npn \@@_font_shape: { \upshape } \tl_set:Nn \l_@@_font_family_tl { rm } \bool_set_true:N \l_@@_font_math_mode_bool } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_detect_font_weight:} % The font weight detection code depends on whether the current text is % math or text, and also the type of math (if appropriate). For % inline math, there is a choice of what test to apply. % \begin{macrocode} \cs_new_protected:Npn \@@_detect_font_weight: { \mode_if_math:TF { \bool_if:NTF \l_@@_display_math_bool { \bool_if:NTF \l_@@_detect_display_math_bool { \@@_detect_font_weight_math: } { \@@_detect_font_weight_text: } } { \use:c { @@_detect_font_weight_ \l_@@_detect_inline_weight_tl : } } } { \@@_detect_font_weight_text: } } % \end{macrocode} %\end{macro} %\begin{macro}{ % \@@_detect_font_weight_math: , % \@@_detect_font_weight_text: %} % The tests for font weight depend on whether the module is testing % text or math content. % \begin{macrocode} \cs_new_protected:Npn \@@_detect_font_weight_math: { \str_if_eq:VnT \math@version { bold } { \cs_set:Npn \@@_font_weight: { \boldmath \bfseries } } \str_if_eq:VnT \math@version { light } { \cs_set:Npn \@@_font_weight: { \lseries } } } \cs_new_protected:Npn \@@_detect_font_weight_text: { \tl_set:Nx \l_@@_tmpa_tl { \tl_head:N \f@series } \str_if_eq:VnT \l_@@_tmpa_tl { b } { \cs_set:Npn \@@_font_weight: { \boldmath \bfseries } } \str_if_eq:VnT \l_@@_tmpa_tl { l } { \cs_set:Npn \@@_font_weight: { \lseries } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_detect_font_family:} % Family detection usually picks up the surrounding text. However, for % display math there are two options, and so a second test may be made. % \begin{macrocode} \cs_new_protected:Npn \@@_detect_font_family: { \mode_if_math:TF { \bool_if:NTF \l_@@_display_math_bool { \bool_if:NTF \l_@@_detect_display_math_bool { \@@_detect_font_family_math: } { \@@_detect_font_family_text: } } { \use:c { @@_detect_font_family_ \l_@@_detect_inline_family_tl : } } } { \@@_detect_font_family_text: } } % \end{macrocode} %\end{macro} %\begin{macro}{ % \@@_detect_font_family_math: , % \@@_detect_font_family_text: %} % The two detections routines check if the current font is sans serif or % monospaced. The method used depends on whether the current math or % text font is of interest. The math detection routine re-applies the % default (\texttt{rm}), as the text function is always called and may % have changed things. % \begin{macrocode} \cs_new_protected:Npn \@@_detect_font_family_math: { \tl_set:Nn \l_@@_font_family_tl { rm } \int_compare:nNnT { \fam } = { \c_@@_mathsf_int } { \tl_set:Nn \l_@@_font_family_tl { sf } } \int_compare:nNnT { \fam } = { \c_@@_mathtt_int } { \tl_set:Nn \l_@@_font_family_tl { tt } } } \cs_new_protected:Npn \@@_detect_font_family_text: { \tl_if_eq:NNT \f@family \c_@@_textsf_tl { \tl_set:Nn \l_@@_font_family_tl { sf } } \tl_if_eq:NNT \f@family \c_@@_texttt_tl { \tl_set:Nn \l_@@_font_family_tl { tt } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_detect_font_shape:} % The shape test uses \cs{f@shape} as a handy indicator. % \begin{macrocode} \cs_new_protected:Npn \@@_detect_font_shape: { \cs_if_exist:cT { \f@shape shape } { \cs_set:Npx \@@_font_shape: { \exp_not:c { \f@shape shape } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_detect_font_mode:} % The mode switch works from the fact that math mode output it the % standard. % \begin{macrocode} \cs_new_protected:Npn \@@_detect_font_mode: { \mode_if_math:F { \bool_set_false:N \l_@@_font_math_mode_bool \bool_set_false:N \l_@@_number_math_mode_bool \bool_set_false:N \l_@@_unit_math_mode_bool } } % \end{macrocode} %\end{macro} % %\subsection{Font macros} % % With the detection routines in place, the module can apply the result % to control the font used for output. This requires a series of font % names to be available. The appropriate storage areas will be selected % by name, based on output type (\texttt{unit} or \texttt{value}) and % the family selected by the detector. % %\begin{macro}{ % \l_@@_number_math_mode_bool , % \l_@@_unit_math_mode_bool %} % Most of the variables are created by the keys system: these are not. % \begin{macrocode} \bool_new:N \l_@@_number_math_mode_bool \bool_new:N \l_@@_unit_math_mode_bool % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_number_mathrm:n , % \@@_number_mathsf:n , % \@@_number_mathtt:n , % \@@_number_textrm: , % \@@_number_textsf: , % \@@_number_texttt: %} % Functions for number-mode fonts. % \begin{macrocode} \cs_new:Npn \@@_number_mathrm:n #1 { } \cs_new:Npn \@@_number_mathsf:n #1 { } \cs_new:Npn \@@_number_mathtt:n #1 { } \cs_new:Npn \@@_number_textrm: { } \cs_new:Npn \@@_number_textsf: { } \cs_new:Npn \@@_number_texttt: { } % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_number_color_tl} % The settings are actually created separately for numbers and units: % numbers first. % \begin{macrocode} \keys_define:nn { siunitx } { number-color .tl_set:N = \l_@@_number_color_tl, number-math-rm .code:n = { \cs_set:Npn \@@_number_mathrm:n ##1 { #1 {##1} } }, number-math-sf .code:n = { \cs_set:Npn \@@_number_mathsf:n ##1 { #1 {##1} } }, number-math-tt .code:n = { \cs_set:Npn \@@_number_mathtt:n ##1 { #1 {##1} } }, number-mode .choice:, number-mode / math .code:n = { \bool_set_true:N \l_@@_number_math_mode_bool }, number-mode / text .code:n = { \bool_set_false:N \l_@@_number_math_mode_bool }, number-text-rm .code:n = { \cs_set:Npn \@@_number_textrm: {#1} }, number-text-sf .code:n = { \cs_set:Npn \@@_number_textsf: {#1} }, number-text-tt .code:n = { \cs_set:Npn \@@_number_texttt: {#1} } } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_unit_mathrm:n , % \@@_unit_mathsf:n , % \@@_unit_mathtt:n , % \@@_unit_textrm: , % \@@_unit_textsf: , % \@@_unit_texttt: %} % The same storage for unit-mode fonts. % \begin{macrocode} \cs_new:Npn \@@_unit_mathrm: { } \cs_new:Npn \@@_unit_mathsf: { } \cs_new:Npn \@@_unit_mathtt: { } \cs_new:Npn \@@_unit_textrm: { } \cs_new:Npn \@@_unit_textsf: { } \cs_new:Npn \@@_unit_texttt: { } % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_unit_color_tl} % Units look exactly the same. % \begin{macrocode} \keys_define:nn { siunitx } { unit-color .tl_set:N = \l_@@_unit_color_tl, unit-math-rm .code:n = { \cs_set:Npn \@@_unit_mathrm:n ##1 { #1 {##1} } }, unit-math-sf .code:n = { \cs_set:Npn \@@_unit_mathsf:n ##1 { #1 {##1} } }, unit-math-tt .code:n = { \cs_set:Npn \@@_unit_mathtt:n ##1 { #1 {##1} } }, unit-mode .choice:, unit-mode / math .code:n = { \bool_set_true:N \l_@@_unit_math_mode_bool }, unit-mode / text .code:n = { \bool_set_false:N \l_@@_unit_math_mode_bool }, unit-text-rm .code:n = { \cs_set:Npn \@@_unit_textrm: {#1} }, unit-text-sf .code:n = { \cs_set:Npn \@@_unit_textsf: {#1} }, unit-text-tt .code:n = { \cs_set:Npn \@@_unit_texttt: {#1} } } % \end{macrocode} %\end{macro} % % The general settings are all meta-keys. A few initial values are set % here as they are needed for everything to work. % \begin{macrocode} \keys_define:nn { siunitx } { color .meta:n = { number-color = #1, unit-color = #1 }, math-rm .meta:n = { number-math-rm = #1, unit-math-rm = #1 }, math-sf .meta:n = { number-math-sf = #1, unit-math-sf = #1 }, math-tt .meta:n = { number-math-tt = #1, unit-math-tt = #1 }, mode .choice:, mode / math .meta:n = { number-mode = math, unit-mode = math }, mode / text .meta:n = { number-mode = text, unit-mode = text }, text-rm .meta:n = { number-text-rm = #1, unit-text-rm = #1 }, text-sf .meta:n = { number-text-sf = #1, unit-text-sf = #1 }, text-tt .meta:n = { number-text-tt = #1, unit-text-tt = #1 } } \keys_set:nn { siunitx } { math-rm = \mathrm, math-sf = \mathsf, math-tt = \mathtt, mode = math, text-rm = \rmfamily, text-sf = \sffamily, text-tt = \ttfamily, } % \end{macrocode} % % Some packages and classes (for example \pkg{beamer}) set the default % family to be something other than serif family. A one-off detection % will make life easier % all round. % \begin{macrocode} \AtBeginDocument { \tl_set:Nx \l_@@_tmpa_tl { \familydefault } \@ifpackageloaded { eulervm } { \cs_set:Npn \@@_tmp:w #1 { \mathrm {#1} } \cs_if_eq:NNT \@@_number_mathrm:n \@@_tmp:w { \keys_set:nn { siunitx } { number-math-rm = \mathnormal } } \cs_if_eq:NNT \@@_unit_mathrm:n \@@_tmp:w { \keys_set:nn { siunitx } { unit-math-rm = \mathnormal } } } { } \tl_if_eq:NNT \l_@@_tmpa_tl \c_@@_textsf_tl { \@ifpackageloaded { arev } { } { \@ifpackageloaded { cmbright } { } { \cs_set:Npn \@@_tmp:w #1 { \mathrm {#1} } \cs_if_eq:NNT \@@_number_mathrm:n \@@_tmp:w { \keys_set:nn { siunitx } { number-math-rm = \mathsf } } \cs_if_eq:NNT \@@_unit_mathrm:n \@@_tmp:w { \keys_set:nn { siunitx } { unit-math-rm = \mathsf } } } } \cs_set:Npn \@@_tmp:w { \rmfamily } \cs_if_eq:NNT \@@_number_textrm: \@@_tmp:w { \keys_set:nn { siunitx } { number-text-rm = \sffamily } } \cs_if_eq:NNT \@@_unit_textrm: \@@_tmp:w { \keys_set:nn { siunitx } { unit-text-rm = \sffamily } } } \tl_if_eq:NNT \l_@@_tmpa_tl \c_@@_texttt_tl { \cs_set:Npn \@@_tmp:w #1 { \mathrm {#1} } \cs_if_eq:NNT \@@_number_mathrm:n \@@_tmp:w { \keys_set:nn { siunitx } { number-math-rm = \mathtt } } \cs_if_eq:NNT \@@_unit_mathrm:n \@@_tmp:w { \keys_set:nn { siunitx } { unit-math-rm = \mathtt } } \cs_set:Npn \@@_tmp:w { \rmfamily } \cs_if_eq:NNT \@@_number_textrm: \@@_tmp:w { \keys_set:nn { siunitx } { number-text-rm = \ttfamily } } \cs_if_eq:NNT \@@_unit_textrm: \@@_tmp:w { \keys_set:nn { siunitx } { unit-text-rm = \ttfamily } } } } % \end{macrocode} % %\subsection{Output control} % % The \pkg{siunitx} output routine uses all of the font information % gathered earlier to print the text given in whatever font is required. % The low-level stuff is done here, with the calling routines expected % to have taken some steps first (this is to allow line breaks in the % appropriate places). % %\begin{macro}{\l_@@_print_arg_tl} % The text to print. % \begin{macrocode} \tl_new:N \l_@@_print_arg_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_print_type_tl} % The type of output (\texttt{number} or \texttt{unit}) is always % needed. % \begin{macrocode} \tl_new:N \l_@@_print_type_tl % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_print:nn , % \@@_print:nV %} %\begin{macro}[aux]{\@@_print_aux:} % The main printing function does everything inside a group, as % there are category code and definition changes to make. First, set % the fonts. Then move on to printing mode, before moving to actual % printing. % \begin{macrocode} \cs_new_protected:Npn \@@_print:nn #1#2 { \group_begin: \tl_set:Nn \l_@@_print_type_tl {#1} \tl_set:Nn \l_@@_print_arg_tl {#2} \@@_detect_font: \bool_if:NF \l_@@_detect_mode_bool { \bool_if:cTF { l_@@_ #1 _math_mode_bool } { \bool_set_true:N \l_@@_font_math_mode_bool } { \bool_set_false:N \l_@@_font_math_mode_bool } } \@@_print_aux: \group_end: } \cs_generate_variant:Nn \@@_print:nn { nV } % \end{macrocode} % The various font changes are set up, then the correct printing % function is called. Everything is inside \cs{text} as this allows % proper setting of the various mode settings. % \begin{macrocode} \cs_new_protected:Npn \@@_print_aux: { \text { \@@_ensure_ltr:n { \@@_print_color: \@@_font_shape: \@@_font_weight: \use:c { @@_ \l_@@_print_type_tl _ text \l_@@_font_family_tl : } \bool_if:NTF \l_@@_font_math_mode_bool { \@@_print_math: } { \@@_print_text: } } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{ % \@@_print_color: , % \@@_textcolor:n %} % The colour system checks if \pkg{color} is loaded, and only does % anything if it is. This will change when \LaTeX3 proper is available: % there will be colour out of the box! % \begin{macrocode} \cs_new_protected:Npn \@@_print_color: { \tl_if_empty:cF { l_@@_ \l_@@_print_type_tl _color_tl } { \color { \tl_use:c { l_@@_ \l_@@_print_type_tl _color_tl } } } } \AtBeginDocument { \@ifpackageloaded { color } { \cs_new_eq:NN \@@_textcolor:n \textcolor } { \cs_set_eq:NN \@@_print_color: \scan_stop: \cs_new_eq:NN \@@_textcolor:n \use_none:n } } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_print_math: , % \@@_print_text:, % \@@_print_text_aux: %} % Printing the text means replacing any awkward characters, which is % dependent on the output mode. The rest of the package uses "_" and % "^" to represent sub- and superscripts, respectively. In this way, % mode decisions can be delayed as long as possible. The % \pkg{underscore} package may make "_" active, or more likely % it will be a superscript character. Both are tested for here. % \begin{macrocode} \cs_new_protected:Npn \@@_print_math: { \cs_set_eq:NN \PrintSubscript \sb \cs_set_eq:NN \PrintSuperscript \sp \ensuremath { \use:c { @@_ \l_@@_print_type_tl _ math \l_@@_font_family_tl :n } { \l_@@_print_arg_tl } } } \group_begin: \char_set_lccode:nn { `\@ } { `\_ } \char_set_catcode_math_subscript:N \@ \char_set_lccode:nn { `\! } { `\_ } \char_set_catcode_active:N \! \char_set_lccode:nn { `\= } { `\_ } \char_set_lccode:nn { `\+ } { `\^ } \tl_to_lowercase:n { \group_end: \cs_new_protected:Npn \@@_print_text: { \tl_replace_all:Nnn \l_@@_print_arg_tl { - } { \c_@@_minus_tl } \@@_print_text_aux: \tl_replace_all:Nnn \l_@@_print_arg_tl { \mp } { \ensuremath { \mp } } \tl_remove_all:Nn \l_@@_print_arg_tl { \mathord } \cs_set_eq:NN \PrintSubscript \@@_print_text_sub:n \cs_set_eq:NN \PrintSuperscript \@@_print_text_super:n \tl_replace_all:Nnn \l_@@_print_arg_tl { @ } { \@@_print_text_sub:n } \tl_replace_all:Nnn \l_@@_print_arg_tl { ! } { \@@_print_text_sub:n } \tl_replace_all:Nnn \l_@@_print_arg_tl { = } { \@@_print_text_sub:n } \tl_replace_all:Nnn \l_@@_print_arg_tl { ^ } { \@@_print_text_super:n } \tl_replace_all:Nnn \l_@@_print_arg_tl { + } { \@@_print_text_super:n } \l_@@_print_arg_tl } } \cs_new_protected:Npn \@@_print_text_aux: { \tl_replace_all:Nnn \l_@@_print_arg_tl { \pm } { \ensuremath { \pm } } } \AtBeginDocument { \@ifpackageloaded { textcomp } { \cs_set_protected:Npn \@@_print_text_aux: { \tl_replace_all:Nnn \l_@@_print_arg_tl { \pm } { \textpm } } } { } } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_print_text_sub:n , % \@@_print_text_super:n %} %\begin{macro}[aux]{\@@_print_text_sub_super:n} % \begin{macro}[aux]{\@@_print_text_sub_peek:} % \begin{macro}[aux]{\@@_peek_true:, \@@_peek_false:} % The appropriate macros for sub- and superscript in text mode ensure % the appearance is the same as math mode. The search and replace % code for superscripts deals with the case where a literal number has % been given with text mode printing. There is currently an issue with % \pkg{expl3}'s \cs{peek_\ldots} functions, which means that the peek % code is written out here in full. % \begin{macrocode} \cs_new_protected:Npn \@@_print_text_sub:n #1 { \cs_set:Npn \@@_print_text_sub_super:n ##1 { \ensuremath { \sb { \text {#1} } \sp { \text {##1} } } } \cs_set_protected_nopar:Npn \@@_peek_true: { \tex_afterassignment:D \@@_print_text_sub_super:n \cs_set_eq:NN \@@_tmp:w } \cs_set_protected_nopar:Npn \@@_peek_false: { \ensuremath { \sb { \text {#1} } } } \peek_after:Nw \@@_print_text_sub_peek: } \cs_new_protected:Npn \@@_print_text_sub_peek: { \if_meaning:w \l_peek_token \@@_print_text_super:n \exp_after:wN \@@_peek_true: \else: \exp_after:wN \@@_peek_false: \fi: } \cs_new_protected_nopar:Npn \@@_peek_true: { } \cs_new_protected_nopar:Npn \@@_peek_false: { } \cs_new_protected:Npn \@@_print_text_sub_super:n { } \cs_new_protected:Npn \@@_print_text_super:n #1 { \tl_set:Nn \l_@@_tmpa_tl {#1} \tl_replace_all:Nnn \l_@@_tmpa_tl { - } { \c_@@_minus_tl } \tl_set:Nx \l_@@_tmpa_tl { \exp_not:N \ensuremath { \sp { \exp_not:N \text { \exp_not:V \l_@@_tmpa_tl } } } } \l_@@_tmpa_tl } % \end{macrocode} %\end{macro} %\end{macro} % \end{macro} % \end{macro} % %\begin{macro}{ % \PrintSubscript , % \PrintSuperscript %} % In the unit-construction code, there are places where it cannot % be guarenteed that the search-and-replace approach will work. % Instead, two user-space functions are needed. These are only % defined within the above code: the names are not needed elsewhere. %\end{macro} % %\subsection{Pre-processing numbers} % % Before the main parsing routine can be called, there is a need to % pre-process the input. The possibility that the data in can contain % more than one number needs to be handled. % %\begin{macro}{\l_@@_input_product_tl} %\begin{macro}{\l_@@_input_quotient_tl} % There are a couple of settings which are created here as they are used % only for pre-processing. % \begin{macrocode} \keys_define:nn { siunitx } { input-product .tl_set:N = \l_@@_input_product_tl, input-quotient .tl_set:N = \l_@@_input_quotient_tl, } \keys_set:nn { siunitx } { input-product = x, input-quotient = / } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{ % \l_@@_number_arg_tl , % \l_@@_number_next_tl %} % Storage for the pre-parsed material. The \texttt{arg} variable % contains the current argument, the \texttt{next} variable contains % anything held-over for the next round. % \begin{macrocode} \tl_new:N \l_@@_number_arg_tl \tl_new:N \l_@@_number_next_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_number_multi_tl} % For products and quotients, a way of feeding information back. % \begin{macrocode} \tl_new:N \l_@@_number_multi_tl % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_number_denominator_tl , % \l_@@_number_numerator_tl %} % When searching for quotients, some more storage is needed. % \begin{macrocode} \tl_new:N \l_@@_number_denominator_tl \tl_new:N \l_@@_number_numerator_tl % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_number_preprocess:n , % \@@_number_preprocess:V %} % The pre-processor starts with the obvious: the most likely outcome is % that all of the argument is passed through unchanged. % \begin{macrocode} \cs_new_protected:Npn \@@_number_preprocess:n #1 { \@@_number_preprocess_init: \tl_set:Nn \l_@@_number_arg_tl {#1} \@@_number_preprocess_product: \tl_if_empty:NT \l_@@_number_multi_tl { \@@_number_preprocess_quotient: } } \cs_generate_variant:Nn \@@_number_preprocess:n { V } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_preprocess_init:} % A little initialisation as normal. % \begin{macrocode} \cs_new_protected:Npn \@@_number_preprocess_init: { \bool_set_false:N \l_@@_error_bool \tl_clear:N \l_@@_number_multi_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_preprocess_product:} %\begin{macro}[aux]{\@@_number_preprocess_product_aux:N} % Rather than search through the entire argument, we use the % delimited-argument trick. % \begin{macrocode} \cs_new_protected:Npn \@@_number_preprocess_product: { \tl_map_function:NN \l_@@_input_product_tl \@@_number_preprocess_product_aux:N } \cs_new_protected:Npn \@@_number_preprocess_product_aux:N #1 { \tl_if_in:NnT \l_@@_number_arg_tl {#1} { \cs_set:Npn \@@_tmp:w ##1 #1 ##2 \q_stop { \tl_set:Nn \l_@@_number_arg_tl {##1} \tl_set:Nn \l_@@_number_next_tl {##2} \tl_set:Nn \l_@@_number_multi_tl { product } } \exp_after:wN \@@_tmp:w \l_@@_number_arg_tl \q_stop \tl_if_empty:NT \l_@@_number_arg_tl { \@@_error:n { starting-product-token } } \tl_if_empty:NT \l_@@_number_next_tl { \@@_error:n { ending-product-token } } \tl_map_break: } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_preprocess_quotient:} %\begin{macro}[aux]{\@@_number_preprocess_quotient_aux:N} % For the quotient, only one token can appear in each part. So there % is an additional error check. % \begin{macrocode} \cs_new_protected:Npn \@@_number_preprocess_quotient: { \tl_map_function:NN \l_@@_input_quotient_tl \@@_number_preprocess_quotient_aux:N } \cs_new_protected:Npn \@@_number_preprocess_quotient_aux:N #1 { \tl_if_in:NnT \l_@@_number_arg_tl {#1} { \cs_set:Npn \@@_tmp:w ##1 #1 ##2 \q_stop { \tl_set:Nn \l_@@_number_numerator_tl {##1} \tl_set:Nn \l_@@_number_denominator_tl {##2} \tl_set:Nn \l_@@_number_multi_tl { quotient } } \exp_after:wN \@@_tmp:w \l_@@_number_arg_tl \q_stop \tl_if_empty:NT \l_@@_number_numerator_tl { \@@_error:n { starting-quotient-token } } \tl_if_empty:NT \l_@@_number_denominator_tl { \@@_error:n { ending-quotient-token } } \tl_if_in:NnT \l_@@_number_denominator_tl {#1} { \@@_error:n { duplicate-quotient-token } } \tl_map_break: } } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Parsing numbers} % % The parser is designed to be relativity fast, which means some code is % more or less duplicated to gain more speed. It is also loaded so % that simple numbers (such as \num{-1.23}) are parsed particularly % quickly. For most documents, this gain more than offsets any slight % losses with more complicated numbers. % %\begin{macro}{\c_@@_number_part_complex_tl} % A couple of the comparisons needed for checking complex numbers % are done using stored text. To make them a little quicker, a % pre-stored version of the text is stored here. % \begin{macrocode} \tl_new:N \c_@@_number_part_complex_tl \tl_set:Nn \c_@@_number_part_complex_tl { complex } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_number_in_complex_bool , % \l_@@_number_in_complex_root_bool , % \l_@@_number_in_decimal_bool , % \l_@@_number_in_exponent_bool , % \l_@@_number_in_first_bool , % \l_@@_number_in_sign_bool , % \l_@@_number_in_uncert_bool , % \l_@@_number_in_value_bool %} % \begin{macrocode} \bool_new:N \l_@@_number_in_complex_bool \bool_new:N \l_@@_number_in_complex_root_bool \bool_new:N \l_@@_number_in_decimal_bool \bool_new:N \l_@@_number_in_exponent_bool \bool_new:N \l_@@_number_in_first_bool \bool_new:N \l_@@_number_in_sign_bool \bool_new:N \l_@@_number_in_uncert_bool \bool_new:N \l_@@_number_in_value_bool % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_number_in_prop} % The parsed number is stored in a property list as its constituent % parts. % \begin{macrocode} \prop_new:N \l_@@_number_in_prop % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_number_parsed_tl} % Each part of the number parsed has to be built up in a token list. % \begin{macrocode} \tl_new:N \l_@@_number_parsed_tl % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_number_part_tl , % \l_@@_number_part_decimal_tl , % \l_@@_number_part_decimal_marker_tl , % \l_@@_number_part_integer_tl , % \l_@@_number_part_sign_tl , % \l_@@_number_part_uncert_tl %} % The names of various parts of a number are set up as stored values. % This lets some code be used for different parts of a number, while % pre-storing everything brings a performance (and clarity) benefit. % \begin{macrocode} \tl_new:N \l_@@_number_part_tl \tl_new:N \l_@@_number_part_decimal_tl \tl_new:N \l_@@_number_part_decimal_marker_tl \tl_new:N \l_@@_number_part_integer_tl \tl_new:N \l_@@_number_part_sign_tl \tl_new:N \l_@@_number_part_uncert_tl % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_number_mantissa_length_int % \l_@@_number_uncert_tl % \l_@@_number_uncert_length_int %} % Conversion of uncertainty forms requires some storage, mainly for % performance reasons. % \begin{macrocode} \int_new:N \l_@@_number_mantissa_length_int \tl_new:N \l_@@_number_uncert_tl \int_new:N \l_@@_number_uncert_length_int % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_input_uncert_sign_tl} % This one is stored by some low-level code, so is declared explicitly. % \begin{macrocode} \tl_new:N \l_@@_input_uncert_sign_tl % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_input_uncert_close_tl , % \l_@@_input_complex_tl , % \l_@@_input_comparator_tl , % \l_@@_input_decimal_tl , % \l_@@_input_digit_tl , % \l_@@_input_exponent_tl , % \l_@@_input_ignore_tl , % \l_@@_input_uncert_open_tl , % \l_@@_input_protect_tl , % \l_@@_input_sign_tl , % \l_@@_input_symbol_tl , % \l_@@_input_uncert_sign_tl %} % The various tokens to check against when parsing are all set up here. % These are valid inside a single number: the pre-processor has already % set up the appropriate things for products and quotients. % \begin{macrocode} \keys_define:nn { siunitx } { input-close-uncertainty .tl_set:N = \l_@@_input_uncert_close_tl , input-complex-roots .tl_set:N = \l_@@_input_complex_tl , input-comparators .tl_set:N = \l_@@_input_comparator_tl , input-decimal-markers .tl_set:N = \l_@@_input_decimal_tl , input-digits .tl_set:N = \l_@@_input_digit_tl , input-exponent-markers .tl_set:N = \l_@@_input_exponent_tl , input-ignore .tl_set:N = \l_@@_input_ignore_tl , input-open-uncertainty .tl_set:N = \l_@@_input_uncert_open_tl , input-protect-tokens .tl_set:N = \l_@@_input_protect_tl , input-signs .tl_set:N = \l_@@_input_sign_tl , input-symbols .tl_set:N = \l_@@_input_symbol_tl , input-uncertainty-signs .code:n = { \tl_set:Nn \l_@@_input_uncert_sign_tl {#1} \tl_map_inline:nn {#1} { \tl_if_in:NnF \l_@@_input_sign_tl {##1} { \tl_put_right:Nn \l_@@_input_sign_tl {##1} } } } , } \keys_set:nn { siunitx } { % ( input-close-uncertainty = ), input-complex-roots = ij, input-comparators = {<=>\approx\ge\geq\gg\le\leq\ll\sim}, input-decimal-markers = {.,}, input-digits = 0123456789, input-exponent-markers = dDeE, input-open-uncertainty = (, % ) input-protect-tokens = \approx\dots\ge\geq\gg\le\leq\ll\mp\pi\pm\sim, input-signs = +-\mp\pm, input-symbols = \dots\pi, input-uncertainty-signs = \pm, } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_number_in_parse:n , % \@@_number_in_parse:V %} %\begin{macro}[aux]{\@@_number_in_parse_aux:n} % The parsing routine starts by replacing any formatting in the input % using \cs{tl_set_rescan:Nnx}. Next, there is a quick routine to % ensure that all signs are single tokens. The main loop then takes % place, which will parse the input into the property list and also % set up the flags. There are then some checks and possible corrections. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_parse:n #1 { \tl_if_empty:nF {#1} { \@@_number_in_init: \cs_set_eq:NN \@@_number_in_parse_more:N \@@_number_in_parse_mantissa_aux:N \@@_number_in_parse_aux:n {#1} } } \cs_generate_variant:Nn \@@_number_in_parse:n { V } \group_begin: \char_set_catcode_active:N \~ \char_set_catcode_space:N \ % \cs_new_protected:Npn \@@_number_in_parse_aux:n#1% {% \group_begin: \@@_number_in_protect: \cs_set_eq:NN\,\prg_do_nothing: \cs_set_eq:NN~\prg_do_nothing: \tl_set_rescan:Nnx\l_@@_number_arg_tl {% \char_set_catcode_ignore:N\ % \char_set_catcode_other:N\,% \char_set_catcode_other:N\.% }% {#1}% \exp_args:NNNV\group_end: \tl_set:Nn\l_@@_number_arg_tl\l_@@_number_arg_tl \@@_number_in_sign_replace:N\l_@@_number_arg_tl \@@_number_in_parse_relation:N\l_@@_number_arg_tl \tl_map_function:NN\l_@@_number_arg_tl \@@_number_in_parse_loop:N \tl_if_empty:NF\l_@@_number_parsed_tl {% \bool_if:NTF\l_@@_number_in_uncert_bool {\@@_error:nx{invalid-number}{#1}}% {% \prop_put:NVn \l_@@_number_in_prop \l_@@_number_part_tl {true}% \bool_if:NTF\l_@@_number_in_decimal_bool {% \prop_put:NVV\l_@@_number_in_prop \l_@@_number_part_decimal_tl \l_@@_number_parsed_tl }% {% \prop_put:NVV\l_@@_number_in_prop \l_@@_number_part_integer_tl \l_@@_number_parsed_tl }% }% }% \@@_number_in_check:n {#1}% } \group_end: % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{ % \@@_number_in_init: , % \@@_number_in_init_part:n %} % The set up code is divided into to parts. First, code only needed % once to start the entire parser. Then a second group, which is % carried out at the start of each part of a number, and so is called % from a few places. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_init: { \cs_set_eq:NN \@@_number_in_parse_loop:N \@@_number_in_parse_mantissa:N \cs_set_eq:NN \@@_number_in_check:n \@@_number_in_check_short:n \tl_clear:N \l_@@_number_parsed_tl \prop_clear:N \l_@@_number_in_prop \bool_set_false:N \l_@@_error_bool \bool_set_false:N \l_@@_number_in_complex_bool \bool_set_false:N \l_@@_number_in_complex_root_bool \bool_set_false:N \l_@@_number_in_exponent_bool \bool_set_false:N \l_@@_number_in_uncert_bool \@@_number_in_init_part:n { mantissa } } \cs_new_protected:Npn \@@_number_in_init_part:n #1 { \bool_set_false:N \l_@@_number_in_decimal_bool \bool_set_true:N \l_@@_number_in_first_bool \bool_set_false:N \l_@@_number_in_sign_bool \bool_set_false:N \l_@@_number_in_value_bool \tl_set:Nn \l_@@_number_part_tl {#1} \tl_set:Nn \l_@@_number_part_decimal_tl { #1 -decimal } \tl_set:Nn \l_@@_number_part_decimal_marker_tl { #1 -decimal-marker } \tl_set:Nn \l_@@_number_part_integer_tl { #1 -integer } \tl_set:Nn \l_@@_number_part_sign_tl { #1 -sign } \tl_set:Nn \l_@@_number_part_uncert_tl { #1 -uncertainty } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_in_protect:} %\begin{macro}[aux]{\@@_number_in_protect_aux:N} % Under some circumstances (for example when loading \pkg{breqn}) % some tokens do not behave safely under \texttt{x} expansion (at the % moment). To get round this, they are redefined here. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_protect: { \tl_map_function:NN \l_@@_input_protect_tl \@@_number_in_protect_aux:N } \cs_new_protected:Npn \@@_number_in_protect_aux:N #1 { \cs_set_eq:NN #1 \scan_stop: } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_in_sign_replace:N} % A short spin-out to keep the replacement of tokens clear. % \begin{macrocode} \group_begin: \char_set_catcode_active:N \* \char_set_lccode:nn { `\* } { `\- } \tl_to_lowercase:n { \group_end: \cs_new_protected:Npn \@@_number_in_sign_replace:N #1 { \tl_replace_all:Nnn #1 { * } { - } \tl_replace_all:Nnn #1 { -+ } { \mp } \tl_replace_all:Nnn #1 { +- } { \pm } \tl_replace_all:Nnn #1 { << } { \ll } \tl_replace_all:Nnn #1 { <= } { \le } \tl_replace_all:Nnn #1 { >> } { \gg } \tl_replace_all:Nnn #1 { >= } { \ge } } } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_number_in_parse_error:nn , % \@@_number_in_parse_error:nV %} % There are lots of rather similar errors in the parser, all of which % require a \cs{tl_map_break:}. To keep life simple, this is set up % here. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_parse_error:nn #1#2 { \@@_error:nx {#1} { \exp_not:n {#2} } \tl_map_break: } \cs_generate_variant:Nn \@@_number_in_parse_error:nn { nV } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_number_in_parse_loop:N , % \@@_number_in_parse_more:N %} % The main loop is set up as a place holder, as the definition is % varied to keep things fast. There is also a place holder for the % extended routing for normal mantissas. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_parse_loop:N #1 { } \cs_new_protected:Npn \@@_number_in_parse_more:N #1 { } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_in_parse_relation:N} %\begin{macro}[aux]{\@@_number_in_parse_relation:w} % The idea here is that a relation with be the very first token in the % input, or it is not valid. So the test for a relation can be very % simple and hopefully efficient. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_parse_relation:N #1 { \exp_after:wN \@@_number_in_parse_relation:w #1 \q_stop #1 } \cs_new_protected:Npn \@@_number_in_parse_relation:w #1#2 \q_stop #3 { \tl_if_in:NnT \l_@@_input_comparator_tl {#1} { \prop_put:Nnn \l_@@_number_in_prop { comparator } {#1} \tl_set:Nn #3 {#2} } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_in_parse_restricted:N} % When parsing numbers for the \cs{ang} function, no extended input % is permitted at all. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_parse_restricted:N #1 { \tl_if_in:NnTF \l_@@_input_exponent_tl {#1} { \@@_number_in_parse_error:nn { restricted-number } {#1} } { \tl_if_in:NnTF \l_@@_input_uncert_open_tl {#1} { \@@_number_in_parse_error:nV { restricted-number } \l_@@_number_arg_tl } { \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#1} { \@@_number_in_parse_error:nV { restricted-number } \l_@@_number_arg_tl } { \tl_if_in:NnTF \l_@@_input_complex_tl {#1} { \@@_number_in_parse_error:nV { restricted-number } \l_@@_number_arg_tl } { \@@_number_in_parse_error:nn { restricted-number } {#1} } } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_in_parse_complex:N} % After a complex root when the root is \emph{after} the number, there % are a very limited range of legitimate tokens. Thus most cases can be % trapped with a modified parser. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_parse_complex:N #1 { \tl_if_in:NnTF \l_@@_input_exponent_tl {#1} { \cs_set_eq:NN \@@_number_in_parse_loop:N \@@_number_in_parse_mantissa:N \@@_number_in_exponent:N #1 } { \tl_if_in:NnF \l_@@_input_ignore_tl {#1} { \@@_number_in_parse_error:nV { misplaced-complex-root-token } \l_@@_number_arg_tl } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_in_parse_exponent:N} % When processing an exponent, the \enquote{extended} part of the % number which is valid in a mantissa is no longer needed. So the % auxiliary function is pointed to a series of errors instead. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_parse_exponent:N #1 { \tl_if_in:NnTF \l_@@_input_exponent_tl {#1} { \@@_number_in_parse_error:nn { duplicate-exponent-token } { \token_to_str:N #1 } } { \tl_if_in:NnTF \l_@@_input_uncert_open_tl {#1} { \@@_number_in_parse_error:nV { invalid-token-in-exponent } \l_@@_number_arg_tl } { \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#1} { \@@_number_in_parse_error:nV { invalid-token-in-exponent } \l_@@_number_arg_tl } { \tl_if_in:NnTF \l_@@_input_complex_tl {#1} { \@@_number_in_parse_error:nV { invalid-token-in-exponent } \l_@@_number_arg_tl } { \@@_number_in_parse_error:nn { invalid-token-in-number } {#1} } } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_in_parse_mantissa:N} %\begin{macro}[aux]{\@@_number_in_parse_mantissa_aux:N} % For the mantissa, most things are valid. The procedure is split % into two parts, with the simple symbols handled here and the more % complex ones in a second part(which needs to be varied). Essentially % everything here is a comparison, done so that the code is a fast as % possible. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_parse_mantissa:N #1 { \tl_if_in:NnTF \l_@@_input_digit_tl {#1} { \@@_number_in_digit:n {#1} } { \tl_if_in:NnTF \l_@@_input_decimal_tl {#1} { \@@_number_in_decimal:N #1 } { \tl_if_in:NnTF \l_@@_input_sign_tl {#1} { \@@_number_in_sign:N #1 } { \tl_if_in:NnTF \l_@@_input_symbol_tl {#1} { \prop_put:Nnn \l_@@_number_in_prop { symbolic } { true } \@@_number_in_digit:n { \ensuremath {#1} } } { \tl_if_in:NnF \l_@@_input_ignore_tl {#1} { \@@_number_in_parse_more:N #1 } } } } } } \cs_new_protected:Npn \@@_number_in_parse_mantissa_aux:N #1 { \tl_if_in:NnTF \l_@@_input_exponent_tl {#1} { \@@_number_in_exponent:N #1 } { \tl_if_in:NnTF \l_@@_input_uncert_open_tl {#1} { \@@_number_in_uncert_open:N #1 } { \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#1} { \@@_number_in_parse_error:nn { misplaced-uncertainty-token } {#1} } { \tl_if_in:NnTF \l_@@_input_complex_tl {#1} { \@@_number_in_complex:N #1 } { \@@_number_in_parse_error:nn { invalid-token-in-number } {#1} } } } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_in_parse_uncert:N} % Within uncertainties, the range of tokens is limited. An alternative % parsing system can therefore be used. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_parse_uncert:N #1 { \tl_if_in:NnTF \l_@@_input_digit_tl {#1} { \@@_number_in_digit:n {#1} } { \tl_if_in:NnTF \l_@@_input_decimal_tl {#1} { \@@_number_in_parse_error:nV { invalid-token-in-uncertainty } \l_@@_number_arg_tl } { \tl_if_in:NnTF \l_@@_input_sign_tl {#1} { \@@_number_in_parse_error:nV { invalid-token-in-uncertainty } \l_@@_number_arg_tl } { \tl_if_in:NnTF \l_@@_input_symbol_tl {#1} { \prop_put:Nnn \l_@@_number_in_prop { symbolic } { true } \@@_number_in_digit:n {#1} } { \tl_if_in:NnF \l_@@_input_ignore_tl {#1} { \tl_if_in:NnTF \l_@@_input_uncert_close_tl {#1} { \@@_number_in_uncert_close:N #1 } { \@@_number_in_parse_error:nV { invalid-token-in-uncertainty } \l_@@_number_arg_tl } } } } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_in_parse_uncert_after:N} % After an uncertainty, there is once again a very limited range of % tokens that can be present in a valid number. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_parse_uncert_after:N #1 { \tl_if_in:NnTF \l_@@_input_exponent_tl {#1} { \cs_set_eq:NN \@@_number_in_parse_loop:N \@@_number_in_parse_mantissa:N \@@_number_in_exponent:N #1 } { \tl_if_in:NnTF \l_@@_input_sign_tl {#1} { \cs_set_eq:NN \@@_number_in_parse_loop:N \@@_number_in_parse_mantissa:N \@@_number_in_sign:N #1 } { \tl_if_in:NnF \l_@@_input_ignore_tl {#1} { \tl_if_in:NnTF \l_@@_input_complex_tl {#1} { \cs_set_eq:NN \@@_number_in_parse_loop:N \@@_number_in_parse_mantissa:N \@@_number_in_complex:N #1 } { \@@_number_in_parse_error:nV { invalid-number } \l_@@_number_arg_tl } } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_in_complex:N} %\begin{macro}[aux]{\@@_number_in_complex_aux:nn} % Only one complex root token can be give, hence the initial test. % More tests are needed for complex numbers than other systems, so % the additional ones are turned on, followed by some flag setting. % The complex root is stored, then there is a check to see if the % root is at the end of the number: if it is, prevent any more tokens % being added. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_complex:N #1 { \bool_set_false:N \l_@@_number_in_first_bool \bool_if:NTF \l_@@_number_in_complex_root_bool { \@@_number_in_parse_error:nn { duplicate-complex-root-token } { \token_to_str:N #1 } } { \cs_set_eq:NN \@@_number_in_check:n \@@_number_in_check_full:n \bool_set_true:N \l_@@_number_in_complex_root_bool \prop_put:Nnn \l_@@_number_in_prop { complex-root } {#1} \tl_if_empty:NF \l_@@_number_parsed_tl { \cs_set_eq:NN \@@_number_in_parse_loop:N \@@_number_in_parse_complex:N } \bool_if:NT \l_@@_number_in_decimal_bool { \bool_if:NF \l_@@_number_in_complex_bool { \prop_if_in:NnT \l_@@_number_in_prop { mantissa-uncertainty } { \@@_number_in_complex_aux:nn { mantissa-decimal } { complex-decimal } \@@_number_in_complex_aux:nn { mantissa-uncertainty } { complex-uncertainty } } \@@_number_in_complex_aux:nn { mantissa-integer } { complex-integer } \@@_number_in_complex_aux:nn { mantissa-decimal-marker } { complex-decimal-marker } \prop_remove:Nn \l_@@_number_in_prop { mantissa } \prop_put:Nnn \l_@@_number_in_prop { complex } { true } } } \prop_if_in:NnF \l_@@_number_in_prop { mantissa } { \prop_if_in:NnT \l_@@_number_in_prop { mantissa-sign } { \@@_number_in_complex_aux:nn { mantissa-sign } { complex-sign } } } \bool_set_true:N \l_@@_number_in_complex_bool \bool_set_false:N \l_@@_number_in_first_bool \@@_number_in_init_part:n { complex } \prop_if_in:NnT \l_@@_number_in_prop { complex-decimal-marker } { \bool_set_true:N \l_@@_number_in_decimal_bool } \prop_if_in:NnTF \l_@@_number_in_prop { complex-sign } { \bool_set_true:N \l_@@_number_in_sign_bool } { \prop_remove:Nn \l_@@_number_in_prop { mantissa } } } } \cs_new_protected:Npn \@@_number_in_complex_aux:nn #1#2 { \prop_get:NnNT \l_@@_number_in_prop {#1} \l_@@_tmpa_tl { \prop_remove:Nn \l_@@_number_in_prop {#1} \prop_put:NnV \l_@@_number_in_prop {#2} \l_@@_tmpa_tl } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_in_decimal:N} % Only one decimal marker allowed, so a test for this. If an integer % part has been found, it is saved. The flag for the number being % found is not set unless there is an integer, to watch for the case % of invalid numbers. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_decimal:N #1 { \bool_set_false:N \l_@@_number_in_first_bool \bool_if:NTF \l_@@_number_in_decimal_bool { \@@_number_in_parse_error:nn { duplicate-decimal-token } {#1} } { \bool_set_true:N \l_@@_number_in_decimal_bool \tl_if_empty:NF \l_@@_number_parsed_tl { \prop_put:NVn \l_@@_number_in_prop \l_@@_number_part_tl { true } \prop_put:NVV \l_@@_number_in_prop \l_@@_number_part_integer_tl \l_@@_number_parsed_tl \tl_clear:N \l_@@_number_parsed_tl } \prop_put:NVn \l_@@_number_in_prop \l_@@_number_part_decimal_marker_tl {#1} } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_in_digit:n} % For digits, only in an uncertainty can the value be stored % directly. Otherwise, there is a need to see if the value is non-zero. % This is used to drop leading zeros and to validate any sign (as zero % is unsigned). % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_digit:n #1 { \bool_set_false:N \l_@@_number_in_first_bool \bool_if:NTF \l_@@_number_in_uncert_bool { \tl_put_right:Nn \l_@@_number_parsed_tl {#1} } { \bool_if:NTF \l_@@_number_in_decimal_bool { \tl_put_right:Nn \l_@@_number_parsed_tl {#1} \str_if_eq:nnF {#1} { 0 } { \bool_set_true:N \l_@@_number_in_value_bool } } { \str_if_eq:nnTF {#1} { 0 } { \prop_put:NVn \l_@@_number_in_prop \l_@@_number_part_tl { true } \prop_put:NVn \l_@@_number_in_prop \l_@@_number_part_integer_tl { 0 } } { \bool_set_true:N \l_@@_number_in_value_bool } \bool_if:NT \l_@@_number_in_value_bool { \tl_put_right:Nn \l_@@_number_parsed_tl {#1} } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_in_exponent:N} % A duplicate token test starts off the code, which if passed % leads to some simple storage manipulation. As exponents are % more simple than the mantissa, the extra processing is swapped for % some that only raises errors. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_exponent:N #1 { \bool_if:NTF \l_@@_number_in_exponent_bool { \@@_number_in_parse_error:nn { duplicate-exponent-token } { \token_to_str:N #1 } } { \cs_set_eq:NN \@@_number_in_parse_more:N \@@_number_in_parse_exponent:N \tl_if_empty:NF \l_@@_number_parsed_tl { \@@_number_in_store: } \bool_set_true:N \l_@@_number_in_exponent_bool \@@_number_in_init_part:n { exponent } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_in_sign:N} % The code for signs is complicated by complex numbers. A sign token % must be the fist thing in a number, but after the real part of the % mantissa a second sign token can appear to start a complex number. % So most of the code here is to detect that case. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_sign:N #1 { \bool_if:NTF \l_@@_number_in_first_bool { \bool_set_false:N \l_@@_number_in_first_bool \bool_set_true:N \l_@@_number_in_sign_bool \prop_put:NVn \l_@@_number_in_prop \l_@@_number_part_sign_tl {#1} } { \bool_if:NTF \l_@@_number_in_exponent_bool { \@@_number_in_parse_error:nn { misplaced-sign-token } {#1} } { \bool_if:NTF \l_@@_number_in_complex_bool { \@@_number_in_parse_error:nn { misplaced-sign-token } {#1} } { \tl_if_empty:NF \l_@@_number_parsed_tl { \@@_number_in_store: } \cs_set_eq:NN \@@_number_in_check:n \@@_number_in_check_full:n \@@_number_in_init_part:n { complex } \prop_put:Nnn \l_@@_number_in_prop { complex-sign } {#1} \bool_set_true:N \l_@@_number_in_complex_bool } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_number_in_uncert_open:N , % \@@_number_in_uncert_close:N %} % Opening and closing uncertainty tokens are handled separately. For % opening tokens, a check is made that there is something else to the % number before collecting material up. For the closing token, the % uncertainty must contain some numbers. A special loop function is then % set up to prevent any additional digits after the closing token. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_uncert_open:N #1 { \bool_set_false:N \l_@@_number_in_first_bool \cs_set_eq:NN \@@_number_in_parse_loop:N \@@_number_in_parse_uncert:N \bool_set_true:N \l_@@_number_in_uncert_bool \tl_if_empty:NTF \l_@@_number_parsed_tl { \prop_if_in:NVF \l_@@_number_in_prop \l_@@_number_part_integer_tl { \@@_number_in_parse_error:nV { invalid-number } \l_@@_number_arg_tl } } { \@@_number_in_store: } } \cs_new_protected:Npn \@@_number_in_uncert_close:N #1 { \bool_set_false:N \l_@@_number_in_uncert_bool \tl_if_empty:NTF \l_@@_number_parsed_tl { \@@_number_in_parse_error:nV { empty-uncertainty } \l_@@_number_arg_tl } { \prop_put:NVV \l_@@_number_in_prop \l_@@_number_part_uncert_tl \l_@@_number_parsed_tl \prop_put:Nnn \l_@@_number_in_prop { uncertainty } { true } \tl_clear:N \l_@@_number_parsed_tl \cs_set_eq:NN \@@_number_in_parse_loop:N \@@_number_in_parse_uncert_after:N } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_in_store:} % A short auxiliary function needed in various places for storing % either the integer or decimal part of a number, as appropriate. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_store: { \prop_put:NVn \l_@@_number_in_prop \l_@@_number_part_tl { true } \bool_if:NTF \l_@@_number_in_decimal_bool { \prop_put:NVV \l_@@_number_in_prop \l_@@_number_part_decimal_tl \l_@@_number_parsed_tl } { \prop_put:NVV \l_@@_number_in_prop \l_@@_number_part_integer_tl \l_@@_number_parsed_tl } \tl_clear:N \l_@@_number_parsed_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_number_in_check:n , % \@@_number_in_check_short:n , % \@@_number_in_check_full:n %} % The checks needed for a number depend on whether there is a complex % part. In all cases, there must be some digits, as well as a sign or % decimal marker. There is also a check for a zero-valued input, which % has any sign deleted. For complex numbers, the check is needed in % case there was no real part. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_check:n #1 { } \cs_new_protected:Npn \@@_number_in_check_short:n #1 { \prop_if_in:NVF \l_@@_number_in_prop \l_@@_number_part_integer_tl { \prop_if_in:NVF \l_@@_number_in_prop \l_@@_number_part_decimal_tl { \@@_error:nx { invalid-number } {#1} } } \bool_if:NF \l_@@_number_in_value_bool { \tl_if_eq:NNF \l_@@_number_part_tl \c_@@_number_part_complex_tl { \prop_get:NVNT \l_@@_number_in_prop \l_@@_number_part_sign_tl \l_@@_tmpa_tl { \tl_set:Nx \l_@@_tmpb_tl { \l_@@_number_part_sign_tl -deleted } \prop_put:NVV \l_@@_number_in_prop \l_@@_tmpb_tl \l_@@_tmpa_tl } \prop_remove:NV \l_@@_number_in_prop \l_@@_number_part_sign_tl } } } \cs_new_protected:Npn \@@_number_in_check_full:n #1 { \tl_if_eq:NNF \l_@@_number_part_tl \c_@@_number_part_complex_tl { \@@_number_in_check_short:n {#1} } \bool_if:NF \l_@@_number_in_complex_root_bool { \prop_get:NnN \l_@@_number_in_prop { complex-sign } \l_@@_tmpa_tl \tl_if_in:NVTF \l_@@_input_uncert_sign_tl \l_@@_tmpa_tl { \prop_if_in:NnTF \l_@@_number_in_prop { uncertainty } { \@@_error:nx { misplaced-sign-token } { \exp_not:n {#1} } } { \@@_number_in_complex_to_uncert:n {#1} } } { \@@_error:nx { misplaced-sign-token } { \exp_not:n {#1} } } } \prop_get:NnNT \l_@@_number_in_prop { mantissa-sign } \l_@@_tmpa_tl { \prop_if_in:NnF \l_@@_number_in_prop { mantissa } { \prop_remove:Nn \l_@@_number_in_prop { mantissa-sign } \prop_put:NnV \l_@@_number_in_prop { complex-sign } \l_@@_tmpa_tl } } } % \end{macrocode} %\end{macro} % % %\begin{macro}{\@@_number_in_complex_to_uncert:n} %\begin{macro}[aux]{ % \@@_number_in_complex_to_uncert_int: , % \@@_number_in_complex_to_uncert_dec: %} % Internally, uncertainties are stored in \enquote{compact} form. % The code here takes a putative complex part and converts it to % a compact uncertainty, with checks for the cases where things look % wrong. The method needed depends on whether there is an integer % part. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_complex_to_uncert:n #1 { \prop_remove:Nn \l_@@_number_in_prop { complex } \prop_remove:Nn \l_@@_number_in_prop { complex-decimal-marker } \prop_remove:Nn \l_@@_number_in_prop { complex-sign } \prop_put:Nnn \l_@@_number_in_prop { uncertainty } { true } \prop_get:NnNTF \l_@@_number_in_prop { complex-integer } \l_@@_number_uncert_tl { \tl_if_single:NTF \l_@@_number_uncert_tl { \int_compare:nNnTF { \l_@@_number_uncert_tl } = { \c_zero } { \@@_number_in_complex_to_uncert_dec:n {#1} } { \@@_number_in_complex_to_uncert_int: } } { \@@_number_in_complex_to_uncert_int: } } { \@@_number_in_complex_to_uncert_dec:n {#1} } \prop_remove:Nn \l_@@_number_in_prop { complex-integer } \prop_remove:Nn \l_@@_number_in_prop { complex-decimal } } % \end{macrocode} % When the input has an integer part to the uncertainty, the % conversion is easy as all of the decimal part can be copied % across. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_complex_to_uncert_int: { \prop_get:NnNF \l_@@_number_in_prop { complex-decimal } \l_@@_tmpa_tl { \tl_clear:N \l_@@_tmpa_tl } \prop_get:NnNF \l_@@_number_in_prop { mantissa-decimal } \l_@@_tmpb_tl { \tl_clear:N \l_@@_tmpb_tl } \@@_number_in_complex_to_uncert_pad: } % \end{macrocode} % For a number in which all of the uncertainty is in the decimal part, % only the significant digits are needed. This means that a loop is % needed to drop non-significant ones. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_complex_to_uncert_dec:n #1 { \tl_clear:N \l_@@_number_uncert_tl \prop_get:NnNTF \l_@@_number_in_prop { complex-decimal } \l_@@_tmpa_tl { \prop_get:NnN \l_@@_number_in_prop { mantissa-decimal } \l_@@_tmpb_tl \quark_if_no_value:NT \l_@@_tmpb_tl { \tl_clear:N \l_@@_tmpb_tl } \tl_map_function:NN \l_@@_tmpa_tl \@@_number_in_complex_to_uncert_dec_loop:N \@@_number_in_complex_to_uncert_pad: } { \@@_error:nx { misplaced-sign-token } { \exp_not:n {#1} } } } \cs_new_protected:Npn \@@_number_in_complex_to_uncert_dec_loop:N #1 { \str_if_eq:nnTF {#1} { 0 } { \tl_set:Nx \l_@@_tmpa_tl { \tl_tail:N \l_@@_tmpa_tl } \tl_if_empty:NF \l_@@_tmpb_tl { \tl_set:Nx \l_@@_tmpb_tl { \tl_tail:N \l_@@_tmpb_tl } } } { \tl_map_break: } } % \end{macrocode} % In all cases, there is a need to pad out either the uncertainty or % the decimal part so the places agree. To allow the two branches to % share code, some of the order here is slightly odd. The code % also re-obtains the decimal part from the mantissa, as the stored % value may have been trimmed to drop non-significant zeros. % \begin{macrocode} \cs_new_protected:Npn \@@_number_in_complex_to_uncert_pad: { \int_set:Nn \l_@@_number_uncert_length_int { \tl_count:N \l_@@_tmpa_tl } \int_set:Nn \l_@@_number_mantissa_length_int { \tl_count:N \l_@@_tmpb_tl } \int_compare:nNnTF { \l_@@_number_mantissa_length_int } > { \l_@@_number_uncert_length_int } { \tl_set:Nx \l_@@_tmpa_tl { \exp_not:V \l_@@_tmpa_tl \prg_replicate:nn { \l_@@_number_mantissa_length_int - \l_@@_number_uncert_length_int } { 0 } } } { \prop_get:NnNF \l_@@_number_in_prop { mantissa-decimal } \l_@@_tmpb_tl { \tl_set:Nn \l_@@_tmpb_tl { 0 } } \tl_set:Nx \l_@@_tmpb_tl { \exp_not:V \l_@@_tmpb_tl \prg_replicate:nn { \l_@@_number_uncert_length_int - \l_@@_number_mantissa_length_int } { 0 } } \tl_if_empty:NF \l_@@_tmpb_tl { \prop_put:NnV \l_@@_number_in_prop { mantissa-decimal } \l_@@_tmpb_tl \prop_if_in:NnF \l_@@_number_in_prop { mantissa-decimal-marker } { \prop_put:Nnn \l_@@_number_in_prop { mantissa-decimal-marker } { . } } } } \tl_put_right:NV \l_@@_number_uncert_tl \l_@@_tmpa_tl \prop_put:NnV \l_@@_number_in_prop { mantissa-uncertainty } \l_@@_number_uncert_tl } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Post-processing numbers} % % After finding the basic number in the code above, there may be some % manipulation to do. This covers things such as tidying up excess % information and rounding numbers. Nothing is added here that is % for \enquote{formatting}: this is left for the output part of the % system. % % \begin{variable} % { % \l_@@_round_int , % \l_@@_round_tl , % \l_@@_round_bool , % \l_@@_round_decimal_in_tl , % \l_@@_round_decimal_out_tl , % \l_@@_round_discard_tl , % \l_@@_round_even_bool , % \l_@@_round_integer_in_tl , % \l_@@_round_integer_out_tl , % \l_@@_round_half_up_bool % } % The rounding system needs a number of variables. % \begin{macrocode} \int_new:N \l_@@_round_int \tl_new:N \l_@@_round_tl \bool_new:N \l_@@_round_bool \tl_new:N \l_@@_round_decimal_in_tl \tl_new:N \l_@@_round_decimal_out_tl \tl_new:N \l_@@_round_discard_tl \tl_new:N \l_@@_round_even_bool \tl_new:N \l_@@_round_integer_in_tl \tl_new:N \l_@@_round_integer_out_tl \bool_new:N \l_@@_round_half_up_bool % \end{macrocode} % \end{variable} % %\begin{macro}{ % \l_@@_process_decimal_int , % \l_@@_process_uncertainty_int , % \l_@@_uncertainty_decimal_tl , % \l_@@_uncertainty_integer_tl %} % The code to expand uncertainties needs to know numbers of digits, and % to store various data. % \begin{macrocode} \int_new:N \l_@@_process_decimal_int \int_new:N \l_@@_process_uncertainty_int \tl_new:N \l_@@_uncertainty_decimal_tl \tl_new:N \l_@@_uncertainty_integer_tl % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_process_fixed_bool , % \l_@@_process_engineering_bool , % \l_@@_process_scientific_bool %} % Settings for the scientific notation system. % \begin{macrocode} \bool_new:N \l_@@_process_fixed_bool \bool_new:N \l_@@_process_engineering_bool \bool_new:N \l_@@_process_scientific_bool % \end{macrocode} %\end{macro} % % \begin{variable}{\l_@@_process_drop_exponent_bool} % Used to drop the exponent when this is necessary. % \begin{macrocode} \bool_new:N \l_@@_process_drop_exponent_bool % \end{macrocode} % \end{variable} % % \begin{variable} % { % \l_@@_process_decimal_zero_bool , % \l_@@_process_integer_zero_bool , % \l_@@_process_sign_tl , % \l_@@_process_fixed_int , % \l_@@_process_integer_min_int , % \l_@@_process_plus_bool , % \l_@@_omit_uncert_bool , % \l_@@_process_unity_mantissa_tl , % \l_@@_process_zero_exponent_bool , % \l_@@_process_int_to_dec_bool , % \l_@@_process_round_min_tl , % \l_@@_process_precision_int , % \l_@@_zero_decimal_to_integer_bool % } % First, the options are set up. % \begin{macrocode} \keys_define:nn { siunitx } { add-decimal-zero .bool_set:N = \l_@@_process_decimal_zero_bool, add-integer-zero .bool_set:N = \l_@@_process_integer_zero_bool, explicit-sign .tl_set:N = \l_@@_process_sign_tl, fixed-exponent .int_set:N = \l_@@_process_fixed_int, minimum-integer-digits .int_set:N = \l_@@_process_integer_min_int, retain-explicit-plus .bool_set:N = \l_@@_process_plus_bool, omit-uncertainty .bool_set:N = \l_@@_omit_uncert_bool, retain-unity-mantissa .bool_set:N = \l_@@_process_unity_mantissa_bool, retain-zero-exponent .bool_set:N = \l_@@_process_zero_exponent_bool, round-half .choice:, round-half / even .code:n = { \bool_set_false:N \l_@@_round_half_up_bool }, round-half / up .code:n = { \bool_set_true:N \l_@@_round_half_up_bool }, round-integer-to-decimal .bool_set:N = \l_@@_process_int_to_dec_bool, round-minimum .tl_set:N = \l_@@_process_round_min_tl, round-mode .choice: , round-mode / figures .code:n = { \tl_set:Nn \l_@@_round_tl { figures } }, round-mode / off .code:n = { \tl_clear:N \l_@@_round_tl }, round-mode / places .code:n = { \tl_set:Nn \l_@@_round_tl { places } }, round-precision .int_set:N = \l_@@_process_precision_int, scientific-notation .choice: , scientific-notation / false .code:n = { \bool_set_false:N \l_@@_process_fixed_bool \bool_set_false:N \l_@@_process_engineering_bool \bool_set_false:N \l_@@_process_scientific_bool }, scientific-notation / engineering .code:n = { \bool_set_false:N \l_@@_process_fixed_bool \bool_set_true:N \l_@@_process_engineering_bool \bool_set_true:N \l_@@_process_scientific_bool }, scientific-notation / fixed .code:n = { \bool_set_true:N \l_@@_process_fixed_bool \bool_set_false:N \l_@@_process_engineering_bool \bool_set_false:N \l_@@_process_scientific_bool }, scientific-notation / true .code:n = { \bool_set_false:N \l_@@_process_fixed_bool \bool_set_false:N \l_@@_process_engineering_bool \bool_set_true:N \l_@@_process_scientific_bool }, zero-decimal-to-integer .bool_set:N = \l_@@_zero_decimal_to_integer_bool } \keys_set:nn { siunitx } { add-decimal-zero = true, add-integer-zero = true, retain-unity-mantissa = true, round-half = up, round-minimum = 0, round-precision = 2 } % \end{macrocode} % \end{variable} % % \begin{macro}{\@@_number_process:} % Post-processing is a series of small tasks. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process: { \@@_number_process_sign: \@@_number_process_zero_fill: \@@_number_process_mantissa: \prop_if_in:NnF \l_@@_number_in_prop { symbolic } { \bool_if:NTF \l_@@_process_fixed_bool { \@@_number_process_fixed: } { \bool_if:NT \l_@@_process_scientific_bool { \@@_number_process_scientific: } } \@@_number_process_exponent: \@@_number_process_uncertainty: \bool_if:NT \l_@@_exp_to_prefix_bool { \tl_if_empty:NF \l_@@_unit_tl { \@@_number_exp_to_prefix: } } \prop_if_in:NnTF \l_@@_number_in_prop { uncertainty } { \bool_if:NT \l_@@_omit_uncert_bool { \prop_remove:Nn \l_@@_number_in_prop { uncertainty } \prop_remove:Nn \l_@@_number_in_prop { mantissa-uncertainty } } } { \@@_number_process_round: } } \@@_number_process_zero_to_integer: \@@_number_process_integer_digits: \bool_if:NT \l_@@_process_drop_exponent_bool { \prop_remove:Nn \l_@@_number_in_prop { exponent } \prop_remove:Nn \l_@@_number_in_prop { exponent-integer } } } % \end{macrocode} % \end{macro} % %\begin{macro}{\@@_number_process_exponent:} %\begin{macro}[aux]{\@@_number_process_exponent_aux:n} % To check for a totally zero exponent, the possibility that one or more % of the exponent storage areas is zero needs to be considered. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_exponent: { \bool_if:NF \l_@@_process_zero_exponent_bool { \prop_if_in:NnT \l_@@_number_in_prop { exponent } { \bool_set_false:N \l_@@_tmp_bool \@@_number_process_exponent_aux:n { integer } \bool_if:NF \l_@@_tmp_bool { \@@_number_process_exponent_aux:n { decimal } } \bool_if:NF \l_@@_tmp_bool { \prop_remove:Nn \l_@@_number_in_prop { exponent } \prop_remove:Nn \l_@@_number_in_prop { exponent-integer } \prop_remove:Nn \l_@@_number_in_prop { exponent-decimal } } } } } \cs_new_protected:Npn \@@_number_process_exponent_aux:n #1 { \prop_get:NnNT \l_@@_number_in_prop { exponent- #1 } \l_@@_tmpa_tl { \int_compare:nNnF { \l_@@_tmpa_tl } = { 0 } { \bool_set_true:N \l_@@_tmp_bool } } } % \end{macrocode} %\end{macro} %\end{macro} % % \begin{macro}{\@@_number_process_figures:n} % \begin{macro}[aux] % { % \@@_number_process_figures_aux:n , % \@@_number_process_figures_init:n % } % The approach here is to find how many digits there are in each part % of the number, working out which are significant. The next stage is % reconstruction of the number. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_figures:n #1 { \int_compare:nNnTF \l_@@_process_precision_int > \c_zero { \prop_if_in:NnT \l_@@_number_in_prop {#1} { \@@_number_process_figures_aux:n {#1} } } { \prop_remove:Nn \l_@@_number_in_prop { #1 -sign } \prop_put:Nnn \l_@@_number_in_prop { #1 -integer } { 0 } \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal } \bool_if:NF \l_@@_process_int_to_dec_bool { \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal-marker } } } } \cs_new_protected:Npn \@@_number_process_figures_aux:n #1 { \@@_number_process_figures_init:n {#1} \@@_number_process_figures_count:n { integer } \@@_number_process_figures_count:n { decimal } \bool_if:NTF \l_@@_round_bool { \bool_set_false:N \l_@@_round_bool \int_compare:nNnTF \l_@@_round_int > \l_@@_process_precision_int { \@@_number_process_figures_round: \@@_number_process_round_tidy:n {#1} } { \@@_number_process_figures_pad:n {#1} } } { \prop_put:Nnn \l_@@_number_in_prop { #1 -integer } { 0 } \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal } } } \cs_new_protected:Npn \@@_number_process_figures_init:n #1 { \int_zero:N \l_@@_round_int \bool_set_false:N \l_@@_round_bool \bool_set_false:N \l_@@_round_even_bool \prop_get:NnNF \l_@@_number_in_prop { #1 -decimal } \l_@@_round_decimal_in_tl { \tl_clear:N \l_@@_round_decimal_in_tl } \prop_get:NnNF \l_@@_number_in_prop { #1 -integer } \l_@@_round_integer_in_tl { \tl_clear:N \l_@@_round_integer_in_tl } \tl_clear:N \l_@@_round_decimal_out_tl \tl_clear:N \l_@@_round_integer_out_tl \tl_clear:N \l_@@_round_discard_tl } % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\@@_number_process_figures_count:n} % \begin{macro}[aux]{\@@_number_process_figures_count_aux:n} % The counting code has to check that characters are actually % significant. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_figures_count:n #1 { \tl_if_empty:cF { l_@@_round_ #1 _in_tl } { \prop_if_in:NnF \l_@@_number_in_prop { #1 -uncertainty } { \@@_number_process_figures_count_aux:n {#1} } } } \cs_new_protected:Npn \@@_number_process_figures_count_aux:n #1 { \int_set:Nn \l_@@_tmp_int { \tl_head:v { l_@@_round_ #1 _in_tl } } \tl_set:cx { l_@@_round_ #1 _in_tl } { \tl_tail:v { l_@@_round_ #1 _in_tl } } \tl_put_left:cV { l_@@_round_ #1 _out_tl } \l_@@_tmp_int \bool_if:NF \l_@@_round_bool { \int_compare:nNnF { \l_@@_tmp_int } = \c_zero { \bool_set_true:N \l_@@_round_bool } } \bool_if:NT \l_@@_round_bool { \int_incr:N \l_@@_round_int } \tl_if_empty:cTF { l_@@_round_ #1 _in_tl } { \tl_set_eq:cc { l_@@_round_ #1 _in_tl } { l_@@_round_ #1 _out_tl } \tl_clear:c { l_@@_round_ #1 _out_tl } } { \@@_number_process_figures_count_aux:n {#1} } } % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\@@_number_process_figures_round:} % \begin{macro}[aux]{\@@_number_process_figures_round_loop:} % The control macro for rounding to figures does the decimal part % then the integer part as loops. There is then some tidying up if a % digit is carried at the end. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_figures_round: { \int_set:Nn \l_@@_round_int { \l_@@_round_int - \l_@@_process_precision_int } \tl_if_empty:NF \l_@@_round_decimal_in_tl { \@@_number_process_figures_round_loop: } \tl_if_empty:NF \l_@@_round_integer_in_tl { \@@_number_process_figures_integer: } \bool_if:NT \l_@@_round_bool { \tl_put_left:Nn \l_@@_round_integer_out_tl { 1 } } } \cs_new_protected:Npn \@@_number_process_figures_round_loop: { \@@_number_process_round_decimal: \tl_if_empty:NF \l_@@_round_decimal_in_tl { \@@_number_process_figures_round_loop: } } % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\@@_number_process_figures_integer:} % For figures, the integer part is a little complicated as zeros need % to be included. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_figures_integer: { \int_compare:nNnT \l_@@_round_int > \c_zero { \tl_put_left:Nn \l_@@_round_integer_out_tl { 0 } } \int_compare:nNnF \l_@@_round_int > \c_one { \int_set:Nn \l_@@_tmp_int { \tl_head:N \l_@@_round_integer_in_tl } \@@_number_process_round_up: \int_compare:nNnTF \l_@@_round_int = \c_one { \int_compare:nNnT \l_@@_tmp_int > \c_four { \bool_set_true:N \l_@@_round_bool } } { \int_compare:nNnT \l_@@_tmp_int = \c_ten { \bool_set_true:N \l_@@_round_bool \int_zero:N \l_@@_tmp_int } \tl_put_left:NV \l_@@_round_integer_out_tl \l_@@_tmp_int } } \int_decr:N \l_@@_round_int \tl_set:Nx \l_@@_round_integer_in_tl { \tl_tail:N \l_@@_round_integer_in_tl } \tl_if_empty:NF \l_@@_round_integer_in_tl { \@@_number_process_figures_integer: } } % \end{macrocode} %\end{macro} %\begin{macro}{\@@_number_process_figures_pad:n} % If the number is too short, then the reversal is undone and the % padding routine is called. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_figures_pad:n #1 { \prop_get:NnN \l_@@_number_in_prop { #1 -integer } \l_@@_round_integer_in_tl \prop_get:NnN \l_@@_number_in_prop { #1 -decimal } \l_@@_round_decimal_in_tl \int_set:Nn \l_@@_round_int { \l_@@_process_precision_int - \l_@@_round_int } \@@_number_process_pad:n {#1} } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_process_fixed:} %\begin{macro}[aux]{ % \@@_number_process_fixed_aux_i:nnn , % \@@_number_process_fixed_aux_ii:nnn , % \@@_number_process_fixed_aux_iii:nnn , % \@@_number_process_fixed_large:nnn , % \@@_number_process_fixed_large_aux:w , % \@@_number_process_fixed_small:nnn , % \@@_number_process_fixed_small_aux:w %} % When working to a fixed exponent value, the idea is to use the stack % to do the work. First, there is some set up to do. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_fixed: { \prop_if_in:NnF \l_@@_number_in_prop { complex } { \prop_get:NnNF \l_@@_number_in_prop { mantissa-integer } \l_@@_tmpa_tl { \tl_set:Nn \l_@@_tmpa_tl { 0 } } \prop_get:NnNF \l_@@_number_in_prop { mantissa-decimal } \l_@@_tmpb_tl { \tl_clear:N \l_@@_tmpb_tl } \tl_set:Nx \l_@@_tmpa_tl { { \l_@@_tmpa_tl } { \l_@@_tmpb_tl } } \prop_get:NnNF \l_@@_number_in_prop { exponent-integer } \l_@@_tmpb_tl { \tl_set:Nn \l_@@_tmpb_tl { 0 } } \group_begin: \prop_get:NnNT \l_@@_number_in_prop { exponent-sign } \l_@@_tmpa_tl { \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpa_tl } \exp_args:NNNV \group_end: \tl_set:Nn \l_@@_tmpb_tl \l_@@_tmpb_tl \tl_set:Nx \l_@@_tmpa_tl { \l_@@_tmpa_tl { \l_@@_tmpb_tl } } \exp_after:wN \@@_number_process_fixed_aux_i:nnn \l_@@_tmpa_tl } } % \end{macrocode} % The main loop checks to see which way to adjust the exponent then % does the work. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_fixed_aux_i:nnn #1#2#3 { \prop_put:Nnn \l_@@_number_in_prop { exponent } { true } \int_compare:nNnTF { \l_@@_process_fixed_int } > { \c_zero } { \prop_put:NnV \l_@@_number_in_prop { exponent-integer } \l_@@_process_fixed_int \prop_remove:Nn \l_@@_number_in_prop { exponent-sign } } { \prop_put:Nnx \l_@@_number_in_prop { exponent-integer } { \int_eval:n { - \l_@@_process_fixed_int } } \prop_put:Nnn \l_@@_number_in_prop { exponent-sign } { - } } \@@_number_process_fixed_aux_ii:nnn {#1} {#2} {#3} } \cs_new_protected:Npn \@@_number_process_fixed_aux_ii:nnn #1#2#3 { \bool_set_true:N \l_@@_tmp_bool \tl_map_inline:nn {#1#2} { \str_if_eq:nnF {##1} { 0 } { \bool_set_false:N \l_@@_tmp_bool \tl_map_break: } } \bool_if:NF \l_@@_tmp_bool { \@@_number_process_fixed_aux_iii:nnn {#1} {#2} {#3} } } \cs_new_protected:Npn \@@_number_process_fixed_aux_iii:nnn #1#2#3 { \int_compare:nNnTF {#3} > { \l_@@_process_fixed_int } { \@@_number_process_fixed_large:nnn {#1} {#2} {#3} } { \int_compare:nNnTF {#3} < { \l_@@_process_fixed_int } { \@@_number_process_fixed_small:nnn {#1} {#2} {#3} } { \prop_put:Nnn \l_@@_number_in_prop { mantissa-integer } {#1} \tl_if_empty:nTF {#2} { \prop_remove:Nn \l_@@_number_in_prop { mantissa-decimal } \prop_remove:Nn \l_@@_number_in_prop { mantissa-decimal-marker } } { \prop_put:Nnn \l_@@_number_in_prop { mantissa-decimal } {#2} \prop_if_in:NnF \l_@@_number_in_prop { mantissa-decimal-marker } { \prop_put:Nnn \l_@@_number_in_prop { mantissa-decimal-marker } { . } } } } } } % \end{macrocode} % Simple stack-based manipulation of the input for number which are % either too big or too small. There are a couple of checks needed to % deal with cases where there is no decimal part and where there are % leading zeros to dispose of. There is also a check to avoid adding % an additional zero to the decimal part of the number. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_fixed_large:nnn #1 { \int_compare:nNnTF {#1} = \c_zero { \@@_number_process_fixed_large_aux:nnn { } } { \@@_number_process_fixed_large_aux:nnn {#1} } } \cs_new_protected:Npn \@@_number_process_fixed_large_aux:nnn #1#2#3 { \cs_set_protected:Npn \@@_number_process_fixed_large_aux:w ##1##2 \q_stop { \tl_if_empty:nTF {##2} { \int_compare:nNnTF { #3 - 1 } = { \l_@@_process_fixed_int } { \@@_number_process_fixed_aux_ii:nnn { #1 ##1 } { } { #3 - 1 } } { \@@_number_process_fixed_aux_ii:nnn { #1 ##1 } { 0 } { #3 - 1 } } } { \int_compare:nNnTF { 0 #1 } = { 0 } { \@@_number_process_fixed_aux_ii:nnn {##1} {##2} { #3 - 1 } } { \@@_number_process_fixed_aux_ii:nnn { #1 ##1 } {##2} { #3 - 1 } } } } \tl_if_empty:nTF {#2} { \@@_number_process_fixed_aux_ii:nnn { #1 0 } { } { #3 - 1 } } { \@@_number_process_fixed_large_aux:w #2 \q_stop } } \cs_new_protected:Npn \@@_number_process_fixed_large_aux:w { } \cs_new_protected:Npn \@@_number_process_fixed_small:nnn #1#2#3 { \cs_set_protected:Npn \@@_number_process_fixed_small_aux:w ##1##2 \q_stop ##3 { \tl_if_empty:nTF {##2} { \tl_if_empty:nTF {##3} { \@@_number_process_fixed_aux_ii:nnn { 0 } { ##1 #2 } { #3 + 1 } } { \@@_number_process_fixed_aux_ii:nnn {##3} { ##1 #2 } { #3 + 1 } } } { \@@_number_process_fixed_small_aux:w ##2 \q_stop { ##3 ##1 } } } \@@_number_process_fixed_small_aux:w #1 \q_stop { } } \cs_new_protected:Npn \@@_number_process_fixed_small_aux:w { } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_process_integer_digits:} % Producing extra digits for the integer part is a simple process % once the target is known. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_integer_digits: { \int_compare:nNnT { \l_@@_process_integer_min_int } > { \c_zero } { \prop_get:NnNT \l_@@_number_in_prop { mantissa-integer } \l_@@_tmpa_tl { \int_set:Nn \l_@@_tmp_int { \l_@@_process_integer_min_int - \tl_count:N \l_@@_tmpa_tl } \int_compare:nNnT { \l_@@_tmp_int } > { \c_zero } { \tl_set:Nx \l_@@_tmpa_tl { \prg_replicate:nn { \l_@@_tmp_int } { 0 } \exp_not:V \l_@@_tmpa_tl } \prop_put:NnV \l_@@_number_in_prop { mantissa-integer } \l_@@_tmpa_tl } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_process_mantissa:} %\begin{macro}{\c_@@_unity_tl} % A check for the mantissa consisting only of the token \texttt{1}, when % an exponent is also available. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_mantissa: { \bool_if:NF \l_@@_process_unity_mantissa_bool { \prop_if_in:NnT \l_@@_number_in_prop { exponent } { \prop_get:NnNT \l_@@_number_in_prop { mantissa-integer } \l_@@_tmpa_tl { \tl_if_eq:NNT \c_@@_unity_tl \l_@@_tmpa_tl { \prop_if_in:NnF \l_@@_number_in_prop { mantissa-decimal-marker } { \prop_remove:Nn \l_@@_number_in_prop { mantissa } \prop_remove:Nn \l_@@_number_in_prop { mantissa-integer } } } } } } } \tl_new:N \c_@@_unity_tl \tl_set:Nn \c_@@_unity_tl { 1 } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_process_pad:n} % For padding a number by adding zero to the end repeatedly. This can % happen if the input was zero or if the number is too short. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_pad:n #1 { \prop_get:NnNT \l_@@_number_in_prop { #1 -decimal } \l_@@_tmpa_tl { \int_while_do:nNnn { \l_@@_round_int } > { 0 } { \tl_put_right:Nn \l_@@_tmpa_tl { 0 } \int_decr:N \l_@@_round_int } \prop_put:NnV \l_@@_number_in_prop { #1 -decimal } \l_@@_tmpa_tl } } % \end{macrocode} %\end{macro} % % \begin{macro}{\@@_number_process_places:n} % \begin{macro}[aux] % { % \@@_number_process_places_init:n , % \@@_number_process_places_aux_i:n , % \@@_number_process_places_aux_i:TF , % \@@_number_process_places_none: , % \@@_number_process_places_aux_ii:n , % \@@_number_process_places_loop:n , % \@@_number_process_places_integer:n % } % For rounding to a fixed number of places, a check is made to see if % the decimal part is exactly zero. If it is, just create the % appropriate number of zeros in the padding routine. Otherwise, do the % real work. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_places:n #1 { \prop_if_in:NnT \l_@@_number_in_prop {#1} { \prop_if_in:NnF \l_@@_number_in_prop { #1 -uncertainty } { \@@_number_process_places_aux_i:n {#1} } } } \cs_new_protected:Npn \@@_number_process_places_aux_i:n #1 { \int_compare:nNnTF \l_@@_process_precision_int = \c_zero { \@@_number_process_places_none:n {#1} } { \prop_get:NnNT \l_@@_number_in_prop { #1 -decimal } \l_@@_tmpa_tl { \tl_if_empty:NT \l_@@_tmpa_tl { \tl_set:Nn \l_@@_tmpa_tl { 0 } } \@@_number_process_places_aux_i:TF { \prop_put:Nnn \l_@@_number_in_prop { #1 -decimal } { } \int_set:Nn \l_@@_round_int { \l_@@_process_precision_int } \@@_number_process_pad:n {#1} } { \int_set:Nn \l_@@_round_int { \tl_count:N \l_@@_tmpa_tl } \@@_number_process_places_aux_ii:n {#1} } } } } % \end{macrocode} % The number of digits in the decimal part could be more that \TeX{} can % handle, so a slow loop is used to see if we need to round. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_places_aux_i:TF { \bool_set_true:N \l_@@_tmp_bool \tl_map_inline:Nn \l_@@_tmpa_tl { \int_compare:nNnF {##1} = \c_zero { \bool_set_false:N \l_@@_tmp_bool \tl_map_break: } } \bool_if:NTF \l_@@_tmp_bool } % \end{macrocode} % Rounding to no places at all requires a few checks to see if there is any % work to do. That includes a check for rounding half to even, where if % the decimal part is exactly half then special action is required. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_places_none:n #1 { \prop_get:NnNT \l_@@_number_in_prop { #1 -decimal } \l_@@_tmpa_tl { \int_compare:nNnTF { \tl_head:N \l_@@_tmpa_tl } > \c_four { \prop_get:NnNTF \l_@@_number_in_prop { #1 -integer } \l_@@_tmpb_tl { \tl_set:Nx \l_@@_tmpb_tl { \int_eval:n { \l_@@_tmpb_tl + 1 } } \bool_if:NF \l_@@_round_half_up_bool { \int_compare:nNnT { 0 \tl_tail:N \l_@@_tmpa_tl } = \c_zero { \int_if_odd:nT \l_@@_tmpb_tl { \tl_set:Nx \l_@@_tmpb_tl { \int_eval:n { \l_@@_tmpb_tl - 1 } } } } } } { \tl_set:Nn \l_@@_tmpb_tl { 1 } } \prop_put:NnV \l_@@_number_in_prop { #1 -integer } \l_@@_tmpb_tl } { \prop_if_in:NnF \l_@@_number_in_prop { #1 -integer } { \prop_put:Nnn \l_@@_number_in_prop { #1 -integer } { 0 } } } } \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal } \bool_if:NF \l_@@_process_int_to_dec_bool { \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal-marker } } } % \end{macrocode} % For rounding to a fixed number of places, the package finds the % difference in length between what is present and what is required. % If the number is too short, there is some simple padding to do. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_places_aux_ii:n #1 { \int_sub:Nn \l_@@_round_int { \l_@@_process_precision_int } \int_compare:nNnTF \l_@@_round_int < \c_zero { \int_set:Nn \l_@@_round_int { - \l_@@_round_int } \@@_number_process_pad:n {#1} } { \@@_number_process_places_init:n {#1} \@@_number_process_places_loop:n {#1} \@@_number_process_round_tidy:n {#1} } } % \end{macrocode} % To keep the code a little clearer. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_places_init:n #1 { \prop_get:NnNF \l_@@_number_in_prop { #1 -integer } \l_@@_round_integer_in_tl { \tl_clear:N \l_@@_round_integer_in_tl } \prop_get:NnN \l_@@_number_in_prop { #1 -decimal } \l_@@_round_decimal_in_tl \tl_reverse:N \l_@@_round_integer_in_tl \tl_reverse:N \l_@@_round_decimal_in_tl \tl_clear:N \l_@@_round_integer_out_tl \tl_clear:N \l_@@_round_decimal_out_tl \tl_clear:N \l_@@_round_discard_tl \bool_set_false:N \l_@@_round_bool \bool_set_false:N \l_@@_round_even_bool } % \end{macrocode} % If there is a decimal, do the decimal processing then come back here. % If there is an integer, do the same. Only if both are empty does the % loop stop. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_places_loop:n #1 { \tl_if_empty:NTF \l_@@_round_decimal_in_tl { \tl_if_empty:NF \l_@@_round_integer_in_tl { \@@_number_process_places_integer:n {#1} \@@_number_process_places_loop:n {#1} } \bool_if:NT \l_@@_round_bool { \tl_put_left:Nn \l_@@_round_integer_out_tl { 1 } \bool_set_false:N \l_@@_round_bool } } { \@@_number_process_round_decimal: \@@_number_process_places_loop:n {#1} } } % \end{macrocode} % Rounding for integers is just a case of carrying digits. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_places_integer:n #1 { \int_set:Nn \l_@@_tmp_int { \tl_head:N \l_@@_round_integer_in_tl } \tl_set:Nx \l_@@_round_integer_in_tl { \tl_tail:N \l_@@_round_integer_in_tl } \@@_number_process_round_up: \bool_set_false:N \l_@@_round_bool \int_compare:nNnT \l_@@_tmp_int = \c_ten { \int_zero:N \l_@@_tmp_int \bool_set_true:N \l_@@_round_bool } \tl_put_left:NV \l_@@_round_integer_out_tl \l_@@_tmp_int } % \end{macrocode} %\end{macro} %\end{macro} % % \begin{macro}{\@@_number_process_round:} % The lead-off for rounding is the same for decimal places and % significant figures. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_round: { \tl_if_empty:NF \l_@@_round_tl { \bool_if:NT \l_@@_process_int_to_dec_bool { \prop_if_in:NnF \l_@@_number_in_prop { mantissa-decimal } { \prop_put:Nnn \l_@@_number_in_prop { mantissa-decimal } { 0 } } \prop_if_in:NnF \l_@@_number_in_prop { mantissa-decimal-marker } { \prop_put:Nnn \l_@@_number_in_prop { mantissa-decimal-marker } { . } } } \clist_map_function:nc { mantissa , complex } { @@_number_process_ \l_@@_round_tl :n } } } % \end{macrocode} % \end{macro} % \begin{macro}{\@@_number_process_round_decimal:} % \begin{macro}[aux]{\@@_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_protected:Npn \@@_number_process_round_decimal: { \int_compare:nNnF \l_@@_round_int > \c_one { \@@_number_process_round_decimal_aux: } \tl_put_right:Nx \l_@@_round_discard_tl { \tl_head:N \l_@@_round_decimal_in_tl } \tl_set:Nx \l_@@_round_decimal_in_tl { \tl_tail:N \l_@@_round_decimal_in_tl } \int_decr:N \l_@@_round_int } % \end{macrocode} % The logic here has to deal with the (simpler) rounding up method and the % case where there is a need to check for rounding to an even number. The % later is only required when the discarded part is exactly equal to % half of the least-significant digit. So there is a somewhat complex check % for that, along with a somewhat simpler check when carrying out the % rounding. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_round_decimal_aux: { \int_set:Nn \l_@@_tmp_int { \tl_head:N \l_@@_round_decimal_in_tl } \@@_number_process_round_up: \int_compare:nNnTF \l_@@_round_int = \c_one { \int_compare:nNnT \l_@@_tmp_int > \c_four { \bool_set_true:N \l_@@_round_bool \bool_if:NF \l_@@_round_half_up_bool { \int_compare:nNnT { \l_@@_round_discard_tl \int_use:N \l_@@_tmp_int } = \c_five { \bool_set_true:N \l_@@_round_even_bool } } } } { \int_compare:nNnT \l_@@_tmp_int = \c_ten { \bool_set_true:N \l_@@_round_bool \int_zero:N \l_@@_tmp_int } \tl_put_left:NV \l_@@_round_decimal_out_tl \l_@@_tmp_int } } % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\@@_number_process_round_up:} % This is needed a few times, to round up the current digit unless % it is even and \enquote{half to even} is active. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_round_up: { \bool_if:NT \l_@@_round_bool { \bool_if:NTF \l_@@_round_even_bool { \bool_set_false:N \l_@@_round_even_bool \int_if_even:nF \l_@@_tmp_int { \int_incr:N \l_@@_tmp_int } } { \int_incr:N \l_@@_tmp_int } } \bool_set_false:N \l_@@_round_bool } % \end{macrocode} % \end{macro} % \begin{macro}{\@@_number_process_round_tidy:n} % \begin{macro}[aux]{\@@_number_process_round_tidy_aux:w} % To put data back again: there is a check to see if the number has been % r ounded to zero and a minimal value has been requested. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_round_tidy:n #1 { \int_compare:nNnTF { 0 \l_@@_round_integer_out_tl + 0 \l_@@_round_decimal_out_tl } = \c_zero { \str_if_eq:VnTF \l_@@_process_round_min_tl { 0 } { \prop_put:Nnn \l_@@_number_in_prop { #1 -integer } { 0 } \prop_put:NnV \l_@@_number_in_prop { #1 -decimal } \l_@@_round_decimal_out_tl } { \exp_after:wN \@@_number_process_round_tidy_aux:w \l_@@_process_round_min_tl . . \q_stop {#1} } } { \prop_put:NnV \l_@@_number_in_prop { #1 -integer } \l_@@_round_integer_out_tl \tl_if_empty:NTF \l_@@_round_decimal_out_tl { \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal } \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal-marker } } { \prop_put:NnV \l_@@_number_in_prop { #1 -decimal } \l_@@_round_decimal_out_tl } } } \cs_new_protected:Npn \@@_number_process_round_tidy_aux:w #1 . #2 . #3 \q_stop #4 { \prop_put:Nnn \l_@@_number_in_prop { comparator } { < } \prop_put:Nnn \l_@@_number_in_prop { #4 -integer } {#1} \tl_if_empty:nTF {#2} { \prop_remove:Nn \l_@@_number_in_prop { #4 -decimal } } { \prop_put:Nnn \l_@@_number_in_prop { #4 -decimal } {#2} } } % \end{macrocode} % \end{macro} % \end{macro} % %\begin{macro}{\@@_number_process_scientific:} %\begin{macro}[aux]{ % \@@_number_process_scientific_aux_i:nnn , % \@@_number_process_scientific_aux_ii:nnn , % \@@_number_process_scientific_large:nnn , % \@@_number_process_scientific_small:wn , % \@@_number_process_scientific_store:nnn , % \@@_number_process_scientific_engineering:nnn , % \@@_number_process_scientific_engineering_0:nnn , % \@@_number_process_scientific_engineering_1:nnn , % \@@_number_process_scientific_engineering_1:nw , % \@@_number_process_scientific_engineering_2:nnn , % \@@_number_process_scientific_engineering_2_i:nw , % \@@_number_process_scientific_engineering_2_ii:nw %} % Converting a number to scientific form is done such that the number % of places involved is unchanged. The first step is to skip any % complex-number containing input and to recover the stored data. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_scientific: { \prop_if_in:NnF \l_@@_number_in_prop { complex } { \prop_get:NnNF \l_@@_number_in_prop { mantissa-integer } \l_@@_tmpa_tl { \tl_set:Nn \l_@@_tmpa_tl { 0 } } \prop_get:NnNF \l_@@_number_in_prop { mantissa-decimal } \l_@@_tmpb_tl { \tl_clear:N \l_@@_tmpb_tl } \tl_set:Nx \l_@@_tmpa_tl { { \l_@@_tmpa_tl } { \l_@@_tmpb_tl } } \prop_get:NnNF \l_@@_number_in_prop { exponent-integer } \l_@@_tmpb_tl { \tl_set:Nn \l_@@_tmpb_tl { 0 } } \group_begin: \prop_get:NnNT \l_@@_number_in_prop { exponent-sign } \l_@@_tmpa_tl { \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpa_tl } \exp_args:NNNV \group_end: \tl_set:Nn \l_@@_tmpb_tl \l_@@_tmpb_tl \tl_set:Nx \l_@@_tmpa_tl { \l_@@_tmpa_tl { \l_@@_tmpb_tl } } \exp_after:wN \@@_number_process_scientific_aux_i:nnn \l_@@_tmpa_tl } } \cs_new_protected:Npn \@@_number_process_scientific_aux_i:nnn #1#2#3 { \bool_set_true:N \l_@@_tmp_bool \tl_map_inline:nn {#1#2} { \str_if_eq:nnF {##1} { 0 } { \bool_set_false:N \l_@@_tmp_bool \tl_map_break: } } \bool_if:NF \l_@@_tmp_bool { \@@_number_process_scientific_aux_ii:nnn {#1} {#2} {#3} } } % \end{macrocode} % The code here works on a loop, standardising the mantissa into the % range \( 1 \le x < 10 \). % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_scientific_aux_ii:nnn #1#2#3 { \int_compare:nNnTF {#1} > { 9 } { \@@_number_process_scientific_large:nnn {#1} {#2} {#3} } { \int_compare:nNnTF {#1} > { 0 } { \bool_if:NTF \l_@@_process_engineering_bool { \@@_number_process_scientific_engineering:nnn } { \@@_number_process_scientific_store:nnn } {#1} {#2} {#3} } { \@@_number_process_scientific_small:wn #2 \q_stop {#3} } } } % \end{macrocode} % The fastest way to find the smallest digit of the integer part is % using some mathematics. This does limit the range of the input, but % in real cases this should not be an issue. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_scientific_large:nnn #1#2#3 { \int_set:Nn \l_@@_tmp_int { \int_div_truncate:nn {#1} { 10 } } \tl_set:Nx \l_@@_tmpa_tl { \int_use:N \l_@@_tmp_int } \int_set:Nn \l_@@_tmp_int { #1 - 10 * \l_@@_tmp_int } \tl_set:Nx \l_@@_tmpa_tl { { \l_@@_tmpa_tl } { \int_use:N \l_@@_tmp_int #2 } { #3 + 1 } } \exp_after:wN \@@_number_process_scientific_aux_ii:nnn \l_@@_tmpa_tl } % \end{macrocode} % For small numbers, the important digit is easy to find. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_scientific_small:wn #1#2 \q_stop #3 { \@@_number_process_scientific_aux_ii:nnn {#1} {#2} { #3 - 1 } } % \end{macrocode} % A tidy-up and store routine. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_scientific_store:nnn #1#2#3 { \prop_put:Nnn \l_@@_number_in_prop { mantissa-integer } {#1} \tl_if_empty:nTF {#2} { \prop_remove:Nn \l_@@_number_in_prop { mantissa-decimal } \prop_remove:Nn \l_@@_number_in_prop { mantissa-decimal-marker } } { \prop_put:Nnn \l_@@_number_in_prop { mantissa-decimal } {#2} \prop_if_in:NnF \l_@@_number_in_prop { mantissa-decimal-marker } { \prop_put:Nnn \l_@@_number_in_prop { mantissa-decimal-marker } { . } } } \int_compare:nNnTF {#3} = { 0 } { \prop_remove:Nn \l_@@_number_in_prop { exponent } \prop_remove:Nn \l_@@_number_in_prop { exponent-sign } \prop_remove:Nn \l_@@_number_in_prop { exponent-integer } } { \prop_put:Nnn \l_@@_number_in_prop { exponent } { true } \int_compare:nNnTF {#3} > { 0 } { \int_set:Nn \l_@@_tmp_int {#3} \prop_put:NnV \l_@@_number_in_prop { exponent-integer } \l_@@_tmp_int \prop_remove:Nn \l_@@_number_in_prop { exponent-sign } } { \int_set:Nn \l_@@_tmp_int { 0 - (#3) } \prop_put:NnV \l_@@_number_in_prop { exponent-integer } \l_@@_tmp_int \prop_put:Nnn \l_@@_number_in_prop { exponent-sign } { - } } } } % \end{macrocode} % For engineering style, the exponent has to be a power of three. % The fastest way to do this is by expansion, as the number of tokens % is known. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_scientific_engineering:nnn #1#2#3 { \use:c { @@_number_process_scientific_engineering_ \int_compare:nNnTF {#3} < { 0 } { \int_case:nnn { \int_mod:nn { 0 - (#3) } { 3 } } { { 1 } { 2 } { 2 } { 1 } } { 0 } } { \int_mod:nn {#3} { 3 } } :nnn } {#1} {#2} {#3} } \cs_new_eq:cN { @@_number_process_scientific_engineering_0:nnn } \@@_number_process_scientific_store:nnn \cs_new_protected:cpn { @@_number_process_scientific_engineering_1:nnn } #1#2#3 { \tl_if_empty:nTF {#2} { \@@_number_process_scientific_store:nnn { #1 0 } { } { #3 - 1 } } { \use:c { @@_number_process_scientific_engineering_1:nw } {#1} #2 \q_stop {#3} } } \cs_new_protected:cpn { @@_number_process_scientific_engineering_1:nw } #1#2#3 \q_stop #4 { \@@_number_process_scientific_store:nnn {#1#2} {#3} { #4 - 1 } } \cs_new_protected:cpn { @@_number_process_scientific_engineering_2:nnn } #1#2#3 { \tl_if_empty:nTF {#2} { \@@_number_process_scientific_store:nnn { #1 00 } { } { #3 - 2 } } { \use:c { @@_number_process_scientific_engineering_2_i:nw } {#1} #2 \q_stop {#3} } } \cs_new_protected:cpn { @@_number_process_scientific_engineering_2_i:nw } #1#2#3 \q_stop #4 { \tl_if_empty:nTF {#3} { \@@_number_process_scientific_store:nnn { #1#2 0 } { } { #4 - 2 } } { \use:c { @@_number_process_scientific_engineering_2_ii:nw } {#1#2} #3 \q_stop {#4} } } \cs_new_protected:cpn { @@_number_process_scientific_engineering_2_ii:nw } #1#2#3 \q_stop #4 { \@@_number_process_scientific_store:nnn { #1#2 } {#3} { #4 - 2 } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_process_sign:} %\begin{macro}[aux]{ % \@@_number_process_sign_add:n , % \@@_number_process_sign_plus:n %} %\begin{macro}{\c_@@_plus_tl} % Sorting out signs consists of two parts: retaining a plus if necessary % and adding an explicit sign. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_sign: { \bool_if:NF \l_@@_process_plus_bool { \prop_if_in:NnTF \l_@@_number_in_prop { mantissa-sign } { \@@_number_process_sign_plus:n { mantissa } } { \prop_if_in:NnT \l_@@_number_in_prop { complex-sign } { \prop_if_in:NnF \l_@@_number_in_prop { mantissa } { \@@_number_process_sign_plus:n { complex } } } } \prop_if_in:NnT \l_@@_number_in_prop { exponent-sign } { \@@_number_process_sign_plus:n { exponent } } } \tl_if_empty:NF \l_@@_process_sign_tl { \@@_number_process_sign_add:n { mantissa } \prop_if_in:NnTF \l_@@_number_in_prop { complex } { \@@_number_process_sign_add:n { complex } } } } % \end{macrocode} % Adding a sign to an existing number needs a couple of to make sure % there is a number to add to, and to see if there is a sign already. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_sign_add:n #1 { \prop_if_in:NnF \l_@@_number_in_prop { #1 -sign } { \prop_if_in:NnF \l_@@_number_in_prop { #1 -had-sign } { \prop_get:NnN \l_@@_number_in_prop {#1} \l_@@_tmpa_tl \tl_if_empty:NTF \l_@@_tmpa_tl { \prop_put:NnV \l_@@_number_in_prop { sign } \l_@@_process_sign_tl } { \prop_put:NnV \l_@@_number_in_prop { #1 -sign } \l_@@_process_sign_tl } } } } % \end{macrocode} % Holding onto a plus works very much in the same way as adding a sign: % some quick tests and an assignment. Using a pre-defined token list is % a speed-related choice: very slightly faster comparison. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_sign_plus:n #1 { \prop_get:NnN \l_@@_number_in_prop { #1 -sign } \l_@@_tmpa_tl \tl_if_eq:NNT \c_@@_plus_tl \l_@@_tmpa_tl { \prop_remove:Nn \l_@@_number_in_prop { #1 -sign } \prop_put:Nnn \l_@@_number_in_prop { #1 -had-sign } { true } } } \tl_new:N \c_@@_plus_tl \tl_set:Nn \c_@@_plus_tl { + } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_process_uncertainty:} %\begin{macro}[aux]{\@@_number_process_uncertainty_aux:n} % There may be a need to expand uncertainties into a decimal and integer % part. This is done here so that the core \texttt{in} code is faster. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_uncertainty: { \clist_map_function:nN { mantissa , complex } \@@_number_process_uncertainty_aux:n } \cs_new_protected:Npn \@@_number_process_uncertainty_aux:n #1 { \prop_if_in:NnT \l_@@_number_in_prop { #1 -uncertainty } { \prop_if_in:NnTF \l_@@_number_in_prop { #1 -decimal-marker } { \@@_number_process_uncertainty_decimal:n {#1} } { \@@_number_process_uncertainty_integer:n {#1} } } } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\@@_number_process_uncertainty_decimal:n} %\begin{macro}[aux]{\@@_number_process_uncertainty_count:nn} % To deal with an error in the decimal part, care needs to be taken to % correctly pad with zeros and also to allow for the possibility that % the error crosses the decimal--integer boundary. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_uncertainty_decimal:n #1 { \@@_number_process_uncertainty_count:nn {#1} { decimal } \@@_number_process_uncertainty_count:nn {#1} { uncertainty } \tl_clear:N \l_@@_uncertainty_decimal_tl \tl_clear:N \l_@@_uncertainty_integer_tl \int_compare:nNnTF { \l_@@_process_uncertainty_int } > { \l_@@_process_decimal_int } { \@@_number_process_uncertainty_separate: } { \@@_number_process_uncertainty_pad: } \tl_if_empty:NF \l_@@_uncertainty_integer_tl { \prop_put:NnV \l_@@_number_in_prop { #1 -uncertainty-integer } \l_@@_uncertainty_integer_tl } \prop_put:NnV \l_@@_number_in_prop { #1 -uncertainty-decimal } \l_@@_uncertainty_decimal_tl \prop_get:NnN \l_@@_number_in_prop { #1 -decimal-marker } \l_@@_tmpa_tl \prop_put:NnV \l_@@_number_in_prop { #1 -uncertainty-decimal-marker } \l_@@_tmpa_tl } \cs_new_protected:Npn \@@_number_process_uncertainty_count:nn #1#2 { \prop_get:NnN \l_@@_number_in_prop { #1 - #2 } \l_@@_tmpa_tl \int_set:cn { l_@@_process_ #2 _int } { \tl_count:N \l_@@_tmpa_tl } } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\@@_number_process_uncertainty_pad:} % Uncertainty is short: add zeros. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_uncertainty_pad: { \int_while_do:nNnn { \l_@@_process_uncertainty_int } < { \l_@@_process_decimal_int } { \tl_put_right:Nn \l_@@_uncertainty_decimal_tl {0} \int_incr:N \l_@@_process_uncertainty_int } \tl_put_right:NV \l_@@_uncertainty_decimal_tl \l_@@_tmpa_tl } % \end{macrocode} %\end{macro} %\begin{macro}{\@@_number_process_uncertainty_separate:} %\begin{macro}[aux]{\@@_number_process_uncertainty_separate_aux:N} % Find the integer--decimal boundary and work appropriately. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_uncertainty_separate: { \tl_map_function:NN \l_@@_tmpa_tl \@@_number_process_uncertainty_separate_aux:N } \cs_new_protected:Npn \@@_number_process_uncertainty_separate_aux:N #1 { \int_compare:nNnTF { \l_@@_process_uncertainty_int } > { \l_@@_process_decimal_int } { \tl_put_right:Nn \l_@@_uncertainty_integer_tl {#1} } { \tl_put_right:Nn \l_@@_uncertainty_decimal_tl {#1} } \int_decr:N \l_@@_process_uncertainty_int } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\@@_number_process_uncertainty_integer:n} % Relatively easy: the uncertainty is in the integer part of the number, % and so there is no need to generate zeros. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_uncertainty_integer:n #1 { \prop_get:NnN \l_@@_number_in_prop { #1 -uncertainty } \l_@@_tmpa_tl \prop_put:NnV \l_@@_number_in_prop { #1 -uncertainty-integer } \l_@@_tmpa_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_process_zero_fill:} %\begin{macro}[aux]{ % \@@_number_process_zero_fill_aux:n , % \@@_number_process_zero_fill_aux:nn %} % Checks for adding zeros to each component are carried out. The nesting % here makes checking the appropriate flag a little more efficient. % \begin{macrocode} \cs_new_protected:Npn \@@_number_process_zero_fill: { \@@_number_process_zero_fill_aux:n { integer } \@@_number_process_zero_fill_aux:n { decimal } } \cs_new:Npn \@@_number_process_zero_fill_aux:n #1 { \bool_if:cT { l_@@_process_ #1 _zero_bool } { \@@_number_process_zero_fill_aux:nn { mantissa } {#1} \@@_number_process_zero_fill_aux:nn { complex } {#1} \@@_number_process_zero_fill_aux:nn { exponent } {#1} } } \cs_new_protected:Npn \@@_number_process_zero_fill_aux:nn #1#2 { \prop_if_in:NnT \l_@@_number_in_prop { #1 -decimal-marker } { \prop_if_in:NnF \l_@@_number_in_prop { #1 - #2 } { \prop_put:Nnn \l_@@_number_in_prop { #1 - #2 } { 0 } } } } % \end{macrocode} %\end{macro} %\end{macro} % % \begin{macro}{\@@_number_process_zero_to_integer:} % \begin{macro}[aux]{\@@_number_process_zero_to_integer_aux:n} % Look for a decimal part which is simply zero, and if found delete it. % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_number_process_zero_to_integer: { \bool_if:NT \l_@@_zero_decimal_to_integer_bool { \@@_number_process_zero_to_integer_aux:n { mantissa } \@@_number_process_zero_to_integer_aux:n { complex } } } \cs_new_protected:Npn \@@_number_process_zero_to_integer_aux:n #1 { \prop_get:NnNT \l_@@_number_in_prop { #1 -decimal } \l_@@_tmpa_tl { \bool_set_true:N \l_@@_tmp_bool \tl_map_inline:Nn \l_@@_tmpa_tl { \str_if_eq:nnF {##1} { 0 } { \bool_set_false:N \l_@@_tmp_bool \tl_map_break: } } \bool_if:NT \l_@@_tmp_bool { \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal } \prop_remove:Nn \l_@@_number_in_prop { #1 -decimal-marker } } } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@@_number_exp_to_prefix:} % This function is a bit awkward, as it essentially cuts across the % unit processor. The idea here is first to recover the numerical exponent, % and sign if there is one. % \begin{macrocode} \cs_new_protected:Npn \@@_number_exp_to_prefix: { \prop_set_eq:NN \l_@@_unit_prop \l_@@_unit_saved_prop \prop_get:NnNT \l_@@_number_in_prop { exponent-integer } \l_@@_tmpa_tl { \prop_get:NnNT \l_@@_number_in_prop { exponent-sign } \l_@@_tmpb_tl { \tl_put_left:NV \l_@@_tmpa_tl \l_@@_tmpb_tl } \prop_get:NnNT \l_@@_unit_prop { prefix-1 } \l_@@_tmpb_tl { \prop_remove:Nn \l_@@_unit_prop { prefix-1 } \prop_remove:Nn \l_@@_unit_prop { prefix-symbol-1 } \prop_get:NVN \l_@@_prefix_forward_prop \l_@@_tmpb_tl \l_@@_tmpb_tl \tl_set:Nx \l_@@_tmpa_tl { \int_eval:n { \l_@@_tmpa_tl + \l_@@_tmpb_tl } } } \prop_get:NVNTF \l_@@_prefix_reverse_prop \l_@@_tmpa_tl \l_@@_tmpb_tl { \prop_remove:Nn \l_@@_number_in_prop { exponent } \use:c { @@_ \exp_after:wN \token_to_str:N \l_@@_tmpb_tl _function:w } \@@_unit_format: } { \msg_error:nnx { siunitx } { non-convertible-exponent } { \l_@@_tmpa_tl } } } } % \end{macrocode} % \end{macro} % %\subsection{Formatting numbers for output} % % Getting numbers ready for printing requires the reconstruction of the % number from the various parts processed earlier. Spaces and brackets % are added back into the main numbers, as the various parts are also % correctly formatted. The difference between the \texttt{in} and % \texttt{out} store is that the later can include formatting such as % hard spaces. % %\begin{macro}{\l_@@_number_out_prop} % Like the \texttt{in} version! % \begin{macrocode} \prop_new:N \l_@@_number_out_prop % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_group_sep_tl , % \l_@@_output_decimal_tl %} % A couple of variables are declared here, as they need a little more % work than just storage. % \begin{macrocode} \tl_new:N \l_@@_group_sep_tl \tl_new:N \l_@@_output_decimal_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_complex_after_bool} % A setting for where complex numbers go. % \begin{macrocode} \bool_new:N \l_@@_complex_after_bool % \end{macrocode} %\end{macro} % % \begin{variable} % {\l_@@_group_decimal_bool, \l_@@_group_integer_bool} % Used for grouping digits. % \begin{macrocode} \bool_new:N \l_@@_group_decimal_bool \bool_new:N \l_@@_group_integer_bool % \end{macrocode} % \end{variable} % %\begin{macro}{ % \l_@@_negative_bracket_bool , % \l_@@_brackets_bool , % \l_@@_bracket_close_tl , % \l_@@_output_complex_copy_bool , % \l_@@_output_decimal_copy_bool , % \l_@@_exponent_base_tl , % \l_@@_exponent_product_tl , % \l_@@_group_min_int , % \l_@@_negative_color_tl , % \l_@@_bracket_open_tl , % \l_@@_output_uncert_close_tl , % \l_@@_output_complex_tl , % \l_@@_output_exponent_tl , % \l_@@_output_uncert_open_tl , % \l_@@_uncert_sep_bool , % \l_@@_tight_bool , % \l_@@_uncert_sep_tl %} % Lots of settings, some used only for numbers, some more widely. % \begin{macrocode} \keys_define:nn { siunitx } { bracket-negative-numbers .bool_set:N = \l_@@_negative_bracket_bool , bracket-numbers .bool_set:N = \l_@@_brackets_bool, close-bracket .tl_set:N = \l_@@_bracket_close_tl, complex-root-position .choice:, complex-root-position / after-number .code:n = { \bool_set_true:N \l_@@_complex_after_bool } , complex-root-position / before-number .code:n = { \bool_set_false:N \l_@@_complex_after_bool } , copy-complex-root .bool_set:N = \l_@@_output_complex_copy_bool, copy-decimal-marker .bool_set:N = \l_@@_output_decimal_copy_bool, exponent-base .tl_set:N = \l_@@_exponent_base_tl, exponent-product .tl_set:N = \l_@@_exponent_product_tl, group-decimal-digits .meta:n = { group-digits = decimal }, group-digits .choice: , group-digits / decimal .code:n = { \bool_set_true:N \l_@@_group_decimal_bool \bool_set_false:N \l_@@_group_integer_bool }, group-digits / false .code:n = { \bool_set_false:N \l_@@_group_decimal_bool \bool_set_false:N \l_@@_group_integer_bool }, group-digits / integer .code:n = { \bool_set_false:N \l_@@_group_decimal_bool \bool_set_true:N \l_@@_group_integer_bool }, group-digits / true .code:n = { \bool_set_true:N \l_@@_group_decimal_bool \bool_set_true:N \l_@@_group_integer_bool }, group-digits .default:n = true , group-four-digits .choice:, group-four-digits / false .meta:n = { group-minimum-digits = 5 }, group-four-digits / true .meta:n = { group-minimum-digits = 4 }, group-four-digits .default:n = true, group-integer-digits .meta:n = { group-digits = integer }, group-minimum-digits .int_set:N = \l_@@_group_min_int, group-separator .code:n = { \tl_set:Nn \l_@@_group_sep_tl { {#1} } }, negative-color .tl_set:N = \l_@@_negative_color_tl, open-bracket .tl_set:N = \l_@@_bracket_open_tl, output-close-uncertainty .tl_set:N = \l_@@_output_uncert_close_tl, output-complex-root .tl_set:N = \l_@@_output_complex_tl , output-decimal-marker .code:n = { \tl_set:Nn \l_@@_output_decimal_tl { {#1} } }, output-exponent-marker .tl_set:N = \l_@@_output_exponent_tl, output-open-uncertainty .tl_set:N = \l_@@_output_uncert_open_tl, separate-uncertainty .bool_set:N = \l_@@_uncert_sep_bool, tight-spacing .bool_set:N = \l_@@_tight_bool, uncertainty-separator .tl_set:N = \l_@@_uncert_sep_tl, } \keys_set:nn { siunitx } { bracket-numbers = true , % ( close-bracket = ) , complex-root-position = after-number , copy-decimal-marker = false , exponent-base = 10 , exponent-product = \times , group-digits = true , group-minimum-digits = 5 , group-separator = \, , open-bracket = ( , % ) ( output-close-uncertainty = ) , output-complex-root = \ensuremath { \mathrm { i } } , output-decimal-marker = . , output-open-uncertainty = ( % ) } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_format:} % The master control function for formatting output: the usual set up. % The number is put back together in stages. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format: { \prop_if_empty:NF \l_@@_number_in_prop { \prop_clear:N \l_@@_number_out_prop \@@_number_format_reassemble: \@@_number_format_complex: \@@_number_format_sign:n { mantissa } \@@_number_format_sign:n { exponent } \@@_number_format_relation: \@@_number_format_color: \@@_number_format_final: } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_format_brackets:n} %\begin{macro}[aux]{\@@_number_format_brackets_aux:n} % There are various points at which brackets might be added to % avoid ambiguity. The function here adds the appropriate tokens % around whatever is in the supplied named store. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_brackets:n #1 { \bool_if:NT \l_@@_brackets_bool { \prop_if_in:NnT \l_@@_number_out_prop { #1 -bracket } { \@@_number_format_brackets_aux:n {#1} \prop_remove:Nn \l_@@_number_out_prop { #1 -bracket } } } } \cs_new_protected:Npn \@@_number_format_brackets_aux:n #1 { \prop_get:NnNF \l_@@_number_out_prop { #1 -result } \l_@@_tmpa_tl { \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpa_tl } \tl_put_left:NV \l_@@_tmpa_tl \l_@@_bracket_open_tl \tl_put_right:NV \l_@@_tmpa_tl \l_@@_bracket_close_tl \str_if_eq:nnTF {#1} { result } { \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpa_tl } { \prop_put:NnV \l_@@_number_out_prop { #1 -result } \l_@@_tmpa_tl } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_format_color:} %\begin{macro}[aux]{\@@_number_format_color_aux:n} % If the mantissa is negative, then any colour for output might change. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_color: { \tl_if_empty:NF \l_@@_negative_color_tl { \@@_number_format_color_aux:n { mantissa-sign } \@@_number_format_color_aux:n { sign } } } \cs_new_protected:Npn \@@_number_format_color_aux:n #1 { \prop_get:NnNT \l_@@_number_in_prop {#1} \l_@@_tmpa_tl { \str_if_eq:VnT \l_@@_tmpa_tl { - } { \prop_put:NnV \l_@@_number_out_prop { color } \l_@@_negative_color_tl } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_format_complex:} %\begin{macro}[aux]{ % \@@_number_format_complex_aux:n , % \@@_number_format_complex_aux: %} % The real and complex parts of each number are reassembled, with % brackets if needed. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_complex: { \prop_if_in:NnT \l_@@_number_in_prop { complex-root } { \prop_if_in:NnTF \l_@@_number_out_prop { complex } { \@@_number_format_brackets:n { complex } \@@_number_format_complex_aux:n { complex } \@@_number_format_complex_aux:n { complex-result } \prop_if_in:NnT \l_@@_number_out_prop { complex-uncertainty } { \@@_number_format_complex_aux:n { complex-uncertainty } } } { \prop_put:NnV \l_@@_number_out_prop { complex } \l_@@_output_complex_tl } \@@_number_format_join_complex: } } \cs_new_protected:Npn \@@_number_format_complex_aux:n #1 { \bool_if:NTF \l_@@_output_complex_copy_bool { \prop_get:NnN \l_@@_number_in_prop { complex-root } \l_@@_tmpa_tl } { \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_output_complex_tl } \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpb_tl \bool_if:NTF \l_@@_complex_after_bool { \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpa_tl } { \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpa_tl } \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpb_tl } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{ % \@@_number_format_copy:n , % \@@_number_format_copy:nn %} % Just copy across. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_copy:n #1 { \prop_get:NnN \l_@@_number_in_prop {#1} \l_@@_tmpa_tl \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpa_tl } \cs_new_protected:Npn \@@_number_format_copy:nn #1#2 { \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpa_tl \prop_put:NnV \l_@@_number_out_prop {#2} \l_@@_tmpa_tl } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_format_final:} % For numbers which do not contain an exponent, the mantissa result is % simply copied to the final output position. On the other hand, for % exponents there are further checks, which are handed off to dedicated % functions. There is also a check for complex numbers with no real % part, which needs to be \enquote{copied} to the standard result % slot. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_final: { \prop_if_in:NnT \l_@@_number_out_prop { complex } { \prop_if_in:NnF \l_@@_number_out_prop { mantissa-result } { \@@_number_format_copy:nn { complex } { mantissa-result } } } \prop_if_in:NnTF \l_@@_number_out_prop { exponent } { \@@_number_format_final_exponent: \prop_if_in:NnTF \l_@@_number_out_prop { mantissa-result } { \@@_number_format_final_combined: } { \@@_number_format_final_exponent_only: } } { \@@_number_format_copy:nn { mantissa-result } { result } } \prop_if_in:NnT \l_@@_number_out_prop { mantissa-bracket } { \prop_put:Nnn \l_@@_number_out_prop { result-bracket } { true } \prop_remove:Nn \l_@@_number_out_prop { mantissa-bracket } } \prop_if_in:NnT \l_@@_number_out_prop { comparator } { \@@_number_format_brackets:n { result } \prop_get:NnN \l_@@_number_out_prop { comparator } \l_@@_tmpa_tl \prop_get:NnN \l_@@_number_out_prop { result } \l_@@_tmpb_tl \tl_set:Nx \l_@@_tmpa_tl { \exp_not:N \mathord \exp_not:V \l_@@_tmpa_tl \exp_not:V \l_@@_tmpb_tl } \prop_put:NnV \l_@@_number_out_prop { result } \l_@@_tmpa_tl } } % \end{macrocode} %\end{macro} %\begin{macro}{\@@_number_format_final_combined:} % When there is both a mantissa and an exponent, the mantissa is % combined with the product sign before adding the exponent part on. % The combined result is then stored. The marker % \texttt{result-bracket-exponent} indicates that the number needs % brackets due to the exponent part, but not in other cases. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_final_combined: { \@@_number_format_brackets:n { mantissa } \prop_get:NnN \l_@@_number_out_prop { mantissa-result } \l_@@_tmpa_tl \tl_if_empty:NT \l_@@_output_exponent_tl { \tl_put_right:Nx \l_@@_tmpa_tl { \exp_not:N \ensuremath { \bool_if:NTF \l_@@_tight_bool { { \exp_not:V \l_@@_exponent_product_tl } } { { } \exp_not:V \l_@@_exponent_product_tl { } } } } } \prop_get:NnN \l_@@_number_out_prop { exponent-result } \l_@@_tmpb_tl \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl \prop_put:NnV \l_@@_number_out_prop { result } \l_@@_tmpa_tl \prop_put:Nnn \l_@@_number_out_prop { result-bracket-exponent } { true } } % \end{macrocode} %\end{macro} %\begin{macro}{\@@_number_format_final_exponent:} % When there is an exponent, the base always needs to be added to the % front of the number itself. The number must be superscripted, of % course. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_final_exponent: { \prop_get:NnN \l_@@_number_out_prop { exponent } \l_@@_tmpa_tl \tl_if_empty:NTF \l_@@_output_exponent_tl { \tl_set:Nx \l_@@_tmpa_tl { ^ { \exp_not:V \l_@@_tmpa_tl } } \tl_put_left:NV \l_@@_tmpa_tl \l_@@_exponent_base_tl } { \tl_set:Nx \l_@@_tmpa_tl { \exp_not:V \l_@@_output_exponent_tl \exp_not:N \mathord \exp_not:V \l_@@_tmpa_tl } } \prop_put:NnV \l_@@_number_out_prop { exponent-result } \l_@@_tmpa_tl } % \end{macrocode} %\end{macro} %\begin{macro}{\@@_number_format_final_exponent_only:} % When there is only an exponent, a check must be made for a % sign in the mantissa part. If there is one, it is copied across. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_final_exponent_only: { \prop_get:NnNT \l_@@_number_in_prop { mantissa-sign } \l_@@_tmpa_tl { \prop_get:NnN \l_@@_number_out_prop { exponent-result } \l_@@_tmpb_tl \@@_tl_put_left_math:NV \l_@@_tmpb_tl \l_@@_tmpa_tl \prop_put:NnV \l_@@_number_out_prop { exponent-result } \l_@@_tmpb_tl } \@@_number_format_copy:nn { exponent-result } { result } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_format_group:n} %\begin{macro}[aux]{\@@_number_format_group_aux:nn} % Grouping digits only happens if there are no symbols in the input, and % of course if grouping has been requested. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_group:n #1 { \@@_number_format_group_aux:nn {#1} { integer } \@@_number_format_group_aux:nn {#1} { decimal } \prop_if_in:NnTF \l_@@_number_out_prop { #1 -integer } { \@@_number_format_copy:nn { #1 -integer } {#1} } { \tl_clear:N \l_@@_tmpa_tl } \prop_get:NnNT \l_@@_number_in_prop { #1 -decimal-marker } \l_@@_tmpb_tl { \bool_if:NTF \l_@@_output_decimal_copy_bool { \tl_set:Nx \l_@@_tmpb_tl { { \l_@@_tmpb_tl } } } { \tl_set_eq:NN \l_@@_tmpb_tl \l_@@_output_decimal_tl } \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl \prop_put:NnV \l_@@_number_out_prop { #1 -decimal-marker } \l_@@_tmpb_tl \prop_get:NnNF \l_@@_number_out_prop { #1 -decimal } \l_@@_tmpb_tl { \tl_clear:N \l_@@_tmpb_tl } \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpa_tl } } \cs_new_protected:Npn \@@_number_format_group_aux:nn #1#2 { \prop_if_in:NnT \l_@@_number_in_prop { #1 - #2 } { \bool_if:cTF { l_@@_group_ #2 _bool } { \@@_number_format_group:nn {#1} {#2} } { \@@_number_format_copy:n { #1 - #2 } } } } % \end{macrocode} %\end{macro} %\end{macro} % \begin{macro}{\@@_number_format_group:nn} % The idea here is that grouping is only needed for numbers with sufficient % digits: this is done simply by counting up all of the digits. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_group:nn #1#2 { \prop_get:NnN \l_@@_number_in_prop { #1 - #2 } \l_@@_tmpa_tl \int_compare:nNnTF { \tl_count:N \l_@@_tmpa_tl } < \l_@@_group_min_int { \@@_number_format_copy:n { #1 - #2 } } { \tl_clear:N \l_@@_tmpb_tl \use:c { @@_number_format_group_ #2 : } \prop_put:NnV \l_@@_number_out_prop { #1 - #2 } \l_@@_tmpb_tl } } % \end{macrocode} % \end{macro} %\begin{macro}{\@@_number_format_group_decimal:} %\begin{macro}[aux]{\@@_number_format_group_decimal_aux:} % Using the \enquote{keep everything on the stack} approach, relatively % simple recursion is needed. This trick is taken more or less directly % from \pkg{numprint}. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_group_decimal: { \tl_if_empty:NF \l_@@_tmpa_tl { \exp_after:wN \@@_number_format_group_decimal_aux:NNNN \l_@@_tmpa_tl { } { } { } } } \cs_new_protected:Npn \@@_number_format_group_decimal_aux:NNNN #1#2#3#4 { \tl_if_empty:nTF {#2} { \tl_put_right:Nn \l_@@_tmpb_tl {#1} } { \tl_if_empty:nTF {#3} { \tl_put_right:Nn \l_@@_tmpb_tl { #1 #2 } } { \tl_put_right:Nn \l_@@_tmpb_tl { #1 #2 #3 } \tl_if_empty:nF {#4} { \tl_put_right:NV \l_@@_tmpb_tl \l_@@_group_sep_tl \@@_number_format_group_decimal_aux:NNNN #4 } } } } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\@@_number_format_group_integer:} %\begin{macro}[aux]{ % \@@_number_format_group_integer_setup:n , % \@@_number_format_group_integer_setup:V , % \@@_number_format_group_integer_setup_aux:NNNN , % \@@_number_format_group_integer_aux:NNNN %} % By keeping everything on the stack, recursion can occur quite % efficiently here. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_group_integer: { \tl_if_empty:NF \l_@@_tmpa_tl { \@@_number_format_group_integer_setup:V \l_@@_tmpa_tl } } \cs_new_protected:Npn \@@_number_format_group_integer_setup:n #1 { \@@_number_format_group_integer_setup_aux:NNNN { } #1 { } { } { } } \cs_generate_variant:Nn \@@_number_format_group_integer_setup:n { V } \cs_new_protected:Npn \@@_number_format_group_integer_setup_aux:NNNN #1#2#3#4 { \tl_if_empty:nTF {#2} { \@@_number_format_group_integer_aux:NNNN #1 \q_nil } { \tl_if_empty:nTF {#3} { \@@_number_format_group_integer_aux:NNNN { } { } #1#2 \q_nil } { \tl_if_empty:nTF {#4} { \@@_number_format_group_integer_aux:NNNN { } #1#2#3 \q_nil } { \@@_number_format_group_integer_setup_aux:NNNN {#1#2#3#4} } } } } \cs_new_protected:Npn \@@_number_format_group_integer_aux:NNNN #1#2#3#4 { \tl_put_right:Nn \l_@@_tmpb_tl {#1#2#3} \quark_if_nil:nF {#4} { \tl_put_right:NV \l_@@_tmpb_tl \l_@@_group_sep_tl \@@_number_format_group_integer_aux:NNNN #4 } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_format_join_complex:} % For adding the complex part to the main part of a number. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_join_complex: { \@@_number_format_sign_complex: \prop_if_in:NnT \l_@@_number_out_prop { mantissa } { \@@_number_format_brackets:n { mantissa } \prop_get:NnN \l_@@_number_out_prop { mantissa-result } \l_@@_tmpa_tl \prop_get:NnNF \l_@@_number_out_prop { complex-result } \l_@@_tmpb_tl { \prop_get:NnN \l_@@_number_out_prop { complex } \l_@@_tmpb_tl } \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl \prop_put:NnV \l_@@_number_out_prop { mantissa-result } \l_@@_tmpa_tl \prop_put:Nnn \l_@@_number_out_prop { mantissa-bracket } { true } } } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_number_format_join_uncert: , % \@@_number_format_join_uncert:n %} %\begin{macro}[aux]{\@@_number_format_join_uncert_pm:N} % For adding separated uncertainties to the main part of a number. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_join_uncert: { \@@_number_format_join_uncert:n { mantissa } \@@_number_format_join_uncert:n { complex } } \cs_new_protected:Npn \@@_number_format_join_uncert:n #1 { \prop_get:NnNT \l_@@_number_out_prop {#1} \l_@@_tmpa_tl { \prop_get:NnNTF \l_@@_number_out_prop { #1 -uncertainty } \l_@@_tmpb_tl { \bool_if:NT \l_@@_uncert_sep_bool { \@@_number_format_join_uncert_pm:N \l_@@_tmpb_tl } \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl \prop_put:NnV \l_@@_number_out_prop { #1 -result } \l_@@_tmpa_tl \prop_put:Nnn \l_@@_number_out_prop { #1 -bracket } { true } } { \@@_number_format_copy:nn {#1} { #1 -result } } } } \cs_new_protected:Npn \@@_number_format_join_uncert_pm:N #1 { \bool_if:NTF \l_@@_tight_bool { \tl_put_left:Nn #1 { \ensuremath { { \pm } } } } { \tl_put_left:Nn #1 { \ensuremath { { } \pm { } } } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_format_reassemble:} % The integer, decimal and any non-separated uncertainty parts are % put back together. This gives a \enquote{minimal} unit which cannot % need any brackets or repeated units (if applicable). If the % uncertainty is separate, it is stored at this stage pending later % re-attachment. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_reassemble: { \prop_if_in:NnT \l_@@_number_in_prop { mantissa } { \@@_number_format_group:n { mantissa } \@@_number_format_uncertainty:n { mantissa } } \prop_if_in:NnT \l_@@_number_in_prop { complex } { \@@_number_format_group:n { complex } \@@_number_format_uncertainty:n { complex } } \prop_if_in:NnT \l_@@_number_in_prop { exponent } { \@@_number_format_group:n { exponent } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_format_relation:} % A simple check and copy operation for a relation: this will still need % to be added to the result, of course. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_relation: { \prop_get:NnNT \l_@@_number_in_prop { comparator } \l_@@_tmpa_tl { \tl_set:Nx \l_@@_tmpa_tl { \exp_not:N \ensuremath { \exp_not:V \l_@@_tmpa_tl } } \prop_put:NnV \l_@@_number_out_prop { comparator } \l_@@_tmpa_tl } } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_number_format_sign:n , % \@@_number_format_sign_complex: %} %\begin{macro}[aux]{ % \@@_number_format_sign_aux:n , % \@@_number_format_sign_negative_brackets:n , % \@@_number_format_sign_complex:n %} % Some simple sign manipulation: for tight signs, a little shuffling. % In the complex number case, there is a need for a correction to get % the right formatting in text mode. For speed reasons, this is done in % a separate function. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_sign:n #1 { \prop_if_in:NnT \l_@@_number_out_prop {#1} { \prop_get:NnNT \l_@@_number_in_prop { #1 -sign } \l_@@_tmpa_tl { \bool_if:NTF \l_@@_negative_bracket_bool { \str_if_eq:VnTF \l_@@_tmpa_tl { - } { \@@_number_format_sign_negative_brackets:n {#1} } { \@@_number_format_sign_aux:n {#1} } } { \@@_number_format_sign_aux:n {#1} } } } } \cs_new_protected:Npn \@@_number_format_sign_aux:n #1 { \tl_clear:N \l_@@_tmpb_tl \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpa_tl \prop_put:NnV \l_@@_number_out_prop { #1 -sign } \l_@@_tmpb_tl \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpa_tl \tl_put_left:NV \l_@@_tmpa_tl \l_@@_tmpb_tl \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpa_tl \prop_get:NnNT \l_@@_number_out_prop { #1 -result } \l_@@_tmpa_tl { \tl_put_left:NV \l_@@_tmpa_tl \l_@@_tmpb_tl \prop_put:NnV \l_@@_number_out_prop { #1 -result } \l_@@_tmpa_tl } } \cs_new_protected:Npn \@@_number_format_sign_negative_brackets:n #1 { \@@_number_format_brackets_aux:n {#1} \prop_get:NnNT \l_@@_number_out_prop { #1 } \l_@@_tmpa_tl { \tl_put_left:NV \l_@@_tmpa_tl \l_@@_bracket_open_tl \tl_put_right:NV \l_@@_tmpa_tl \l_@@_bracket_close_tl \prop_put:NnV \l_@@_number_out_prop { #1 } \l_@@_tmpa_tl } } \cs_new_protected:Npn \@@_number_format_sign_complex: { \@@_number_format_sign_complex:n { complex } \@@_number_format_sign_complex:n { complex-result } } \cs_new_protected:Npn \@@_number_format_sign_complex:n #1 { \prop_if_in:NnT \l_@@_number_out_prop {#1} { \prop_get:NnNT \l_@@_number_in_prop { complex-sign } \l_@@_tmpa_tl { \bool_if:NTF \l_@@_tight_bool { \tl_set:Nx \l_@@_tmpa_tl { \exp_not:N \mathord \exp_not:V \l_@@_tmpa_tl } } { \prop_if_in:NnT \l_@@_number_out_prop { mantissa } { \tl_set:Nx \l_@@_tmpa_tl { { } \exp_not:V \l_@@_tmpa_tl { } } } } \tl_clear:N \l_@@_tmpb_tl \tl_put_left:NV \l_@@_tmpb_tl \l_@@_tmpa_tl \prop_put:NnV \l_@@_number_out_prop { complex-sign } \l_@@_tmpb_tl \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpa_tl \tl_put_left:NV \l_@@_tmpa_tl \l_@@_tmpb_tl \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpa_tl } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_format_uncertainty:n} %\begin{macro}[aux]{ % \@@_number_format_uncertainty_joined:n , % \@@_number_format_uncertainty_sep:n %} % Uncertainty output varies depending on whether there is a need to % separate the error form the number in the output. % \begin{macrocode} \cs_new_protected:Npn \@@_number_format_uncertainty:n #1 { \prop_if_in:NnTF \l_@@_number_in_prop { #1 -uncertainty } { \bool_if:NTF \l_@@_uncert_sep_bool { \@@_number_format_uncertainty_sep:n {#1} } { \@@_number_format_uncertainty_joined:n {#1} } \@@_number_format_join_uncert: } { \@@_number_format_copy:nn {#1} { #1 -result } } } \cs_new_protected:Npn \@@_number_format_uncertainty_joined:n #1 { \prop_get:NnN \l_@@_number_in_prop { #1 -uncertainty } \l_@@_tmpa_tl \prop_remove:Nn \l_@@_number_in_prop { #1 -uncertainty } \tl_put_left:NV \l_@@_tmpa_tl \l_@@_output_uncert_open_tl \tl_put_left:NV \l_@@_tmpa_tl \l_@@_uncert_sep_tl \tl_put_right:NV \l_@@_tmpa_tl \l_@@_output_uncert_close_tl \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpb_tl \tl_put_right:NV \l_@@_tmpb_tl \l_@@_tmpa_tl \prop_put:NnV \l_@@_number_out_prop {#1} \l_@@_tmpb_tl } \cs_new_protected:Npn \@@_number_format_uncertainty_sep:n #1 { \prop_if_in:NnT \l_@@_number_out_prop { #1 -integer } { \prop_if_in:NnF \l_@@_number_out_prop { #1 -uncertainty-integer } { \prop_put:Nnn \l_@@_number_out_prop { #1 -uncertainty-integer } { 0 } } } \@@_number_format_group:n { #1 -uncertainty } \prop_put:NnV \l_@@_number_out_prop { #1 -uncertainty } \l_@@_tmpa_tl } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Numerical output} % % The outer level of number processing for actually printing things. % %\begin{macro}{ % \l_@@_number_out_tl , % \l_@@_number_out_saved_tl %} % The final result, plus a version for loops. % \begin{macrocode} \tl_new:N \l_@@_number_out_tl \tl_new:N \l_@@_number_out_saved_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_number_fraction_tl} % Fractions need to be build separately, so that there is no problem % with stack order. % \begin{macrocode} \tl_new:N \l_@@_number_fraction_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_number_compound_bool} % To help with brackets. % \begin{macrocode} \bool_new:N \l_@@_number_compound_bool % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_quotient_mode_tl} % The action for quotients is stored as a token list variable. % \begin{macrocode} \tl_new:N \l_@@_quotient_mode_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_fraction:nn} % The function used for fractions should be stored here. % \begin{macrocode} \cs_new_protected:Npn \@@_fraction:nn { } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_output_quotient_tl , % \l_siunix_number_parse_bool %} % Some options related to numbers at the output stage. % \begin{macrocode} \keys_define:nn { siunitx } { fraction-function .code:n = { \cs_set_protected:Npn \@@_fraction:nn {#1} }, output-product .tl_set:N = \l_@@_output_product_tl, output-quotient .tl_set:N = \l_@@_output_quotient_tl, parse-numbers .bool_set:N = \l_@@_number_parse_bool, quotient-mode .choice:, quotient-mode / fraction .code:n = { \tl_set:Nn \l_@@_quotient_mode_tl { fraction } }, quotient-mode / symbol .code:n = { \tl_set:Nn \l_@@_quotient_mode_tl { symbol } }, } \keys_set:nn { siunitx } { fraction-function = \frac , output-product = \times , output-quotient = / , parse-numbers = true , quotient-mode = symbol } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_number_output:n , % \@@_number_output:V %} % The number output system simply sets up for the combined number and % unit system. % \begin{macrocode} \cs_new_protected:Npn \@@_number_output:n #1 { \tl_clear:N \l_@@_unit_tl \tl_clear:N \l_@@_preunit_tl \@@_combined_output:n {#1} } \cs_generate_variant:Nn \@@_number_output:n { V } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_output_bracket:} % Compound numbers may need brackets adding. % \begin{macrocode} \cs_new_protected:Npn \@@_number_output_bracket: { \bool_if:NF \l_@@_error_bool { \bool_if:NT \l_@@_number_compound_bool { \@@_number_format_brackets:n { result } } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_output_color:} % If a colour needs to be set, it is recovered here and put into the % appropriate place. % \begin{macrocode} \cs_new_protected:Npn \@@_number_output_color: { \prop_if_in:NnT \l_@@_number_out_prop { color } { \prop_get:NnN \l_@@_number_out_prop { color } \l_@@_number_color_tl } } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_number_output_parse:n , % \@@_number_output_parse:V %} %\begin{macro}[aux]{\@@_number_output_parse_aux:} % The parsing system just has to check if there are multiple parts to % worry about. % \begin{macrocode} \cs_new_protected:Npn \@@_number_output_parse:n #1 { \@@_number_preprocess:n {#1} \bool_if:NF \l_@@_error_bool { \tl_if_empty:NTF \l_@@_number_multi_tl { \@@_number_output_parse_aux: } { \use:c { @@_number_output_ \l_@@_number_multi_tl : } } } } \cs_generate_variant:Nn \@@_number_output_parse:n { V } % \end{macrocode} % There are a few additional tests for printing partwise, as this is % only needed if there are brackets to add and these are not due to % an exponent. The test for an exponent is needed as this must force % the units to come at the end of the number, and there then have to % be brackets in the output if there are any separate parts. % \begin{macrocode} \cs_new_protected:Npn \@@_number_output_parse_aux: { \@@_number_in_parse:V \l_@@_number_arg_tl \bool_if:NF \l_@@_error_bool { \@@_number_process: \@@_number_format: \@@_number_output_color: \bool_if:NTF \l_@@_brackets_bool { \@@_number_output_single: } { \prop_if_in:NnTF \l_@@_number_out_prop { result-bracket } { \@@_number_output_parts: } { \@@_number_output_single: } } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_output_parts:} %\begin{macro}[aux]{ % \@@_number_output_parts_aux: , % \@@_number_output_parts_aux:n , % \@@_number_output_parts_print:n %} % Printing numbers by parts is necessary when there are units to % repeat. That means doing things that have already been done by the % number formatter again. % \begin{macrocode} \cs_new_protected:Npn \@@_number_output_parts: { \bool_if:nTF { \tl_if_empty_p:N \l_@@_pre_unit_tl && \tl_if_empty_p:N \l_@@_unit_tl } { \@@_number_output_single: } { \@@_number_output_parts_aux: } } \cs_new_protected:Npn \@@_number_output_parts_aux: { \bool_if:NTF \l_@@_multi_repeat_bool { \prop_if_in:NnT \l_@@_number_out_prop { mantissa-result } { \@@_number_output_parts_aux:n { mantissa } \@@_number_output_parts_aux:n { complex } } \prop_get:NnNT \l_@@_number_out_prop { exponent-result } \l_@@_tmpa_tl { \prop_if_in:NnT \l_@@_number_out_prop { mantissa-result } { \tl_put_left:Nx \l_@@_tmpa_tl { \exp_not:N \ensuremath { \bool_if:NTF \l_@@_tight_bool { { \exp_not:V \l_@@_exponent_product_tl } } { { } \exp_not:V \l_@@_exponent_product_tl { } } } } \prop_put:NnV \l_@@_number_out_prop { exponent } \l_@@_tmpa_tl } \@@_number_output_parts_print:n { exponent } } } { \@@_number_output_single: } } \cs_new_protected:Npn \@@_number_output_parts_aux:n #1 { \prop_if_in:NnT \l_@@_number_out_prop {#1} { \@@_number_output_parts_print:n {#1} } \prop_if_in:NnT \l_@@_number_out_prop { #1 -uncertainty } { \bool_if:NTF \l_@@_tight_bool { \@@_print:nn { number } { \ensuremath { { \pm } } } } { \@@_print:nn { number } { \ensuremath { { } \pm { } } } } \@@_number_output_parts_print:n { #1 -uncertainty } } } \cs_new_protected:Npn \@@_number_output_parts_print:n #1 { \@@_unit_output_pre_print: \prop_get:NnN \l_@@_number_out_prop {#1} \l_@@_tmpa_tl \@@_print:nV { number } \l_@@_tmpa_tl \@@_unit_output_print: } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_number_output_product:} % For products, there may need to be the addition of brackets if there % are units about. When not repeating units, some work has to be done to % print everything correctly. The extra group here is necessary % otherwise looping will delete the units entirely! % \begin{macrocode} \cs_new_protected:Npn \@@_number_output_product: { \bool_if:NTF \l_@@_product_brackets_bool { \bool_if:nTF { \tl_if_empty_p:N \l_@@_pre_unit_tl && \tl_if_empty_p:N \l_@@_unit_tl } { \@@_number_output_product_aux: } { \@@_number_output_product_brackets: } } { \bool_if:NTF \l_@@_product_repeat_bool { \@@_number_output_product_aux: } { \@@_unit_output_pre_print: \tl_set_eq:NN \l_@@_unit_saved_tl \l_@@_unit_tl \tl_clear:N \l_@@_pre_unit_tl \tl_clear:N \l_@@_unit_tl \group_begin: \@@_number_output_product_aux: \group_end: \tl_set_eq:NN \l_@@_unit_tl \l_@@_unit_saved_tl \@@_unit_output_print: } } } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{\@@_number_output_product_brackets:} % When printing products that have to be bracketed, there is a need to % shuffle the units about a bit. % \begin{macrocode} \cs_new_protected:Npn \@@_number_output_product_brackets: { \@@_unit_output_pre_print: \@@_print:nV { number } \l_@@_bracket_open_tl \nobreak \tl_set_eq:NN \l_@@_unit_saved_tl \l_@@_unit_tl \tl_clear:N \l_@@_pre_unit_tl \tl_clear:N \l_@@_unit_tl \@@_number_output_product_aux: \nobreak \tl_set_eq:NN \l_@@_unit_tl \l_@@_unit_saved_tl \@@_print:nV { number } \l_@@_bracket_close_tl \@@_unit_output_print: } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{\@@_number_output_product_aux:} % Printing the products needs a looping function. % \begin{macrocode} \cs_new_protected:Npn \@@_number_output_product_aux: { \bool_set_true:N \l_@@_number_compound_bool \@@_number_preprocess:V \l_@@_number_arg_tl \bool_if:NF \l_@@_error_bool { \tl_if_empty:NTF \l_@@_number_multi_tl { \@@_number_output_parse_aux: } { \@@_number_output_quotient: } \tl_if_empty:NF \l_@@_number_next_tl { \bool_if:NTF \l_@@_tight_bool { \@@_print:nn { number } { \ensuremath { \l_@@_output_product_tl } } } { \@@_print:nn { number } { \ensuremath { { } \l_@@_output_product_tl { } } } } \@@_number_output_parse:V \l_@@_number_next_tl } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_output_quotient:} % For quotients, there are two options. % \begin{macrocode} \cs_new_protected:Npn \@@_number_output_quotient: { \use:c { @@_number_output_quotient_ \l_@@_quotient_mode_tl : } } % \end{macrocode} %\end{macro} %\begin{macro}{\@@_number_output_quotient_fraction:} % For fraction output, there are quite a lot of braces to construct, % unfortunately. % \begin{macrocode} \cs_new_protected:Npn \@@_number_output_quotient_fraction: { \bool_set_false:N \l_@@_number_compound_bool \@@_number_output_quotient_aux_i: \tl_set:Nx \l_@@_number_out_tl { { \exp_not:V \l_@@_number_numerator_tl } } \tl_set:Nx \l_@@_tmpa_tl { { \exp_not:V \l_@@_number_denominator_tl } } \tl_put_right:NV \l_@@_number_out_tl \l_@@_tmpa_tl \tl_put_left:Nn \l_@@_number_out_tl { \@@_fraction:nn } \tl_set:Nx \l_@@_number_out_tl { \exp_not:N \ensuremath { \exp_not:V \l_@@_number_out_tl } } \@@_number_output_single_aux: } % \end{macrocode} %\end{macro} %\begin{macro}{\@@_number_output_quotient_symbol:} % If a symbol is used for the division, the build process is less % complex. % \begin{macrocode} \cs_new_protected:Npn \@@_number_output_quotient_symbol: { \bool_set_true:N \l_@@_number_compound_bool \@@_number_output_quotient_aux_i: \tl_set_eq:NN \l_@@_number_out_tl \l_@@_number_numerator_tl \tl_put_right:NV \l_@@_number_out_tl \l_@@_output_quotient_tl \tl_put_right:NV \l_@@_number_out_tl \l_@@_number_denominator_tl \@@_number_output_single_aux: } % \end{macrocode} %\end{macro} %\begin{macro}[aux]{ % \@@_number_output_quotient_aux_i: , % \@@_number_output_quotient_aux_ii: %} % The two parts of the number are parsed and formatted. % \begin{macrocode} \cs_new_protected:Npn \@@_number_output_quotient_aux_i: { \@@_number_in_parse:V \l_@@_number_numerator_tl \@@_number_output_quotient_aux_ii: \@@_number_output_color: \prop_if_in:NnT \l_@@_number_out_prop { complex } { \prop_if_in:NnT \l_@@_number_out_prop { mantissa } { \prop_put:Nnn \l_@@_number_out_prop { result-bracket } { true } \@@_number_format_brackets:n { result } } } \prop_get:NnN \l_@@_number_out_prop { result } \l_@@_number_numerator_tl \@@_number_in_parse:V \l_@@_number_denominator_tl \@@_number_output_quotient_aux_ii: \prop_if_in:NnT \l_@@_number_out_prop { result-bracket-exponent } { \prop_put:Nnn \l_@@_number_out_prop { result-bracket } { true } } \@@_number_output_bracket: \prop_get:NnN \l_@@_number_out_prop { result } \l_@@_number_denominator_tl } \cs_new_protected:Npn \@@_number_output_quotient_aux_ii: { \@@_number_process: \@@_number_format: } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_number_output_single:} %\begin{macro}[aux]{\@@_number_output_single_aux:} % Printing a number with no multiple parts is easy. There is a check for % any units, which if present may force the number to have brackets % added. there is then simply a short run to print the units and number. % The test for bracketing numbers does not happen if there is an % exponent: if there is, any other parts will already be bracketed and % mathematically there is no need for brackets at this point. % \begin{macrocode} \cs_new_protected:Npn \@@_number_output_single: { \bool_if:nF { \tl_if_empty_p:N \l_@@_pre_unit_tl && \tl_if_empty_p:N \l_@@_unit_tl } { \prop_if_in:NnF \l_@@_number_out_prop { exponent } { \@@_number_format_brackets:n { result } } } \@@_number_output_bracket: \prop_get:NnN \l_@@_number_out_prop { result } \l_@@_number_out_tl \@@_number_output_single_aux: } \cs_new_protected:Npn \@@_number_output_single_aux: { \@@_unit_output_pre_print: \quark_if_no_value:NTF \l_@@_number_out_tl { \tl_clear:N \l_@@_number_unit_product_tl } { \@@_print:nV { number } \l_@@_number_out_tl } \@@_unit_output_print: } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Angles} % % Angles are a special case of numbers for two reasons. First, there % is always a unit, which is known in advance. Second, there are two % possible input syntaxes, "\ang{1.23}" and "\ang{1;2;3}". Both need % to be handled correctly. % %\begin{macro}{ % \l_@@_angle_degree_space_bool , % \l_@@_angle_minute_space_bool %} % The need for spaces between parts of an arc needs to be accommodated: % this is achieved by flagging up the need for such spaces using two % switches. % \begin{macrocode} \bool_new:N \l_@@_angle_degree_space_bool \bool_new:N \l_@@_angle_minute_space_bool % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_angle_marker_box , % \l_@@_angle_unit_box , % \l_@@_angle_marker_dim , % \l_@@_angle_unit_dim %} % When creating astronomy-style angles, the decimal marker and angle % symbol have to be boxed up and measured. % \begin{macrocode} \box_new:N \l_@@_angle_marker_box \box_new:N \l_@@_angle_unit_box \dim_new:N \l_@@_angle_marker_dim \dim_new:N \l_@@_angle_unit_dim % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_angle_degree_prop , % \l_@@_angle_minute_prop , % \l_@@_angle_second_prop %} % As there are potentially three numbers to parse, three properly lists % are made available to hold the results. This allows the code to be % generalised, with only the name of the storage area varying. % \begin{macrocode} \prop_new:N \l_@@_angle_degree_prop \prop_new:N \l_@@_angle_minute_prop \prop_new:N \l_@@_angle_second_prop % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_angle_degree_zero_bool , % \l_@@_angle_minute_zero_bool , % \l_@@_angle_second_zero_bool , % \l_@@_angle_arc_separator_tl , % \l_@@_angle_astronomy_bool , % \l_@@_angle_unit_product_tl %} % The angle-specific options are created here. % \begin{macrocode} \keys_define:nn { siunitx } { add-arc-degree-zero .bool_set:N = \l_@@_angle_degree_zero_bool , add-arc-minute-zero .bool_set:N = \l_@@_angle_minute_zero_bool , add-arc-second-zero .bool_set:N = \l_@@_angle_second_zero_bool , angle-symbol-over-decimal .bool_set:N = \l_@@_angle_astronomy_bool , arc-separator .tl_set:N = \l_@@_angle_arc_separator_tl , number-angle-product .tl_set:N = \l_@@_angle_unit_product_tl , number-angle-separator .tl_set:N = \l_@@_angle_unit_product_tl , } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_angle_output:nnn} %\begin{macro}[aux]{\@@_angle_output_aux:nnn} % The input will have been split up by \pkg{xparse}, and so the various % possible inputs can be picked up. To keep to a minimal route through % the code, a decimal angle is simply treated like an arc, but with % any zero-filling disabled. % \begin{macrocode} \cs_new_protected:Npn \@@_angle_output:nnn #1#2#3 { \@@_angle_init: \IfNoValueTF {#2} { \bool_set_false:N \l_@@_angle_minute_zero_bool \bool_set_false:N \l_@@_angle_second_zero_bool \@@_angle_output_aux:nnn {#1} { } { } } { \IfNoValueTF {#3} { \@@_error:nx { invalid-arc-format } { #1 ; #2 } } { \@@_angle_output_aux:nnn {#1} {#2} {#3} } } } \cs_new_protected:Npn \@@_angle_output_aux:nnn #1#2#3 { \tl_if_empty:nTF { #1#2#3 } { \@@_error:n { empty-arc } } { \bool_if:NTF \l_@@_number_parse_bool { \@@_angle_parse:nnn {#1} {#2} {#3} } { \@@_angle_direct:nnn {#1} {#2} {#3} } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_angle_init:} % The usual separation of initial storage resets. % \begin{macrocode} \cs_new_protected:Npn \@@_angle_init: { \bool_set_false:N \l_@@_angle_degree_space_bool \bool_set_false:N \l_@@_angle_minute_space_bool \prop_clear:N \l_@@_angle_degree_prop \prop_clear:N \l_@@_angle_minute_prop \prop_clear:N \l_@@_angle_second_prop \tl_clear:N \l_@@_preunit_tl \tl_set_eq:NN \l_@@_number_unit_product_tl \l_@@_angle_unit_product_tl \cs_set_eq:NN \@@_number_in_parse_more:N \@@_number_in_parse_restricted:N } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_angle_direct:nnn} %\begin{macro}[aux]{ % \@@_angle_direct_aux_i:nnn , % \@@_angle_direct_aux_ii:nnn , % \@@_angle_direct_aux_iii:nnn %} % When printing an arc directly, there is still the need to fill in % any zero values required and to check the spacing is correct. That % is done using a chain approach, which is easy to implement and % reasonably clear. % \begin{macrocode} \cs_new_protected:Npn \@@_angle_direct:nnn #1 { \tl_if_empty:nTF {#1} { \bool_if:NTF \l_@@_angle_degree_zero_bool { \@@_angle_direct_aux_i:nnn { 0 } } { \@@_angle_direct_aux_i:nnn { } } } { \@@_angle_direct_aux_i:nnn {#1} } } \cs_new_protected:Npn \@@_angle_direct_aux_i:nnn #1#2 { \tl_if_empty:nTF {#2} { \bool_if:NTF \l_@@_angle_minte_zero_bool { \@@_angle_direct_aux_ii:nnn {#1} { 0 } } { \@@_angle_direct_aux_ii:nnn {#1} { } } } { \@@_angle_direct_aux_ii:nnn {#1} {#2} } } \cs_new_protected:Npn \@@_angle_direct_aux_ii:nnn #1#2#3 { \tl_if_empty:nTF {#3} { \bool_if:NTF \l_@@_angle_second_zero_bool { \@@_angle_direct_aux_iii:nnn {#1} {#2} { 0 } } { \@@_angle_direct_aux_iii:nnn {#1} {#2} { } } } { \@@_angle_direct_aux_iii:nnn {#1} {#2} {#3} } } \cs_new_protected:Npn \@@_angle_direct_aux_iii:nnn #1#2#3 { \tl_if_empty:nF {#1} { \tl_if_empty:nF {#2#3} { \bool_set_true:N \l_@@_angle_degree_space_bool } } \tl_if_empty:nF {#2} { \tl_if_empty:nF {#3} { \bool_set_true:N \l_@@_angle_minute_space_bool } } \@@_angle_print_direct:nnn {#1} {#2} {#3} } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{ % \@@_angle_parse:nnn , % \@@_angle_check_sign: , % \@@_angle_zero_fill: , % \@@_angle_sign_shuffle:nn %} %\begin{macro}[aux]{ % \@@_angle_parse_aux:nnn , % \@@_angle_check_sign:n , % \@@_angle_sign_shuffle_aux:nnn %} % Parsing an arc requires a number of stages. First, there is the % basic conversion of the input numbers into three property lists, % which will contain the data required. There is then a zero-filling % step, done here so that signs can be shuffled into the correct places. % After that, a check to make sure there is only one sign for an arc % before setting up the inter-part spacing and actually printing. % \begin{macrocode} \cs_new_protected:Npn \@@_angle_parse:nnn #1#2#3 { \@@_angle_parse_aux:nn {#1} { degree } \@@_angle_parse_aux:nn {#2} { minute } \@@_angle_parse_aux:nn {#3} { second } \@@_angle_check_sign: \@@_angle_zero_fill: \prop_if_empty:NF \l_@@_angle_degree_prop { \prop_if_empty:NF \l_@@_angle_minute_prop { \bool_set_true:N \l_@@_angle_degree_space_bool } \prop_if_empty:NF \l_@@_angle_second_prop { \bool_set_true:N \l_@@_angle_degree_space_bool } } \prop_if_empty:NF \l_@@_angle_minute_prop { \prop_if_empty:NF \l_@@_angle_second_prop { \bool_set_true:N \l_@@_angle_minute_space_bool } } \@@_angle_print: } \cs_new_protected:Npn \@@_angle_parse_aux:nn #1#2 { \prop_clear:N \l_@@_number_in_prop \tl_if_empty:nF {#1} { \@@_number_in_init: \@@_number_in_parse_aux:n {#1} } \prop_get:NnNT \l_@@_number_in_prop { mantissa-sign-deleted } \l_@@_tmpa_tl { \prop_put:NnV \l_@@_number_in_prop { mantissa-sign } \l_@@_tmpa_tl } \@@_number_process: \prop_set_eq:cN { l_@@_angle_ #2 _prop } \l_@@_number_in_prop } % \end{macrocode} % Only the highest-order part of an arc can have a sign. This is checked % now so that the shuffling code is easier to write. % \begin{macrocode} \cs_new_protected:Npn \@@_angle_check_sign: { \prop_if_empty:NTF \l_@@_angle_degree_prop { \prop_if_empty:NF \l_@@_angle_minute_prop { \@@_angle_check_sign_aux:n { second } } } { \@@_angle_check_sign_aux:n { minute } \@@_angle_check_sign_aux:n { second } } } \cs_new_protected:Npn \@@_angle_check_sign_aux:n #1 { \prop_if_in:cnTF { l_@@_angle_ #1 _prop } { mantissa-sign } { \msg_error:nn { siunitx } { bad-arc-sign } } { \prop_if_in:cnT { l_@@_angle_ #1 _prop } { mantissa-sign-deleted } { \msg_error:nn { siunitx } { bad-arc-sign } } } } % \end{macrocode} % Filling in the zero values is rather awkward as there are signs % to worry about. There is therefore a shuffle to move them into the % correct places. % \begin{macrocode} \cs_new_protected:Npn \@@_angle_zero_fill: { \bool_if:nT { \prop_if_empty_p:N \l_@@_angle_second_prop && \l_@@_angle_second_zero_bool } { \prop_put:Nnn \l_@@_angle_second_prop { mantissa } { true } \prop_put:Nnn \l_@@_angle_second_prop { mantissa-integer } { 0 } } \bool_if:nT { \prop_if_empty_p:N \l_@@_angle_minute_prop && \l_@@_angle_minute_zero_bool } { \prop_put:Nnn \l_@@_angle_minute_prop { mantissa } { true } \prop_put:Nnn \l_@@_angle_minute_prop { mantissa-integer } { 0 } \@@_angle_sign_shuffle:nn { second } { minute } } \bool_if:nT { \prop_if_empty_p:N \l_@@_angle_degree_prop && \l_@@_angle_degree_zero_bool } { \prop_put:Nnn \l_@@_angle_degree_prop { mantissa } { true } \prop_put:Nnn \l_@@_angle_degree_prop { mantissa-integer } { 0 } \@@_angle_sign_shuffle:nn { second } { degree } \@@_angle_sign_shuffle:nn { minute } { degree } } } \cs_new_protected:Npn \@@_angle_sign_shuffle:nn #1#2 { \@@_angle_sign_shuffle_aux:nnn {#1} {#2} { } \@@_angle_sign_shuffle_aux:nnn {#1} {#2} { -deleted } } \cs_new_protected:Npn \@@_angle_sign_shuffle_aux:nnn #1#2#3 { \prop_get:cnN { l_@@_angle_ #1 _prop } { mantissa-sign #3 } \l_@@_tmpa_tl \prop_remove:cn { l_@@_angle_ #1 _prop } { mantissa-sign #3 } \quark_if_no_value:NF \l_@@_tmpa_tl { \prop_put:cnV { l_@@_angle_ #2 _prop } { mantissa-sign #3 } \l_@@_tmpa_tl } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_angle_print:} %\begin{macro}[aux]{\@@_angle_print:nn} % The standard printing routine examines each part of the arc in turn % and either does a standard format or calls the special astronomy-style % routine. There may also be some spaces to add. % \begin{macrocode} \cs_new_protected:Npn \@@_angle_print: { \@@_angle_print_aux:nn { degree } { \SIUnitSymbolDegree } \bool_if:NT \l_@@_angle_degree_space_bool { \nobreak \l_@@_angle_arc_separator_tl } \@@_angle_print_aux:nn { minute } { \SIUnitSymbolArcminute } \bool_if:NT \l_@@_angle_minute_space_bool { \nobreak \l_@@_angle_arc_separator_tl } \@@_angle_print_aux:nn { second } { \SIUnitSymbolArcsecond } } \cs_new_protected:Npn \@@_angle_print_aux:nn #1#2 { \prop_if_empty:cF { l_@@_angle_ #1 _prop } { \prop_set_eq:Nc \l_@@_number_in_prop { l_@@_angle_ #1 _prop } \tl_set:Nn \l_@@_unit_tl {#2} \tl_clear:N \l_@@_number_out_tl \@@_number_format: \@@_number_output_color: \bool_if:NTF \l_@@_angle_astronomy_bool { \@@_angle_print_astronomy: } { \@@_number_output_single: } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_angle_print_astronomy:} %\begin{macro}[aux]{ % \@@_angle_print_astronomy_aux: , % \@@_angle_print_astronomy_aux:n , % \@@_angle_print_astronomy_marker: , % \@@_angle_print_astronomy_unit: %} % The first check for astronomy-style angles is that there is a decimal % marker in the current input: if not, the standard method can be used. % The method for the astronomy-style angle is not straight-forward, so % needs a little explanation. The integer and decimal parts of the % number are printed at each end of the function. In the middle is a % method to centre the unit symbol on the decimal marker. This is done % by typesetting the two symbols and measuring their respective widths. % The two are then put into zero-width boxes, which allows them to be % aligned horizontally centred with no vertical change. The larger % dimension is then used to reconstruct the appropriate width for the % final output. There is also a need to allow for the \cs{scriptspace} % added in after superscripts, which otherwise messes up the % calculation. % \begin{macrocode} \cs_new_protected:Npn \@@_angle_print_astronomy: { \prop_if_in:NnTF \l_@@_number_in_prop { mantissa-decimal-marker } { \@@_angle_print_astronomy_aux: } { \@@_number_output_single: } } \cs_new_protected:Npn \@@_angle_print_astronomy_aux: { \prop_get:NnNT \l_@@_number_out_prop { mantissa-integer } \l_@@_tmpa_tl { \@@_print:nV { number } \l_@@_tmpa_tl } \hbox_set:Nn \l_@@_angle_marker_box { \@@_print:nn { number } { { \l_@@_output_decimal_tl } } } \hbox_set:Nn \l_@@_angle_unit_box { \@@_print:nV { unit } \l_@@_unit_tl \skip_horizontal:n { -\scriptspace } } \@@_angle_print_astronomy_aux:n { marker } \@@_angle_print_astronomy_aux:n { unit } \hbox_set:Nn \l_@@_angle_marker_box { \box_use:N \l_@@_angle_marker_box \box_use:N \l_@@_angle_unit_box } \dim_compare:nNnTF { \l_@@_angle_marker_dim } > { \l_@@_angle_unit_dim } { \@@_angle_print_astronomy_marker: } { \@@_angle_print_astronomy_unit: } \prop_get:NnNT \l_@@_number_out_prop { mantissa-decimal } \l_@@_tmpa_tl { \@@_print:nV { number } \l_@@_tmpa_tl } } \cs_new_protected:Npn \@@_angle_print_astronomy_aux:n #1 { \dim_set:cn { l_@@_angle_ #1 _dim } { \box_wd:c { l_@@_angle_ #1 _box } } \hbox_set_to_wd:cnn { l_@@_angle_ #1 _box } { \c_zero_skip } { \tex_hss:D \hbox_unpack:c { l_@@_angle_ #1_box } \tex_hss:D } } \cs_new_protected:Npn \@@_angle_print_astronomy_marker: { \hbox_set_to_wd:Nnn \l_@@_angle_marker_box { \l_@@_angle_marker_dim } { \tex_hss:D \hbox_unpack:N \l_@@_angle_marker_box \tex_hss:D } \box_use:N \l_@@_angle_marker_box } \cs_new_protected:Npn \@@_angle_print_astronomy_unit: { \hbox_set_to_wd:Nnn \l_@@_angle_marker_box { \l_@@_angle_unit_dim } { \tex_hss:D \hbox_unpack:N \l_@@_angle_marker_box \tex_hss:D } \box_use:N \l_@@_angle_marker_box \skip_horizontal:N \scriptspace } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_angle_print_direct:nnn} %\begin{macro}[aux]{\@@_angle_print_direct_aux:nn} % The direct printing routine is rather similar to the standard % one, with just a modified final step. % \begin{macrocode} \cs_new_protected:Npn \@@_angle_print_direct:nnn #1#2#3 { \@@_angle_print_direct_aux:nn {#1} { \SIUnitSymbolDegree } \bool_if:NT \l_@@_angle_degree_space_bool { \nobreak \l_@@_angle_arc_separator_tl } \@@_angle_print_direct_aux:nn {#2} { \SIUnitSymbolArcminute } \bool_if:NT \l_@@_angle_minute_space_bool { \nobreak \l_@@_angle_arc_separator_tl } \@@_angle_print_direct_aux:nn {#3} { \SIUnitSymbolArcsecond } } \cs_new_protected:Npn \@@_angle_print_direct_aux:nn #1#2 { \tl_if_empty:nF {#1} { \tl_set:Nn \l_@@_unit_tl {#2} \@@_print:nn { number } { \ensuremath {#1} } \@@_unit_output_print: } } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Creating unit macros} % % Unit macros and related support are created here. To avoid cluttering % up the user name-space with a lot of short macro names, the standard % method only makes these available inside the unit-processing functions % (\cs{SI}, \cs{si} and the \texttt{S} column). % %\begin{macro}{\l_@@_declare_list_seq} % A list of all unit and related functions. % \begin{macrocode} \seq_new:N \l_@@_declare_list_seq \seq_put_right:Nn \l_@@_declare_list_seq { \of } \seq_put_right:Nn \l_@@_declare_list_seq { \highlight } \seq_put_right:Nn \l_@@_declare_list_seq { \per } \seq_put_right:Nn \l_@@_declare_list_seq { \raiseto } \seq_put_right:Nn \l_@@_declare_list_seq { \tothe } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_declare_power_after:Nn , % \@@_declare_power_before:Nn %} % Creating powers is all about storing values. % \begin{macrocode} \cs_new_protected:Npn \@@_declare_power_after:Nn #1#2 { \seq_put_right:Nn \l_@@_declare_list_seq {#1} \cs_set:cpn { @@_ \token_to_str:N #1 _literal:w } { \@@_textsuperscript:n {#2} } \cs_set:cpn { @@_ \token_to_str:N #1 _function:w } { \@@_unit_parse_power_after:n {#2} } } \cs_new_protected:Npn \@@_declare_power_before:Nn #1#2 { \seq_put_right:Nn \l_@@_declare_list_seq {#1} \cs_set:cpn { @@_ \token_to_str:N #1 _literal:w } ##1 { ##1 \@@_textsuperscript:n {#2} } \cs_set:cpn { @@_ \token_to_str:N #1 _function:w } { \@@_unit_parse_power_before:n {#2} } } % \end{macrocode} %\end{macro} % % \begin{macro}{\@@_declare_prefix:Nnnn} % \begin{variable} % {\l_@@_prefix_forward_prop, \l_@@_prefix_reverse_prop} % Prefixes need to store both the symbol and the power they represent. % A reverse system is also set up, to allow powers to be converted to % prefixes. % \begin{macrocode} \cs_new_protected:Npn \@@_declare_prefix:Nnnn #1#2#3#4 { \seq_put_right:Nn \l_@@_declare_list_seq {#1} \prop_put:Nnn \l_@@_prefix_forward_prop {#1} {#4} \prop_put:Nnn \l_@@_prefix_reverse_prop {#4} {#1} \cs_set:cpn { @@_ \token_to_str:N #1 _literal:w } {#2} \cs_set:cpn { @@_ \token_to_str:N #1 _function:w } { \bool_if:NTF \l_@@_prefix_symbols_bool { \@@_unit_parse_prefix:Nn #1 {#2} } { \@@_unit_parse_prefix:nn {#3} {#4} } } } \prop_new:N \l_@@_prefix_forward_prop \prop_new:N \l_@@_prefix_reverse_prop % \end{macrocode} % \end{variable} % \end{macro} % %\begin{macro}{\@@_declare_qualifier:Nn} % Qualifiers just need storing. % \begin{macrocode} \cs_new_protected:Npn \@@_declare_qualifier:Nn #1#2 { \seq_put_right:Nn \l_@@_declare_list_seq {#1} \cs_set:cpn { @@_ \token_to_str:N #1 _literal:w } { \text { ~ } ( #2 ) } \cs_set:cpn { @@_ \token_to_str:N #1 _function:w } { \@@_unit_parse_qualifier:n {#2} } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_declare_unit:Nnn} %\begin{macro}[aux]{\@@_unit_first_token:n} % Creating units requires various things to be stored. This is done % with several storage bins to keep the code clear. For the % \texttt{macro} definition, the test occurs at use so that there is no % problem with the creation order for units. % \begin{macrocode} \cs_new_protected:Npn \@@_declare_unit:Nnn #1#2#3 { \seq_put_right:Nn \l_@@_declare_list_seq {#1} \cs_set:cpn { @@_ \token_to_str:N #1 _literal:w } {#2} \cs_set_protected:cpn { @@_ \token_to_str:N #1 _function:w } { \@@_unit_if_literal:nTF {#2} { \@@_unit_parse_unit:Nn #1 {#2} } {#2} } \tl_if_empty:nTF {#3} { \cs_undefine:c { l_@@_ \token_to_str:N #1 _options_tl } } { \tl_clear_new:c { l_@@_ \token_to_str:N #1 _options_tl } \tl_set:cn { l_@@_ \token_to_str:N #1 _options_tl } {#3} } } \cs_new_protected:Npn \@@_unit_first_token:n #1 { \exp_last_unbraced:No \token_to_str:N { \tl_head:w #1 \q_stop } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\per} % The \cs{per} function is pretty simple. % \begin{macrocode} \cs_new:cpn { @@_ \token_to_str:N \per _literal:w } { / } \cs_new_protected:cpn { @@_ \token_to_str:N \per _function:w } { \bool_set_true:N \l_@@_per_bool \@@_unit_parse_per: } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \raiseto , % \tothe %} % Generic versions of the pre-set powers. % \begin{macrocode} \cs_new:cpn { @@_ \token_to_str:N \raiseto _literal:w } #1#2 { #2 \@@_textsuperscript:n {#1} } \cs_new_protected:cpn { @@_ \token_to_str:N \raiseto _function:w } #1 { \@@_unit_parse_power_before:n {#1} } \cs_new:cpn { @@_ \token_to_str:N \tothe _literal:w } #1 { \@@_textsuperscript:n {#1} } \cs_new_protected:cpn { @@_ \token_to_str:N \tothe _function:w } #1 { \@@_unit_parse_power_after:n {#1} } % \end{macrocode} %\end{macro} % %\begin{macro}{\of} % A flexible qualifier as well. % \begin{macrocode} \cs_new:cpn { @@_ \token_to_str:N \of _literal:w } #1 { \text { ~ } ( #1 ) } \cs_new_protected:cpn { @@_ \token_to_str:N \of _function:w } #1 { \@@_unit_parse_qualifier:n {#1} } % \end{macrocode} %\end{macro} % %\begin{macro}{\cancel} %\begin{macro}[aux]{\@@_cancel:n} % The \cs{cancel} macro is odd as it is only defined if the appropriate % package is loaded. % \begin{macrocode} \AtBeginDocument { \cs_if_exist:NT \cancel { \cs_set_eq:NN \@@_cancel:n \cancel \seq_put_right:Nn \l_@@_declare_list_seq { \cancel } \cs_new_protected:cpn { @@_ \token_to_str:N \cancel _function:w } { \@@_unit_parse_special:n { \@@_cancel:n } } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\highlight} % Another special function: selective colour. % \begin{macrocode} \cs_new:cpn { @@_ \token_to_str:N \highlight _literal:w } #1 { \@@_textcolor:n {#1} } \cs_new_protected:cpn { @@_ \token_to_str:N \highlight _function:w } #1 { \@@_unit_parse_special:n { \@@_textcolor:n {#1} } } % \end{macrocode} %\end{macro} % %\subsection{Creating body unit macros} % % The user might have asked for the unit macros to be available in the % document body. If so, then these are created at the start of the % document body. % %\begin{macro}{ % \l_@@_create_free_bool , % \l_@@_create_overwrite_bool , % \l_@@_create_prespace_bool , % \l_@@_create_optional_bool , % \l_@@_create_xspace_bool %} % There are a few options which control this behaviour: these are all % preamble-only. % \begin{macrocode} \keys_define:nn { siunitx } { free-standing-units .bool_set:N = \l_@@_create_free_bool , overwrite-functions .bool_set:N = \l_@@_create_overwrite_bool, space-before-unit .bool_set:N = \l_@@_create_prespace_bool , unit-optional-argument .bool_set:N = \l_@@_create_optional_bool , use-xspace .bool_set:N = \l_@@_create_xspace_bool , } \@@_option_deactivate:n { free-standing-units , overwrite-functions , space-before-unit , unit-optional-argument , use-xspace , } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_unit_create_empty_functions:} %\begin{macro}[aux]{\@@_unit_create_empty_functions_aux:N} % Without this, horrible things happen with \pkg{memoir} and % \pkg{hyperref}. % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_unit_create_empty_functions: { \@@_unit_create_functions_aux_i: \seq_map_function:NN \l_@@_declare_list_seq \@@_unit_create_empty_functions_aux:N \@@_unit_create_functions_aux_ii: } \cs_new_protected:Npn \@@_unit_create_empty_functions_aux:N #1 { \cs_if_free:NT #1 { \cs_set_protected:Npn #1 { \ERROR } } } % \end{macrocode} %\end{macro} %\end{macro} % % \begin{macro}{\@@_unit_create_functions:} % \begin{macro}[aux] % { % \@@_unit_create_functions_aux_i:, % \@@_unit_create_functions_aux_ii: % } % Creation of macros essentially involves picking up a couple of loops. % \begin{macrocode} \cs_new_protected_nopar:Npn \@@_unit_create_functions: { \@@_unit_create_functions_aux_i: \bool_if:NT \l_@@_create_overwrite_bool { \seq_map_function:NN \l_@@_declare_list_seq \cs_undefine:N } \bool_if:NTF \l_@@_create_optional_bool { \seq_map_function:NN \l_@@_declare_list_seq \@@_unit_create_with_arg:N } { \seq_map_function:NN \l_@@_declare_list_seq \@@_unit_create:N } \@@_unit_create_functions_aux_ii: \bool_if:NT \l_@@_create_xspace_bool { \RequirePackage { xspace } } } \cs_new_protected_nopar:Npn \@@_unit_create_functions_aux_i: { \@ifpackageloaded { soulpos } { \@ifpackageloaded { soul } { } { \cs_set_protected_nopar:Npn \@@_unit_create_functions_aux_ii: { \cs_undefine:N \hl \cs_undefine:N \ul } } } { } } \cs_new_protected_nopar:Npn \@@_unit_create_functions_aux_ii: { } % \end{macrocode} % \end{macro} % \end{macro} % %\begin{macro}{ % \@@_unit_create:N , % \@@_unit_create_with_arg:N %} % The creation functions expand everything as far as possible so that % there is less to do in the document. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_create:N #1 { \cs_if_free:NT #1 { \cs_set:Npx \@@_tmp:w { \ProvideDocumentCommand \exp_not:N #1 { } { \group_begin: \exp_not:N \cs_if_free:NF \exp_not:c { l_@@_ \token_to_str:N #1 _options_tl } { \keys_set:nV { siunitx } \exp_not:c { l_@@_ \token_to_str:N #1 _options_tl } } \bool_if:NT \l_@@_create_prespace_bool { \exp_not:N \l_@@_number_unit_product_tl } \exp_not:n { \@@_unit_output:nn {#1} { } } \group_end: \bool_if:NT \l_@@_create_xspace_bool { \exp_not:N \xspace } } } \@@_tmp:w } } \cs_new_protected:Npn \@@_unit_create_with_arg:N #1 { \cs_if_free:NT #1 { \cs_set:Npx \@@_tmp:w { \ProvideDocumentCommand \exp_not:N #1 { o } { \group_begin: \exp_not:N \cs_if_free:NF \exp_not:c { l_@@_ \token_to_str:N #1 _options_tl } { \keys_set:nV { siunitx } \exp_not:c { l_@@_ \token_to_str:N #1 _options_tl } } \exp_not:N \IfNoValueTF {####1} { \bool_if:NT \l_@@_create_prespace_bool { \exp_not:N \l_@@_number_unit_product_tl } \exp_not:n { \@@_unit_output:nn {#1} { } } } { \SI {####1} { \exp_not:N #1 } } \group_end: \bool_if:NT \l_@@_create_xspace_bool { \exp_not:N \xspace } } } \@@_tmp:w } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_protect_symbols:N} % There are a few unit names which may be defined by other parts of % \LaTeX. They need to be unexpandable, as in an \texttt{S} column % \TeX{} will look for \cs{omit} \emph{before} starting the internal % version of \cs{si} and doing a redefinition. The same is true % for the \cs{color} function, which may well be the first thing in % a table cell. The same is true for \cs{array@row@rst}, from REV\TeX, % which otherwise gives an error. % \begin{macrocode} \AtBeginDocument { \cs_if_eq:NNT \color \use_none:n { \cs_set_protected:Npn \color #1 { } } \cs_set:Npn \@@_tmp:w #1 { } \cs_if_eq:NNT \color \@@_tmp:w { \cs_set_protected:Npn \color #1 { } } \tl_map_function:nN { \bar \color \ng \pm \array@row@rst } \@@_protect_symbols:N } \tl_put_right:Nn \document { \@@_protect_symbols:N \fg } \cs_new_protected:Npn \@@_protect_symbols:N #1 { \cs_if_exist:NT #1 { \@@_cs_if_macro:NT #1 { \cs_set_protected:Npx #1 { \exp_not:V #1 } } } } % \end{macrocode} %\end{macro} % %\subsection{Initial unit processing} % % The unit processor has to convert the input (which may be all macros % or may contain literal input) into formatted text for output. The % input part of the process is used to sort out parsed or literal units. % %\begin{macro}{ % \l_@@_unit_forbid_literal_bool , % \l_@@_unit_parse_bool %} % One option is related to how units are pre-processed. % \begin{macrocode} \keys_define:nn { siunitx } { forbid-literal-units .bool_set:N = \l_@@_unit_forbid_literal_bool, parse-units .bool_set:N = \l_@@_unit_parse_bool } \keys_set:nn { siunitx } { forbid-literal-units = false, parse-units = true } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_unit_in:nn , % \@@_unit_in:Vn , % \@@_pm: %} % The master function does a very simple checks then hands off. % The definition of \cs{pm} needs to be saved here so that it can % safely be used as an abbreviation for picometre and also in numbers % for \( \pm \). % \begin{macrocode} \cs_new_protected:Npn \@@_unit_in:nn #1#2 { \bool_if:NTF \l_@@_unit_parse_bool { \tl_if_empty:nF {#1} { \@@_unit_if_literal:nTF {#1} { \tl_clear:N \l_@@_per_mode_tl \bool_if:NTF \l_@@_unit_forbid_literal_bool { \msg_error:nnx { siunitx } { literal-unit } { \exp_not:n {#1} } } { \cs_set_eq:NN \@@_pm: \pm \@@_unit_format_literal:n {#1} \cs_set_eq:NN \pm \@@_pm: } } { \cs_set_eq:NN \@@_pm: \pm \@@_unit_parse:nn {#1} {#2} \@@_unit_format: \prop_set_eq:NN \l_@@_unit_saved_prop \l_@@_unit_prop \cs_set_eq:NN \pm \@@_pm: } } } { \@@_unit_format_literal:n {#1} } } \cs_generate_variant:Nn \@@_unit_in:nn { V } \cs_new:Npn \@@_pm: { } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_unit_if_literal:nTF} %\begin{macro}[aux]{\@@_unit_if_literal_aux:N} % A test is needed to see if the input only contains unit macros. This % is done by altering setting all of the unit macros to expand to % nothing at all. Thus there will only be anything left if there is % a literal in the unit. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_if_literal:nTF #1#2#3 { \group_begin: \seq_map_function:NN \l_@@_declare_list_seq \@@_unit_if_literal_aux:N \cs_set_eq:NN \of \use_none:n \cs_set_eq:NN \highlight \use_none:n \cs_set_eq:NN \raiseto \use_none:n \cs_set_eq:NN \tothe \use_none:n \protected@edef \l_@@_tmpa_tl {#1} \exp_args:NNNV \group_end: \tl_set:Nn \l_@@_tmpa_tl \l_@@_tmpa_tl \tl_if_blank:VTF \l_@@_tmpa_tl {#3} {#2} } \cs_new_protected:Npn \@@_unit_if_literal_aux:N #1 { \cs_set_eq:NN #1 \prg_do_nothing: } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Parsing macro units} % % For macro-based units, the macros are converted into literal text, % which is then passed on for printing. The code reads through the % input to collect up the units, before re-combining everything into % a single block at the end of the process. % % \begin{variable} % { % \l_@@_unit_int , % \l_@@_unit_prop , % \l_@@_unit_saved_prop % } % Parsed units are stored in a property list, to keep things compact. % An integer is also needed to count up units. % \begin{macrocode} \int_new:N \l_@@_unit_int \prop_new:N \l_@@_unit_prop \prop_new:N \l_@@_unit_saved_prop % \end{macrocode} % \end{variable} % %\begin{macro}{\l_@@_per_bool} % To allow \cs{per} to be \enquote{sticky}. % \begin{macrocode} \bool_new:N \l_@@_per_bool % \end{macrocode} %\end{macro} % % \begin{variable} % { % \l_@@_exp_to_prefix_bool , % \l_@@_prefix_symbols_bool , % \l_@@_sticky_per_bool % } % Some options are directly related to how units are handled at this % stage, so need be created before the reconstruction part of the code. % \begin{macrocode} \keys_define:nn { siunitx } { exponent-to-prefix .bool_set:N = \l_@@_exp_to_prefix_bool , prefixes-as-symbols .bool_set:N = \l_@@_prefix_symbols_bool , sticky-per .bool_set:N = \l_@@_sticky_per_bool } \keys_set:nn { siunitx } { prefixes-as-symbols = true } % \end{macrocode} % \end{variable} % %\begin{macro}{\@@_unit_parse:nn} % The unit to be parsed is received here along with any options given. % The later are needed so that the user can override any saved options % on a one-off basis. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_parse:nn #1#2 { \@@_unit_parse_init: \@@_unit_parse_options:nn {#1} {#2} #1 } % \end{macrocode} %\end{macro} % % \begin{macro}{\@@_unit_parse_init:} % As always, the initialisation is a separate routine to make life a % little clearer. The definition of \cs{pm} is saved here as it % is used by units and numbers. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_parse_init: { \prop_clear:N \l_@@_unit_prop \int_zero:N \l_@@_unit_int \bool_set_false:N \l_@@_per_bool \seq_map_inline:Nn \l_@@_declare_list_seq { \cs_set_eq:Nc ##1 { @@_ \token_to_str:N ##1 _function:w } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_unit_parse_options:n} % Any unit-specific options are loaded, followed by re-applying any % options given for this particular macro. The second call to % \cs{keys_set:nn} is needed to allow the local overriding of settings. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_parse_options:nn #1#2 { \tl_if_single:nT {#1} { \cs_if_free:cF { l_@@_ \@@_unit_first_token:n {#1} _options_tl } { \keys_set:nv { siunitx } { l_@@_ \@@_unit_first_token:n {#1} _options_tl } \keys_set:nn { siunitx } {#2} } } } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_unit_parse_power_before:n , % \@@_unit_parse_power_after:n %} % Storing powers depends on whether they are given before or after % the unit. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_parse_power_before:n #1 { \tl_set:Nx \l_@@_tmpa_tl { power- \int_eval:n { \l_@@_unit_int + 1 } } \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#1} } \cs_new_protected:Npn \@@_unit_parse_power_after:n #1 { \tl_set:Nx \l_@@_tmpa_tl { power- \int_use:N \l_@@_unit_int } \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#1} } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \@@_unit_parse_prefix:Nn , % \@@_unit_parse_prefix:nn %} % Saving prefixes always increments the counter. For non-symbolic % mode, the base needs to be saved along with the power. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_parse_prefix:Nn #1#2 { \int_incr:N \l_@@_unit_int \tl_set:Nx \l_@@_tmpa_tl { prefix- \int_use:N \l_@@_unit_int } \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#1} \tl_set:Nx \l_@@_tmpa_tl { prefix-symbol- \int_use:N \l_@@_unit_int } \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#2} } \cs_new_protected:Npn \@@_unit_parse_prefix:nn #1#2 { \@@_unit_parse_prefix:Nn \ERROR {#2} \tl_set:Nx \l_@@_tmpa_tl { prefix-base- \int_use:N \l_@@_unit_int } \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#1} } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_unit_parse_per:} % The \cs{per} function always applies to the next unit seen, so % the counter has to be advanced by one. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_parse_per: { \tl_set:Nx \l_@@_tmpa_tl { per- \int_eval:n { \l_@@_unit_int + 1 } } \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl { true } \bool_if:NT \l_@@_sticky_per_bool { \cs_set_eq:NN \per \@@_unit_parse_per_error: } } \cs_new_protected:Npn \@@_unit_parse_per_error: { \msg_error:nn { siunitx } { duplicate-sticky-per } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_unit_parse_qualifier:n} % Qualifiers never alter the number of units. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_parse_qualifier:n #1 { \tl_set:Nx \l_@@_tmpa_tl { symbol- \int_use:N \l_@@_unit_int } \prop_if_in:NVF \l_@@_unit_prop \l_@@_tmpa_tl { \msg_error:nn { siunitx } { qualifier-before-unit } } \tl_set:Nx \l_@@_tmpa_tl { qualifier- \int_use:N \l_@@_unit_int } \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#1} } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_unit_parse_special:n} % Special effects are possible by adding code to the unit property % list here: this is pretty much arbitrary, so there is no real % processing done. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_parse_special:n #1 { \tl_set:Nx \l_@@_tmpa_tl { special- \int_eval:n { \l_@@_unit_int + 1 } } \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#1} } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_unit_parse_unit:Nn} %\begin{macro}[aux]{\@@_unit_parse_unit_per:} % For units, there is a check in case a prefix is present (which will % have incremented the counter). With the counter correct, simply add % the literal to the property list. There is also a check to see if % there is a \enquote{sticky} \cs{per} to think about. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_parse_unit:Nn #1#2 { \tl_set:Nx \l_@@_tmpa_tl { prefix-symbol- \int_use:N \l_@@_unit_int } \prop_if_in:NVTF \l_@@_unit_prop \l_@@_tmpa_tl { \tl_set:Nx \l_@@_tmpa_tl { symbol- \int_use:N \l_@@_unit_int } \prop_if_in:NVT \l_@@_unit_prop \l_@@_tmpa_tl { \int_incr:N \l_@@_unit_int } } { \int_incr:N \l_@@_unit_int } \tl_set:Nx \l_@@_tmpa_tl { unit- \int_use:N \l_@@_unit_int } \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#1} \tl_set:Nx \l_@@_tmpa_tl { symbol- \int_use:N \l_@@_unit_int } \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl {#2} \@@_unit_parse_unit_per: } \cs_new_protected:Npn \@@_unit_parse_unit_per: { \bool_if:NT \l_@@_sticky_per_bool { \bool_if:NT \l_@@_per_bool { \tl_set:Nx \l_@@_tmpa_tl { per- \int_use:N \l_@@_unit_int } \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl { true } } } } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Unit formatting} % %\begin{macro}{ % \l_@@_preunit_tl , % \l_@@_unit_tl , % \l_@@_unit_current_tl , % \l_@@_unit_denominator_tl , % \l_@@_unit_numerator_tl , % \l_@@_unit_saved_tl %} % Storage space for creating unit output. % \begin{macrocode} \tl_new:N \l_@@_preunit_tl \tl_new:N \l_@@_unit_tl \tl_new:N \l_@@_unit_current_tl \tl_new:N \l_@@_unit_denominator_tl \tl_new:N \l_@@_unit_numerator_tl \tl_new:N \l_@@_unit_saved_tl % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_unit_denominator_int , % \l_@@_unit_numerator_int %} % For tracking in case brackets are needed. % \begin{macrocode} \int_new:N \l_@@_unit_denominator_int \int_new:N \l_@@_unit_numerator_int % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_unit_prefix_int , % \l_@@_unit_prefix_base_int , % \l_@@_unit_prefix_current_tl %} % Used to calculate the overall prefix value. % \begin{macrocode} \int_new:N \l_@@_unit_prefix_int \int_new:N \l_@@_unit_prefix_base_int \tl_new:N \l_@@_unit_prefix_current_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_unit_prefix_gram_int} % Formatting units is complicated by the fact that the kilogram is a % base unit, making conversions a little more awkward. % \begin{macrocode} \int_new:N \l_@@_unit_prefix_gram_int % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_omit_unit_space_bool} % Needed to omit the space between a number an a unit when printing % symbols and when there is no numerator unit. % \begin{macrocode} \bool_new:N \l_@@_omit_unit_space_bool % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_per_auto_bool , % \l_@@_per_fraction_bool , % \l_@@_per_mode_tl , % \l_@@_power_number_bool , % \l_@@_qualifier_mode_tl , % \l_@@_per_two_parts_bool %} % For saving settings. % \begin{macrocode} \bool_new:N \l_@@_per_auto_bool \bool_new:N \l_@@_per_fraction_bool \tl_new:N \l_@@_per_mode_tl \bool_new:N \l_@@_power_number_bool \bool_new:N \l_@@_two_parts_bool \tl_new:N \l_@@_qualifier_mode_tl % \end{macrocode} %\end{macro} % %\begin{macro}{ % \l_@@_unit_denominator_bracket_bool , % \l_@@_unit_product_tl , % \l_@@_literal_power_bool , % \l_@@_per_symbol_tl , % \l_@@_qualifier_phrase_tl %} % At this stage, output formatting options are created. % \begin{macrocode} \keys_define:nn { siunitx } { bracket-unit-denominator .bool_set:N = \l_@@_unit_denominator_bracket_bool, inter-unit-product .tl_set:N = \l_@@_unit_product_tl , inter-unit-separator .tl_set:N = \l_@@_unit_product_tl , literal-superscript-as-power .bool_set:N = \l_@@_literal_power_bool, per-mode .choice:, per-mode / fraction .code:n = { \bool_set_false:N \l_@@_per_auto_bool \bool_set_true:N \l_@@_per_fraction_bool \bool_set_true:N \l_@@_per_two_parts_bool \tl_set:Nn \l_@@_per_mode_tl { fraction } }, per-mode / power .meta:n = { per-mode = reciprocal } , per-mode / power-positive-first .meta:n = { per-mode = reciprocal-positive-first } , per-mode / reciprocal .code:n = { \bool_set_false:N \l_@@_per_auto_bool \bool_set_false:N \l_@@_per_fraction_bool \bool_set_false:N \l_@@_per_two_parts_bool \tl_clear:N \l_@@_per_mode_tl }, per-mode / reciprocal-positive-first .code:n = { \bool_set_false:N \l_@@_per_auto_bool \bool_set_false:N \l_@@_per_fraction_bool \bool_set_true:N \l_@@_per_two_parts_bool \tl_clear:N \l_@@_per_mode_tl }, per-mode / repeated-symbol .code:n = { \bool_set_false:N \l_@@_per_auto_bool \bool_set_false:N \l_@@_per_fraction_bool \bool_set_false:N \l_@@_per_two_parts_bool \tl_set:Nn \l_@@_per_mode_tl { repeat } }, per-mode / symbol .code:n = { \bool_set_false:N \l_@@_per_auto_bool \bool_set_true:N \l_@@_per_fraction_bool \bool_set_true:N \l_@@_per_two_parts_bool \tl_set:Nn \l_@@_per_mode_tl { symbol } }, per-mode / symbol-or-fraction .code:n = { \bool_set_true:N \l_@@_per_auto_bool \bool_set_true:N \l_@@_per_fraction_bool \bool_set_true:N \l_@@_per_two_parts_bool \tl_set:Nn \l_@@_per_mode_tl { symbol } }, per-symbol .tl_set:N = \l_@@_per_symbol_tl, power-font .choice:, power-font / number .code:n = { \bool_set_true:N \l_@@_power_number_bool }, power-font / unit .code:n = { \bool_set_false:N \l_@@_power_number_bool }, qualifier-mode .choice:, qualifier-mode / brackets .code:n = { \tl_set:Nn \l_@@_qualifier_mode_tl { brackets } }, qualifier-mode / phrase .code:n = { \tl_set:Nn \l_@@_qualifier_mode_tl { phrase } }, qualifier-mode / space .code:n = { \tl_set:Nn \l_@@_qualifier_mode_tl { space } }, qualifier-mode / subscript .code:n = { \tl_set:Nn \l_@@_qualifier_mode_tl { subscript } }, qualifier-mode / text .code:n = { \tl_set:Nn \l_@@_qualifier_mode_tl { text } }, qualifier-phrase .tl_set:N = \l_@@_qualifier_phrase_tl } \keys_set:nn { siunitx } { bracket-unit-denominator = true, inter-unit-product = \,, literal-superscript-as-power = true, per-mode = reciprocal, per-symbol = /, power-font = number, qualifier-mode = subscript, qualifier-phrase = { ~ of ~ } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_unit_format:} % Most of the work is done by the loop, with a little tidying up for % fraction-like output. Before starting the loop, there is a check for % the case of a single reciprocal unit when per is set up to create a % symbol. In that special case, the space between a number and a unit % has to be removed. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format: { \@@_unit_format_init: \int_while_do:nNnn { \l_@@_unit_int } > { 0 } { \@@_unit_format_prefix: \@@_unit_format_symbol: \@@_unit_format_qualifier: \@@_unit_format_power: \@@_unit_format_add: \int_decr:N \l_@@_unit_int } \bool_if:NT \l_@@_per_two_parts_bool { \bool_if:NTF \l_@@_per_fraction_bool { \@@_unit_format_fraction: } { \@@_unit_format_sorted: } } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_unit_format_add:} %\begin{macro}[aux]{\@@_unit_format_add_aux:n} % Adding the current unit to the output means checking where it goes. % The odd code when adding a space is to pick up repeated per symbols, % which need to suppress the space. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format_add: { \bool_if:NTF \l_@@_per_two_parts_bool { \tl_set:Nx \l_@@_tmpb_tl { per- \int_use:N \l_@@_unit_int } \prop_if_in:NVTF \l_@@_unit_prop \l_@@_tmpb_tl { \@@_unit_format_add_aux:n { _denominator } \int_incr:N \l_@@_unit_denominator_int } { \@@_unit_format_add_aux:n { _numerator } \int_incr:N \l_@@_unit_numerator_int } } { \@@_unit_format_add_aux:n { } } \tl_clear:N \l_@@_unit_current_tl } \cs_new_protected:Npn \@@_unit_format_add_aux:n #1 { \tl_if_empty:cF { l_@@_unit #1 _tl } { \str_if_eq:VnTF \l_@@_per_mode_tl { repeat } { \tl_set:Nx \l_@@_tmpa_tl { per- \int_eval:n { \l_@@_unit_int + 1 } } \prop_if_in:NVF \l_@@_unit_prop \l_@@_tmpa_tl { \tl_put_right:NV \l_@@_unit_current_tl \l_@@_unit_product_tl } } { \tl_put_right:NV \l_@@_unit_current_tl \l_@@_unit_product_tl } } \tl_set:Nx \l_@@_tmpa_tl { special- \int_use:N \l_@@_unit_int } \prop_get:NVNTF \l_@@_unit_prop \l_@@_tmpa_tl \l_@@_tmpa_tl { \tl_put_left:cx { l_@@_unit #1 _tl } { \exp_not:V \l_@@_tmpa_tl { \exp_not:V \l_@@_unit_current_tl } } } { \tl_put_left:cV { l_@@_unit #1 _tl } \l_@@_unit_current_tl } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_unit_format_fraction:} %\begin{macro}[aux]{ % \@@_unit_format_fraction: , % \@@_unit_format_auto: , % \@@_unit_format_symbol: , % \@@_unit_format_symbol_aux: , % \@@_unit_format_symbol_aux_alt: %} % When making (\emph{psuedo}-)fractions there is a check to place a % \( 1 \) in the numerator is it's blank. For symbol mode, this is % only done if there is no number. Then some construction work. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format_fraction: { \int_compare:nNnT { \l_@@_unit_numerator_int } = { 0 } { \str_if_eq:VnT \l_@@_per_mode_tl { symbol } { \bool_set_true:N \l_@@_omit_unit_space_bool } } \int_compare:nNnTF { \l_@@_unit_denominator_int } > { 0 } { \bool_if:NTF \l_@@_per_auto_bool { \@@_unit_format_fraction_auto: } { \use:c { @@_unit_format_fraction_ \l_@@_per_mode_tl : } } } { \tl_set_eq:NN \l_@@_unit_tl \l_@@_unit_numerator_tl } } \cs_new_protected:Npn \@@_unit_format_fraction_fraction: { \tl_if_empty:NT \l_@@_unit_numerator_tl { \tl_set:Nn \l_@@_unit_numerator_tl { 1 } } \tl_set:Nx \l_@@_unit_numerator_tl { { \exp_not:V \l_@@_unit_numerator_tl } } \tl_put_left:Nn \l_@@_unit_numerator_tl { \@@_print:nn { unit } } \tl_set:Nx \l_@@_unit_numerator_tl { { \exp_not:V \l_@@_unit_numerator_tl } } \tl_set:Nx \l_@@_unit_denominator_tl { { \exp_not:V \l_@@_unit_denominator_tl } } \tl_put_left:Nn \l_@@_unit_denominator_tl { \@@_print:nn { unit } } \tl_set:Nx \l_@@_unit_denominator_tl { { \exp_not:V \l_@@_unit_denominator_tl } } \tl_set:Nn \l_@@_unit_tl { \@@_fraction:nn } \tl_put_right:NV \l_@@_unit_tl \l_@@_unit_numerator_tl \tl_put_right:NV \l_@@_unit_tl \l_@@_unit_denominator_tl \tl_set:Nx \l_@@_unit_tl { \exp_not:N \ensuremath { \exp_not:V \l_@@_unit_tl } } } % \end{macrocode} % For the \opt{symbol} setting, there is a need to deal with the % possible \opt{symbol-or-fraction} choice. That is achieved by % setting up both the \opt{fraction} and \opt{symbol} output. % In the automatic mode, both cases are combined inside a % \cs{tex_mathchoice:D}, with appropriate protection, before sending % everything through for printing. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format_fraction_auto: { \mode_if_math:TF { \group_begin: \@@_unit_format_fraction_fraction: \exp_args:NNNV \group_end: \tl_set:Nn \l_@@_tmpa_tl \l_@@_unit_tl \group_begin: \@@_unit_format_fraction_symbol: \exp_args:NNNV \group_end: \tl_set:Nn \l_@@_tmpb_tl \l_@@_unit_tl \tl_set:Nx \l_@@_tmpb_tl { \@@_print:nn { unit } { \exp_not:V \l_@@_tmpb_tl } } \tl_set:Nx \l_@@_unit_tl { \exp_not:N \ensuremath { \tex_mathchoice:D { \exp_not:V \l_@@_tmpa_tl } { \exp_not:V \l_@@_tmpb_tl } { \exp_not:V \l_@@_tmpb_tl } { \exp_not:V \l_@@_tmpb_tl } } } } { \@@_unit_format_fraction_symbol: } } % \end{macrocode} % For a normal symbol, the two parts of the input are arranged either % side of the symbol itself in math mode. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format_fraction_symbol: { \@@_unit_format_fraction_symbol_aux: \int_compare:nNnT { \l_@@_unit_denominator_int } > { 1 } { \bool_if:NT \l_@@_unit_denominator_bracket_bool { \tl_put_left:NV \l_@@_unit_denominator_tl \l_@@_bracket_open_tl \tl_put_right:NV \l_@@_unit_denominator_tl \l_@@_bracket_close_tl } } \tl_set_eq:NN \l_@@_unit_tl \l_@@_unit_numerator_tl \tl_put_right:NV \l_@@_unit_tl \l_@@_per_symbol_tl \tl_put_right:NV \l_@@_unit_tl \l_@@_unit_denominator_tl } \cs_new_protected:Npn \@@_unit_format_fraction_symbol_aux: { } \cs_new_protected:Npn \@@_unit_format_fraction_symbol_aux_alt: { \tl_if_empty:NT \l_@@_unit_numerator_tl { \tl_set:Nn \l_@@_unit_numerator_tl { 1 } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_unit_format_init:} % The normal initialisation stuff. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format_init: { \bool_set_false:N \l_@@_omit_unit_space_bool \tl_clear:N \l_@@_unit_tl \tl_clear:N \l_@@_unit_current_tl \tl_clear:N \l_@@_unit_denominator_tl \int_zero:N \l_@@_unit_prefix_gram_int \tl_clear:N \l_@@_unit_numerator_tl \int_zero:N \l_@@_unit_prefix_base_int \int_zero:N \l_@@_unit_prefix_int \int_zero:N \l_@@_unit_denominator_int \int_zero:N \l_@@_unit_numerator_int \seq_map_inline:Nn \l_@@_declare_list_seq { \@@_unit_print_literal_aux:N ##1 } } % \end{macrocode} %\end{macro} % % \begin{macro}{\@@_unit_format_literal:n} % \begin{macro}[aux]{\@@_unit_format_literal_aux:N} % \begin{macro}[aux]{\@@_unit_format_literal_power:n} % If the unit given contains anything which is not a unit macro, then % any unit macros that are there simply dump literal meanings. There is % then a little work to do sorting out |~| and |.| characters at % the outer level. % \begin{macrocode} \group_begin: \char_set_lccode:nn { `\+ } { `\^ } \char_set_catcode_active:N \~ \tl_to_lowercase:n { \group_end: \cs_new_protected:Npn \@@_unit_format_literal:n #1 { \int_zero:N \l_@@_unit_prefix_int \seq_map_inline:Nn \l_@@_declare_list_seq { \@@_unit_print_literal_aux:N ##1 } \tl_set:Nn \l_@@_unit_tl {#1} \tl_replace_all:NnV \l_@@_unit_tl { . } \l_@@_unit_product_tl \tl_replace_all:NnV \l_@@_unit_tl { ~ } \l_@@_unit_product_tl \bool_if:NT \l_@@_literal_power_bool { \tl_replace_all:Nnn \l_@@_unit_tl { ^ } { \@@_unit_format_literal_power:n } \tl_replace_all:Nnn \l_@@_unit_tl { + } { \@@_unit_format_literal_power:n } } \@@_unit_format_literal_extras: } } \cs_new_protected:Npn \@@_unit_print_literal_aux:N #1 { \cs_set_eq:Nc #1 { @@_ \token_to_str:N #1 _literal:w } } \cs_new_protected:Npn \@@_unit_format_literal_power:n #1 { \PrintSuperscript { \@@_unit_format_power_aux:n {#1} } } % \end{macrocode} % \end{macro} % \end{macro} %\end{macro} % %\begin{macro}{\@@_unit_format_literal_extras:} %\begin{macro}[aux]{\@@_unit_format_literal_extras_aux:nN} % The code here deals with characters outside the normal range that % can appear in units in UTF-8 and related encodings. The idea is to % do a search and replace, thus avoiding any active characters. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format_literal_extras: { \@@_unit_format_literal_extras_aux:nN { 176 } \SIUnitSymbolDegree \@@_unit_format_literal_extras_aux:nN { 181 } \SIUnitSymbolMicro \@@_unit_format_literal_extras_aux:nN { 197 } \SIUnitSymbolAngstrom } \cs_new_protected:Npn \@@_unit_format_literal_extras_aux:nN #1#2 { \char_set_lccode:nn { `\@ } {#1} \tl_to_lowercase:n { \tl_replace_all:NnV \l_@@_unit_tl { @ } #2 } } \pdftex_if_engine:T { \AtBeginDocument { \cs_if_exist:NTF \inputencodingname { \tl_set:Nn \l_@@_tmpa_tl { latin1 , latin5 , latin9 } \clist_if_in:NVF \l_@@_tmpa_tl \inputencodingname { \cs_set_eq:NN \@@_unit_format_literal_extras: \scan_stop: } } { \cs_set_eq:NN \@@_unit_format_literal_extras: \scan_stop: } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_unit_format_power:} %\begin{macro}[aux]{ % \@@_unit_format_power_aux: , % \@@_unit_format_power_aux:n , % \@@_unit_format_power_aux:nn , % \@@_unit_format_power_brackets: , % \@@_unit_format_power_per: , % \@@_unit_format_power_repeat: %} % To format powers, there are a few issues: are brackets needed, is % the power reciprocal and is fraction-formatting in operation. Repeated % per symbols make life a little more complex, as they have to be % handled here as well. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format_power: { \tl_set:Nx \l_@@_tmpa_tl { power- \int_use:N \l_@@_unit_int } \prop_get:NVNTF \l_@@_unit_prop \l_@@_tmpa_tl \l_@@_tmpa_tl { \@@_unit_format_power_aux: } { \tl_set:Nx \l_@@_tmpa_tl { per- \int_use:N \l_@@_unit_int } \prop_if_in:NVT \l_@@_unit_prop \l_@@_tmpa_tl { \tl_set:Nn \l_@@_tmpa_tl { 1 } \@@_unit_format_power_aux: } } } % \end{macrocode} % The auxiliary function needs to make sure that the printing routine % prints the power as a number, not as text: the two modes may be % different. A search and replace function is needed for superscripts % in text mode so that negative signs get printed correctly. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format_power_aux: { \str_if_eq:VnTF \l_@@_per_mode_tl { repeat } { \@@_unit_format_power_repeat: } { \@@_unit_format_power_per: } \str_if_eq:VnF \l_@@_tmpa_tl { 1 } { \@@_unit_format_power_brackets: \tl_put_right:Nx \l_@@_unit_current_tl { \exp_not:N \PrintSuperscript { \@@_unit_format_power_aux:n { \exp_not:V \l_@@_tmpa_tl } } } } } \cs_new_protected:Npn \@@_unit_format_power_aux:n #1 { \bool_if:NTF \l_@@_power_number_bool { \@@_unit_format_power_aux:nn { number } {#1} } { \@@_unit_format_power_aux:nn { unit } {#1} } } \cs_new_protected:Npn \@@_unit_format_power_aux:nn #1#2 { \bool_if:cTF { l_@@_ #1 _math_mode_bool } { \@@_print:nn {#1} {#2} } { \tl_set:Nn \l_@@_tmpa_tl {#2} \tl_replace_all:Nnn \l_@@_tmpa_tl { - } { \text { \c_@@_minus_tl } } \@@_print:nV {#1} \l_@@_tmpa_tl } } % \end{macrocode} % A check is made for a qualifier with a space, which needs brackets % if there is also a power. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format_power_brackets: { \tl_set:Nx \l_@@_tmpb_tl { bracket- \int_use:N \l_@@_unit_int } \prop_if_in:NVT \l_@@_unit_prop \l_@@_tmpb_tl { \tl_put_left:NV \l_@@_unit_current_tl \l_@@_bracket_open_tl \tl_put_right:NV \l_@@_unit_current_tl \l_@@_bracket_close_tl } } % \end{macrocode} % For dealing with \cs{per} and repeated \cs{per} symbols. The sign % change does not use any numbers, as this makes life easier with % non-integer values. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format_power_per: { \tl_set:Nx \l_@@_tmpb_tl { per- \int_use:N \l_@@_unit_int } \prop_if_in:NVT \l_@@_unit_prop \l_@@_tmpb_tl { \bool_if:NF \l_@@_per_fraction_bool { \tl_if_in:NnTF \l_@@_tmpa_tl { - } { \cs_set:Npn \@@_tmp:w ##1 - ##2 \q_stop { \tl_set:Nn \l_@@_tmpa_tl {##2} } \exp_after:wN \@@_tmp:w \l_@@_tmpa_tl \q_stop } { \tl_put_left:Nn \l_@@_tmpa_tl { - } } } } } \cs_new_protected:Npn \@@_unit_format_power_repeat: { \tl_set:Nx \l_@@_tmpb_tl { per- \int_use:N \l_@@_unit_int } \prop_if_in:NVT \l_@@_unit_prop \l_@@_tmpb_tl { \tl_put_left:NV \l_@@_unit_current_tl \l_@@_per_symbol_tl } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_unit_format_prefix:} %\begin{macro}[aux]{ % \@@_unit_format_prefix_number: , % \@@_unit_format_prefix_number_calc: , % \@@_unit_format_prefix_symbol: %} % If there is a prefix, it is added to the output. When using numerical % output, some conversion is needed instead. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format_prefix: { \tl_set:Nx \l_@@_tmpa_tl { prefix-symbol- \int_use:N \l_@@_unit_int } \prop_if_in:NVT \l_@@_unit_prop \l_@@_tmpa_tl { \prop_get:NVN \l_@@_unit_prop \l_@@_tmpa_tl \l_@@_unit_prefix_current_tl \bool_if:NTF \l_@@_prefix_symbols_bool { \@@_unit_format_prefix_symbol: } { \@@_unit_format_prefix_number: } } } \cs_new_protected:Npn \@@_unit_format_prefix_number: { \tl_set:Nx \l_@@_tmpa_tl { prefix-base- \int_use:N \l_@@_unit_int } \prop_get:NVN \l_@@_unit_prop \l_@@_tmpa_tl \l_@@_tmpa_tl \int_compare:nNnT { \l_@@_unit_prefix_base_int } = { 0 } { \int_set:Nn \l_@@_unit_prefix_base_int { \l_@@_tmpa_tl } } \int_compare:nNnTF { \l_@@_unit_prefix_base_int } = { \l_@@_tmpa_tl } { \@@_unit_format_prefix_number_calc: } { \msg_error:nn { siunitx } { prefix-base-mismatch } } } % \end{macrocode} % The calculation for converting a unit prefix into a number is % simple unless there are grammes involved. In that case, the base unit % is the kilogram and so there is some code to convert the number % back correctly. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format_prefix_number_calc: { \tl_set:Nx \l_@@_tmpa_tl { power- \int_use:N \l_@@_unit_int } \prop_get:NVNF \l_@@_unit_prop \l_@@_tmpa_tl \l_@@_tmpa_tl { \tl_set:Nn \l_@@_tmpa_tl { 1 } } \tl_set:Nx \l_@@_tmpb_tl { unit- \int_use:N \l_@@_unit_int } \prop_get:NVN \l_@@_unit_prop \l_@@_tmpb_tl \l_@@_tmpb_tl \str_if_eq:VnT \l_@@_tmpb_tl { \gram } { \tl_set:Nx \l_@@_unit_prefix_current_tl { \int_eval:n { \l_@@_unit_prefix_current_tl - 3 } } \tl_set:Nx \l_@@_tmpb_tl { symbol- \int_use:N \l_@@_unit_int } \prop_put:NVn \l_@@_unit_prop \l_@@_tmpb_tl { kg } } \tl_set:Nx \l_@@_unit_prefix_current_tl { \int_eval:n { \l_@@_unit_prefix_current_tl * \l_@@_tmpa_tl } } \tl_set:Nx \l_@@_tmpa_tl { per- \int_use:N \l_@@_unit_int } \prop_if_in:NVTF \l_@@_unit_prop \l_@@_tmpa_tl { \int_set:Nn \l_@@_unit_prefix_int { \l_@@_unit_prefix_int - \l_@@_unit_prefix_current_tl } } { \int_set:Nn \l_@@_unit_prefix_int { \l_@@_unit_prefix_int + \l_@@_unit_prefix_current_tl } } } \cs_new_protected:Npn \@@_unit_format_prefix_symbol: { \tl_set_eq:NN \l_@@_unit_current_tl \l_@@_unit_prefix_current_tl } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_unit_format_qualifier:} %\begin{macro}[aux]{ % \@@_unit_format_qualifier_brackets: , % \@@_unit_format_qualifier_phrase: , % \@@_unit_format_qualifier_space: , % \@@_unit_format_qualifier_subscript: , % \@@_unit_format_qualifier_text: %} % Four methods for showing qualifiers, each with its own sub-function. % For the \texttt{space} methods, a warning is set in the property list % as if there is a power then some brackets will be needed. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format_qualifier: { \tl_set:Nx \l_@@_tmpa_tl { qualifier- \int_use:N \l_@@_unit_int } \prop_get:NVNT \l_@@_unit_prop \l_@@_tmpa_tl \l_@@_tmpa_tl { \use:c { @@_unit_format_qualifier_ \l_@@_qualifier_mode_tl : } } } \cs_new_protected:Npn \@@_unit_format_qualifier_brackets: { \tl_put_right:NV \l_@@_unit_current_tl \l_@@_bracket_open_tl \tl_put_right:NV \l_@@_unit_current_tl \l_@@_tmpa_tl \tl_put_right:NV \l_@@_unit_current_tl \l_@@_bracket_close_tl } \cs_new_protected_nopar:Npn \@@_unit_format_qualifier_phrase: { \tl_put_right:NV \l_@@_unit_current_tl \l_@@_qualifier_phrase_tl \tl_put_right:NV \l_@@_unit_current_tl \l_@@_tmpa_tl \tl_set:Nx \l_@@_tmpa_tl { bracket- \int_use:N \l_@@_unit_int } \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl { true } } \char_set_catcode_active:N \~ \cs_new_protected:Npn \@@_unit_format_qualifier_space: { \tl_put_right:Nn \l_@@_unit_current_tl { \text { ~ } } \tl_put_right:NV \l_@@_unit_current_tl \l_@@_tmpa_tl \tl_set:Nx \l_@@_tmpa_tl { bracket- \int_use:N \l_@@_unit_int } \prop_put:NVn \l_@@_unit_prop \l_@@_tmpa_tl { true } } \char_set_catcode_space:N \~ \cs_new_protected:Npn \@@_unit_format_qualifier_subscript: { \tl_put_right:Nx \l_@@_unit_current_tl { \exp_not:N \PrintSubscript { \exp_not:V \l_@@_tmpa_tl } } } \cs_new_protected:Npn \@@_unit_format_qualifier_text: { \tl_put_right:NV \l_@@_unit_current_tl \l_@@_tmpa_tl } % \end{macrocode} %\end{macro} %\end{macro} % % \begin{macro}{\@@_unit_format_sorted:} % For when the powers are sorted with the positive ones first. The only % slight issue is making sure that the additional space is included % between the two units, if needed. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format_sorted: { \tl_set_eq:NN \l_@@_unit_tl \l_@@_unit_numerator_tl \tl_if_empty:NT \l_@@_unit_tl { \tl_if_empty:NF \l_@@_unit_denominator_tl { \tl_put_right:NV \l_@@_unit_tl \l_@@_unit_product_tl } } \tl_put_right:NV \l_@@_unit_tl \l_@@_unit_denominator_tl } % \end{macrocode} % \end{macro} % %\begin{macro}{\@@_unit_format_symbol:} %\begin{macro}[aux]{ % \@@_unit_format_symbol_aux: , % \@@_unit_format_symbol_aux_alt: %} % If there is no symbol, something is wrong! The only exception is % when the code is inside the \cs{si} function (or similar) and there % is only a prefix with nothing else present at all. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_format_symbol: { \tl_set:Nx \l_@@_tmpa_tl { symbol- \int_use:N \l_@@_unit_int } \prop_get:NVNTF \l_@@_unit_prop \l_@@_tmpa_tl \l_@@_tmpa_tl { \tl_put_right:NV \l_@@_unit_current_tl \l_@@_tmpa_tl } { \@@_unit_format_symbol_aux: } } \cs_new_protected:Npn \@@_unit_format_symbol_aux: { \msg_error:nn { siunitx } { prefix-only } } \cs_new_protected:Npn \@@_unit_format_symbol_aux_alt: { \int_compare:nNnTF { \l_@@_unit_int } = { 1 } { \prop_remove:Nn \l_@@_unit_prop { prefix-1 } \prop_remove:Nn \l_@@_unit_prop { prefix-symbol-1 } \prop_remove:Nn \l_@@_unit_prop { prefix-base-1 } \prop_if_empty:NF \l_@@_unit_prop { \msg_error:nn { siunitx } { prefix-only } } } { \msg_error:nn { siunitx } { prefix-only } } } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Unit output} % % A collection of the internal parts of various user functions. % %\begin{macro}{\l_@@_multi_brackets_bool} %\begin{macro}{\l_@@_multi_repeat_bool} % Flags for multi-part numbers. % \begin{macrocode} \bool_new:N \l_@@_multi_brackets_bool \bool_new:N \l_@@_multi_repeat_bool % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_@@_product_brackets_bool} %\begin{macro}{\l_@@_product_power_bool} %\begin{macro}{\l_@@_number_unit_repeat_bool} % Flags for product units. % \begin{macrocode} \bool_new:N \l_@@_product_brackets_bool \bool_new:N \l_@@_product_power_bool \bool_new:N \l_@@_number_unit_repeat_bool % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_@@_number_unit_breaks_bool} %\begin{macro}{\l_@@_number_unit_product_tl} % Options for printing units or units with numbers. % \begin{macrocode} \keys_define:nn { siunitx } { allow-number-unit-breaks .bool_set:N = \l_@@_number_unit_breaks_bool, multi-part-units .choice:, multi-part-units / brackets .code:n = { \bool_set_true:N \l_@@_multi_brackets_bool \bool_set_false:N \l_@@_multi_repeat_bool }, multi-part-units / repeat .code:n = { \bool_set_false:N \l_@@_multi_brackets_bool \bool_set_true:N \l_@@_multi_repeat_bool }, multi-part-units / single .code:n = { \bool_set_false:N \l_@@_multi_brackets_bool \bool_set_false:N \l_@@_multi_repeat_bool }, number-unit-product .tl_set:N = \l_@@_number_unit_product_tl, number-unit-separator .tl_set:N = \l_@@_number_unit_product_tl, product-units .choice:, product-units / brackets .code:n = { \bool_set_true:N \l_@@_product_brackets_bool \bool_set_false:N \l_@@_product_power_bool \bool_set_false:N \l_@@_product_repeat_bool }, product-units / brackets-power .code:n = { \bool_set_true:N \l_@@_product_brackets_bool \bool_set_true:N \l_@@_product_power_bool \bool_set_false:N \l_@@_product_repeat_bool }, product-units / power .code:n = { \bool_set_false:N \l_@@_product_brackets_bool \bool_set_true:N \l_@@_product_power_bool \bool_set_false:N \l_@@_product_repeat_bool }, product-units / repeat .code:n = { \bool_set_false:N \l_@@_product_brackets_bool \bool_set_false:N \l_@@_product_power_bool \bool_set_true:N \l_@@_product_repeat_bool }, product-units / single .code:n = { \bool_set_false:N \l_@@_product_brackets_bool \bool_set_false:N \l_@@_product_power_bool \bool_set_false:N \l_@@_product_repeat_bool }, } \keys_set:nn { siunitx } { multi-part-units = brackets, number-unit-product = \, , product-units = repeat } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_unit_output:nn} %\begin{macro}{\@@_unit_output:Vn} % For typesetting a unit directly: used by \cs{si} and the \texttt{s} % column. The second argument is any options to set locally. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_output:nn #1#2 { \cs_set_eq:NN \@@_unit_format_symbol_aux: \@@_unit_format_symbol_aux_alt: \cs_set_eq:NN \@@_unit_format_fraction_symbol_aux_ii: \@@_unit_format_fraction_symbol_aux_alt: \@@_unit_in:nn {#1} {#2} \int_compare:nNnTF { \l_@@_unit_prefix_int } = { 0 } { \str_if_eq:VnT \l_@@_per_mode_tl { symbol } { \int_compare:nNnT { \l_@@_unit_numerator_int } = { 0 } { \@@_print:nn { unit } { 1 } } } } { \tl_set:Nx \l_@@_tmpa_tl { \int_use:N \l_@@_unit_prefix_base_int \exp_not:N \PrintSuperscript { \int_use:N \l_@@_unit_prefix_int } } \@@_print:nV { number } \l_@@_tmpa_tl \@@_unit_output_number_sep: } \@@_print:nV { unit } \l_@@_unit_tl } \cs_generate_variant:Nn \@@_unit_output:nn { V } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_unit_output_number_sep:} %\begin{macro}{\@@_unit_output_number_sep_aux:} % For printing the number separator. The \cs{tex_mathchoice:D} code % deals with the \opt{symbol-or-fraction} setting for \opt{per-mode}, % as in that case omission of the space between a number and unit % depends on the current math style. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_output_number_sep: { \bool_if:NTF \l_@@_number_unit_breaks_bool { \penalty \binoppenalty } { \nobreak } \bool_if:NTF \l_@@_per_auto_bool { \mode_if_math:TF { \tex_mathchoice:D { \l_@@_number_unit_product_tl } { \@@_unit_output_number_sep_aux: } { \@@_unit_output_number_sep_aux: } { \@@_unit_output_number_sep_aux: } } { \@@_unit_output_number_sep_aux: } } { \@@_unit_output_number_sep_aux: } } \cs_new_protected:Npn \@@_unit_output_number_sep_aux: { \bool_if:NF \l_@@_omit_unit_space_bool { \l_@@_number_unit_product_tl } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_unit_output_pre_print:} %\begin{macro}{\@@_unit_output_print:} % The printing functions for units do some simple tests then % actually print there output. % \begin{macrocode} \cs_new_protected:Npn \@@_unit_output_pre_print: { \tl_if_empty:NF \l_@@_pre_unit_tl { \nobreak \@@_print:nV { unit } \l_@@_pre_unit_tl } } \cs_new_protected:Npn \@@_unit_output_print: { \int_compare:nNnF { \l_@@_unit_prefix_int } = { 0 } { \tl_set:Nx \l_@@_tmpa_tl { \bool_if:NTF \l_@@_tight_bool { \exp_not:N \ensuremath { { \exp_not:V \l_@@_exponent_product_tl } } } { \exp_not:N \ensuremath { { } \exp_not:V \l_@@_exponent_product_tl { } } } \int_use:N \l_@@_unit_prefix_base_int ^ { \int_use:N \l_@@_unit_prefix_int } } \@@_print:nV { number } \l_@@_tmpa_tl } \tl_if_empty:NF \l_@@_unit_tl { \@@_unit_output_number_sep: \@@_print:nV { unit } \l_@@_unit_tl } } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Numbers with units} % % Numbers with units have to be formatted in a more complex way than % simply sticking the two together. % %\begin{macro}{\l_@@_preunit_tl} % A pre-unit is optional, so can be handled using the setting system. % \begin{macrocode} \keys_define:nn { siunitx } { preunit .tl_set:N = \l_@@_preunit_tl , } % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_pre_unit_tl} % When there is a pre-unit, it gets stored here. % \begin{macrocode} \tl_new:N \l_@@_pre_unit_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_number_product_int} % Used to count up the number of product tokens in a number. % \begin{macrocode} \int_new:N \l_@@_number_product_int % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_combined:nnnn} % Printing numbers and units means first processing the units, then % handing off this information to the combined number and unit % processor. % \begin{macrocode} \cs_new_protected:Npn \@@_combined:nnnn #1#2#3#4 { \IfNoValueTF {#3} { \tl_clear:N \l_@@_pre_unit_tl } { \group_begin: \@@_unit_in:nn {#3} {#1} \cs_set_eq:NN \l_@@_pre_unit_tl \l_@@_unit_tl \exp_args:NNNo \group_end: \tl_set:Nn \l_@@_pre_unit_tl { \l_@@_unit_tl } } \cs_set_eq:NN \l_@@_brackets_bool \l_@@_multi_brackets_bool \@@_combined_unit:nnn {#2} {#4} {#1} \@@_combined_output:n {#2} } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_combined_output:n} % Printing the combination of a number and a unit means checking for % parsing then parsing the number part. % \begin{macrocode} \cs_new_protected:Npn \@@_combined_output:n #1 { \bool_if:NTF \l_@@_number_parse_bool { \tl_clear:N \l_@@_number_out_tl \bool_set_false:N \l_@@_number_compound_bool \@@_number_output_parse:n {#1} } { \@@_unit_output_pre_print: \@@_print:nn { number } { \ensuremath {#1} } \@@_unit_output_print: } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_combined_unit:nnn} % In most cases, sorting out the main unit is easy: simply set up for % printing using \cs{@@_unit_in:nn}. However, if there are multiple % parts to the number, and they are to be combined into the unit, then % there is more work to do. In either case, the result is the % correctly-prepared unit stored in \cs{l_@@_unit_tl}. % \begin{macrocode} \cs_new_protected:Npn \@@_combined_unit:nnn #1#2#3 { \bool_if:NTF \l_@@_product_power_bool { \@@_combined_product_count:n {#1} \int_compare:nNnTF { \l_@@_number_product_int } > { 0 } { \int_incr:N \l_@@_number_product_int \tl_set:Nn \l_@@_tmpa_tl {#2} \tl_set:Nx \l_@@_tmpb_tl { \tothe { \exp_not:V \l_@@_number_product_int } } \tl_put_right:NV \l_@@_tmpa_tl \l_@@_tmpb_tl \@@_unit_in:Vn \l_@@_tmpa_tl {#3} } { \@@_unit_in:nn {#2} {#3} } } { \@@_unit_in:nn {#2} {#3} } } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_combined_product_count:n} %\begin{macro}[aux]{\@@_combined_product_count_aux:n} % For counting how many products are in a number, so that the unit % can be adjusted if needed. % \begin{macrocode} \cs_new_protected:Npn \@@_combined_product_count:n #1 { \int_zero:N \l_@@_number_product_int \tl_set:Nn \l_@@_tmpa_tl {#1} \tl_map_function:NN \l_@@_input_product_tl \@@_combined_product_count_aux:N } \cs_new_protected:Npn \@@_combined_product_count_aux:N #1 { \tl_if_in:NnT \l_@@_tmpa_tl {#1} { \int_incr:N \l_@@_number_product_int \tl_remove_once:Nn \l_@@_tmpa_tl {#1} \@@_combined_product_count_aux:N #1 } } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Lists of numbers} % %\begin{macro}{\l_@@_list_brackets_bool} %\begin{macro}{\l_@@_list_repeat_bool} % For storing the behaviour of list items with respect to units. % \begin{macrocode} \bool_new:N \l_@@_list_brackets_bool \bool_new:N \l_@@_list_repeat_bool % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_@@_list_current_tl} %\begin{macro}{\l_@@_list_tl} % Two token list variables used to store the list for output. % \begin{macrocode} \tl_new:N \l_@@_list_current_tl \tl_new:N \l_@@_list_tl % \end{macrocode} %\end{macro} %\end{macro} % % \begin{variable} % { % \l_@@_list_separator_pair_tl , % \l_@@_list_separator_final_tl , % \l_@@_list_separator_tl, % } % Settings for lists. % \begin{macrocode} \keys_define:nn { siunitx } { list-final-separator .tl_set:N = \l_@@_list_separator_final_tl , list-pair-separator .tl_set:N = \l_@@_list_separator_pair_tl , list-separator .tl_set:N = \l_@@_list_separator_tl , list-units .choice:, list-units / brackets .code:n = { \bool_set_true:N \l_@@_list_brackets_bool \bool_set_false:N \l_@@_list_repeat_bool }, list-units / repeat .code:n = { \bool_set_false:N \l_@@_list_brackets_bool \bool_set_true:N \l_@@_list_repeat_bool }, list-units / single .code:n = { \bool_set_false:N \l_@@_list_brackets_bool \bool_set_false:N \l_@@_list_repeat_bool } } \keys_set:nn { siunitx } { list-final-separator = { ~ and ~ } , list-pair-separator = { ~ and ~ } , list-separator = { , ~ } , list-units = repeat } % \end{macrocode} % \end{variable} % % \begin{macro}{\@@_list_numbers:n} % \begin{macro}[aux] % {\@@_list_numbers_aux_i:n, \@@_list_numbers_aux_ii:n} % \begin{macro}{\@@_list_numbers_aux:nn} % Setting up lists is made slightly complicated by the need to handle the % case of exactly two items and the case of the very last separator % differently from everything else. Beyond that, there is not too much % to any of this code. % \begin{macrocode} \cs_new_protected:Npn \@@_list_numbers:n #1 { \tl_clear:N \l_@@_unit_tl \tl_clear:N \l_@@_preunit_tl \@@_list_numbers_aux_i:n {#1} } \cs_new_protected:Npn \@@_list_numbers_aux_i:n #1 { \bool_set_true:N \l_@@_list_first_bool \tl_clear:N \l_@@_list_current_tl \int_compare:nNnTF { \tl_count:n {#1} } > \c_two { \tl_map_function:nN {#1} \@@_list_numbers_aux_ii:n \l_@@_list_tl \l_@@_list_separator_final_tl \l_@@_list_current_tl } { \int_compare:nNnTF { \tl_count:n {#1} } = \c_two { \@@_list_numbers_aux:nn #1 } { \@@_combined_output:n #1 } } } \cs_new_protected:Npn \@@_list_numbers_aux_ii:n #1 { \tl_if_empty:NTF \l_@@_list_tl { \tl_set_eq:NN \l_@@_list_tl \l_@@_list_current_tl } { \tl_put_right:NV \l_@@_list_tl \l_@@_list_separator_tl \tl_put_right:NV \l_@@_list_tl \l_@@_list_current_tl } \tl_set:Nn \l_@@_list_current_tl { \@@_combined_output:n {#1} } } \cs_new_protected:Npn \@@_list_numbers_aux:nn #1#2 { \@@_combined_output:n {#1} \l_@@_list_separator_pair_tl \@@_combined_output:n {#2} } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\@@_list_units:nnn} % For a list of items with units, the method is to first parse the % unit when repeating (to save time), then to use the number loop above % for the actual work. On the other hand, when the unit is only printed % once life is easier as the normal unit printer can operate. % \begin{macrocode} \cs_new_protected:Npn \@@_list_units:nnn #1#2#3 { \@@_unit_parse_options:nn {#2} {#3} \bool_if:NTF \l_@@_list_repeat_bool { \@@_unit_in:nn {#2} {#3} \@@_list_numbers_aux_i:n {#1} } { \bool_if:NT \l_@@_process_fixed_bool { \bool_set_true:N \l_@@_process_drop_exponent_bool } \bool_if:NT \l_@@_list_brackets_bool { \@@_print:nV { number } \l_@@_bracket_open_tl } \@@_list_numbers:n {#1} \bool_if:NT \l_@@_list_brackets_bool { \@@_print:nV { number } \l_@@_bracket_close_tl } \@@_range_exponent: \@@_unit_output_number_sep: \@@_unit_output:nn {#2} {#3} } } % \end{macrocode} % \end{macro} % %\subsection{Ranges} % %\begin{macro}{\l_@@_range_brackets_bool} %\begin{macro}{\l_@@_range_repeat_bool} % Settings for ranges with units. % \begin{macrocode} \bool_new:N \l_@@_range_brackets_bool \bool_new:N \l_@@_range_repeat_bool % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\l_@@_range_phrase_tl} % Simple settings for ranges. % \begin{macrocode} \keys_define:nn { siunitx } { range-phrase .tl_set:N = \l_@@_range_phrase_tl, range-units .choice:, range-units / brackets .code:n = { \bool_set_true:N \l_@@_range_brackets_bool \bool_set_false:N \l_@@_range_repeat_bool }, range-units / repeat .code:n = { \bool_set_false:N \l_@@_range_brackets_bool \bool_set_true:N \l_@@_range_repeat_bool }, range-units / single .code:n = { \bool_set_false:N \l_@@_range_brackets_bool \bool_set_false:N \l_@@_range_repeat_bool }, } \keys_set:nn { siunitx } { range-phrase = { ~ to ~ }, range-units = repeat, } % \end{macrocode} %\end{macro} % % \begin{macro}{\@@_range_numbers:nn} % \begin{macro}[aux]{\@@_range_numbers_core:nn} % \begin{macro}[aux]{\@@_range_numbers_aux:n} % A range of numbers. This is more restrictive than the \cs{num} % function: nothing compound. % \begin{macrocode} \cs_new_protected:Npn \@@_range_numbers:nn #1#2 { \@@_range_numbers_aux:n {#1} \l_@@_range_phrase_tl \@@_range_numbers_aux:n {#2} } \cs_new_protected:Npn \@@_range_numbers_aux:n #1 { \bool_if:NTF \l_@@_number_parse_bool { \tl_clear:N \l_@@_number_out_tl \tl_clear:N \l_@@_number_out_saved_tl \bool_set_false:N \l_@@_number_compound_bool \@@_number_output_parse:n {#1} \bool_if:NT \l_@@_number_compound_bool { \msg_error:nnx { siunitx } { multi-part-range } {#1} } } { \@@_unit_output_pre_print: \@@_print:nn { number } {#1} \@@_unit_output_print: } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % %\begin{macro}{\@@_range_unit:nnnn} % Unit printing is also simple: basically a past-up job. The only compl % \begin{macrocode} \cs_new_protected:Npn \@@_range_unit:nnnn #1#2#3#4 { \@@_unit_parse_options:nn {#1} {#2} \bool_if:NTF \l_@@_range_repeat_bool { \@@_unit_in:nn {#1} {#2} \@@_range_numbers_aux:n {#3} \l_@@_range_phrase_tl \@@_range_numbers_aux:n {#4} } { \bool_if:NT \l_@@_process_fixed_bool { \bool_set_true:N \l_@@_process_drop_exponent_bool } \bool_if:NT \l_@@_range_brackets_bool { \@@_print:nV { number } \l_@@_bracket_open_tl } \@@_range_numbers:nn {#3} {#4} \bool_if:NT \l_@@_range_brackets_bool { \@@_print:nV { number } \l_@@_bracket_close_tl } \@@_range_exponent: \@@_unit_output_number_sep: \@@_unit_output:nn {#1} {#2} } } % \end{macrocode} %\end{macro} % % \begin{macro}{\@@_range_exponent:} % The idea here is to construct and print an exponent if this is fixed, % and thus removed from the range. This function is also used by the % related list concept. % \begin{macrocode} \cs_new_protected:Npn \@@_range_exponent: { \bool_if:NT \l_@@_process_fixed_bool { \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_exponent_product_tl \bool_if:NT \l_@@_tight_bool { \tl_set:Nx \l_@@_tmpa_tl { \exp_not:N \mathord \exp_not:o \l_@@_tmpa_tl } } \tl_set:Nx \l_@@_tmpa_tl { \exp_not:N \ensuremath { { } \exp_not:o \l_@@_tmpa_tl { } } 10 \exp_not:N \PrintSuperscript { \int_use:N \l_@@_process_fixed_int } } \@@_print:nV { number } \l_@@_tmpa_tl } } % \end{macrocode} % \end{macro} % %\subsection{Setting up tables} % % There is a slight problem with the \pkg{cellspace} package: it also % uses \texttt{S} for a column type Here, \texttt{S} seems to make % more sense for \pkg{siunitx}, with \texttt{C} used for % \pkg{cellspace}. To enable this to work well, the column % rewriting code happens \cs{AtBeginDocument}. The \texttt{S} column % is deleted from \cs{NC@list} so that no warning appears. % \begin{macrocode} \AtBeginDocument { \@ifpackageloaded { cellspace } { \newcolumntype { C } [1] { > { \bcolumn #1 \@nil } #1 < { \ecolumn } } \cs_set:Npn \@@_tmp:w #1 \NC@do S #2 \q_stop { \NC@list { #1 #2 } } \exp_after:wN \@@_tmp:w \tex_the:D \NC@list \q_stop \cs_undefine:N \NC@find@S \msg_new:nnn { siunitx } { moved-cellspace-column } { Column~type~for~cellspace~package~moved~to~'#1'. } \msg_warning:nnn { siunitx } { moved-cellspace-column } { C } } { } } % \end{macrocode} % %\begin{macro}{\@@_table_rewrite_create:N} %\begin{macro}[aux]{\@@_table_rewrite_create_aux:w} % The \texttt{s} and \texttt{S} column types are both created using % the \pkg{array} package, but with the internal macros redefined % to work with optional argument. First, there is a need to do a % quick shuffle with the \cs{NC@list} macro. The \pkg{siunitx} % columns have to be listed first, as otherwise the optional % arguments do not work correctly. So they are added \enquote{by hand} % to the appropriate macro. % \begin{macrocode} \cs_new_protected:Npn \@@_table_rewrite_create:N #1 { \newcolumntype {#1} { } \cs_set_protected:Npn \@@_table_rewrite_create_aux:w \NC@do ##1##2 \NC@do #1 { \NC@list { \NC@do ##1 \NC@do #1 ##2 } } \exp_after:wN \@@_table_rewrite_create_aux:w \tex_the:D \NC@list \exp_args:NNc \renewcommand * { NC@rewrite@ #1 } [1] [ ] { \@temptokena \exp_after:wN { \tex_the:D \@temptokena > { \@@_table_collect_begin:Nn #1 {##1} } c < { \@@_table_print: } } \NC@find } } \AtBeginDocument { \@ifpackageloaded { mdwtab } { \cs_set_protected:Npn \@@_table_rewrite_create:N #1 { \newcolumntype {#1} [1] [] { > { \__siunitx_table_collect_begin:Nn #1 {##1} } c < { \__siunitx_table_print: } } } } { } } \cs_new_protected:Npn \@@_table_rewrite_create_aux:w { } \AtBeginDocument { \@@_table_rewrite_create:N s } \AtBeginDocument { \@@_table_rewrite_create:N S } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Collecting tokens in tables} % % The table system is in two parts, collecting tokens and typesetting % the result. The collection routine tries to ensure that the % typesetting part only receives real cell contents. % %\begin{macro}{\l_@@_table_collect_tl} %\begin{macro}{\l_@@_table_collect_pre_tl} %\begin{macro}{\l_@@_table_collect_post_tl} % Three storage areas. % \begin{macrocode} \tl_new:N \l_@@_table_collect_tl \tl_new:N \l_@@_table_collect_pre_tl \tl_new:N \l_@@_table_collect_post_tl % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\l_@@_number_valid_tl} % As the \texttt{S} column has to make a judgement about tokens which % can be part of a number, there is a need to have a list of valid % tokens. % \begin{macrocode} \tl_new:N \l_@@_number_valid_tl % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_table_math_bool} % A flag used inside the table cell to track math mode: there is % a need to do things by hand as otherwise the grouping goes % wrong. % \begin{macrocode} \bool_new:N \l_@@_table_math_bool % \end{macrocode} %\end{macro} % %\begin{macro}{\l_@@_table_collect_pre_bool} %\begin{macro}{\l_@@_table_collect_post_bool} % Flags for having found a number in an \texttt{S} column. % \begin{macrocode} \bool_new:N \l_@@_table_collect_pre_bool \bool_new:N \l_@@_table_collect_post_bool % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_table_collect_begin:Nn} %\begin{macro}[aux]{\@@_table_collect_begin_s:} %\begin{macro}[aux]{\@@_table_collect_begin_S:} % The collector starts by setting up local options, then clears and % initialises the storage and testing system. Font detection for the % \texttt{S} column happens here as this ensures that it is not inside % a box, which will give the wrong result for \opt{detect-mode}. % \begin{macrocode} \cs_new_protected:Npn \@@_table_collect_begin:Nn #1#2 { \keys_set:nn { siunitx } {#2} \use:c { @@_table_collect_begin_ #1 : } } \cs_new_protected:Npn \@@_table_collect_begin_s: { \cs_set_eq:NN \@@_table_collect_token:N \@@_table_collect_token_s:N \cs_set_eq:NN \@@_table_print: \@@_table_print_s: \@@_table_collect_init_s: \@@_table_collect_get: } \cs_new_protected:Npn \@@_table_collect_begin_S: { \cs_set_eq:NN \@@_table_collect_token:N \@@_table_collect_token_S:N \cs_set_eq:NN \@@_table_print: \@@_table_print_S: \@@_table_collect_init_S: \@@_detect_font: \bool_if:NTF \l_@@_number_parse_bool { \@@_table_collect_get: } { \@@_table_print_S_direct:N } } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\@@_table_collect_braced:n} % The collection of braced items depends on the column type. So we % start of with an empty definition. % \begin{macrocode} \cs_new_protected:Npn \@@_table_collect_braced:n #1 { } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_table_collect_expand:N} %\begin{macro}[aux]{\@@_table_collect_expand_math:N} % The idea here is to expand content if possible. There are a few % things to note. Only macros which are not long or protected are % expanded. There is the possibility that the macro may need the % contents of the pre-numeral part to be executed, for example see % \cref{tab:xmpl:calc} in the user part of the documentation. % \begin{macrocode} \cs_new_protected:Npn \@@_table_collect_expand:N #1 { \cs_if_eq:NNTF #1 \color { \bool_if:NTF \l_@@_table_collect_pre_bool { \tl_clear:N \l_@@_number_color_tl \tl_clear:N \l_@@_unit_color_tl \tl_put_right:Nn \l_@@_table_collect_pre_tl {#1} } { \bool_set_true:N \l_@@_table_collect_post_bool \tl_put_right:Nn \l_@@_table_collect_post_tl {#1} } } { \@@_cs_if_tl:NTF #1 { \tl_use:N \l_@@_table_collect_pre_tl \tl_clear:N \l_@@_table_collect_pre_tl \cs_set:Npn \@@_table_collect_next: { \exp_after:wN \@@_table_collect_get: #1 } } { \bool_if:NTF \l_@@_table_collect_pre_bool { \tl_put_right:Nn \l_@@_table_collect_pre_tl {#1} \@@_table_collect_expand_math:N #1 } { \bool_set_true:N \l_@@_table_collect_post_bool \tl_put_right:Nn \l_@@_table_collect_post_tl {#1} } } } } % \end{macrocode} % There is a need to keep a track of math mode, so that there are no % disasters when the tokens are boxed up later. The ideal is to know % the math state of the collected tokens so that appropriate % steps can be taken to insert math shift tokens later. % \begin{macrocode} \cs_new_protected:Npn \@@_table_collect_expand_math:N #1 { \token_if_math_toggle:NTF #1 { \bool_if:NTF \l_@@_table_math_bool { \bool_set_false:N \l_@@_table_math_bool } { \bool_set_true:N \l_@@_table_math_bool } } { \cs_if_eq:NNTF #1 \( % \) { \bool_set_true:N \l_@@_table_math_bool } { % \( \cs_if_eq:NNT #1 \) { \bool_set_false:N \l_@@_table_math_bool } } } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_table_collect_get:} %\begin{macro}{\@@_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_protected:Npn \@@_table_collect_get: { \cs_set_eq:NN \@@_table_collect_next: \@@_table_collect_get: \cs_set:Npn \__peek_execute_branches: { \if_catcode:w \exp_not:N \l_peek_token \c_group_begin_token \exp_after:wN \@@_table_collect_braced:n \else: \exp_after:wN \@@_table_collect_not_braced:N \fi: } \peek_after:Nw \__peek_ignore_spaces_execute_branches: } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_table_collect_init:} % The usual spin-out of basics. % \begin{macrocode} \cs_new_protected:Npn \@@_table_collect_init: { \tl_clear:N \l_@@_table_collect_tl \tl_clear:N \l_@@_table_collect_pre_tl \tl_clear:N \l_@@_table_collect_post_tl \bool_set_false:N \l_@@_table_collect_post_bool \bool_set_false:N \l_@@_table_math_bool } % \end{macrocode} %\end{macro} %\begin{macro}{\@@_table_collect_init_s:} %\begin{macro}{\@@_table_collect_init_S:} % Some type-specific definitions. In the \texttt{S} case, the % initialisation function for numbers is used to set % \cs{l_@@_number_valid_tl} correctly. % \begin{macrocode} \cs_new_protected:Npn \@@_table_collect_init_s: { \@@_table_collect_init: \bool_set_false:N \l_@@_table_collect_pre_bool \cs_set_protected:Npn \@@_table_collect_braced:n ##1 { \tl_put_right:Nn \l_@@_table_collect_tl { {##1} } \@@_table_collect_next: } } \cs_new_protected:Npn \@@_table_collect_init_S: { \@@_number_in_init: \tl_set:Nx \l_@@_number_valid_tl { \exp_not:V \l_@@_input_complex_tl \exp_not:V \l_@@_input_decimal_tl \exp_not:V \l_@@_input_digit_tl \exp_not:V \l_@@_input_exponent_tl \exp_not:V \l_@@_input_ignore_tl \exp_not:V \l_@@_input_comparator_tl \exp_not:V \l_@@_input_uncert_close_tl \exp_not:V \l_@@_input_uncert_open_tl \exp_not:V \l_@@_input_sign_tl \exp_not:V \l_@@_input_symbol_tl } \bool_set_true:N \l_@@_table_collect_pre_bool \cs_set_protected:Npn \@@_table_collect_braced:n ##1 { \bool_if:NTF \l_@@_table_collect_pre_bool { \tl_put_right:Nn \l_@@_table_collect_pre_tl { {##1} } } { \bool_set_true:N \l_@@_table_collect_post_bool \tl_put_right:Nn \l_@@_table_collect_post_tl { {##1} } } \@@_table_collect_next: } } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\@@_table_collect_next:} % A holder for the next thing to do. % \begin{macrocode} \cs_new_protected:Npn \@@_table_collect_next: { } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_table_collect_newline:} % The end macro needs to come before the new line is called. The % print function is redefined so that it only actually does stuff once. % As each cell is a group anyway, there is no need to save the % definition of \cs{@@_table_print:}, as it will re-appear on its % own. % \begin{macrocode} \cs_new_protected:Npn \@@_table_collect_newline: { \@@_table_print: \cs_set_eq:NN \@@_table_print: \prg_do_nothing: \tabularnewline } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_table_collect_end:} % The same concept applies to the \cs{end} macro. % \begin{macrocode} \cs_new_protected:Npn \@@_table_collect_end: { \@@_table_print: \cs_set_eq:NN \@@_table_print: \prg_do_nothing: \end } % \end{macrocode} %\end{macro} % %\begin{macro}{\@@_table_collect_not_braced:N} %\begin{macro}[aux]{\@@_table_collect_not_braced_aux_i:N} %\begin{macro}[aux]{\@@_table_collect_not_braced_aux_ii:N} % A few macros are simply passed through to be executed; this is mainly % so that the table actually works. The newline function needs its own % function, which is picked up by hand. % \begin{macrocode} \cs_new_protected:Npn \@@_table_collect_not_braced:N #1 { \token_if_eq_meaning:NNF #1 \tex_ignorespaces:D { \token_if_eq_meaning:NNF #1 \tex_unskip:D { \@@_table_collect_not_braced_aux_i:N #1 } } \@@_table_collect_next: } \AtBeginDocument { \@ifpackageloaded { mdwtab } { \cs_set_protected:Npn \@@_table_collect_not_braced:N #1 { \token_if_eq_meaning:NNF #1 \tex_ignorespaces:D { \token_if_eq_meaning:NNF #1 \tex_unskip:D { \token_if_eq_meaning:NNF #1 \tab@setcr { \@@_table_collect_not_braced_aux_i:N #1 } } } \@@_table_collect_next: } } { } } \cs_new_protected:Npn \@@_table_collect_not_braced_aux_i:N #1 { \cs_set:Npn \@@_table_collect_not_braced_aux_ii:N ##1 { \token_if_eq_meaning:NNT #1 ##1 { \cs_set_eq:NN \@@_table_collect_next: ##1 } } \tl_map_function:nN { \cs:w \scan_stop: \@@_table_print: } \@@_table_collect_not_braced_aux_ii:N \token_if_eq_meaning:NNT \@@_table_collect_next: \@@_table_collect_get: { \token_if_eq_meaning:NNTF #1 \tabularnewline { \cs_set_eq:NN \@@_table_collect_next: \@@_table_collect_newline: } { \token_if_eq_meaning:NNTF #1 \end { \cs_set_eq:NN \@@_table_collect_next: \@@_table_collect_end: } { \@@_table_collect_token:N #1 } } } } \cs_new_protected:Npn \@@_table_collect_not_braced_aux_ii:N #1 { } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\@@_table_collect_token:N} %\begin{macro}{\@@_table_collect_token_s:N} % For the \texttt{s} column, every token is added to the same storage % area, so life is simple. % \begin{macrocode} \cs_new_protected:Npn \@@_table_collect_token:N #1 { } \cs_new_protected:Npn \@@_table_collect_token_s:N #1 { \tl_put_right:Nn \l_@@_table_collect_tl {#1} } % \end{macrocode} %\end{macro} %\end{macro} %\begin{macro}{\@@_table_collect_token_S:N} % Not so easy for the \texttt{S} column type. If the content is after % a number, things are easy. On the other hand, if the token might be % a number, then a check is made. It the token is still unmatched, then % it is passed on to the expansion handler. % \begin{macrocode} \cs_new_protected:Npn \@@_table_collect_token_S:N #1 { \bool_if:NTF \l_@@_table_collect_post_bool { \tl_put_right:Nn \l_@@_table_collect_post_tl {#1} } { \tl_if_in:NnTF \l_@@_number_valid_tl {#1} { \bool_set_false:N \l_@@_table_collect_pre_bool \tl_put_right:Nn \l_@@_table_collect_tl {#1} } { \@@_table_collect_expand:N #1 } } } % \end{macrocode} %\end{macro} % % \subsection{Table printing: general code} % % Getting the general alignment correct in tables is made more % complex than one would like by the \pkg{colortbl} package. In the % original \LaTeXe{} definition, cell material is centred by a % construction of the (primitive) form % \begin{verbatim} % \hfil % # % \hfil % \end{verbatim} % which only uses \texttt{fil} stretch. That is altered by % \pkg{colortbl} to broadly % \begin{verbatim} % \hskip 0 pt plus 0.5 fill % \kern 0 pt % # % \hskip 0 pt plus 0.5 fill % \end{verbatim} % which means there is \texttt{fill} stretch to worry about and % the kern as well. % % \begin{variable}{\c_@@_one_fill_skip} % A fixed skip of one \texttt{fill}. % \begin{macrocode} \skip_new:N \c_@@_one_fill_skip \skip_set:Nn \c_@@_one_fill_skip { \c_zero_dim plus 1 fill } % \end{macrocode} % \end{variable} % % \begin{macro}{\@@_table_colortbl_correction:} % If the package \pkg{colortbl} is loaded, there is a need to allow % that it changes how centring is carried out. % \begin{macrocode} \AtBeginDocument { \@ifpackageloaded { colortbl } { \cs_new_protected:Npn \@@_table_colortbl_correction: { \skip_horizontal:n { \c_zero_dim plus -0.5 fill } \tex_kern:D \c_zero_skip } } { \cs_new_protected:Npn \@@_table_colortbl_correction: { } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_table_align_left:n} % \begin{macro}{\@@_table_align_right:n} % These are simple shortcuts to keep life clearer in the rest of the % code. The idea is that the kern acts as a \enquote{stop} for the % horizontal skip. The correction for \pkg{colortbl} is separate as the % spacing needs to be explicitly deleted. % \begin{macrocode} \cs_new_protected:Npn \@@_table_align_left:n #1 { \@@_table_colortbl_correction: \skip_horizontal:n {#1} \tex_kern:D \c_zero_skip } \cs_new_protected:Npn \@@_table_align_right:n #1 { \skip_horizontal:n { \c_@@_one_fill_skip - #1 } \tex_kern:D \c_zero_skip \@@_table_colortbl_correction: } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@@_table_column_begin:} % \begin{macro}{\@@_table_column_end:} % \begin{macrocode} \cs_new_eq:NN \@@_table_column_begin:n \@@_table_align_left:n \cs_new_eq:NN \@@_table_column_end:n \@@_table_align_right:n % \end{macrocode} % \end{macro} % \end{macro} % % Setting up for a fixed column width is done so that the check is % made at the key-setting stage. In that way, there will be some % speed gained if the key is set before the table, as the comparison % is not made for every cell. % \begin{macrocode} \keys_define:nn { siunitx } { table-column-width .code:n = { \dim_compare:nNnTF {#1} = { \c_zero_dim } { \cs_set_eq:NN \@@_table_column_begin:n \@@_table_align_left:n \cs_set_eq:NN \@@_table_column_end:n \@@_table_align_right:n } { \cs_set_protected:Npn \@@_table_column_begin:n ##1 { \@@_table_colortbl_correction: \tex_hbox:D to \dim_eval:n {#1} \c_group_begin_token \skip_horizontal:n {##1} \tex_kern:D \c_zero_skip } \cs_set_protected:Npn \@@_table_column_end:n ##1 { \skip_horizontal:n { \c_@@_one_fill_skip - ##1 } \tex_kern:D \c_zero_skip \hbox_set_inline_end: \@@_table_colortbl_correction: } } } } % \end{macrocode} % % \subsection{Printing units in \texttt{s} columns} % % The easiest type of printing is the \texttt{s} column. Here, there is % no real problem with alignment. All that has to happen is to print the % collected input as the argument to the internal part of an \cs{si} % function. % % \begin{variable}{\l_@@_table_unit_align_skip} % The spacing used is stored as a skip, which needs to be set up first. % \begin{macrocode} \skip_new:N \l_@@_table_unit_align_skip % \end{macrocode} % \end{variable} % % \begin{macrocode} \keys_define:nn { siunitx } { table-unit-alignment .choice:, table-unit-alignment / center .code:n = { \skip_set:Nn \l_@@_table_unit_align_skip { \c_zero_dim plus 0.5 fill } }, table-unit-alignment / left .code:n = { \skip_set:Nn \l_@@_table_unit_align_skip { \c_zero_skip } }, table-unit-alignment / right .code:n = { \skip_set:Nn \l_@@_table_unit_align_skip { \c_zero_dim plus 1 fill } } } \keys_set:nn { siunitx } { table-unit-alignment = center } % \end{macrocode} % % \begin{macro}{\@@_table_print_s:} % Actually printing an \texttt{s} column is not very complex. There is % some spacing to do at each side, with the main part of the job being % to print the material using the internal version of \cs{si}. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_s: { \@@_table_column_begin:n { \l_@@_table_unit_align_skip } \tl_if_empty:NF \l_@@_table_collect_tl { \@@_unit_output:Vn \l_@@_table_collect_tl { } } \@@_table_column_end:n { \l_@@_table_unit_align_skip } } % \end{macrocode} % \end{macro} % % \subsection{Formatting and printing in tables} % % With the content grabbed, the next stage is to turn it into formatted % output then print it. Most of the formatting is done elsewhere, so % most of the work here is in printing. % % \begin{variable}{\l_@@_table_model_prop} % A place to store the model for reserved-space table columns. % \begin{macrocode} \prop_new:N \l_@@_table_model_prop % \end{macrocode} % \end{variable} % % \begin{variable} % { % \l_@@_table_exponent_dim , % \l_@@_table_integer_dim , % \l_@@_table_mantissa_dim , % \l_@@_table_marker_dim , % \l_@@_table_result_dim , % \l_@@_table_uncert_dim % } % Dimensions to track the various spaces needed. % \begin{macrocode} \dim_new:N \l_@@_table_exponent_dim \dim_new:N \l_@@_table_integer_dim \dim_new:N \l_@@_table_mantissa_dim \dim_new:N \l_@@_table_marker_dim \dim_new:N \l_@@_table_result_dim \dim_new:N \l_@@_table_uncert_dim % \end{macrocode} %\end{variable} % % \begin{variable} % {\l_@@_table_fill_pre_dim, \l_@@_table_fill_post_dim} % Calculating the fill needed can be a bit complicated, so is best % done using a dedicated dimension. There is a second one for cases dealing % with fill at the end of a number, where there may be some rearrangement. % \begin{macrocode} \dim_new:N \l_@@_table_fill_pre_dim \dim_new:N \l_@@_table_fill_post_dim % \end{macrocode} % \end{variable} % % \begin{variable}{\l_@@_table_fill_mid_dim} % For the reserved space approach there is also the need for a third % piece of fill, which may or may not be used. % \begin{macrocode} \dim_new:N \l_@@_table_fill_mid_dim % \end{macrocode} % \end{variable} % % \begin{variable}{\l_@@_table_pre_box, \l_@@_table_post_box} % Boxes for the content before and after the numerical part. % \begin{macrocode} \box_new:N \l_@@_table_pre_box \box_new:N \l_@@_table_post_box % \end{macrocode} % \end{variable} % % \begin{variable}{\l_@@_table_mantissa_box} % When printing with space reserved, the mantissa needs to hang around % for a while. This is best done by storing the typeset result in a box. % \begin{macrocode} \box_new:N \l_@@_table_mantissa_box % \end{macrocode} % \end{variable} % % \begin{variable}{\l_@@_table_result_box} % The box which is actually needed for printing. % \begin{macrocode} \box_new:N \l_@@_table_result_box % \end{macrocode} % \end{variable} % % \begin{variable} % {\l_@@_table_number_align_skip, \l_@@_table_text_align_skip} % Skips for aligning text and numbers. % \begin{macrocode} \skip_new:N \l_@@_table_number_align_skip \skip_new:N \l_@@_table_text_align_skip % \end{macrocode} % \end{variable} % % \begin{macro} % { % \@@_table_print_S_direct_main: , % \@@_table_print_S_parsed: % } % \begin{macro}{\@@_table_print_S_reserved_store_fill:n} % Various functions which are set up by the option system, and so are % reserved here first for completeness. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_direct_main: { } \cs_new_protected:Npn \@@_table_print_S_parsed: { } \cs_new_protected:Npn \@@_table_print_S_reserved_store_fill:n #1 { } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{variable} % { % \l_@@_table_align_exponent_bool, % \l_@@_table_align_text_pre_bool, % \l_@@_table_align_text_post_bool, % \l_@@_table_align_uncert_bool, % \l_@@_table_auto_round_bool, % \l_@@_table_omit_exponent_bool, % \l_@@_table_parse_only_bool, % \l_@@_table_pre_tl, % \l_@@_table_post_tl % } % \begin{macrocode} \keys_define:nn { siunitx } { table-align-comparator .choice:, table-align-comparator / false .code:n = { \cs_set_eq:NN \@@_table_print_S_reserved_store_fill:n \@@_table_print_S_reserved_store_fill_pre:n }, table-align-comparator / true .code:n = { \cs_set_eq:NN \@@_table_print_S_reserved_store_fill:n \@@_table_print_S_reserved_store_fill_mid:n }, table-align-comparator .default:n = true, table-align-exponent .bool_set:N = \l_@@_table_align_exponent_bool, table-align-text-pre .bool_set:N = \l_@@_table_align_text_pre_bool, table-align-text-post .bool_set:N = \l_@@_table_align_text_post_bool, table-align-uncertainty .bool_set:N = \l_@@_table_align_uncert_bool, table-auto-round .bool_set:N = \l_@@_table_auto_round_bool, table-number-alignment .choice:, table-number-alignment / center .code:n = { \skip_set:Nn \l_@@_table_number_align_skip { \c_zero_dim plus 0.5 fill } \cs_set_eq:NN \@@_table_print_S_direct_main: \@@_table_print_S_direct_reserved: \cs_set_eq:NN \@@_table_print_S_parsed: \@@_table_print_S_reserved: }, table-number-alignment / center-decimal-marker .code:n = { \skip_set:Nn \l_@@_table_number_align_skip { \c_zero_dim plus 0.5 fill } \cs_set_eq:NN \@@_table_print_S_direct_main: \@@_table_print_S_direct_centered: \cs_set_eq:NN \@@_table_print_S_parsed: \@@_table_print_S_centered: }, table-number-alignment / left .code:n = { \skip_zero:N \l_@@_table_number_align_skip \cs_set_eq:NN \@@_table_print_S_direct_main: \@@_table_print_S_direct_reserved: \cs_set_eq:NN \@@_table_print_S_parsed: \@@_table_print_S_reserved: }, table-number-alignment / right .code:n = { \skip_set:Nn \l_@@_table_number_align_skip { \c_zero_dim plus 1 fill } \cs_set_eq:NN \@@_table_print_S_direct_main: \@@_table_print_S_direct_reserved: \cs_set_eq:NN \@@_table_print_S_parsed: \@@_table_print_S_reserved: }, table-omit-exponent .bool_set:N = \l_@@_table_omit_exponent_bool, table-text-alignment .choice:, table-text-alignment / center .code:n = { \skip_set:Nn \l_@@_table_text_align_skip { \c_zero_dim plus 0.5 fill } }, table-text-alignment / left .code:n = { \skip_zero:N \l_@@_table_text_align_skip }, table-text-alignment / right .code:n = { \skip_set:Nn \l_@@_table_text_align_skip { \c_zero_dim plus 1 fill } }, table-comparator .choice:, table-comparator / false .code:n = { \prop_remove:Nn \l_@@_table_model_prop { comparator } }, table-comparator / true .code:n = { \prop_put:Nnn \l_@@_table_model_prop { comparator } { > } }, table-comparator .default:n = true, table-figures-decimal .code:n = { \int_compare:nNnTF {#1} = \c_zero { \prop_remove:Nn \l_@@_table_model_prop { mantissa-decimal } \prop_remove:Nn \l_@@_table_model_prop { mantissa-decimal-raw } \prop_remove:Nn \l_@@_table_model_prop { mantissa-decimal-marker } \prop_if_in:NnTF \l_@@_table_model_prop { mantissa-integer } { \prop_put:Nnn \l_@@_table_model_prop { mantissa } { true } } { \prop_remove:Nn \l_@@_table_model_prop { mantissa } } } { \prop_put:Nnx \l_@@_table_model_prop { mantissa-decimal } { \prg_replicate:nn {#1} { 8 } } \prop_put:Nnn \l_@@_table_model_prop { mantissa-decimal-raw } {#1} \prop_put:Nnn \l_@@_table_model_prop { mantissa } { true } \prop_put:NnV \l_@@_table_model_prop { mantissa-decimal-marker } \l_@@_output_decimal_tl } }, table-figures-exponent .code:n = { \int_compare:nNnTF {#1} = \c_zero { \prop_remove:Nn \l_@@_table_model_prop { exponent-integer } } { \prop_put:Nnx \l_@@_table_model_prop { exponent-integer } { \prg_replicate:nn {#1} { 8 } } \prop_put:Nnn \l_@@_table_model_prop { exponent } { true } } }, table-figures-integer .code:n = { \int_compare:nNnTF {#1} = \c_zero { \prop_remove:Nn \l_@@_table_model_prop { mantissa-integer } \prop_if_in:NnTF \l_@@_table_model_prop { mantissa-decimal } { \prop_put:Nnn \l_@@_table_model_prop { mantissa } { true } } { \prop_remove:Nn \l_@@_table_model_prop { mantissa } } } { \prop_put:Nnx \l_@@_table_model_prop { mantissa-integer } { \prg_replicate:nn {#1} { 8 } } \prop_put:Nnn \l_@@_table_model_prop { mantissa } { true } } }, table-figures-uncertainty .code:n = { \int_compare:nNnTF {#1} = \c_zero { \prop_remove:Nn \l_@@_table_model_prop { mantissa-uncertainty } } { \prop_put:Nnx \l_@@_table_model_prop { mantissa-uncertainty } { \prg_replicate:nn {#1} { 8 } } } }, table-parse-only .bool_set:N = \l_@@_table_parse_only_bool, table-space-text-pre .tl_set:N = \l_@@_table_pre_tl, table-space-text-post .tl_set:N = \l_@@_table_post_tl, table-sign-exponent .code:n = { \prop_put:Nnn \l_@@_table_model_prop { exponent-sign } { - } }, table-sign-mantissa .code:n = { \prop_put:Nnn \l_@@_table_model_prop { mantissa-sign } { - } }, } % \end{macrocode} % \end{variable} % % A meta-choice for all table alignment is also provided. % \begin{macrocode} \keys_define:nn { siunitx } { table-alignment .meta:n = { table-number-alignment = #1, table-text-alignment = #1, table-unit-alignment = #1 } } % \end{macrocode} % % Another special option. This converts a number format in compacted % form into the various internal settings needed. % \begin{macrocode} \keys_define:nn { siunitx } { table-format .code:n = { \@@_number_in_parse:n {#1} \prop_set_eq:NN \l_@@_table_model_prop \l_@@_number_in_prop \tl_clear:N \l_@@_tmpa_tl \prop_get:NnNT \l_@@_number_in_prop { mantissa-integer } \l_@@_tmpb_tl { \tl_set:Nx \l_@@_tmpa_tl { table-figures-integer = \l_@@_tmpb_tl } } \prop_get:NnNT \l_@@_number_in_prop { mantissa-decimal } \l_@@_tmpb_tl { \clist_put_right:Nx \l_@@_tmpa_tl { table-figures-decimal = \l_@@_tmpb_tl } } \prop_get:NnNT \l_@@_number_in_prop { mantissa-uncertainty } \l_@@_tmpb_tl { \clist_put_right:Nx \l_@@_tmpa_tl { table-figures-uncertainty = \l_@@_tmpb_tl } } \prop_get:NnNT \l_@@_number_in_prop { exponent-integer } \l_@@_tmpb_tl { \clist_put_right:Nx \l_@@_tmpa_tl { table-figures-exponent = \l_@@_tmpb_tl } } \clist_put_right:Nn \l_@@_tmpa_tl { table-number-alignment = center } \keys_set:nV { siunitx } \l_@@_tmpa_tl } } % \end{macrocode} % % \begin{macro}{\@@_table_print_S:} % The main printing function makes a choice depending on whether there is % any numerical part to print at all. This affects which set of skips to % insert. Font detection for the \texttt{S} column is included here as % this is needed to do this work outside of an \cs{hbox}. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S: { \bool_if:NTF \l_@@_table_collect_pre_bool { \@@_table_column_begin:n { \l_@@_table_text_align_skip } \l_@@_table_collect_pre_tl \@@_table_column_end:n { \l_@@_table_text_align_skip } } { \@@_table_column_begin:n { \l_@@_table_number_align_skip } \bool_if:NTF \l_@@_table_parse_only_bool { \@@_table_print_S_no_alignment: } { \@@_table_print_S_alignment: } \bool_if:NTF \l_@@_table_align_text_pre_bool { \@@_table_print_S_pre_aligned: } { \@@_table_print_S_pre_not_aligned: } \box_use:N \l_@@_table_result_box \bool_if:NTF \l_@@_table_align_text_post_bool { \@@_table_print_S_post_aligned: } { \@@_table_print_S_post_not_aligned: } \@@_table_column_end:n { \l_@@_table_number_align_skip } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_table_print_S_no_alignment:} % With no alignment to do, the code can be pretty simple. The collected % number is simply printed between the two non-numerical parts. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_no_alignment: { \l_@@_table_collect_pre_tl \@@_number_output:V \l_@@_table_collect_tl \l_@@_table_collect_post_tl } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_table_print_S_alignment:} % This is a pass-through, so that the appropriate alignment mode is % retained without needing to retest on each use. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_alignment: { \@@_table_print_S_parsed: } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_table_print_S_parse:} % A modified version of the number parser for tables. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_parse: { \bool_set_false:N \l_@@_error_bool \@@_number_in_parse:V \l_@@_table_collect_tl \bool_if:NF \l_@@_error_bool { \bool_if:NTF \l_@@_table_omit_exponent_bool { \bool_set_true:N \l_@@_process_fixed_bool \@@_number_process: \prop_remove:Nn \l_@@_number_in_prop { exponent } \prop_remove:Nn \l_@@_number_in_prop { exponent-integer } } { \@@_number_process: } \@@_number_format: \@@_number_output_color: } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_table_print_S_measure:NN} % A short routine to measure up whatever has been extracted from the % storage system. Boxing up is avoided for the empty cases, as this saves % a little time(the print routine is relatively slow). % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_measure:NN #1#2 { \tl_if_empty:NTF #1 { \dim_zero:N #2 } { \group_begin: \hbox_set:Nn \l_@@_tmp_box { \@@_print:nV { number } #1 } \exp_args:NNNo \group_end: \dim_set:Nn #2 { \dim_use:N \box_wd:N \l_@@_tmp_box } } } % \end{macrocode} % \end{macro} % % \begin{macro} % { % \@@_table_print_S_pre_aligned: , % \@@_table_print_S_pre_not_aligned: , % \@@_table_print_S_post_aligned: , % \@@_table_print_S_post_not_aligned: % } % The non-numerical material is inserted along with the filler needed % to maintain alignment. The order in which the two are inserted depends % on whether those parts are also aligned. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_pre_aligned: { \box_use:N \l_@@_table_pre_box \hbox_to_wd:nn { \l_@@_table_fill_pre_dim } { \tex_hfil:D } } \cs_new_protected:Npn \@@_table_print_S_pre_not_aligned: { \hbox_to_wd:nn { \l_@@_table_fill_pre_dim } { \tex_hfil:D } \box_use:N \l_@@_table_pre_box } \cs_new_protected:Npn \@@_table_print_S_post_aligned: { \hbox_to_wd:nn { \l_@@_table_fill_post_dim } { \tex_hfil:D } \box_use:N \l_@@_table_post_box } \cs_new_protected:Npn \@@_table_print_S_post_not_aligned: { \box_use:N \l_@@_table_post_box \hbox_to_wd:nn { \l_@@_table_fill_post_dim } { \tex_hfil:D } } % \end{macrocode} % \end{macro} % % \subsection{Printing the \texttt{S} column with the decimal marker centred} % % \begin{macro}{\@@_table_print_S_centered:} % The main routine for decimal-centred alignment works by boxing up the % entire output, the integer part and the decimal marker. It then works % out which part is bigger and calculates the fill correction accordingly. % Once all of that is done, the various boxes and fill can be inserted. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_centered: { \@@_table_print_S_centered_ends: \bool_if:NT \l_@@_table_math_bool { \c_math_toggle_token } \@@_table_print_S_parse: \bool_if:NF \l_@@_error_bool { \@@_table_print_S_centered_measure: \bool_if:NT \l_@@_table_math_bool { \c_math_toggle_token } \dim_set:Nn \l_@@_table_fill_pre_dim { \l_@@_table_result_dim - \l_@@_table_integer_dim \prop_if_in:NnT \l_@@_number_out_prop { mantissa-decimal-marker } { - \l_@@_table_marker_dim } } \dim_compare:nNnTF \l_@@_table_integer_dim > \l_@@_table_fill_pre_dim { \@@_table_print_S_centered_integer: } { \@@_table_print_S_centered_decimal: } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_table_print_S_centered_ends:} % To deal with the material outside of the number, the first step is to % box up both parts. If the pre-numeral part has no width, the tokens are % inserted into the input stream to cover cases where they make a change % to the colour, font or so forth. After that, the narrower of the two % boxes is made the same size as the wider: this maintains the alignment. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_centered_ends: { \hbox_set:Nn \l_@@_table_pre_box { { \l_@@_table_collect_pre_tl \bool_if:NT \l_@@_table_math_bool { \scan_stop: \c_math_toggle_token } } } \dim_compare:nNnT { \box_wd:N \l_@@_table_pre_box } = \c_zero_dim { \l_@@_table_collect_pre_tl \bool_set_false:N \l_@@_font_set_bool } \hbox_set:Nn \l_@@_table_post_box { \bool_if:NT \l_@@_table_math_bool { \c_math_toggle_token \scan_stop: } \l_@@_table_collect_post_tl } \dim_compare:nNnTF { \box_wd:N \l_@@_table_pre_box } > { \box_wd:N \l_@@_table_post_box } { \hbox_set_to_wd:Nnn \l_@@_table_post_box { \box_wd:N \l_@@_table_pre_box } { \hbox_unpack:N \l_@@_table_post_box \tex_hfil:D } } { \hbox_set_to_wd:Nnn \l_@@_table_pre_box { \box_wd:N \l_@@_table_post_box } { \tex_hfil:D \hbox_unpack:N \l_@@_table_pre_box } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_table_print_S_centered_measure:} % \begin{macro}[aux] % { % \@@_table_print_S_centered_measure_int_part: , % \@@_table_print_S_centered_measure_marker: , % \@@_table_print_S_centered_measure_result: % } % Here, there are three parts of the number to measure: the integer part, % the decimal marker and the entire number. Most of the work consists % of collecting up parts of the number. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_centered_measure: { \@@_table_print_S_centered_measure_int_part: \@@_table_print_S_centered_measure_marker: \@@_table_print_S_centered_measure_result: } \cs_new_protected:Npn \@@_table_print_S_centered_measure_int_part: { \prop_get:NnNF \l_@@_number_out_prop { comparator } \l_@@_tmpa_tl { \tl_clear:N \l_@@_tmpa_tl } \prop_get:NnNT \l_@@_number_out_prop { mantissa-sign } \l_@@_tmpb_tl { \tl_put_right:No \l_@@_tmpa_tl \l_@@_tmpb_tl } \prop_get:NnNT \l_@@_number_out_prop { mantissa-integer } \l_@@_tmpb_tl { \tl_put_right:No \l_@@_tmpa_tl \l_@@_tmpb_tl } \@@_table_print_S_measure:NN \l_@@_tmpa_tl \l_@@_table_integer_dim } \cs_new_protected:Npn \@@_table_print_S_centered_measure_marker: { \@@_table_print_S_measure:NN \l_@@_output_decimal_tl \l_@@_table_marker_dim } % \end{macrocode} % As the overall result will be needed later, the boxing up here is done % using a named box that will be retained. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_centered_measure_result: { \prop_get:NnN \l_@@_number_out_prop { result } \l_@@_tmpa_tl \hbox_set:Nn \l_@@_table_result_box { \@@_print:nV { number } \l_@@_tmpa_tl } \dim_set:Nn \l_@@_table_result_dim { \box_wd:N \l_@@_table_result_box } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro} % { % \@@_table_print_S_centered_integer: , % \@@_table_print_S_centered_decimal: % } % The appropriate place to insert the fill is determined by whether the % integer or decimal part of the number is bigger. Two dimensions are % therefore set, for fill before the number and after it. One of these % will always be zero. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_centered_integer: { \dim_set:Nn \l_@@_table_fill_post_dim { \l_@@_table_integer_dim - \l_@@_table_fill_pre_dim } \dim_zero:N \l_@@_table_fill_pre_dim } \cs_new_protected:Npn \@@_table_print_S_centered_decimal: { \dim_sub:Nn \l_@@_table_fill_pre_dim { \l_@@_table_integer_dim } \dim_zero:N \l_@@_table_fill_post_dim } % \end{macrocode} % \end{macro} % % \subsection{Printing the \texttt{S} column with space reserved} % % \begin{macro}{\@@_table_print_S_reserved:} % The procedure for inserting a number with space reserved requires a model % for each part of the number. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_reserved: { \@@_table_print_S_reserved_init: \@@_table_print_S_reserved_ends: \bool_if:NT \l_@@_table_auto_round_bool { \@@_table_print_S_reserved_round_auto: } \@@_table_print_S_parse: \bool_if:NF \l_@@_error_bool { \bool_if:NT \l_@@_table_math_bool { \c_math_toggle_token } \@@_table_print_S_reserved_comparator: \@@_table_print_S_reserved_mantissa: \@@_table_print_S_reserved_exponent: \bool_if:NT \l_@@_table_math_bool { \c_math_toggle_token } } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_table_print_S_reserved_init:} % The creation of a model for the cell to follow. Creation of the finalised % model is done here so that all of the other options will apply without % needing complex internal tracking. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_reserved_init: { \dim_zero:N \l_@@_table_fill_mid_dim \dim_zero:N \l_@@_table_fill_post_dim \prop_set_eq:NN \l_@@_number_in_prop \l_@@_table_model_prop \@@_number_process_sign: \@@_number_process_zero_fill: \@@_number_process_mantissa: \prop_if_in:NnF \l_@@_number_in_prop { symbolic } { \@@_number_process_uncertainty: } \@@_number_format: \prop_get:NnNT \l_@@_table_model_prop { mantissa-decimal-raw } \l_@@_tmpa_tl { \prop_put:NnV \l_@@_number_out_prop { mantissa-decimal-raw } \l_@@_tmpa_tl } \prop_set_eq:NN \l_@@_table_model_prop \l_@@_number_out_prop } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_table_print_S_reserved_ends:} % The end material here is boxed up into the space already reserved. % That means doing two boxing ups: one for the model, and one for the % real thing. As in the centred case, if the pre-numeral part has no % width then the tokens are inserted \enquote{as is}. To avoid any issues % with people forgetting to reserve space for the pre-numeral part, it is % boxed up first at natural width so that the measurement is accurate. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_reserved_ends: { \hbox_set:Nn \l_@@_table_pre_box { { \l_@@_table_collect_pre_tl \bool_if:NT \l_@@_table_math_bool { \scan_stop: \c_math_toggle_token } } } \dim_compare:nNnT { \box_wd:N \l_@@_table_pre_box } = \c_zero_dim { \l_@@_table_collect_pre_tl \bool_set_false:N \l_@@_font_set_bool } \hbox_set:Nn \l_@@_tmp_box { { \l_@@_table_pre_tl } } \hbox_set_to_wd:Nnn \l_@@_table_pre_box { \box_wd:N \l_@@_tmp_box } { \tex_hfil:D \hbox_unpack:N \l_@@_table_pre_box } \hbox_set:Nn \l_@@_tmp_box { \l_@@_table_post_tl } \hbox_set_to_wd:Nnn \l_@@_table_post_box { \box_wd:N \l_@@_tmp_box } { { \bool_if:NT \l_@@_table_math_bool { \c_math_toggle_token \scan_stop: } \l_@@_table_collect_post_tl } \tex_hfil:D } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_table_print_S_reserved_round_auto:} % For auto-rounding, the approach is to find how many decimal digits are % allowed for, and if there are none to simply set the rounding value to % zero. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_reserved_round_auto: { \prop_get:NnNTF \l_@@_table_model_prop { mantissa-decimal-raw } \l_@@_tmpa_tl { \int_set:Nn \l_@@_process_precision_int { \l_@@_tmpa_tl } } { \int_zero:N \l_@@_process_precision_int } \tl_set:Nn \l_@@_round_tl { places } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_table_print_S_reserved_comparator:} % The comparator is quite simple to deal with. Assuming that there is a % comparator in the model, this is measured for the reserved width. The % real comparator can then simply be typeset in a box of the same size. % If there is no comparator in the real case, then the space added to % that for filling: this is needed so that any pre-note can be aligned % freely. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_reserved_comparator: { \prop_get:NnNTF \l_@@_table_model_prop { comparator } \l_@@_tmpa_tl { \hbox_set:Nn \l_@@_tmp_box { \@@_print:nV { number } \l_@@_tmpa_tl } \prop_get:NnNTF \l_@@_number_out_prop { comparator } \l_@@_tmpa_tl { \hbox_set_to_wd:Nnn \l_@@_table_result_box { \box_wd:N \l_@@_tmp_box } { \@@_print:nV { number } \l_@@_tmpa_tl } } { \dim_add:Nn \l_@@_table_fill_pre_dim { \box_wd:N \l_@@_tmp_box } \cs_set_eq:NN \@@_table_print_S_reserved_store_fill:n \@@_table_print_S_reserved_store_fill_pre:n } } { \cs_set_eq:NN \@@_table_print_S_reserved_store_fill:n \@@_table_print_S_reserved_store_fill_pre:n \prop_if_in:NnT \l_@@_number_out_prop { comparator } { \msg_error:nnx { siunitx } { table-partial-number } { a~comparator } } } } % \end{macrocode} % \end{macro} % % \begin{macro} % { % \@@_table_print_S_reserved_store_fill_pre:n , % \@@_table_print_S_reserved_store_fill_mid:n % } % To allow for the various alignment options, fill is stored in a % flexible way. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_reserved_store_fill_pre:n { \dim_add:Nn \l_@@_table_fill_pre_dim } \cs_new_protected:Npn \@@_table_print_S_reserved_store_fill_mid:n { \dim_add:Nn \l_@@_table_fill_mid_dim } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_table_print_S_reserved_mantissa:} % \begin{macro}[aux] % { % \@@_table_print_S_reserved_mantissa_parts: , % \@@_table_print_S_reserved_mantissa_integer: % } % The mantissa of a number may contain a sign, an integer part, a % decimal marker, a decimal part and a non-separated uncertainty. That % means that there are two ways to deal with the alignment. Each part % could be done separately, or a correction can be made after setting % the combined mantissa. Here, the later approach is taken. The first % step is to deal with the mantissa as a whole: work out show much space % to reserve, and see if there is anything at all to put in it. The % complexity only starts if there is a mantissa in the current cell. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_reserved_mantissa: { \prop_get:NnNTF \l_@@_table_model_prop { mantissa } \l_@@_tmpa_tl { \hbox_set:Nn \l_@@_tmp_box { \@@_print:nV { number } \l_@@_tmpa_tl } \prop_get:NnNTF \l_@@_number_out_prop { mantissa } \l_@@_tmpa_tl { \dim_set:Nn \l_@@_table_mantissa_dim { \box_wd:N \l_@@_tmp_box } \hbox_set:Nn \l_@@_table_mantissa_box { \@@_print:nV { number } \l_@@_tmpa_tl } \@@_table_print_S_reserved_mantissa_parts: } { \@@_table_print_S_reserved_store_fill:n { \box_wd:N \l_@@_tmp_box } } } { \prop_if_in:NnT \l_@@_number_out_prop { mantissa } { \msg_error:nnx { siunitx } { table-partial-number } { a~mantissa } } } } % \end{macrocode} % The aim here is to deal with the mantissa with as few measurements as % possible. The integer part is therefore measured, with the real and model % versions compared. This allows appropriate fill to be calculated to % add the mantissa to the result box, after any comparator and with % the appropriate width. Once that is done, the amount of filler needed % \emph{after} the integer can be calculated: this is the size of the % model mantissa, minus the size of the real mantissa and the amount of % filler needed in the integer part. That is stored in the intermediate % dimension for the present, although it may get moved. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_reserved_mantissa_parts: { \@@_table_print_S_reserved_mantissa_integer: \hbox_set:Nn \l_@@_table_result_box { \hbox_unpack:N \l_@@_table_result_box \hbox_to_wd:nn { \l_@@_table_fill_mid_dim } { \tex_hfil:D } \hbox_unpack:N \l_@@_table_mantissa_box } \dim_set:Nn \l_@@_table_fill_mid_dim { \l_@@_table_mantissa_dim - \box_wd:N \l_@@_table_mantissa_box - \l_@@_table_integer_dim } \@@_table_print_S_reserved_mantissa_uncert: } % \end{macrocode} % For the integer part, there is a need to measure both the sign and % the integer itself in the model and in the real number. If there is % no integer part in the real number, then fill is stored to add either % before or after any comparator. If there is an integer part, the % size is measured and the any fill needed is stored for re-insertion. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_reserved_mantissa_integer: { \prop_get:NnNF \l_@@_table_model_prop { mantissa-sign } \l_@@_tmpa_tl { \tl_clear:N \l_@@_tmpa_tl } \prop_get:NnNT \l_@@_table_model_prop { mantissa-integer } \l_@@_tmpb_tl { \tl_put_right:No \l_@@_tmpa_tl \l_@@_tmpb_tl } \@@_table_print_S_measure:NN \l_@@_tmpa_tl \l_@@_table_integer_dim \prop_get:NnNF \l_@@_number_out_prop { mantissa-sign } \l_@@_tmpa_tl { \tl_clear:N \l_@@_tmpa_tl } \prop_get:NnNT \l_@@_number_out_prop { mantissa-integer } \l_@@_tmpb_tl { \tl_put_right:No \l_@@_tmpa_tl \l_@@_tmpb_tl } \tl_if_empty:NF \l_@@_tmpa_tl { \@@_table_print_S_measure:NN \l_@@_tmpa_tl \l_@@_tmp_dim \dim_sub:Nn \l_@@_table_integer_dim { \l_@@_tmp_dim } } \@@_table_print_S_reserved_store_fill:n { \l_@@_table_integer_dim } } % \end{macrocode} % Here, a separated uncertainty is handled. If there is one, then there must % be a \cs{pm} part to add. Once the space calculation is done, a flexible % auxiliary does the spacing and pasting up. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_reserved_mantissa_uncert: { \prop_get:NnNT \l_@@_table_model_prop { mantissa-uncertainty } \l_@@_tmpa_tl { \@@_number_format_join_uncert_pm:N \l_@@_tmpa_tl \hbox_set:Nn \l_@@_tmp_box { \@@_print:nV { number } \l_@@_tmpa_tl } \prop_get:NnNTF \l_@@_number_out_prop { mantissa-uncertainty } \l_@@_tmpa_tl { \dim_set:Nn \l_@@_table_uncert_dim { \box_wd:N \l_@@_tmp_box } \@@_number_format_join_uncert_pm:N \l_@@_tmpa_tl \hbox_set:Nn \l_@@_tmp_box { \@@_print:nV { number } \l_@@_tmpa_tl } \bool_if:NTF \l_@@_table_align_uncert_bool { \@@_table_print_S_reserved_mantissa_uncert_aligned: } { \@@_table_print_S_reserved_mantissa_uncert_not_aligned: } } { \cs_set_eq:NN \@@_table_print_S_reserved_store_fill:n \@@_table_print_S_reserved_store_fill_mid:n \@@_table_print_S_reserved_store_fill:n { \box_wd:N \l_@@_tmp_box } } } } % \end{macrocode} % Two auxiliaries, one to place the uncertainty directly next to the rest % of the mantissa, one to maintain alignment. In both cases, any fill ends % up in the middle fill store, but in the alignment case this also removes % any previous fill. The temporary box here contains the uncertainty part. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_reserved_mantissa_uncert_aligned: { \hbox_set:Nn \l_@@_table_result_box { \hbox_unpack:N \l_@@_table_result_box \hbox_to_wd:nn { \l_@@_table_fill_mid_dim } { \tex_hfil:D } \hbox_unpack:N \l_@@_tmp_box } \dim_set:Nn \l_@@_table_fill_mid_dim { \l_@@_table_uncert_dim - \box_wd:N \l_@@_tmp_box } } \cs_new_protected:Npn \@@_table_print_S_reserved_mantissa_uncert_not_aligned: { \hbox_set:Nn \l_@@_table_result_box { \hbox_unpack:N \l_@@_table_result_box \hbox_unpack:N \l_@@_tmp_box } \dim_add:Nn \l_@@_table_fill_mid_dim { \l_@@_table_uncert_dim - \box_wd:N \l_@@_tmp_box } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@@_table_print_S_reserved_exponent:} % \begin{macro}[aux] % { % \@@_table_print_S_reserved_exponent_product: , % \@@_table_print_S_reserved_exponent_product_correction: , % \@@_table_print_S_reserved_exponent_aligned: , % \@@_table_print_S_reserved_exponent_not_aligned: % } % Printing the exponent needs to deal with the exponent product. This % is easiest to do by simply re-checking for a mantissa. If there is no % exponent, then any space which needs to be added must be moved from % the mid space to the post space at this stage. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_reserved_exponent: { \prop_get:NnNTF \l_@@_table_model_prop { exponent-result } \l_@@_tmpa_tl { \prop_if_in:NnT \l_@@_table_model_prop { mantissa } { \@@_table_print_S_reserved_exponent_product: } \hbox_set:Nn \l_@@_tmp_box { \@@_print:nV { number } \l_@@_tmpa_tl } \prop_get:NnNTF \l_@@_number_out_prop { exponent-result } \l_@@_tmpa_tl { \dim_set:Nn \l_@@_table_exponent_dim { \box_wd:N \l_@@_tmp_box } \tl_if_empty:NT \l_@@_output_exponent_tl { \prop_if_in:NnTF \l_@@_number_out_prop { mantissa } { \@@_table_print_S_reserved_exponent_product: } { \@@_table_print_S_reserved_exponent_product_correction: } } \hbox_set:Nn \l_@@_tmp_box { \@@_print:nV { number } \l_@@_tmpa_tl } \bool_if:NTF \l_@@_table_align_exponent_bool { \@@_table_print_S_reserved_exponent_aligned: } { \@@_table_print_S_reserved_exponent_not_aligned: } } { \dim_set:Nn \l_@@_table_fill_post_dim { \l_@@_table_fill_mid_dim + \box_wd:N \l_@@_tmp_box } } } { \prop_if_in:NnT \l_@@_number_out_prop { exponent-result } { \msg_error:nnx { siunitx } { table-partial-number } { an~exponent } } \dim_set_eq:NN \l_@@_table_fill_post_dim \l_@@_table_fill_mid_dim } } % \end{macrocode} % A short sub-function to deal with the appearance of the exponent product % for both the real number and the model. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_reserved_exponent_product: { \tl_set_eq:NN \l_@@_tmpb_tl \l_@@_exponent_product_tl \bool_if:NT \l_@@_tight_bool { \tl_set:Nx \l_@@_tmpb_tl { \exp_not:N \mathord \exp_not:o \l_@@_tmpb_tl } } \tl_set:Nx \l_@@_tmpa_tl { \exp_not:N \ensuremath { { } \exp_not:o \l_@@_tmpb_tl { } } \exp_not:o \l_@@_tmpa_tl } } % \end{macrocode} % If there is no mantissa, then some additional space is needed for the % location where the product symbol would have been. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_reserved_exponent_product_correction: { \group_begin: \tl_clear:N \l_@@_tmpa_tl \@@_table_print_S_reserved_exponent_product: \tl_set:Nx \l_@@_tmpa_tl { { } \exp_not:o \l_@@_tmpa_tl { } } \@@_table_print_S_measure:NN \l_@@_tmpa_tl \l_@@_tmp_dim \exp_args:NNNo \group_end: \dim_set:Nn \l_@@_tmp_dim { \dim_use:N \l_@@_tmp_dim } \@@_table_print_S_reserved_store_fill:n { \l_@@_tmp_dim } \dim_sub:Nn \l_@@_table_exponent_dim { \l_@@_tmp_dim } } % \end{macrocode} % There are two cases for adding the exponent to the result box, one % with additional space to maintain alignment, and one with no space. % The space needed after the exponent then can be set to either include % or exclude the mid fill space. Doing that here avoids one extra assignment % (to clear the mid fill in the aligned case). % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_reserved_exponent_aligned: { \hbox_set:Nn \l_@@_table_result_box { \hbox_unpack:N \l_@@_table_result_box \hbox_to_wd:nn { \l_@@_table_fill_mid_dim } { \tex_hfil:D } \hbox_unpack:N \l_@@_tmp_box } \dim_set:Nn \l_@@_table_fill_post_dim { \l_@@_table_exponent_dim - \box_wd:N \l_@@_tmp_box } } \cs_new_protected:Npn \@@_table_print_S_reserved_exponent_not_aligned: { \hbox_set:Nn \l_@@_table_result_box { \hbox_unpack:N \l_@@_table_result_box \hbox_unpack:N \l_@@_tmp_box } \dim_set:Nn \l_@@_table_fill_post_dim { \l_@@_table_fill_mid_dim + \l_@@_table_exponent_dim - \box_wd:N \l_@@_tmp_box } } % \end{macrocode} % \end{macro} % \end{macro} % % \subsection{Direct printing in \texttt{S} columns} % % When number parsing is turned off the usual approach to printing % tabular material is not suitable. Instead, the strategy used by % \pkg{dcolumn} can be applied, which requires the decimal marker to % be made active in math mode. % % \begin{macro}{\@@_table_print_S_direct:N} % \begin{macro}{\@@_table_print_S_direct_text:n} % The lead-off here first moves the \cs{ignorespaces} in the input to % avoid picking it up. There is then a test to see if the very first item % in the cell is a |{|. If it is, then we use the same approach as for % parsed columns and set the material as text. Otherwise, switch to math % mode and hand off to the main routine. % \begin{macrocode} \cs_new_protected:Npn \@@_table_print_S_direct:N #1 { #1 \cs_set:Npn \__peek_execute_branches: { \if_catcode:w \exp_not:N \l_peek_token \c_group_begin_token \exp_after:wN \@@_table_print_S_direct_text:n \else: \m@th \exp_after:wN \@@_table_print_S_direct_main: \fi: } \peek_after:Nw \__peek_ignore_spaces_execute_branches: } \cs_new_protected:Npn \@@_table_print_S_direct_text:n #1 { \@@_table_column_begin:n { \l_@@_table_text_align_skip } #1 \@@_table_column_end:n { \l_@@_table_text_align_skip } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro} % { % \@@_table_print_S_direct_centered: , % \@@_table_print_S_direct_centered_end: % } % \begin{macro}[aux]{\@@_table_print_S_direct_centered_aux:N} % When centring the content about a decimal marker, the trick is % to collect everything into two boxes and then compare the sizes. % In that sense this is very similar to the normal method, except that % it will work with non-numerical input. % \begin{macrocode} \char_set_catcode_active:N \@ \cs_new_protected:Npn \@@_table_print_S_direct_centered: { \cs_set_eq:NN \@@_table_print: \@@_table_print_S_direct_centered_end: \hbox_set:Nn \l_@@_tmp_box { \ensuremath { \l_@@_output_decimal_tl } } \hbox_set_to_wd:Nnn \l_@@_table_post_box { \box_wd:N \l_@@_tmp_box } { \tex_hfil:D } \hbox_set:Nn \l_@@_table_pre_box \c_group_begin_token \c_math_toggle_token \tl_map_function:NN \l_@@_input_decimal_tl \@@_table_print_S_direct_centered_aux:N } \cs_new_protected:Npn \@@_table_print_S_direct_centered_aux:N #1 { \char_set_lccode:nn { `\@ } { `#1 } \char_set_mathcode:nn { `#1 } { 32768 } \tl_to_lowercase:n { \cs_set:Npn @ } { \c_math_toggle_token \c_group_end_token \hbox_set:Nn \l_@@_table_post_box \c_group_begin_token \c_math_toggle_token \l_@@_output_decimal_tl } } \char_set_catcode_letter:N \@ \cs_new_protected:Npn \@@_table_print_S_direct_centered_end: { \c_math_toggle_token \c_group_end_token \dim_compare:nNnTF { \box_wd:N \l_@@_table_pre_box } > { \box_wd:N \l_@@_table_post_box } { \hbox_set_to_wd:Nnn \l_@@_table_post_box { \box_wd:N \l_@@_table_pre_box } { \hbox_unpack:N \l_@@_table_post_box \tex_hfil:D } } { \hbox_set_to_wd:Nnn \l_@@_table_pre_box { \box_wd:N \l_@@_table_post_box } { \tex_hfil:D \hbox_unpack:N \l_@@_table_pre_box } } \box_use:N \l_@@_table_pre_box \box_use:N \l_@@_table_post_box } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro} % { % \@@_table_print_S_direct_reserved: , % \@@_table_print_S_direct_reserved_end: % } % \begin{macro}[aux]{\@@_table_print_S_direct_reserved_aux:N} % The plan here is to box up the entire number using the information % available about the size of the two parts. Relatively easy, % but needs a bit of measuring. The first box here does need to use % \cs{tex_hill:D} as \texttt{fil} glue will not work. % \begin{macrocode} \char_set_catcode_active:N \@ \cs_new_protected:Npn \@@_table_print_S_direct_reserved: { \cs_set_eq:NN \@@_table_print: \@@_table_print_S_direct_reserved_end: \prop_get:NnNF \l_@@_table_model_prop { mantissa-integer } \l_@@_tmpa_tl { \tl_clear:N \l_@@_tmpa_tl } \hbox_set:Nn \l_@@_tmp_box { \ensuremath { \prop_get:NnNT \l_@@_table_model_prop { mantissa-sign } \l_@@_tmpb_tl { \l_@@_tmpb_tl } \l_@@_tmpa_tl } } \dim_set:Nn \l_@@_table_integer_dim { \box_wd:N \l_@@_tmp_box } \prop_get:NnNF \l_@@_table_model_prop { mantissa-decimal } \l_@@_tmpa_tl { \tl_clear:N \l_@@_tmpa_tl } \hbox_set:Nn \l_@@_tmp_box { \ensuremath { \l_@@_output_decimal_tl \l_@@_tmpa_tl } } \hbox_set_to_wd:Nnn \l_@@_table_post_box { \box_wd:N \l_@@_tmp_box } { \tex_hfil:D } \hbox_set_to_wd:Nnn \l_@@_table_pre_box { \l_@@_table_integer_dim } \c_group_begin_token \c_math_toggle_token \tl_map_function:NN \l_@@_input_decimal_tl \@@_table_print_S_direct_reserved_aux:N \tex_hfill:D } \cs_new_protected:Npn \@@_table_print_S_direct_reserved_aux:N #1 { \char_set_lccode:nn { `\@ } { `#1 } \char_set_mathcode:nn { `#1 } { 32768 } \tl_to_lowercase:n { \cs_set:Npn @ } { \c_math_toggle_token \c_group_end_token \hbox_set_to_wd:Nnn \l_@@_table_post_box { \box_wd:N \l_@@_tmp_box } \c_group_begin_token \c_math_toggle_token \l_@@_output_decimal_tl } } \char_set_catcode_letter:N \@ \cs_new_protected:Npn \@@_table_print_S_direct_reserved_end: { \c_math_toggle_token \tex_hfil:D \c_group_end_token \@@_table_align_left:n { \l_@@_table_number_align_skip } \box_use:N \l_@@_table_pre_box \box_use:N \l_@@_table_post_box \@@_table_align_right:n { \l_@@_table_number_align_skip } } % \end{macrocode} % \end{macro} % \end{macro} % % \subsection{Table settings} % % To allow for the construction above, the table settings are given here. % % \begin{macrocode} \keys_set:nn { siunitx } { table-align-comparator = true, table-align-exponent = true, table-align-text-pre = true, table-align-text-post = true, table-align-uncertainty = true, table-omit-exponent = false, table-parse-only = false, table-number-alignment = center-decimal-marker, table-text-alignment = center, table-figures-decimal = 2, table-figures-integer = 3 } % \end{macrocode} % %\subsection{Symbols} % % Not all units use letters alone for their symbol. This raises two % problems. First, the symbols need to work in math and in text mode. % Second, the user needs to be able to adjust each symbol. % %\begin{macro}{\l_@@_redefine_symbols_bool} % Only one setting applies here! % \begin{macrocode} \keys_define:nn { siunitx } { redefine-symbols .bool_set:N = \l_@@_redefine_symbols_bool } \keys_set:nn { siunitx } { redefine-symbols = true } % \end{macrocode} %\end{macro} % % The redefinition of symbols has to do a number of checks to ensure % that there are no clashes. % \begin{macrocode} \AtBeginDocument { \bool_if:NT \l_@@_redefine_symbols_bool { \@ifpackageloaded { textcomp } { \@@_option_unchanged:Nnn \l_@@_degree_math_tl { { } ^ { \circ } } { \text { \textdegree } } \@@_option_unchanged:Nnn \l_@@_degree_text_tl { \ensuremath { { } ^ { \circ } } } { \textdegree } \@ifpackageloaded { mathptmx } { } { \@@_option_unchanged:Nnn \l_@@_micro_text_tl { \c_@@_mu_tl } { \textmu } \@ifpackageloaded { fourier } { } { \@@_option_unchanged:Nnn \l_@@_ohm_text_tl { \ensuremath { \c_@@_omega_tl } } { \textohm } } } \str_if_eq:VnT \encodingdefault { OT1 } { \@@_option_unchanged:Nnn \l_@@_angstrom_math_tl { \text { \AA } } { \text { \capitalring { A } } } \@@_option_unchanged:Nnn \l_@@_angstrom_text_tl { \AA } { \capitalring { A } } } } { } \@ifpackageloaded { upgreek } { \@@_option_unchanged:Nnn \l_@@_ohm_math_tl { \text { \ensuremath { \c_@@_omega_tl } } } { \Upomega } } { } } } % \end{macrocode} % %\begin{macro}{\l_@@_angstrom_math_tl} %\begin{macro}{\l_@@_arcminute_math_tl} %\begin{macro}{\l_@@_arcsecond_math_tl} %\begin{macro}{\l_@@_celsius_math_tl} %\begin{macro}{\l_@@_degree_math_tl} %\begin{macro}{\l_@@_micro_math_tl} %\begin{macro}{\l_@@_ohm_math_tl} % The symbol storage macros are created separately for math and text % mode, although this is all pretty similar. The default definitions use % what is generally available, except for those for micro, where % Computer Modern does not have the appropriate symbol at all. For the % math mode omega option, the "\text{\ensuremath{...}}" construction % deals with the case where \cs{mathnormal} has the wrong symbol. % \begin{macrocode} \keys_define:nn { siunitx } { math-angstrom .tl_set:N = \l_@@_angstrom_math_tl, math-arcminute .tl_set:N = \l_@@_arcminute_math_tl, math-arcsecond .tl_set:N = \l_@@_arcsecond_math_tl, math-celsius .tl_set:N = \l_@@_celsius_math_tl, math-degree .tl_set:N = \l_@@_degree_math_tl, math-micro .tl_set:N = \l_@@_micro_math_tl, math-ohm .tl_set:N = \l_@@_ohm_math_tl } \keys_set:nn { siunitx } { math-angstrom = \text { \AA }, math-arcminute = { } ^ { \prime }, math-arcsecond = { } ^ { \prime \prime }, math-celsius = { } ^ { \circ } \kern - \scriptspace \mathrm { C }, math-degree = { } ^ { \circ }, math-micro = \text { \c_@@_mu_tl }, math-ohm = \text { \ensuremath { \c_@@_omega_tl } }, } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\l_@@_angstrom_text_tl} %\begin{macro}{\l_@@_arcminute_text_tl} %\begin{macro}{\l_@@_arcsecond_text_tl} %\begin{macro}{\l_@@_celsius_text_tl} %\begin{macro}{\l_@@_degree_text_tl} %\begin{macro}{\l_@@_micro_text_tl} %\begin{macro}{\l_@@_ohm_text_tl} % Text versions are similar. % \begin{macrocode} \keys_define:nn { siunitx } { text-angstrom .tl_set:N = \l_@@_angstrom_text_tl, text-arcminute .tl_set:N = \l_@@_arcminute_text_tl, text-arcsecond .tl_set:N = \l_@@_arcsecond_text_tl, text-celsius .tl_set:N = \l_@@_celsius_text_tl, text-degree .tl_set:N = \l_@@_degree_text_tl, text-micro .tl_set:N = \l_@@_micro_text_tl, text-ohm .tl_set:N = \l_@@_ohm_text_tl, } \keys_set:nn { siunitx } { text-angstrom = \AA, text-arcminute = \ensuremath { { } ^ { \prime } }, text-arcsecond = \ensuremath { { } ^ { \prime \prime } }, text-celsius = \ensuremath { { } ^ { \circ } \kern - \scriptspace \text { C } }, text-degree = \ensuremath { { } ^ { \circ } }, text-micro = \c_@@_mu_tl , text-ohm = \ensuremath { \c_@@_omega_tl }, } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\@@_symbol_new:n} % For creating the outer symbol macro. % \begin{macrocode} \cs_new_protected:Npn \@@_symbol_new:n #1 { \cs_set_protected:cpn { SIUnitSymbol #1 } { \mode_if_math:TF { \tl_to_lowercase:n { \use:c { l_@@_ #1 _math_tl } } } { \tl_to_lowercase:n { \use:c { l_@@_ #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} \@@_symbol_new:n { Angstrom } \@@_symbol_new:n { Arcminute } \@@_symbol_new:n { Arcsecond } \@@_symbol_new:n { Celsius } \@@_symbol_new:n { Degree } \@@_symbol_new:n { Micro } \@@_symbol_new:n { Ohm } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % % \begin{variable} % { % \c_@@_degree_int , % \c_@@_micro_int , % \c_@@_angstrom_int , % \c_@@_ohm_int , % \c_@@_arcminute_int, % \c_@@_arcsecond_int % } % For UTF-8 engines, it may be possible to use better symbols than those set % up as standard. Unicode normalises both the ohm and {\aa}ngstr{\"{o}}m % symbols to the appropriate letters, so these are used directly. On the % other hand, micro is distinct from mu, so the proper symbol is selected. % The single degree Celsius symbol is a compatibility character, and so % the two separate glyphs \enquote{degree} and \enquote{C} are used. % \begin{macrocode} \pdftex_if_engine:F { \AtBeginDocument { \@ifpackageloaded { fontspec } { \int_const:Nn \c_@@_degree_int { 176 } \int_const:Nn \c_@@_micro_int { "003BC } \int_const:Nn \c_@@_angstrom_int { "0212B } \int_const:Nn \c_@@_ohm_int { "003A9 } \@@_option_unchanged:Nnn \l_@@_angstrom_math_tl { \text { \AA } } { \tex_char:D \c_@@_angstrom_int } \@@_option_unchanged:Nnn \l_@@_celsius_math_tl { { } ^ { \circ } \kern - \scriptspace \text { C } } { \tex_char:D \c_@@_degree_int C } \@@_option_unchanged:Nnn \l_@@_degree_math_tl { { } ^ { \circ } } { \tex_char:D \c_@@_degree_int } \@@_option_unchanged:Nnn \l_@@_micro_math_tl { \text { \c_@@_mu_tl } } { \tex_char:D \c_@@_micro_int } \@@_option_unchanged:Nnn \l_@@_ohm_math_tl { \text { \ensuremath { \c_@@_omega_tl } } } { \tex_char:D \c_@@_ohm_int } \@@_option_unchanged:Nnn \l_@@_angstrom_text_tl { \AA } { \tex_char:D \c_@@_angstrom_int } \@@_option_unchanged:Nnn \l_@@_celsius_text_tl { \ensuremath { { } ^ { \circ } \kern - \scriptspace \text { C } } } { \tex_char:D \c_@@_degree_int C } \@@_option_unchanged:Nnn \l_@@_degree_text_tl { \ensuremath { { } ^ { \circ } } } { \tex_char:D \c_@@_degree_int } \@@_option_unchanged:Nnn \l_@@_micro_text_tl { \c_@@_mu_tl } { \tex_char:D \c_@@_micro_int } \@@_option_unchanged:Nnn \l_@@_ohm_text_tl { \ensuremath { \c_@@_omega_tl } } { \tex_char:D \c_@@_ohm_int } } { } % \end{macrocode} % Slightly more specialised: these only work in math mode with % \pkg{unicode-math}. % \begin{macrocode} \@ifpackageloaded { unicode-math } { \int_const:Nn \c_@@_arcminute_int { 8242 } \int_const:Nn \c_@@_arcsecond_int { 8243 } \@@_option_unchanged:Nnn \l_@@_arcminute_math_tl { { } ^ { \prime } } { \ensuremath { \tex_char:D \c_@@_arcminute_int } } \@@_option_unchanged:Nnn \l_@@_arcsecond_math_tl { { } ^ { \prime \prime } } { \ensuremath { \tex_char:D \c_@@_arcsecond_int } } \@@_option_unchanged:Nnn \l_@@_arcminute_text_tl { \ensuremath { { } ^ { \prime } } } { \ensuremath { \tex_char:D \c_@@_arcminute_int } } \@@_option_unchanged:Nnn \l_@@_arcsecond_text_tl { \ensuremath { { } ^ { \prime \prime } } } { \ensuremath { \tex_char:D \c_@@_arcsecond_int } } } { } } } % \end{macrocode} % \end{variable} % %\subsection{Working with other packages} % %\begin{macro}{\l_@@_pgf_link_clist} %\begin{macro}{\@@_pgf_link:} % Here, the settings used by \pkg{siunitx} are translated into those for % \pkg{pgf}. Things could be done more efficiently, but the logic would % be more difficult to follow. % \begin{macrocode} \clist_new:N \l_@@_pgf_link_clist \cs_new_protected:Npn \@@_pgf_link: { \clist_clear:N \l_@@_pgf_link_clist \str_if_eq:VnT \l_@@_round_tl { figure } { \clist_put_right:Nn \l_@@_pgf_link_clist { fixed } \clist_put_right:Nn \l_@@_pgf_link_clist { fixed~zerofill = true } } \clist_put_right:Nx \l_@@_pgf_link_clist { precision = \int_use:N \l_@@_process_precision_int } \clist_put_right:Nx \l_@@_pgf_link_clist { set~decimal~separator = { { \exp_not:V \l_@@_output_decimal_tl } } } \clist_put_right:Nx \l_@@_pgf_link_clist { set~thousands~separator = { \exp_not:V \l_@@_group_sep_tl } } \clist_put_right:Nx \l_@@_pgf_link_clist { min~exponent~for~1000~sep = \int_eval:n { \l_@@_group_min_int - \c_one } } \bool_if:nF { \l_@@_group_decimal_bool || \l_@@_group_integer_bool } { \clist_put_right:Nn \l_@@_pgf_link_clist { min~exponent~for~1000~sep = 999 } } \bool_if:NTF \l_@@_process_integer_zero_bool { \clist_put_right:Nn \l_@@_pgf_link_clist { skip~0. = false } } { \clist_put_right:Nn \l_@@_pgf_link_clist { skip~0. = true } } \str_if_eq:VnTF \l_@@_process_sign_tl { + } { \clist_put_right:Nn \l_@@_pgf_link_clist { showpos = true } } { \clist_put_right:Nn \l_@@_pgf_link_clist { showpos = false } } \use:x { \exp_not:N \pgfqkeys { /pgf/number~format } { \exp_not:V \l_@@_pgf_link_clist } } } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Messages} % % Lots of messages, all of them together in one block to make life % easier. % \begin{macrocode} \msg_new:nnnn { siunitx } { bad-arc-sign } { Incorrect~use~of~sign~in~degree-minute-second~angle. } { Only~the~highest~value~part~of~an~angle~can~have~a~sign. } \msg_new:nnnn { siunitx } { duplicate-complex-root-token } { Duplicate~complex~root~token~'#1'~in~input. } { Only~one~complex~root~token~can~appear~in~a~single~number. } \msg_new:nnnn { siunitx } { duplicate-decimal-token } { Duplicate~decimal~marker~token~'#1'~in~input. } { Only~one~decimal~marker~token~can~appear~in~a~single~number. } \msg_new:nnnn { siunitx } { duplicate-exponent-token } { Duplicate~exponent~marker~token~'#1'~in~input. } { Only~one~exponent~marker~token~can~appear~in~a~single~number. } \msg_new:nnnn { siunitx } { duplicate-quotient-token } { Duplicate~quotient~token. } { Only~one~quotient~token~can~appear~in~a~single~number. } \msg_new:nnnn { siunitx } { duplicate-sticky-per } { Duplicate~\token_to_str:N \per. } { When~the~'sticky-per'~option~is~active,~only~one \token_to_str:N \per may~appear~in~a~unit. } \msg_new:nnnn { siunitx } { empty-arc } { Empty~degree-minute-second~angle. } { The~angle~given~does~not~contain~any~numbers. } \msg_new:nnnn { siunitx } { empty-uncertainty } { Empty~uncertainty~given~in~'#1'. } { The~number~given~contains~an~empty~uncertainty. } \msg_new:nnnn { siunitx } { ending-product-token } { Misplaced~product~token. } { A~number~cannot~end~with~a~product~token. } \msg_new:nnnn { siunitx } { ending-quotient-token } { Misplaced~quotient~token. } { A~number~cannot~end~with~a~quotient~token. } \msg_new:nnnn { siunitx } { invalid-arc-format } { Invalid~degree-minute-second angle~'#1'. } { Angles~given~in~degree-minute-second~format~should~contain~two~';' symbols~to~divide~up~the~parts~of~the~input. } \msg_new:nnnn { siunitx } { invalid-number } { Invalid~numerical~input~'#1'. } { The~input given~as~a~number~does~not~make~logical~sense.~ This~happens,~for example,~if~a~number~only~contains~a~sign. } \msg_new:nnnn { siunitx } { invalid-token-in-exponent } { Invalid~exponent~in~numerical~input~'#1'. } { The~exponent~part~of~a~number~cannot~contain~an~uncertainty~or~ complex~part: \\ the~input~given~appears~to~contain~one~of~these~in~the~exponent. } \msg_new:nnnn { siunitx } { invalid-token-in-number } { Invalid~token~'#1'~in~numerical~input. } { Numbers~can~only~contain~tokens~defined~using~the~ 'input-...'~options:\\ the~token~'#1'~is~not~set~up~as~a~valid~part~of~a~number. } \msg_new:nnnn { siunitx } { invalid-token-in-uncertainty } { Invalid~uncertainty~in~numerical~input~'#1'. } { The~uncertainty~part~of~a~number~may~only~contain~digits~or~ symbols. } \msg_new:nnnn { siunitx } { literal-unit } { Literal~units~disabled. } { You~gave~the~literal~input~'#1'~ but~literal~unit~output~is~disabled. } \msg_new:nnnn { siunitx } { misplaced-sign-token } { Misplaced~sign~token~'#1'. } { Sign~tokens~can~only~come~at~the~beginning~of~a~number. } \msg_new:nnnn { siunitx } { misplaced-complex-root-token } { Misplaced~complex~token~in~numerical~input~'#1'. } { The~root~token~must~come~either~before~or~after~the~real~digits~ of~the~complex~part. } \msg_new:nnnn { siunitx } { misplaced-uncertainty-token } { Misplaced~uncertainty~token~'#1'. } { The~uncertainty~in~a~number~must~be~given~between~a~set~of~ delimiters~as~defined~by~the\\ \ \ 'input-open-uncertainty'~and~'input-close-uncertainty'~ options. } \msg_new:nnnn { siunitx } { multi-part-range } { Numerical~range~with~multiple~parts. } { The~input~'#1'~is~a~number~which~has~more~than~one~part: \\ ranges~can~only~contain~one~number~in~each~part. } \msg_new:nnn { siunitx } { non-convertible-exponent } { Exponent~'#1'~cannot~be~converted~into~a~symbolic~prefix. } \msg_new:nnn { siunitx } { option-not-available } { Option~'#1'~not~available~in~strict~mode. } \msg_new:nnn { siunitx } { option-preamble-only } { Option~'#1'~only~available~in~the~preamble. } \msg_new:nnnn { siunitx } { prefix-base-mismatch } { Prefix~bases~do~not~match. } { You~have~asked~for~prefixes~to~be~converted~into~a~power,~ but~the~bases~do~not~match. } \msg_new:nnn { siunitx } { prefix-only } { Prefix~with~no~unit. } \msg_new:nnnn { siunitx } { qualifier-before-unit } { Qualifier~before~unit. } { Unit~qualifiers~have~to~follow~after~units,~not~before~them. } \msg_new:nnnn { siunitx } { restricted-number } { Token~'#1'~forbidden~in~restricted~numerical~input. } { The~current~input~must~be~a~real~number~and~cannot~contain: \\ \ -~an~exponent; \\ \ -~an~uncertainty; \\ \ -~a~complex~part. } \msg_new:nnnn { siunitx } { starting-product-token } { Misplaced~product~token. } { A~number~cannot~begin~with~a~product~token. } \msg_new:nnnn { siunitx } { starting-quotient-token } { Misplaced~quotient~token. } { A~number~cannot~begin~with~a~quotient~token. } \msg_new:nnnn { siunitx } { table-partial-number } { No~space~reserved~for~#1~\msg_line_context:. } { The~number~in~the~current~table~cell~contains~#1~part, but~you~did~not~reserve~any~space~to~print~it: \\ it~will~be~missing~in~the~output. } \msg_new:nnnn { siunitx } { unknown-option } { Unknown~option~'#1'. } { The~option~file~'#1'~is~not~known~by~siunitx: perhaps~it~is~spelled~incorrectly. } \msg_new:nnnn { siunitx } { version-1-option } { Version~1~option~'#1'~detected. } { Use: \\ \ \ \token_to_str:N \usepackage [ version-1-compatibility ] \iow_char:N \{ siunitx \token_to_str:N \iow_char:N \} \\ in~the~preamble~to~load~the~appropriate~code. } % \end{macrocode} % %\subsection{Design-level macros} % %\begin{macro}{\DeclareBinaryPrefix} %\begin{macro}{\DeclareSIPostPower} %\begin{macro}{\DeclareSIPrefix} %\begin{macro}{\DeclareSIPrePower} %\begin{macro}{\DeclareSIQualifier} %\begin{macro}{\DeclareSIUnit} %\begin{macro}{\DeclareSIUnitWithOptions} % The macros for creating units and so on are in design name space. % Basically, a set of shuffles for arguments. % \begin{macrocode} \NewDocumentCommand \DeclareBinaryPrefix { m m m } { \@@_declare_prefix:Nnnn #1 {#2} { 2 } {#3} } \NewDocumentCommand \DeclareSIPostPower { m m } { \@@_declare_power_after:Nn #1 {#2} } \NewDocumentCommand \DeclareSIPrefix { m m m } { \@@_declare_prefix:Nnnn #1 {#2} { 10 } {#3} } \NewDocumentCommand \DeclareSIPrePower { m m } { \@@_declare_power_before:Nn #1 {#2} } \NewDocumentCommand \DeclareSIQualifier { m m } { \@@_declare_qualifier:Nn #1 {#2} } \NewDocumentCommand \DeclareSIUnit { O { } m m } { \@@_declare_unit:Nnn #2 {#3} {#1} } \NewDocumentCommand \DeclareSIUnitWithOptions { m m m } { \@@_declare_unit:Nnn #1 {#2} {#3} } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % % None of this should be done after the preamble. % \begin{macrocode} \@onlypreamble \DeclareBinaryPrefix \@onlypreamble \DeclareSIPostPower \@onlypreamble \DeclareSIPrefix \@onlypreamble \DeclareSIPrePower \@onlypreamble \DeclareSIQualifier \@onlypreamble \DeclareSIUnit \@onlypreamble \DeclareSIUnitWithOptions % \end{macrocode} % %\begin{macro}{\SendSettingsToPgf} % A settings transfer function. % \begin{macrocode} \cs_new_protected:Npn \SendSettingsToPgf { \@@_pgf_link: } % \end{macrocode} %\end{macro} % %\subsection{Document macros} % % The user document macros are all collected together here for ease. % %\begin{macro}{\ang} % The \cs{ang} function does very little beyond setting the local % keys and passing on the input. % \begin{macrocode} \NewDocumentCommand \ang { o > { \SplitArgument { 2 } { ; } } m } { \group_begin: \IfNoValueF {#1} { \keys_set:nn { siunitx } {#1} } \@@_angle_output:nnn #2 \group_end: } % \end{macrocode} %\end{macro} % %\begin{macro}{\num} % The \cs{num} macro is quite simple: read the number, check it is % correct then print it. % \begin{macrocode} \NewDocumentCommand \num { o m } { \leavevmode \group_begin: \IfNoValueF {#1} { \keys_set:nn { siunitx } {#1} } \@@_number_output:n {#2} \group_end: } % \end{macrocode} %\end{macro} % %\begin{macro}{\numlist} % Lists of numbers are trivially easy to work with. % \begin{macrocode} \NewDocumentCommand \numlist { o > { \SplitList { ; } } m } { \leavevmode \group_begin: \IfNoValueF {#1} { \keys_set:nn { siunitx } {#1} } \@@_list_numbers:n {#2} \group_end: } % \end{macrocode} %\end{macro} % %\begin{macro}{\numrange} % A very simple approach is taken here: this is not intended for % anything complicated. % \begin{macrocode} \NewDocumentCommand \numrange { o m m } { \leavevmode \group_begin: \IfNoValueF {#1} { \keys_set:nn { siunitx } {#1} } \@@_range_numbers:nn {#2} {#3} \group_end: } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \SIlist , % \SIrange %} % Lists and range of values are handled in a very similar way. % Everything is kept relatively simple, and so there is not too much % complexity. In theory the two could be combined together, but % the differences between the two make this less desirable. % \begin{macrocode} \NewDocumentCommand \SIlist { o > { \SplitList { ; } } m m } { \leavevmode \group_begin: \IfNoValueTF {#1} { \@@_list_units:nnn {#2} {#3} { } } { \keys_set:nn { siunitx } {#1} \@@_list_units:nnn {#2} {#3} {#1} } \group_end: } \NewDocumentCommand \SIrange { o m m m } { \leavevmode \group_begin: \IfNoValueTF {#1} { \@@_range_unit:nnnn {#4} { } {#2} {#3} } { \keys_set:nn { siunitx } {#1} \@@_range_unit:nnnn {#4} {#1} {#2} {#3} } \group_end: } % \end{macrocode} %\end{macro} % %\begin{macro}{\SI} % The main \cs{SI} function follows the same pattern as the previous % ones. % \begin{macrocode} \NewDocumentCommand \SI { o m o m } { \leavevmode \group_begin: \IfNoValueTF {#1} { \@@_combined:nnnn { } {#2} {#3} {#4} } { \keys_set:nn { siunitx } {#1} \@@_combined:nnnn {#1} {#2} {#3} {#4} } \group_end: } % \end{macrocode} %\end{macro} % %\begin{macro}{\sisetup} % The set up macro simply moves to the correct path and executes % whatever has been passed. % \begin{macrocode} \NewDocumentCommand \sisetup { m } { \keys_set:nn { siunitx } {#1} } % \end{macrocode} %\end{macro} % %\begin{macro}{\tablenum} % A variation on the \cs{num} macro that will retain alignment within % \cs{multicolumn} and \cs{multirow} situations. The slightly odd code % for the non-parsed case is needed to reinsert the appropriate tokens % after \enquote{collection}. % \begin{macrocode} \NewDocumentCommand \tablenum { o m } { \leavevmode \IfNoValueF {#1} { \keys_set:nn { siunitx } {#1} } \bool_if:NTF \l_@@_number_parse_bool { \tl_set:Nn \l_@@_table_collect_tl {#2} \bool_set_false:N \l_@@_table_collect_pre_bool \@@_table_print_S: } { \@@_table_print_S_direct: #2 \@@_table_print: } } % \end{macrocode} %\end{macro} % %\begin{macro}{\si} % The \cs{si} macro needs to pass options through to the internal % function as well as setting them here. This is used so that options % set for a unit can be overridden on a one-off basis. % \begin{macrocode} \NewDocumentCommand \si { o m } { \leavevmode \group_begin: \IfNoValueTF {#1} { \@@_unit_output:nn {#2} { } } { \keys_set:nn { siunitx } {#1} \@@_unit_output:nn {#2} {#1} } \group_end: } % \end{macrocode} %\end{macro} % %\subsection{Precautions for section headings} % % There are two issues to be handled for section headings, \emph{etc}. % First, within the \cs{addcontentline} macro the various unit functions % need to be \cs{protected}. Secondly, there is a need to worry about % \pkg{hyperref}, and ensure that everything works cleanly and with % no unnecessary warnings. % % \begin{macro}{\@@_contents_add: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} \AtBeginDocument { \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 \seq_map_inline:Nn \l_@@_declare_list_seq { \@@_contents_add:N ##1 } } { \token_to_str:N \@writefile {#1} {#2} } } } \cs_new_protected:Npn \@@_contents_add:N #1 { \cs_set:Npn #1 { \token_to_str:N #1 \c_space_tl } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_contents_bookmarks:} % The idea here is two-fold. First, all of the unit macros are set % up to simply print their literal interpretation: this is hopefully % good enough for most bookmark situations. Secondly, the document % commands are made expandable. This allows a bit of re-arrangement % of the input, removes any set up options (which are being ignored) % and stops \pkg{hyperref} issuing a warning. % \begin{macrocode} \cs_new_protected:Npn \@@_contents_bookmarks: { \seq_map_inline:Nn \l_@@_declare_list_seq { \@@_unit_print_literal_aux:N ##1 } \cs_if_exist:NT \FB@fg { \cs_set_eq:NN \fg \FB@fg } \msg_redirect_name:nnn { xparse } { redefine-command } { none } \cs_set_eq:NN \num \@@_bookmark_num:w \cs_set_eq:NN \numrange \@@_bookmark_numrange:w \cs_set_eq:NN \si \@@_bookmark_si:w \cs_set_eq:NN \SI \@@_bookmark_SI:w \cs_set_eq:NN \SIrange \@@_bookmark_SIrange:w \cs_set_eq:NN \si \@@_bookmark_si:w \cs_set_eq:NN \highlight \use_ii:nn \cs_set_eq:NN \@@_textsuperscript:n \use:n \cs_set:Npn \SIUnitSymbolAngstrom { \AA } \cs_set:Npn \SIUnitSymbolArcminute { ' } \cs_set:Npn \SIUnitSymbolArcsecond { '' } \cs_set:Npn \SIUnitSymbolCelsius { \textcelsius } \cs_set:Npn \SIUnitSymbolDegree { \textdegree } \cs_set:Npn \SIUnitSymbolMicro { \textmu } \cs_set:Npn \SIUnitSymbolOhm { [ohm] } } % \end{macrocode} % \end{macro} % % \begin{macro} % { % \@@_bookmark_num:w , % \@@_bookmark_numrange:w , % \@@_bookmark_SIlist:w , % \@@_bookmark_SIrange:w , % \@@_bookmark_SI:w , % \@@_bookmark_si:w % } % To keep things fast, expandable versions of the document commands % are created only once. These are then used if necessary to remove % and re-order arguments in an expandable fashion. % \begin{macrocode} \DeclareExpandableDocumentCommand \@@_bookmark_num:w { o m } {#2} \DeclareExpandableDocumentCommand \@@_bookmark_numrange:w { o m m } { #2 \l_@@_range_phrase_tl #3 } \DeclareExpandableDocumentCommand \@@_bookmark_SI:w { o m o m } { \IfNoValueF {#3} {#3} #2 ~ #4 } \DeclareExpandableDocumentCommand \@@_bookmark_SIlist:w { o m m } { \@@_bookmark_SIlist_map:nn {#1} {#2} } \DeclareExpandableDocumentCommand \@@_bookmark_SIrange:w { o m m m } { #2 ~ #4 \l_@@_range_phrase_tl #3 ~ #4 } \DeclareExpandableDocumentCommand \@@_bookmark_si:w { o m } {#2} % \end{macrocode} % \end{macro} % %\begin{macro}{\@@_bookmark_SIlist_map:nn} %\begin{macro}[aux]{\@@_bookmark_SIlist_map_aux:nw} % An expandable mapping to replace the list separator in the % input by appropriate output version. % \begin{macrocode} \cs_new:Npn \@@_bookmark_SIlist_map:nn #1#2 { \@@_bookmark_SIlist_map_aux:nw {#2} #1 ; \q_recursion_tail ; \q_recursion_tail ; \q_recursion_stop } \cs_new:Npn \@@_bookmark_SIlist_map_aux:nw #1#2 ; #3 ; #4 { #2 ~ #1 \quark_if_recursion_tail_stop:n {#3} \quark_if_recursion_tail_stop_do:nn {#4} { \l_@@_list_separator_final_tl #3 ~ #1 } \l_@@_list_separator_tl \@@_bookmark_SIlist_map_aux:nw {#1} #3 ; #4 } % \end{macrocode} %\end{macro} %\end{macro} % % A short check to get things working. % \begin{macrocode} \AtBeginDocument { \@ifpackageloaded { hyperref } { \pdfstringdefDisableCommands { \@@_contents_bookmarks: } } { } } % \end{macrocode} % %\subsection{Physical units} % %\begin{macro}{\kilogram} %\begin{macro}{\metre} %\begin{macro}{\meter} %\begin{macro}{\mole} %\begin{macro}{\kelvin} %\begin{macro}{\candela} %\begin{macro}{\second} %\begin{macro}{\ampere} % The basic SI units are always defined, including both variants for % metre. % \begin{macrocode} \DeclareSIUnit \kilogram { \kilo \gram } \DeclareSIUnit \metre { m } \DeclareSIUnit \meter { \metre } \DeclareSIUnit \mole { mol } \DeclareSIUnit \second { s } \DeclareSIUnit \ampere { A } \DeclareSIUnit \kelvin { K } \DeclareSIUnit \candela { cd } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\gram} % The gram is an odd unit as it is needed for the base unit kilogram. % \begin{macrocode} \DeclareSIUnit \gram { g } % \end{macrocode} %\end{macro} % %\begin{macro}{\yocto} %\begin{macro}{\zepto} %\begin{macro}{\atto} %\begin{macro}{\femto} %\begin{macro}{\pico} %\begin{macro}{\nano} %\begin{macro}{\micro} %\begin{macro}{\milli} %\begin{macro}{\centi} %\begin{macro}{\deci} % The various SI multiple prefixes are defined here: first the small % ones. % \begin{macrocode} \DeclareSIPrefix \yocto { y } { -24 } \DeclareSIPrefix \zepto { z } { -21 } \DeclareSIPrefix \atto { a } { -18 } \DeclareSIPrefix \femto { f } { -15 } \DeclareSIPrefix \pico { p } { -12 } \DeclareSIPrefix \nano { n } { -9 } \DeclareSIPrefix \micro { \SIUnitSymbolMicro } { -6 } \DeclareSIPrefix \milli { m } { -3 } \DeclareSIPrefix \centi { c } { -2 } \DeclareSIPrefix \deci { d } { -1 } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\deca} %\begin{macro}{\deka} %\begin{macro}{\hecto} %\begin{macro}{\kilo} %\begin{macro}{\mega} %\begin{macro}{\giga} %\begin{macro}{\tera} %\begin{macro}{\peta} %\begin{macro}{\exa} %\begin{macro}{\zetta} %\begin{macro}{\yotta} % Now the large ones. % \begin{macrocode} \DeclareSIPrefix \deca { da } { 1 } \DeclareSIPrefix \deka { da } { 1 } \DeclareSIPrefix \hecto { h } { 2 } \DeclareSIPrefix \kilo { k } { 3 } \DeclareSIPrefix \mega { M } { 6 } \DeclareSIPrefix \giga { G } { 9 } \DeclareSIPrefix \tera { T } { 12 } \DeclareSIPrefix \peta { P } { 15 } \DeclareSIPrefix \exa { E } { 18 } \DeclareSIPrefix \zetta { Z } { 21 } \DeclareSIPrefix \yotta { Y } { 24 } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\becquerel} %\begin{macro}{\celsius} %\begin{macro}{\degreeCelsius} %\begin{macro}{\coulomb} %\begin{macro}{\farad} %\begin{macro}{\gray} %\begin{macro}{\hertz} %\begin{macro}{\henry} %\begin{macro}{\joule} %\begin{macro}{\katal} %\begin{macro}{\lumen} %\begin{macro}{\lux} % A number of derived units with defined names and symbols. % \begin{macrocode} \DeclareSIUnit \becquerel { Bq } \DeclareSIUnit \celsius { \SIUnitSymbolCelsius } \DeclareSIUnit \degreeCelsius { \SIUnitSymbolCelsius } \DeclareSIUnit \coulomb { C } \DeclareSIUnit \farad { F } \DeclareSIUnit \gray { Gy } \DeclareSIUnit \hertz { Hz } \DeclareSIUnit \henry { H } \DeclareSIUnit \joule { J } \DeclareSIUnit \katal { kat } \DeclareSIUnit \lumen { lm } \DeclareSIUnit \lux { lx } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\begin{macro}{\newton} %\begin{macro}{\ohm} %\begin{macro}{\pascal} %\begin{macro}{\radian} %\begin{macro}{\siemens} %\begin{macro}{\sievert} %\begin{macro}{\steradian} %\begin{macro}{\tesla} %\begin{macro}{\volt} %\begin{macro}{\watt} %\begin{macro}{\weber} % More units. % \begin{macrocode} \DeclareSIUnit \newton { N } \DeclareSIUnit \ohm { \SIUnitSymbolOhm } \DeclareSIUnit \pascal { Pa } \DeclareSIUnit \radian { rad } \DeclareSIUnit \siemens { S } \DeclareSIUnit \sievert { Sv } \DeclareSIUnit \steradian { sr } \DeclareSIUnit \tesla { T } \DeclareSIUnit \volt { V } \DeclareSIUnit \watt { W } \DeclareSIUnit \weber { Wb } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\arcminute} %\begin{macro}{\arcsecond} %\begin{macro}{\day} %\begin{macro}{\degree} %\begin{macro}{\hectare} %\begin{macro}{\hour} %\begin{macro}{\litre} %\begin{macro}{\liter} %\begin{macro}{\minute} %\begin{macro}{\percent} %\begin{macro}{\tonne} % Non-SI, but accepted for general use. % \begin{macrocode} \DeclareSIUnit [ number-unit-product = ] \arcmin { \arcminute } \DeclareSIUnit [ number-unit-product = ] \arcminute { \SIUnitSymbolArcminute } \DeclareSIUnit [ number-unit-product = ] \arcsecond { \SIUnitSymbolArcsecond } \DeclareSIUnit \day { d } \DeclareSIUnit[ number-unit-product = ] \degree { \SIUnitSymbolDegree } \DeclareSIUnit \hectare { ha } \DeclareSIUnit \hour { h } \DeclareSIUnit \litre { l } \DeclareSIUnit \liter { L } \DeclareSIUnit \minute { min } \DeclareSIUnit \percent { \char 37 } \DeclareSIUnit \tonne { t } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\astronomicalunit} %\begin{macro}{\atomicmassunit} %\begin{macro}{\electronvolt} %\begin{macro}{\dalton} % A few units based on physical measurements exist. % \begin{macrocode} \DeclareSIUnit \astronomicalunit { 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_set_catcode_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_set_lccode:nn { `\E } { `\E } \char_set_catcode_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}{\@@_strict_option:n} %\begin{macro}[aux]{\@@_strict_option_aux:n} % When sticking to the rules closely, a few options are not available. % \begin{macrocode} \keys_define:nn { siunitx } { strict .code:n = { \keys_set:nn { siunitx } { bracket-numbers = true, detect-family = false, detect-mode = false, detect-shape = false, detect-weight = false, multi-part-units = brackets, parse-numbers = true, parse-units = true, product-units = repeat } \@@_strict_option:n { bracket-numbers , detect-family , detect-italic , detect-mode , detect-shape , detect-weight , multi-part-units , parse-numbers , parse-units , product-units } \keys_define:nn { siunitx } { per-mode / repeated-symbol .code:n = { \msg_warning:nnx { siunitx } { option-not-available } { per-mode~=~repeated-symbol } } } } } \@@_option_deactivate:n { strict } \cs_new_protected:Npn \@@_strict_option:n #1 { \clist_map_function:nN {#1} \@@_strict_option_aux:n } \cs_new_protected:Npn \@@_strict_option_aux:n #1 { \keys_define:nn { siunitx } { #1 .code:n = { \msg_warning:nnx { siunitx } { option-not-available } {#1} } } } % \end{macrocode} %\end{macro} %\end{macro} % %\subsection{Locales} % % The basics for defining locales are easy: these are just meta keys. % The US locale is simply an alias for the UK one, which is the default. % \begin{macrocode} \keys_define:nn { siunitx } { locale .choice:, locale / DE .meta:n = { exponent-product = \ensuremath { \cdot } , inter-unit-product = \, , output-decimal-marker = { , } }, locale / FR .meta:n = { exponent-product = \ensuremath { \times } , inter-unit-product = \, , output-decimal-marker = { , } }, locale / UK .meta:n = { exponent-product = \ensuremath { \times } , inter-unit-product = \, , output-decimal-marker = . }, locale / US .meta:n = { locale = UK }, locale / USA .meta:n = { locale = UK }, locale / ZA .meta:n = { exponent-product = \ensuremath { \times } , inter-unit-product = \ensuremath { \cdot } , output-decimal-marker = { , } }, } % \end{macrocode} % %\subsection{Localisation} % % Localisation makes use of the \pkg{translator} package. This only % happens if it is available, and is transparent to the user. % \begin{macrocode} \file_if_exist:nT { translator.sty } { \RequirePackage { translator } \usedictionary { translator-basic-dictionary } \providetranslation [ to = English ] { to~(numerical~range) } { to } \providetranslation [ to = French ] { to~(numerical~range) } { \`a } \providetranslation [ to = German ] { to~(numerical~range) } { bis } \sisetup { list-final-separator = { ~ \translate { and } ~ }, list-pair-separator = { ~ \translate { and } ~ }, range-phrase = { ~ \translate { to~(numerical~range) } ~ } } } % \end{macrocode} % % \subsection{Loading additional configurations} % % \begin{variable}{\c_@@_configuration_ext_tl} % Logical mark-up for the file extension. % \begin{macrocode} \tl_const:Nn \c_@@_configuration_ext_tl { cfg } % \end{macrocode} % \end{variable} % % \begin{macro}{\@@_load_abbreviations:} % \begin{macro}{\@@_load_binary:} % Loading abbreviations is on by default, which therefore requires a bit % of juggling. The idea here is that the abbreviations will be loaded unless % specifically turned off. This can occur anywhere in the preamble. % \begin{macrocode} \keys_define:nn { siunitx } { abbreviations .choice:, abbreviations / true .code:n = { \@@_load_abbreviations: }, abbreviations / false .code:n = { \cs_set_eq:NN \@@_load_abbreviations: \prg_do_nothing: } , abbreviations .default:n = true , binary-units .choice:, binary-units / true .code:n = { \AtBeginDocument { \@@_load_binary: } }, binary-units / false .code:n = { \cs_set_eq:NN \@@_load_binary: \prg_do_nothing: } , binary-units .default:n = true } \cs_new_protected_nopar:Npn \@@_load_abbreviations: { \@onefilewithoptions { siunitx-abbreviations } [ ] [ ] \c_@@_configuration_ext_tl } \cs_new_protected_nopar:Npn \@@_load_binary: { \@onefilewithoptions { siunitx-binary } [ ] [ ] \c_@@_configuration_ext_tl } \AtBeginDocument { \@@_load_abbreviations: } \@@_option_deactivate:n { abbreviations , binary } % \end{macrocode} % \end{macro} % \end{macro} % % The version 1 options are not loaded as standard. % \begin{macrocode} \keys_define:nn { siunitx } { version-1-compatibility .choice: , version-1-compatibility / true .code:n = { \@onefilewithoptions { siunitx-version-1 } [ ] [ ] \c_@@_configuration_ext_tl }, version-1-compatibility / false .code:n = { } , version-1-compatibility .default:n = true } \@@_option_deactivate:n { version-1-compatibility } % \end{macrocode} % % Dealing with the old \opt{load-configurations} option is pretty easy, as % only one choice is important. % \begin{macrocode} \keys_define:nn { siunitx } { load-configurations .code:n = { \clist_if_in:nnT {#1} { version-1 } { \@onefilewithoptions { siunitx-version-1 } [ ] [ ] \c_@@_configuration_ext_tl } } } \@@_option_deactivate:n { load-configurations } % \end{macrocode} % % Load any local configuration file. % \begin{macrocode} \file_if_exist:nT { siunitx . \c_@@_configuration_ext_tl } { \@onefilewithoptions { siunitx } [ ] [ ] \c_@@_configuration_ext_tl } % \end{macrocode} % % Finally apply the settings given at load time. % \begin{macrocode} \ProcessKeysOptions { siunitx } % \end{macrocode} % % Creating document commands has to happen here so it is after any load-time % changes to the units available. % \begin{macrocode} \AtBeginDocument { \bool_if:NTF \l_@@_create_free_bool { \@@_unit_create_functions: } { \@@_unit_create_empty_functions: } } % \end{macrocode} % % \begin{macrocode} % % \end{macrocode} % %\subsection{Support for version one} % % \begin{macrocode} %<*version-1> % \end{macrocode} % % \begin{macrocode} \ProvidesExplFile {siunitx-version-1.cfg} {2014/09/27} {2.6b} {siunitx: Version 1 settings} % \end{macrocode} % % The re-arrangements made to the code in version two, and in particular % the new option names, mean that support for version one needs to be % included explicitly. % % \begin{macrocode} \keys_define:nn { siunitx } { addsign .choice: , addsign / all .meta:n = { explicit-sign = + }, addsign / exp .meta:n = { explicit-sign = + }, addsign / false .meta:n = { explicit-sign = }, addsign / mant .meta:n = { explicit-sign = + }, addsign / none .meta:n = { explicit-sign = }, addsign / true .meta:n = { explicit-sign = + }, addsign .default:n = { true }, allowlitunits .meta:n = { free-standing-units = #1 }, allowlitunits .default:n = { true }, allowoptarg .meta:n = { unit-optional-argument = #1 }, allowoptargs .default:n = { true }, allowzeroexp .meta:n = { retain-zero-exponent = #1 }, allowzeroexp .default:n = { true }, alsoload .code:n = , angformat .code:n = , anglesep .choice: , anglesep / cdot .meta:n = { arc-separator = \ensuremath { { } \cdot { } } }, anglesep / comma .meta:n = { arc-separator = \ensuremath { { {,} } } }, anglesep / fullstop .meta:n = { arc-separator = \ensuremath { { { . } } } }, anglesep / med .meta:n = { arc-separator = \ensuremath { \: } }, anglesep / medium .meta:n = { arc-separator = \ensuremath { \: } }, anglesep / none .meta:n = { arc-separator = }, anglesep / period .meta:n = { arc-separator = \ensuremath { { { . } } } }, anglesep / space .meta:n = { arc-separator = \text { ~ } }, anglesep / stop .meta:n = { arc-separator = \ensuremath { { { . } } } }, anglesep / thick .meta:n = { arc-separator = \ensuremath { \; } }, anglesep / thin .meta:n = { arc-separator = \ensuremath { \, } }, anglesep / tightcdot .meta:n = { arc-separator = \ensuremath { \bgroup \cdot \egroup } }, anglesep / tighttimes .meta:n = { arc-separator = \ensuremath { \bgroup \times \egroup } }, anglesep / times .meta:n = { arc-separator = \ensuremath { \times } }, anglesep / unknown .meta:n = { arc-separator = \ensuremath {#1} }, astroang .meta:n = { angle-symbol-over-decimal = #1 }, astroang .default:n = { true }, closeerr .meta:n = { close-bracket = \ensuremath {#1} }, closefrac .meta:n = { close-bracket = \ensuremath {#1} }, closerange .meta:n = { close-bracket = \ensuremath {#1} }, colour .code:n = { color = #1 }, colorall .code:n = , colourall .code:n = , colorneg .code:n = , colourneg .code:n = , colorunits .meta:n = , colourunits .meta:n = , colorvalues .meta:n = , colourvalues .meta:n = , decimalsymbol .choice: , decimalsymbol / cdot .meta:n = { output-decimal-marker = \ensuremath { { } \cdot { } } }, decimalsymbol / comma .meta:n = { output-decimal-marker = { \ensuremath { { , } } } }, decimalsymbol / fullstop .meta:n = { output-decimal-marker = { \ensuremath { { . } } } }, decimalsymbol / period .meta:n = { output-decimal-marker = { \ensuremath { { . } } } }, decimalsymbol / stop .meta:n = { output-decimal-marker = { \ensuremath { { . } } } }, decimalsymbol / tightcdot .code:n = { output-decimal-marker = \ensuremath { \bgroup \cdot \egroup } }, decimalsymbol / unknown .meta:n = { output-decimal-marker = \ensuremath {#1} }, debug .code:n = , detectdisplay .meta:n = { detect-display-math = #1 }, detectdisplay .default:n = { true }, digitsep .choice: , digitsep / cdot .meta:n = { group-separator = \ensuremath { { } \cdot { } } }, digitsep / comma .meta:n = { group-separator = \ensuremath { { , } } }, digitsep / fullstop .meta:n = { group-separator = \ensuremath { . } }, digitsep / med .meta:n = { group-separator = \ensuremath { \: } }, digitsep / medium .meta:n = { group-separator = \ensuremath { \: } }, digitsep / none .meta:n = { group-separator = }, digitsep / period .meta:n = { group-separator = \ensuremath { . } }, digitsep / space .meta:n = { group-separator = \text { ~ } }, digitsep / stop .meta:n = { group-separator = \ensuremath { . } }, digitsep / thick .meta:n = { group-separator = \ensuremath { \; } }, digitsep / thin .meta:n = { group-separator = \ensuremath { \, } }, digitsep / tightcdot .meta:n = { group-separator = \ensuremath { \bgroup \cdot \egroup } }, digitsep / tighttimes .meta:n = { group-separator = \ensuremath { \bgroup \times \egroup } }, digitsep / times .meta:n = { group-separator = \ensuremath { \times } }, digitsep / unknown .meta:n = { group-separator = \ensuremath {#1} }, dp .meta:n = { round-mode = places, round-precision = #1, }, emulate .code:n = , errspace .choice: , errspace / med .meta:n = { uncertainty-separator = \ensuremath { \: } }, errspace / medium .meta:n = { uncertainty-separator = \ensuremath { \: } }, errspace / none .meta:n = { uncertainty-separator = }, errspace / space .meta:n = { uncertainty-separator = \text { ~ } }, errspace / thick .meta:n = { uncertainty-separator = \ensuremath { \; } }, errspace / thin .meta:n = { uncertainty-separator = \ensuremath { \, } }, errspace / unknown .meta:n = { uncertainty-separator = \ensuremath {#1} }, eVcorra .code:n = , eVcorrb .code:n = , expbase .choice: , expbase / ten .meta:n = { exponent-base = 10 }, expbase / two .meta:n = { exponent-base = 2 }, expbase / unknown .meta:n = { exponent-base = #1 }, expproduct .choice: , expproduct / cdot .meta:n = { exponent-product = \ensuremath { { } \cdot { } } }, expproduct / tightcdot .meta:n = { exponent-product = \ensuremath { \bgroup \cdot \egroup } }, expproduct / tighttimes .meta:n = { exponent-product = \ensuremath { \bgroup \times \egroup } }, expproduct / times .meta:n = { exponent-product = \ensuremath { \times } }, expproduct / unknown .meta:n = { exponent-product = \ensuremath {#1} }, fixdp .choice:, fixdp / false .meta:n = { round-mode = none }, fixdp / true .meta:n = { round-mode = places }, fixdp .default:n = { true }, fixsf .choice: , fixsf / false .meta:n = { round-mode = none }, fixsf / true .meta:n = { round-mode = figures }, fixsf .default:n = { true }, fraction .choice: , fraction / frac .meta:n = { fraction-function = \frac }, fraction / nice .meta:n = { fraction-function = \frac }, fraction / sfrac .meta:n = { fraction-function = \sfrac }, fraction / ugly .meta:n = { fraction-function = \frac , per-mode = symbol-or-fraction }, inlinebold .meta:n = { detect-inline-weight = #1 }, log .code:n = , load .code:n = , loctolang .code:n = , mathOmega .meta:n = { math-ohm = #1 }, mathcelsius .meta:n = { math-celsius = #1 }, mathdegree .meta:n = { math-degree = #1 }, mathminute .meta:n = { math-arcminute = #1 }, mathmu .meta:n = { math-micro = #1 }, mathringA .meta:n = { math-angstrom = #1 }, mathrm .code:n = { \use:x { \keys_set:nn { siunitx } { math-rm = \exp_not:c {#1} } } }, mathsOmega .meta:n = { math-ohm = #1 }, mathscelsius .meta:n = { math-celsius = #1 }, mathsdegree .meta:n = { math-degree = #1 }, mathsecond .meta:n = { math-arcsecond = #1 }, mathsf .code:n = { \use:x { \keys_set:nn { siunitx } { math-sf = \exp_not:c {#1} } } }, mathsminute .meta:n = { math-arcminute = #1 }, mathsmu .meta:n = { math-micro = #1 }, mathsringA .meta:n = { math-angstrom = #1 }, mathsrm .code:n = { \use:x { \keys_set:nn { siunitx } { math-rm= \exp_not:c {#1} } } }, mathssecond .meta:n = { math-arcsecond = #1 }, mathssf .code:n = { \use:x { \keys_set:nn { siunitx } { math-sf = \exp_not:c {#1} } } }, mathstt .code:n = { \use:x { \keys_set:nn { siunitx } { math-tt = \exp_not:c {#1} } } }, mathtt .code:n = { \use:x { \keys_set:nn { siunitx } { math-tt = \exp_not:c {#1} } } }, negcolor .meta:n = { negative-color = #1 }, negcolour .meta:n = { negative-color = #1 }, noload .code:n = , numaddn .meta:n = { input-symbols = #1 }, numcloseerr .meta:n = { input-close-uncertainty = #1 }, numdecimal .meta:n = { input-decimal-markers = #1 }, numdigits .meta:n = { input-digits = #1 }, numdiv .meta:n = { input-quotient = #1 }, numexp .meta:n = { input-exponent-markers = #1 }, numgobble .meta:n = { input-ignore = #1 }, numopenerr .meta:n = { input-open-uncertainty = #1 }, numprod .meta:n = { input-product = #1 }, numsign .meta:n = { input-signs = #1 }, obeyall .meta:n = { detect-all = #1 }, obeyall .default:n = { true }, obeybold .meta:n = { detect-weight = #1 }, obeybold .default:n = { true }, obeyfamily .meta:n = { detect-family = #1 }, obeyfamily .default:n = { true }, obeyitalic .meta:n = { detect-shape = #1 }, obeyitalic .default:n = { true }, obeymode .meta:n = { detect-mode = #1 }, obeymode .default:n = { true }, openerr .meta:n = { open-bracket = \ensuremath {#1} }, openfrac .meta:n = { open-bracket = \ensuremath {#1} }, openrange .meta:n = { open-bracket = \ensuremath {#1} }, padangle .choice: , padangle / all .meta:n = { add-arc-degree-zero = true, add-arc-minute-zero = true, add-arc-second-zero = true }, padangle / both .meta:n = { add-arc-degree-zero = true, add-arc-minute-zero = true, add-arc-second-zero = true }, padangle / false .meta:n = { add-arc-degree-zero = false, add-arc-minute-zero = false, add-arc-second-zero = false }, padangle / large .meta:n = { add-arc-degree-zero = true, add-arc-minute-zero = true, add-arc-second-zero = false }, padangle / none .meta:n = { add-arc-degree-zero = false, add-arc-minute-zero = false, add-arc-second-zero = false }, padangle / small .meta:n = { add-arc-degree-zero = false, add-arc-minute-zero = true, add-arc-second-zero = true }, true .meta:n = { add-arc-degree-zero = true, add-arc-minute-zero = true, add-arc-second-zero = true }, padnumber .choice: , padnumber / all .meta:n = { add-decimal-zero = true, add-integer-zero = true }, padnumber / both .meta:n = { add-decimal-zero = true, add-integer-zero = true }, padnumber / false .meta:n = { add-decimal-zero = false, add-integer-zero = false }, padnumber / leading .meta:n = { add-decimal-zero = true, add-integer-zero = false }, padnumber / none .meta:n = { add-decimal-zero = false, add-integer-zero = false }, padnumber / trailing .meta:n = { add-decimal-zero = false, add-integer-zero = true }, padnumber / true .meta:n = { add-decimal-zero = true, add-integer-zero = true }, per .choice: , per / frac .meta:n = { per-mode = fraction }, per / fraction .meta:n = { per-mode = fraction }, per / reciprocal .meta:n = { per-mode = reciprocal }, per / slash .meta:n = { per-mode = symbol }, prefixbase .code:n = , prefixproduct .code:n = , prefixsymbolic .meta:n = { prefixes-as-symbols = #1 }, prefixsymbolic .default:n = { true }, prespace .meta:n = { space-before-unit = #1 }, prespace .default:n = { true }, redefsymbols .meta:n = { redefine-symbols = #1 }, redefsymbols .default:n = { true }, repeatunits .choice: , repeatunits / false .meta:n = { multi-part-units = single, product-units = single, }, repeatunits / power .meta:n = { multi-part-units = repeat, product-units = power, }, repeatunits / true .meta:n = { multi-part-units = repeat, product-units = repeat, }, repeatunits .default:n = { true }, retainplus .meta:n = { retain-explicit-plus = #1 }, retainplus .default:n = { true }, seperr .meta:n = { separate-uncertainty = #1 }, seperr .default:n = { true }, sepfour .meta:n = { group-four-digits = true }, sepfour .default:n = { true }, sf .meta:n = { round-mode = figures, round-precision = #1, }, sign .meta:n = { explicit-sign = #1 }, slash .choice: , slash / slash .meta:n = { per-symbol = \ensuremath { / } }, slash / unknown .meta:n = { per-symbol = \ensuremath {#1} }, stickyper .meta:n = { sticky-per = #1 }, stickyper .default:n = { true }, strictarc .code:n = , tabalign .code:n = { \str_if_eq:nnTF {#1} { centre } { \keys_set:nn { siunitx } { table-alignment = center } } { \keys_set:nn { siunitx } { table-alignment = #1 } } }, tabalignexp .code:n = { table-align-exponent = #1 }, tabautofit .meta:n = { table-auto-round = #1 }, tabautofit .default:n = { true }, tabexpalign .code:n = { table-align-exponent = #1 }, tabformat .meta:n = { table-format = #1 }, tabnumalign .code:n = { \str_if_eq:nnTF {#1} { centre } { \keys_set:nn { siunitx } { table-number-alignment = center } } { \str_if_eq:nnTF {#1} { centredecimal } { \keys_set:nn { siunitx } { table-number-alignment = center-decimal-marker } } { \str_if_eq:nnTF {#1} { centerdecimal } { \keys_set:nn { siunitx } { table-number-alignment = center-decimal-marker } } { \keys_set:nn { siunitx } { table-number-alignment = #1 } } } } }, tabparseonly .meta:n = { table-parse-only = #1 }, tabparseonly .default:n = { true }, tabtextalign .code:n = { \str_if_eq:nnTF {#1} { centre } { \keys_set:nn { siunitx } { table-text-alignment = center } } { \keys_set:nn { siunitx } { table-text-alignment = #1 } } }, tabunitalign .code:n = { \str_if_eq:nnTF {#1} { centre } { \keys_set:nn { siunitx } { table-unit-alignment = center } } { \keys_set:nn { siunitx } { table-unit-alignment = #1 } } }, textOmega .meta:n = { text-ohm = #1 }, textcelsius .meta:n = { text-celsius = #1 }, textdegree .meta:n = { text-degree = #1 }, textminute .meta:n = { text-arcminute = #1 }, textmode .choice: , textmode / true .meta:n = { mode = text }, textmode / false .meta:n = { mode = math }, textmode .default:n = { true }, textmu .meta:n = { text-micro = #1 }, textringA .meta:n = { text-angstrom = #1 }, textrm .code:n = { \use:x { \keys_set:nn { siunitx } { text-rm = \exp_not:c {#1} } } }, textsecond .meta:n = { text-arcsecond = #1 }, textsf .code:n = { \use:x { \keys_set:nn { siunitx } { text-sf = \exp_not:c {#1} } } }, texttt .code:n = { \use:x { \keys_set:nn { siunitx } { text-tt = \exp_not:c {#1} } } }, tightpm .meta:n = { tight-spacing = #1 }, tightpm .default:n = { true }, tophrase .meta:n = { range-phrase = #1 }, trapambigerr .choice: , trapambigerr / false .meta:n = { multi-part-units = single }, trapambigerr / true .meta:n = { multi-part-units = brackets }, trapambigerr .default:n = { true }, trapambigfrac .meta:n = { bracket-numbers = #1 }, trapambigfrac .default:n = { true }, trapambigrange .choice: , trapambigrange / false .meta:n = { range-units = single }, trapambigrange / true .meta:n = { range-units = brackets }, trapambigrange .default:n = { true }, unitcolor .meta:n = { unit-color = #1 }, unitcolour .meta:n = { unit-color = #1 }, unitmathrm .code:n = { \use:x { \keys_set:nn { siunitx } { unit-math-rm = \exp_not:c {#1} } } }, unitmathsf .code:n = { \use:x { \keys_set:nn { siunitx } { unit-math-sf = \exp_not:c {#1} } } }, unitmathsrm .code:n = { \use:x { \keys_set:nn { siunitx } { unit-math-rm = \exp_not:c {#1} } } }, unitmathssf .code:n = { \use:x { \keys_set:nn { siunitx } { unit-math-sf = \exp_not:c {#1} } } }, unitmathstt .code:n = { \use:x { \keys_set:nn { siunitx } { unit-math-tt = \exp_not:c {#1} } } }, unitmathtt .code:n = { \use:x { \keys_set:nn { siunitx } { unit-math-tt = \exp_not:c {#1} } } }, unitmode .meta:n = { unit-mode = #1 }, unitsep .choice: , unitsep / cdot .meta:n = { inter-unit-product = \ensuremath { { } \cdot { } } }, unitsep / comma .meta:n = { inter-unit-product = { {,} } }, unitsep / fullstop .meta:n = { inter-unit-product = { { . } } }, unitsep / med .meta:n = { inter-unit-product = \ensuremath { \: } }, unitsep / medium .meta:n = { inter-unit-product = \ensuremath { \: } }, unitsep / none .meta:n = { inter-unit-product = }, unitsep / period .meta:n = { inter-unit-product = { { . } } }, unitsep / space .meta:n = { inter-unit-product = \text { ~ } }, unitsep / stop .meta:n = { inter-unit-product = { { . } } }, unitsep / thick .meta:n = { inter-unit-product = \ensuremath { \; } }, unitsep / thin .meta:n = { inter-unit-product = \, }, unitsep / tightcdot .meta:n = { inter-unit-product = \ensuremath { \bgroup \cdot \egroup } }, unitsep / tighttimes .meta:n = { inter-unit-product = \ensuremath { \bgroup \times \egroup } }, unitsep / times .meta:n = { inter-unit-product = \ensuremath { \times } }, unitsep / unknown .meta:n = { inter-unit-product = \ensuremath {#1} }, unitspace .choice: , unitspace / med .meta:n = { inter-unit-product = \ensuremath { \: } }, unitspace / medium .meta:n = { inter-unit-product = \ensuremath { \: } }, unitspace / none .meta:n = { inter-unit-product = }, unitspace / space .meta:n = { inter-unit-product = \text { ~ } }, unitspace / thick .meta:n = { inter-unit-product = \ensuremath { \; } }, unitspace / thin .meta:n = { inter-unit-product = \, }, unitspace / unknown .meta:n = { inter-unit-product = \ensuremath {#1} }, valuecolor .meta:n = { number-color = #1 }, valuecolour .meta:n = { number-color = #1 }, valuemathrm .code:n = { \use:x { \keys_set:nn { siunitx } { number-math-rm = \exp_not:c {#1} } } }, valuemathsf .code:n = { \use:x { \keys_set:nn { siunitx } { number-math-sf = \exp_not:c {#1} } } }, valuemathsrm .code:n = { \use:x { \keys_set:nn { siunitx } { number-math-rm = \exp_not:c {#1} } } }, valuemathssf .code:n = { \use:x { \keys_set:nn { siunitx } { number-math-sf = \exp_not:c {#1} } } }, valuemathstt .code:n = { \use:x { \keys_set:nn { siunitx } { number-math-tt = \exp_not:c {#1} } } }, valuemathtt .code:n = { \use:x { \keys_set:nn { siunitx } { number-math-tt = \exp_not:c {#1} } } }, valuemode .meta:n = { number-mode = #1 }, valuesep .choice: , valuesep / cdot .meta:n = { number-unit-product = \ensuremath { { } \cdot { } } }, valuesep / comma .meta:n = { number-unit-product = { {,} } }, valuesep / fullstop .meta:n = { number-unit-product = { { . } } }, valuesep / med .meta:n = { number-unit-product = \ensuremath { \: } }, valuesep / medium .meta:n = { number-unit-product = \ensuremath { \: } }, valuesep / none .meta:n = { number-unit-product = }, valuesep / period .meta:n = { number-unit-product = { { . } } }, valuesep / space .meta:n = { number-unit-product = \text { ~ } }, valuesep / stop .meta:n = { number-unit-product = { { . } } }, valuesep / thick .meta:n = { number-unit-product = \ensuremath { \; } }, valuesep / thin .meta:n = { number-unit-product = \, }, valuesep / tightcdot .meta:n = { number-unit-product = \ensuremath { \bgroup \cdot \egroup } }, valuesep / tighttimes .meta:n = { number-unit-product = \ensuremath { \bgroup \times \egroup } }, valuesep / times .meta:n = { number-unit-product = \ensuremath { \times } }, valuesep / unknown .meta:n = { number-unit-product = \ensuremath {#1} }, xspace .meta:n = { use-xspace = #1 }, xspace .default:n = { true }, } % \end{macrocode} % % The error can be simplified here: if the option is not known, then % it really is an error. % \begin{macrocode} \keys_define:nn { siunitx } { unknown .code:n = { \msg_error:nnx { siunitx } { unknown-option } { \exp_not:V \l_keys_key_tl } } } % \end{macrocode} % % A couple of settings which are slightly different by default in % version 1. % \begin{macrocode} \keys_set:nn { siunitx } {free-standing-units = true} % \end{macrocode} % %\begin{macro}{ % \newunit , % \renewunit , % \provideunit %} % The functions for creating units from version one are easy to create. % \begin{macrocode} \cs_new_eq:NN \newunit \DeclareSIUnit \cs_new_eq:NN \renewunit \DeclareSIUnit \cs_new_eq:NN \provideunit \DeclareSIUnit % \end{macrocode} %\end{macro} % %\begin{macro}{ % \newpower , % \renewpower , % \providepower %} % Slightly more complex: an optional argument to check. A simple % assumption is made that it will be \texttt{post}: anything else % would not make sense anyway. % \begin{macrocode} \NewDocumentCommand \newpower { o m m } { \IfNoValueTF {#1} { \DeclareSIPrePower #2 {#3} } { \DeclareSIPostPower #2 {#3} } } \NewDocumentCommand \renewpower { o m m } { \IfNoValueTF {#1} { \DeclareSIPrePower #2 {#3} } { \DeclareSIPostPower #2 {#3} } } \NewDocumentCommand \providepower { o m m } { \IfNoValueTF {#1} { \DeclareSIPrePower #2 {#3} } { \DeclareSIPostPower #2 {#3} } } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \newprefix , % \renewprefix , % \provideprefix %} % Slightly more complex: an optional argument to check. A simple % assumption is made that it will be \texttt{post}: anything else % would not make sense anyway. % \begin{macrocode} \NewDocumentCommand \newprefix { o m m m } { \IfNoValueTF {#1} { \DeclareSIPrefix #2 {#3} {#4} } { \DeclareBinaryPrefix #2 {#3} {#4} } } \NewDocumentCommand \renewprefix { o m m m } { \IfNoValueTF {#1} { \DeclareSIPrefix #2 {#3} {#4} } { \DeclareBinaryPrefix #2 {#3} {#4} } } \NewDocumentCommand \provideprefix { o m m m } { \IfNoValueTF {#1} { \DeclareSIPrefix #2 {#3} {#4} } { \DeclareBinaryPrefix #2 {#3} {#4} } } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \newqualifier , % \renewqualifier , % \providequalifier %} % The functions for creating qualifiers are easy to create again. % \begin{macrocode} \NewDocumentCommand \newqualifier { m m } { \@@_declare_qualifier:Nn #1 {#2} } \cs_new_eq:NN \renewqualifier \newqualifier \cs_new_eq:NN \providequalifier \newqualifier % \end{macrocode} %\end{macro} % %\begin{macro}{ % \Square , % \ssquare %} % In version 1, \cs{square} is not used with these two alternatives % preferred. % \begin{macrocode} \DeclareSIPrePower \Square { 2 } \DeclareSIPrePower \ssquare { 2 } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \BAR , % \bbar , % \Day , % \dday , % \Gray , % \ggray %} % Units which are given awkward names in version one. % \begin{macrocode} \DeclareSIUnit \BAR { \bar } \DeclareSIUnit \bbar { \bar } \DeclareSIUnit \Day { \day } \DeclareSIUnit \dday { \day } \DeclareSIUnit \Gray { \gray } \DeclareSIUnit \ggray { \gray } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \atomicmass , % \arcmin , % \arcsec %} % Slightly different: given more complete names in version two. % \begin{macrocode} \DeclareSIUnit \atomicmass { \atomicmassunit } \DeclareSIUnit \arcmin { \arcminute } \DeclareSIUnit \arcsec { \arcsecond } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \are , % \curie , % \gal , % \millibar , % \rad , % \rem , % \roentgen %} % Units which were defined in version one but are no longer listed % by the \textsc{bipm} as acceptable. % \begin{macrocode} \DeclareSIUnit \are { a } \DeclareSIUnit \curie { Ci } \DeclareSIUnit \gal { Gal } \DeclareSIUnit \millibar { \milli \bar } \DeclareSIUnit \rad { rad } \DeclareSIUnit \rem { rem } \DeclareSIUnit \roentgen { R } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \micA , % \micmol , % \micl , % \micL , % \nanog , % \micg , % \picm , % \micm , % \Sec , % \mics , % \cmc , % \dmc , % \cms %} % A few abbreviations which have been renamed. % \begin{macrocode} \DeclareSIUnit \micA { \micro \ampere } \DeclareSIUnit \micmol { \micro \mole } \DeclareSIUnit \micl { \micro \litre } \DeclareSIUnit \micL { \micro \liter } \DeclareSIUnit \nanog { \nano \gram } \DeclareSIUnit \micg { \micro \gram } \DeclareSIUnit \picm { \pico \metre } \DeclareSIUnit \micm { \micro \metre } \DeclareSIUnit \Sec { \second } \DeclareSIUnit \mics { \micro \second } \DeclareSIUnit \cmc { \centi \metre \cubed } \DeclareSIUnit \dmc { \deci \metre \cubed } \DeclareSIUnit \cms { \centi \metre \squared } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \centimetrecubed , % \centimetresquared , % \cubiccentimetre , % \cubicdecimetre , % \squarecentimetre , % \squaremetre , % \squarekilometre %} % Units from version one that did not seem like a good idea to retain. % \begin{macrocode} \DeclareSIUnit \centimetrecubed { \centi \metre \cubed } \DeclareSIUnit \centimetresquared { \centi \metre \squared } \DeclareSIUnit \cubiccentimetre { \centi \metre \cubed } \DeclareSIUnit \cubicdecimetre { \deci \metre \cubed } \DeclareSIUnit \squarecentimetre { \centi \metre \squared } \DeclareSIUnit \squaremetre { \metre \squared } \DeclareSIUnit \squarekilometre { \kilo \metre \squared } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \parsec , % \lightyear %} % A few units for astronomy that version 1 provided. % \begin{macrocode} \DeclareSIUnit \parsec { pc } \DeclareSIUnit \lightyear { ly } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \gmol , % \kgmol , % \lbmol %} % Slightly odd chemical engineering units, again provided in version 1. % \begin{macrocode} \DeclareSIUnit \gmol { g \text { - } mol } \DeclareSIUnit \kgmol { kg \text { - } mol } \DeclareSIUnit \lbmol { lb \text { - } mol } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \molar , % \Molar , % \torr %} % A few common units for chemistry from version 1. \cs{molar} is % simply a handy abbreviation: \cs{Molar} is common but rather % questionable. % \begin{macrocode} \DeclareSIUnit \molar { \mole \per \cubic \deci \metre } \DeclareSIUnit \Molar { \textsc { m } } \DeclareSIUnit \torr { Torr } % \end{macrocode} %\end{macro} % %\begin{macro}{\gon} % A single unit for geophysics that version 1 included. % \begin{macrocode} \DeclareSIUnit \gon { gon } % \end{macrocode} %\end{macro} % %\begin{macro}{\clight} % Version one had a different definition for \cs{clight}. % \begin{macrocode} \DeclareSIUnit \clight { \text { \ensuremath { c } } } % \end{macrocode} %\end{macro} % %\begin{macro}{ % \micron , % \mrad , % \gauss , % \eVperc , % \nanobarn , % \picobarn , % \femptobarn , % \attobarn , % \zeptobarn , % \yoctobarn , % \nb , % \pb , % \fb , % \ab , % \zb %} % High-energy physics units from version one. % \begin{macrocode} \DeclareSIUnit \micron { \micro \metre } \DeclareSIUnit \mrad { \milli \rad } \DeclareSIUnit \gauss { G } \DeclareSIUnit \eVperc { \eV \per \clight } \DeclareSIUnit \nanobarn { \nano \barn } \DeclareSIUnit \picobarn { \pico \barn } \DeclareSIUnit \femtobarn { \femto \barn } \DeclareSIUnit \attobarn { \atto \barn } \DeclareSIUnit \zeptobarn { \zepto \barn } \DeclareSIUnit \yoctobarn { \yocto \barn } \DeclareSIUnit \nb { \nano \barn } \DeclareSIUnit \pb { \pico \barn } \DeclareSIUnit \fb { \femto \barn } \DeclareSIUnit \ab { \atto \barn } \DeclareSIUnit \zb { \zepto \barn } \DeclareSIUnit \yb { \yocto \barn } % \end{macrocode} %\end{macro} % % \begin{macro}{\requiresiconfigs} % Version one provides this, and it might pop up so should not % cause errors. % \begin{macrocode} \NewDocumentCommand \requiresiconfigs { m } { \keys_set:nn { siunitx } { version-1-compatibility } } % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \subsection{Abbreviated units} % % \begin{macrocode} %<*abbreviations> % \end{macrocode} % % \begin{macrocode} \ProvidesExplFile {siunitx-abbreviations.cfg} {2014/09/27} {2.6b} {siunitx: Abbreviated units} % \end{macrocode} % % The abbreviation file contains a number of short (mainly two or % three letter) versions of the usual long names. They are divided up % into related groups, mainly to avoid an overly long list in one % place. % % \begin{macro}{\A, \pA, \nA, \uA, \mA, \kA} % Currents. % \begin{macrocode} \DeclareSIUnit \A { \ampere } \DeclareSIUnit \pA { \pico \ampere } \DeclareSIUnit \nA { \nano \ampere } \DeclareSIUnit \uA { \micro \ampere } \DeclareSIUnit \mA { \milli \ampere } \DeclareSIUnit \kA { \kilo \ampere } % \end{macrocode} % \end{macro} % \begin{macro}{\Hz, \mHz, \kHz, \MHz, \GHz, \THz} % Then frequencies. % \begin{macrocode} \DeclareSIUnit \Hz { \hertz } \DeclareSIUnit \mHz { \milli \hertz } \DeclareSIUnit \kHz { \kilo \hertz } \DeclareSIUnit \MHz { \mega \hertz } \DeclareSIUnit \GHz { \giga \hertz } \DeclareSIUnit \THz { \tera \hertz } % \end{macrocode} % \end{macro} % \begin{macro}{\mol, \fmol, \pmol, \nmol, \umol, \mmol, \kmol} % Amounts of substance (moles). % \begin{macrocode} \DeclareSIUnit \mol { \mole } \DeclareSIUnit \fmol { \femto \mole } \DeclareSIUnit \pmol { \pico \mole } \DeclareSIUnit \nmol { \nano \mole } \DeclareSIUnit \umol { \micro \mole } \DeclareSIUnit \mmol { \milli \mole } \DeclareSIUnit \kmol { \kilo \mole } % \end{macrocode} % \end{macro} % \begin{macro}{\V, \pV, \nV, \uV, \mV, \kV} % Potentials. % \begin{macrocode} \DeclareSIUnit \V { \volt } \DeclareSIUnit \pV { \pico \volt } \DeclareSIUnit \nV { \nano \volt } \DeclareSIUnit \uV { \micro \volt } \DeclareSIUnit \mV { \milli \volt } \DeclareSIUnit \kV { \kilo \volt } % \end{macrocode} % \end{macro} % \begin{macro}{\hl, \l, \ml, \ul, \hL, \L, \mL, \uL} % Volumes. % \begin{macrocode} \DeclareSIUnit \hl { \hecto \litre } \DeclareSIUnit \l { \litre } \DeclareSIUnit \ml { \milli \litre } \DeclareSIUnit \ul { \micro \litre } \DeclareSIUnit \hL { \hecto \liter } \DeclareSIUnit \L { \liter } \DeclareSIUnit \mL { \milli \liter } \DeclareSIUnit \uL { \micro \liter } % \end{macrocode} % \end{macro} % \begin{macro}{\fg, \pg, \ng, \ug, \mg, \g, \kg, \amu} % Masses. % \begin{macrocode} \DeclareSIUnit \fg { \femto \gram } \DeclareSIUnit \pg { \pico \gram } \DeclareSIUnit \ng { \nano \gram } \DeclareSIUnit \ug { \micro \gram } \DeclareSIUnit \mg { \milli \gram } \DeclareSIUnit \g { \gram } \DeclareSIUnit \kg { \kilo \gram } \DeclareSIUnit \amu { \atomicmassunit } % \end{macrocode} % \end{macro} % \begin{macro} % {\W, \uW, \mW, \kW,\MW , \GW, \kJ, \J, \eV, \meV, \keV, \MeV, \GeV, \TeV, \kWh} % Energies. % \begin{macrocode} \DeclareSIUnit \W { \watt } \DeclareSIUnit \uW { \micro \watt } \DeclareSIUnit \mW { \milli \watt } \DeclareSIUnit \kW { \kilo \watt } \DeclareSIUnit \MW { \mega \watt } \DeclareSIUnit \GW { \giga \watt } \DeclareSIUnit \J { \joule } \DeclareSIUnit \kJ { \kilo \joule } \DeclareSIUnit \eV { \electronvolt } \DeclareSIUnit \meV { \milli \electronvolt } \DeclareSIUnit \keV { \kilo \electronvolt } \DeclareSIUnit \MeV { \mega \electronvolt } \DeclareSIUnit \GeV { \giga \electronvolt } \DeclareSIUnit \TeV { \tera \electronvolt } \DeclareSIUnit [ inter-unit-product = ] \kWh { \kilo \watt \hour } % \end{macrocode} % \end{macro} % \begin{macro}{\m, \pm, \nm, \um, \mm, \cm, \dm, \km} % Lengths. % \begin{macrocode} \DeclareSIUnit \m { \metre } \DeclareSIUnit \pm { \pico \metre } \DeclareSIUnit \nm { \nano \metre } \DeclareSIUnit \um { \micro \metre } \DeclareSIUnit \mm { \milli \metre } \DeclareSIUnit \cm { \centi \metre } \DeclareSIUnit \dm { \deci \metre } \DeclareSIUnit \km { \kilo \metre } % \end{macrocode} % \end{macro} % \begin{macro}{\K} % Temperatures. % \begin{macrocode} \DeclareSIUnit \K { \kelvin } % \end{macrocode} % \end{macro} % \begin{macro}{\dB} % \begin{macrocode} \DeclareSIUnit \dB { \deci \bel } % \end{macrocode} % \end{macro} % \begin{macro}{\F, \fF, \pF} % \begin{macrocode} \DeclareSIUnit \F { \farad } \DeclareSIUnit \fF { \femto \farad } \DeclareSIUnit \pF { \pico \farad } % \end{macrocode} % \end{macro} % \begin{macro}{\N, \mN, \kN, \MN} % Forces. % \begin{macrocode} \DeclareSIUnit \N { \newton } \DeclareSIUnit \mN { \milli \newton } \DeclareSIUnit \kN { \kilo \newton } \DeclareSIUnit \MN { \mega \newton } % \end{macrocode} % \end{macro} % \begin{macro}{\Pa, \kPa, \MPa, \GPa} % Pressures. % \begin{macrocode} \DeclareSIUnit \Pa { \pascal } \DeclareSIUnit \kPa { \kilo \pascal } \DeclareSIUnit \MPa { \mega \pascal } \DeclareSIUnit \GPa { \giga \pascal } % \end{macrocode} % \end{macro} % \begin{macro}{\mohm, \kohm, \Mohm} % Resistances. % \begin{macrocode} \DeclareSIUnit \mohm { \milli \ohm } \DeclareSIUnit \kohm { \kilo \ohm } \DeclareSIUnit \Mohm { \mega \ohm } % \end{macrocode} % \end{macro} % \begin{macro}{\s, \as, \fs, \ps, \ns, \us, \ms} % Finally, times. % \begin{macrocode} \DeclareSIUnit \s { \second } \DeclareSIUnit \as { \atto \second } \DeclareSIUnit \fs { \femto \second } \DeclareSIUnit \ps { \pico \second } \DeclareSIUnit \ns { \nano \second } \DeclareSIUnit \us { \micro \second } \DeclareSIUnit \ms { \milli \second } % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \subsection{Binary units} % % \begin{macrocode} %<*binary> % \end{macrocode} % % \begin{macrocode} \ProvidesExplFile {siunitx-binary.cfg} {2014/09/27} {2.6b} {siunitx: Binary units} % \end{macrocode} % % \begin{macro}{\kibi, \mebi, \gibi, \tebi, \pebi, \exbi, \zebi, \yobi} % The binary units as specified by the IEC. % \begin{macrocode} \DeclareBinaryPrefix \kibi { Ki } { 10 } \DeclareBinaryPrefix \mebi { Mi } { 20 } \DeclareBinaryPrefix \gibi { Gi } { 30 } \DeclareBinaryPrefix \tebi { Ti } { 40 } \DeclareBinaryPrefix \pebi { Pi } { 50 } \DeclareBinaryPrefix \exbi { Ei } { 60 } \DeclareBinaryPrefix \zebi { Zi } { 70 } \DeclareBinaryPrefix \yobi { Yi } { 80 } % \end{macrocode} % \end{macro} % \begin{macro}{\bit, \byte} % Now the units. % \begin{macrocode} \DeclareSIUnit \bit { bit } \DeclareSIUnit \byte { B } % \end{macrocode} % \end{macro} % % \begin{macrocode} % % \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}. % % \bibitem{SI:5.3.3} % \emph{Formatting the value of a quantity}, % \url{http://www.bipm.org/en/si/si_brochure/chapter5/5-3-2.html#5-3-3}. % % \end{thebibliography} % % \PrintChanges % % \PrintIndex